| author | |
| committer | |
| log | 1a998886c863a1829d649f196093f1058cd9cf13 |
| tree | db1b3b0a043a113cfb6544e8103cb64f8e4e4d8f |
| parent | 5b4b033236a7bed19c90faf7fefbc1990911cfef |
| parent | 10d6db5d7d1fb62ee2915a7ad2c7feb771ea3bbb |
| signature |
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 | 436 | lib/std/elf.zig |
| 437 | 437 | lib/std/fifo.zig |
| 438 | 438 | lib/std/fmt.zig |
| 439 | lib/std/fmt/format_float.zig | |
| 440 | 439 | lib/std/fmt/parse_float.zig |
| 441 | 440 | lib/std/fs.zig |
| 442 | 441 | lib/std/fs/AtomicFile.zig |
build.zig+3-3| ... | ... | @@ -279,7 +279,7 @@ pub fn build(b: *std.Build) !void { |
| 279 | 279 | |
| 280 | 280 | const ancestor_ver = try std.SemanticVersion.parse(tagged_ancestor); |
| 281 | 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 | 283 | std.process.exit(1); |
| 284 | 284 | } |
| 285 | 285 | |
| ... | ... | @@ -1449,7 +1449,7 @@ fn generateLangRef(b: *std.Build) std.Build.LazyPath { |
| 1449 | 1449 | } |
| 1450 | 1450 | |
| 1451 | 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 | 1453 | b.build_root, @errorName(err), |
| 1454 | 1454 | }); |
| 1455 | 1455 | }; |
| ... | ... | @@ -1470,7 +1470,7 @@ fn generateLangRef(b: *std.Build) std.Build.LazyPath { |
| 1470 | 1470 | // in a temporary directory |
| 1471 | 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 | 1474 | cmd.addArgs(&.{"-i"}); |
| 1475 | 1475 | cmd.addFileArg(b.path(b.fmt("doc/langref/{s}", .{entry.name}))); |
| 1476 | 1476 |
doc/langref.html.in+2-1| ... | ... | @@ -374,7 +374,8 @@ |
| 374 | 374 | <p> |
| 375 | 375 | Most of the time, it is more appropriate to write to stderr rather than stdout, and |
| 376 | 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 | 379 | </p> |
| 379 | 380 | {#code|hello_again.zig#} |
| 380 | 381 |
doc/langref/bad_default_value.zig+1-1| ... | ... | @@ -17,7 +17,7 @@ pub fn main() !void { |
| 17 | 17 | .maximum = 0.20, |
| 18 | 18 | }; |
| 19 | 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 | } |
| 22 | 22 | |
| 23 | 23 | const std = @import("std"); |
doc/langref/hello.zig+1-2| ... | ... | @@ -1,8 +1,7 @@ |
| 1 | 1 | const std = @import("std"); |
| 2 | 2 | |
| 3 | 3 | pub fn main() !void { |
| 4 | const stdout = std.io.getStdOut().writer(); | |
| 5 | try stdout.print("Hello, {s}!\n", .{"world"}); | |
| 4 | try std.fs.File.stdout().writeAll("Hello, World!\n"); | |
| 6 | 5 | } |
| 7 | 6 | |
| 8 | 7 | // exe=succeed |
doc/langref/hello_again.zig+1-1| ... | ... | @@ -1,7 +1,7 @@ |
| 1 | 1 | const std = @import("std"); |
| 2 | 2 | |
| 3 | 3 | pub fn main() void { |
| 4 | std.debug.print("Hello, world!\n", .{}); | |
| 4 | std.debug.print("Hello, {s}!\n", .{"World"}); | |
| 5 | 5 | } |
| 6 | 6 | |
| 7 | 7 | // 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 | 1432 | defer buf.deinit(); |
| 1433 | 1433 | |
| 1434 | 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 | 1436 | error.StreamTooLong => if (limit == null) return e, |
| 1437 | 1437 | else => return e, |
| 1438 | 1438 | }; |
lib/compiler/aro/aro/Diagnostics.zig+19-29| ... | ... | @@ -1,4 +1,5 @@ |
| 1 | 1 | const std = @import("std"); |
| 2 | const assert = std.debug.assert; | |
| 2 | 3 | const Allocator = mem.Allocator; |
| 3 | 4 | const mem = std.mem; |
| 4 | 5 | const Source = @import("Source.zig"); |
| ... | ... | @@ -323,12 +324,13 @@ pub fn addExtra( |
| 323 | 324 | |
| 324 | 325 | pub fn render(comp: *Compilation, config: std.io.tty.Config) void { |
| 325 | 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 | 329 | defer m.deinit(); |
| 328 | 330 | renderMessages(comp, &m); |
| 329 | 331 | } |
| 330 | pub fn defaultMsgWriter(config: std.io.tty.Config) MsgWriter { | |
| 331 | return MsgWriter.init(config); | |
| 332 | pub fn defaultMsgWriter(config: std.io.tty.Config, buffer: []u8) MsgWriter { | |
| 333 | return MsgWriter.init(config, buffer); | |
| 332 | 334 | } |
| 333 | 335 | |
| 334 | 336 | pub fn renderMessages(comp: *Compilation, m: anytype) void { |
| ... | ... | @@ -443,18 +445,13 @@ pub fn renderMessage(comp: *Compilation, m: anytype, msg: Message) void { |
| 443 | 445 | printRt(m, prop.msg, .{"{s}"}, .{&str}); |
| 444 | 446 | } else { |
| 445 | 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 | 449 | printRt(m, prop.msg, .{"{s}"}, .{str}); |
| 448 | 450 | } |
| 449 | 451 | }, |
| 450 | 452 | .normalized => { |
| 451 | 453 | const f = struct { |
| 452 | pub fn f( | |
| 453 | bytes: []const u8, | |
| 454 | comptime _: []const u8, | |
| 455 | _: std.fmt.FormatOptions, | |
| 456 | writer: anytype, | |
| 457 | ) !void { | |
| 454 | pub fn f(bytes: []const u8, writer: *std.io.Writer) std.io.Writer.Error!void { | |
| 458 | 455 | var it: std.unicode.Utf8Iterator = .{ |
| 459 | 456 | .bytes = bytes, |
| 460 | 457 | .i = 0, |
| ... | ... | @@ -464,22 +461,16 @@ pub fn renderMessage(comp: *Compilation, m: anytype, msg: Message) void { |
| 464 | 461 | try writer.writeByte(@intCast(codepoint)); |
| 465 | 462 | } else if (codepoint < 0xFFFF) { |
| 466 | 463 | try writer.writeAll("\\u"); |
| 467 | try std.fmt.formatInt(codepoint, 16, .upper, .{ | |
| 468 | .fill = '0', | |
| 469 | .width = 4, | |
| 470 | }, writer); | |
| 464 | try writer.printInt(codepoint, 16, .upper, .{ .fill = '0', .width = 4 }); | |
| 471 | 465 | } else { |
| 472 | 466 | try writer.writeAll("\\U"); |
| 473 | try std.fmt.formatInt(codepoint, 16, .upper, .{ | |
| 474 | .fill = '0', | |
| 475 | .width = 8, | |
| 476 | }, writer); | |
| 467 | try writer.printInt(codepoint, 16, .upper, .{ .fill = '0', .width = 8 }); | |
| 477 | 468 | } |
| 478 | 469 | } |
| 479 | 470 | } |
| 480 | 471 | }.f; |
| 481 | printRt(m, prop.msg, .{"{s}"}, .{ | |
| 482 | std.fmt.Formatter(f){ .data = msg.extra.normalized }, | |
| 472 | printRt(m, prop.msg, .{"{f}"}, .{ | |
| 473 | std.fmt.Formatter([]const u8, f){ .data = msg.extra.normalized }, | |
| 483 | 474 | }); |
| 484 | 475 | }, |
| 485 | 476 | .none, .offset => m.write(prop.msg), |
| ... | ... | @@ -535,32 +526,31 @@ fn tagKind(d: *Diagnostics, tag: Tag, langopts: LangOpts) Kind { |
| 535 | 526 | } |
| 536 | 527 | |
| 537 | 528 | const MsgWriter = struct { |
| 538 | w: std.io.BufferedWriter(4096, std.fs.File.Writer), | |
| 529 | writer: *std.io.Writer, | |
| 539 | 530 | config: std.io.tty.Config, |
| 540 | 531 | |
| 541 | fn init(config: std.io.tty.Config) MsgWriter { | |
| 542 | std.debug.lockStdErr(); | |
| 532 | fn init(config: std.io.tty.Config, buffer: []u8) MsgWriter { | |
| 543 | 533 | return .{ |
| 544 | .w = std.io.bufferedWriter(std.io.getStdErr().writer()), | |
| 534 | .writer = std.debug.lockStderrWriter(buffer), | |
| 545 | 535 | .config = config, |
| 546 | 536 | }; |
| 547 | 537 | } |
| 548 | 538 | |
| 549 | 539 | pub fn deinit(m: *MsgWriter) void { |
| 550 | m.w.flush() catch {}; | |
| 551 | std.debug.unlockStdErr(); | |
| 540 | std.debug.unlockStderrWriter(); | |
| 541 | m.* = undefined; | |
| 552 | 542 | } |
| 553 | 543 | |
| 554 | 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 | } |
| 557 | 547 | |
| 558 | 548 | fn write(m: *MsgWriter, msg: []const u8) void { |
| 559 | m.w.writer().writeAll(msg) catch {}; | |
| 549 | m.writer.writeAll(msg) catch {}; | |
| 560 | 550 | } |
| 561 | 551 | |
| 562 | 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 | } |
| 565 | 555 | |
| 566 | 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 | 519 | |
| 520 | 520 | fn addSource(d: *Driver, path: []const u8) !Source { |
| 521 | 521 | if (mem.eql(u8, "-", path)) { |
| 522 | const stdin = std.io.getStdIn().reader(); | |
| 522 | const stdin = std.fs.File.stdin().deprecatedReader(); | |
| 523 | 523 | const input = try stdin.readAllAlloc(d.comp.gpa, std.math.maxInt(u32)); |
| 524 | 524 | defer d.comp.gpa.free(input); |
| 525 | 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 | 541 | } |
| 542 | 542 | |
| 543 | 543 | pub 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 | } |
| 546 | 546 | |
| 547 | 547 | pub 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 | 591 | var macro_buf = std.ArrayList(u8).init(d.comp.gpa); |
| 592 | 592 | defer macro_buf.deinit(); |
| 593 | 593 | |
| 594 | const std_out = std.io.getStdOut().writer(); | |
| 594 | const std_out = std.fs.File.stdout().deprecatedWriter(); | |
| 595 | 595 | if (try parseArgs(d, std_out, macro_buf.writer(), args)) return; |
| 596 | 596 | |
| 597 | 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 | 686 | std.fs.cwd().createFile(some, .{}) catch |er| |
| 687 | 687 | return d.fatal("unable to create output file '{s}': {s}", .{ some, errorDescription(er) }) |
| 688 | 688 | else |
| 689 | std.io.getStdOut(); | |
| 689 | std.fs.File.stdout(); | |
| 690 | 690 | defer if (d.output_name != null) file.close(); |
| 691 | 691 | |
| 692 | var buf_w = std.io.bufferedWriter(file.writer()); | |
| 692 | var buf_w = std.io.bufferedWriter(file.deprecatedWriter()); | |
| 693 | 693 | |
| 694 | 694 | pp.prettyPrintTokens(buf_w.writer(), dump_mode) catch |er| |
| 695 | 695 | return d.fatal("unable to write result: {s}", .{errorDescription(er)}); |
| ... | ... | @@ -704,8 +704,8 @@ fn processSource( |
| 704 | 704 | defer tree.deinit(); |
| 705 | 705 | |
| 706 | 706 | if (d.verbose_ast) { |
| 707 | const stdout = std.io.getStdOut(); | |
| 708 | var buf_writer = std.io.bufferedWriter(stdout.writer()); | |
| 707 | const stdout = std.fs.File.stdout(); | |
| 708 | var buf_writer = std.io.bufferedWriter(stdout.deprecatedWriter()); | |
| 709 | 709 | tree.dump(d.detectConfig(stdout), buf_writer.writer()) catch {}; |
| 710 | 710 | buf_writer.flush() catch {}; |
| 711 | 711 | } |
| ... | ... | @@ -734,8 +734,8 @@ fn processSource( |
| 734 | 734 | defer ir.deinit(d.comp.gpa); |
| 735 | 735 | |
| 736 | 736 | if (d.verbose_ir) { |
| 737 | const stdout = std.io.getStdOut(); | |
| 738 | var buf_writer = std.io.bufferedWriter(stdout.writer()); | |
| 737 | const stdout = std.fs.File.stdout(); | |
| 738 | var buf_writer = std.io.bufferedWriter(stdout.deprecatedWriter()); | |
| 739 | 739 | ir.dump(d.comp.gpa, d.detectConfig(stdout), buf_writer.writer()) catch {}; |
| 740 | 740 | buf_writer.flush() catch {}; |
| 741 | 741 | } |
| ... | ... | @@ -806,10 +806,10 @@ fn processSource( |
| 806 | 806 | } |
| 807 | 807 | |
| 808 | 808 | fn dumpLinkerArgs(items: []const []const u8) !void { |
| 809 | const stdout = std.io.getStdOut().writer(); | |
| 809 | const stdout = std.fs.File.stdout().deprecatedWriter(); | |
| 810 | 810 | for (items, 0..) |item, i| { |
| 811 | 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 | 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 | 500 | |
| 501 | 501 | const w = p.strings.writer(); |
| 502 | 502 | const msg_str = p.comp.interner.get(@"error".msg.ref()).bytes; |
| 503 | try w.print("call to '{s}' declared with attribute error: {}", .{ | |
| 504 | p.tokSlice(@"error".__name_tok), std.zig.fmtEscapes(msg_str), | |
| 503 | try w.print("call to '{s}' declared with attribute error: {f}", .{ | |
| 504 | p.tokSlice(@"error".__name_tok), std.zig.fmtString(msg_str), | |
| 505 | 505 | }); |
| 506 | 506 | const str = try p.comp.diagnostics.arena.allocator().dupe(u8, p.strings.items[strings_top..]); |
| 507 | 507 | try p.errStr(.error_attribute, usage_tok, str); |
| ... | ... | @@ -512,8 +512,8 @@ fn checkDeprecatedUnavailable(p: *Parser, ty: Type, usage_tok: TokenIndex, decl_ |
| 512 | 512 | |
| 513 | 513 | const w = p.strings.writer(); |
| 514 | 514 | const msg_str = p.comp.interner.get(warning.msg.ref()).bytes; |
| 515 | try w.print("call to '{s}' declared with attribute warning: {}", .{ | |
| 516 | p.tokSlice(warning.__name_tok), std.zig.fmtEscapes(msg_str), | |
| 515 | try w.print("call to '{s}' declared with attribute warning: {f}", .{ | |
| 516 | p.tokSlice(warning.__name_tok), std.zig.fmtString(msg_str), | |
| 517 | 517 | }); |
| 518 | 518 | const str = try p.comp.diagnostics.arena.allocator().dupe(u8, p.strings.items[strings_top..]); |
| 519 | 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 | 542 | try w.writeAll(reason); |
| 543 | 543 | if (msg) |m| { |
| 544 | 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 | 547 | const str = try p.comp.diagnostics.arena.allocator().dupe(u8, p.strings.items[strings_top..]); |
| 548 | 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 | 811 | const source = pp.comp.getSource(raw.source); |
| 812 | 812 | const line_col = source.lineCol(.{ .id = raw.source, .line = raw.line, .byte_offset = raw.start }); |
| 813 | 813 | |
| 814 | const stderr = std.io.getStdErr().writer(); | |
| 814 | const stderr = std.fs.File.stderr().deprecatedWriter(); | |
| 815 | 815 | var buf_writer = std.io.bufferedWriter(stderr); |
| 816 | 816 | const writer = buf_writer.writer(); |
| 817 | 817 | defer buf_writer.flush() catch {}; |
| ... | ... | @@ -3262,7 +3262,8 @@ fn printLinemarker( |
| 3262 | 3262 | // containing the same bytes as the input regardless of encoding. |
| 3263 | 3263 | else => { |
| 3264 | 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 | 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 | 961 | switch (key) { |
| 962 | 962 | .null => return w.writeAll("nullptr_t"), |
| 963 | 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 | 966 | .float => |repr| switch (repr) { |
| 967 | 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 | 982 | const without_null = bytes[0 .. bytes.len - @intFromEnum(size)]; |
| 983 | 983 | try w.writeByte('"'); |
| 984 | 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 | 986 | .@"2" => { |
| 987 | 987 | var items: [2]u16 = undefined; |
| 988 | 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 | 171 | /// strtab |
| 172 | 172 | /// section headers |
| 173 | 173 | pub 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 | 175 | const w = buf_writer.writer(); |
| 176 | 176 | |
| 177 | 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 | 1781 | fn renderErrorsAndExit(comp: *aro.Compilation) noreturn { |
| 1782 | 1782 | defer std.process.exit(1); |
| 1783 | 1783 | |
| 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 | 1786 | defer writer.deinit(); // writer deinit must run *before* exit so that stderr is flushed |
| 1786 | 1787 | |
| 1787 | 1788 | var saw_error = false; |
| ... | ... | @@ -1824,6 +1825,6 @@ pub fn main() !void { |
| 1824 | 1825 | defer tree.deinit(gpa); |
| 1825 | 1826 | |
| 1826 | 1827 | const formatted = try tree.render(arena); |
| 1827 | try std.io.getStdOut().writeAll(formatted); | |
| 1828 | try std.fs.File.stdout().writeAll(formatted); | |
| 1828 | 1829 | return std.process.cleanExit(); |
| 1829 | 1830 | } |
lib/compiler/aro_translate_c/ast.zig+6-6| ... | ... | @@ -849,7 +849,7 @@ const Context = struct { |
| 849 | 849 | fn addIdentifier(c: *Context, bytes: []const u8) Allocator.Error!TokenIndex { |
| 850 | 850 | if (std.zig.primitives.isPrimitive(bytes)) |
| 851 | 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 | } |
| 854 | 854 | |
| 855 | 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 | 1201 | |
| 1202 | 1202 | const compile_error_tok = try c.addToken(.builtin, "@compileError"); |
| 1203 | 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 | 1205 | const err_msg = try c.addNode(.{ |
| 1206 | 1206 | .tag = .string_literal, |
| 1207 | 1207 | .main_token = err_msg_tok, |
| ... | ... | @@ -2116,7 +2116,7 @@ fn renderRecord(c: *Context, node: Node) !NodeIndex { |
| 2116 | 2116 | defer c.gpa.free(members); |
| 2117 | 2117 | |
| 2118 | 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 | 2120 | _ = try c.addToken(.colon, ":"); |
| 2121 | 2121 | const type_expr = try renderNode(c, field.type); |
| 2122 | 2122 | |
| ... | ... | @@ -2205,7 +2205,7 @@ fn renderFieldAccess(c: *Context, lhs: NodeIndex, field_name: []const u8) !NodeI |
| 2205 | 2205 | .main_token = try c.addToken(.period, "."), |
| 2206 | 2206 | .data = .{ .node_and_token = .{ |
| 2207 | 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 | 2681 | _ = try c.addToken(.l_paren, "("); |
| 2682 | 2682 | const res = try c.addNode(.{ |
| 2683 | 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 | 2685 | .data = undefined, |
| 2686 | 2686 | }); |
| 2687 | 2687 | _ = try c.addToken(.r_paren, ")"); |
| ... | ... | @@ -2765,7 +2765,7 @@ fn renderFunc(c: *Context, node: Node) !NodeIndex { |
| 2765 | 2765 | _ = try c.addToken(.l_paren, "("); |
| 2766 | 2766 | const res = try c.addNode(.{ |
| 2767 | 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 | 2769 | .data = undefined, |
| 2770 | 2770 | }); |
| 2771 | 2771 | _ = try c.addToken(.r_paren, ")"); |
lib/compiler/build_runner.zig+82-67| ... | ... | @@ -12,6 +12,7 @@ const Watch = std.Build.Watch; |
| 12 | 12 | const Fuzz = std.Build.Fuzz; |
| 13 | 13 | const Allocator = std.mem.Allocator; |
| 14 | 14 | const fatal = std.process.fatal; |
| 15 | const Writer = std.io.Writer; | |
| 15 | 16 | const runner = @This(); |
| 16 | 17 | |
| 17 | 18 | pub const root = @import("@build"); |
| ... | ... | @@ -330,7 +331,7 @@ pub fn main() !void { |
| 330 | 331 | } |
| 331 | 332 | } |
| 332 | 333 | |
| 333 | const stderr = std.io.getStdErr(); | |
| 334 | const stderr: std.fs.File = .stderr(); | |
| 334 | 335 | const ttyconf = get_tty_conf(color, stderr); |
| 335 | 336 | switch (ttyconf) { |
| 336 | 337 | .no_color => try graph.env_map.put("NO_COLOR", "1"), |
| ... | ... | @@ -365,7 +366,7 @@ pub fn main() !void { |
| 365 | 366 | .data = buffer.items, |
| 366 | 367 | .flags = .{ .exclusive = true }, |
| 367 | 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 | 370 | local_cache_directory, tmp_sub_path, @errorName(err), |
| 370 | 371 | }); |
| 371 | 372 | }; |
| ... | ... | @@ -378,13 +379,19 @@ pub fn main() !void { |
| 378 | 379 | |
| 379 | 380 | validateSystemLibraryOptions(builder); |
| 380 | 381 | |
| 381 | const stdout_writer = io.getStdOut().writer(); | |
| 382 | ||
| 383 | if (help_menu) | |
| 384 | return usage(builder, stdout_writer); | |
| 382 | if (help_menu) { | |
| 383 | var w = initStdoutWriter(); | |
| 384 | printUsage(builder, w) catch return stdout_writer_allocation.err.?; | |
| 385 | w.flush() catch return stdout_writer_allocation.err.?; | |
| 386 | return; | |
| 387 | } | |
| 385 | 388 | |
| 386 | if (steps_menu) | |
| 387 | return steps(builder, stdout_writer); | |
| 389 | if (steps_menu) { | |
| 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 | } | |
| 388 | 395 | |
| 389 | 396 | var run: Run = .{ |
| 390 | 397 | .max_rss = max_rss, |
| ... | ... | @@ -696,24 +703,23 @@ fn runStepNames( |
| 696 | 703 | const ttyconf = run.ttyconf; |
| 697 | 704 | |
| 698 | 705 | if (run.summary != .none) { |
| 699 | std.debug.lockStdErr(); | |
| 700 | defer std.debug.unlockStdErr(); | |
| 701 | const stderr = run.stderr; | |
| 706 | const w = std.debug.lockStderrWriter(&stdio_buffer_allocation); | |
| 707 | defer std.debug.unlockStderrWriter(); | |
| 702 | 708 | |
| 703 | 709 | const total_count = success_count + failure_count + pending_count + skipped_count; |
| 704 | ttyconf.setColor(stderr, .cyan) catch {}; | |
| 705 | stderr.writeAll("Build Summary:") catch {}; | |
| 706 | ttyconf.setColor(stderr, .reset) catch {}; | |
| 707 | stderr.writer().print(" {d}/{d} steps succeeded", .{ success_count, total_count }) catch {}; | |
| 708 | if (skipped_count > 0) stderr.writer().print("; {d} skipped", .{skipped_count}) catch {}; | |
| 709 | if (failure_count > 0) stderr.writer().print("; {d} failed", .{failure_count}) catch {}; | |
| 710 | ttyconf.setColor(w, .cyan) catch {}; | |
| 711 | w.writeAll("Build Summary:") catch {}; | |
| 712 | ttyconf.setColor(w, .reset) catch {}; | |
| 713 | w.print(" {d}/{d} steps succeeded", .{ success_count, total_count }) catch {}; | |
| 714 | if (skipped_count > 0) w.print("; {d} skipped", .{skipped_count}) catch {}; | |
| 715 | if (failure_count > 0) w.print("; {d} failed", .{failure_count}) catch {}; | |
| 710 | 716 | |
| 711 | if (test_count > 0) stderr.writer().print("; {d}/{d} tests passed", .{ test_pass_count, test_count }) catch {}; | |
| 712 | if (test_skip_count > 0) stderr.writer().print("; {d} skipped", .{test_skip_count}) catch {}; | |
| 713 | if (test_fail_count > 0) stderr.writer().print("; {d} failed", .{test_fail_count}) catch {}; | |
| 714 | if (test_leak_count > 0) stderr.writer().print("; {d} leaked", .{test_leak_count}) catch {}; | |
| 717 | if (test_count > 0) w.print("; {d}/{d} tests passed", .{ test_pass_count, test_count }) catch {}; | |
| 718 | if (test_skip_count > 0) w.print("; {d} skipped", .{test_skip_count}) catch {}; | |
| 719 | if (test_fail_count > 0) w.print("; {d} failed", .{test_fail_count}) catch {}; | |
| 720 | if (test_leak_count > 0) w.print("; {d} leaked", .{test_leak_count}) catch {}; | |
| 715 | 721 | |
| 716 | stderr.writeAll("\n") catch {}; | |
| 722 | w.writeAll("\n") catch {}; | |
| 717 | 723 | |
| 718 | 724 | // Print a fancy tree with build results. |
| 719 | 725 | var step_stack_copy = try step_stack.clone(gpa); |
| ... | ... | @@ -722,7 +728,7 @@ fn runStepNames( |
| 722 | 728 | var print_node: PrintNode = .{ .parent = null }; |
| 723 | 729 | if (step_names.len == 0) { |
| 724 | 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 | 732 | } else { |
| 727 | 733 | const last_index = if (run.summary == .all) b.top_level_steps.count() else blk: { |
| 728 | 734 | var i: usize = step_names.len; |
| ... | ... | @@ -741,9 +747,10 @@ fn runStepNames( |
| 741 | 747 | for (step_names, 0..) |step_name, i| { |
| 742 | 748 | const tls = b.top_level_steps.get(step_name).?; |
| 743 | 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 | } |
| 748 | 755 | |
| 749 | 756 | if (failure_count == 0) { |
| ... | ... | @@ -775,7 +782,7 @@ const PrintNode = struct { |
| 775 | 782 | last: bool = false, |
| 776 | 783 | }; |
| 777 | 784 | |
| 778 | fn printPrefix(node: *PrintNode, stderr: File, ttyconf: std.io.tty.Config) !void { | |
| 785 | fn printPrefix(node: *PrintNode, stderr: *Writer, ttyconf: std.io.tty.Config) !void { | |
| 779 | 786 | const parent = node.parent orelse return; |
| 780 | 787 | if (parent.parent == null) return; |
| 781 | 788 | try printPrefix(parent, stderr, ttyconf); |
| ... | ... | @@ -789,7 +796,7 @@ fn printPrefix(node: *PrintNode, stderr: File, ttyconf: std.io.tty.Config) !void |
| 789 | 796 | } |
| 790 | 797 | } |
| 791 | 798 | |
| 792 | fn printChildNodePrefix(stderr: File, ttyconf: std.io.tty.Config) !void { | |
| 799 | fn printChildNodePrefix(stderr: *Writer, ttyconf: std.io.tty.Config) !void { | |
| 793 | 800 | try stderr.writeAll(switch (ttyconf) { |
| 794 | 801 | .no_color, .windows_api => "+- ", |
| 795 | 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 | 805 | |
| 799 | 806 | fn printStepStatus( |
| 800 | 807 | s: *Step, |
| 801 | stderr: File, | |
| 808 | stderr: *Writer, | |
| 802 | 809 | ttyconf: std.io.tty.Config, |
| 803 | 810 | run: *const Run, |
| 804 | 811 | ) !void { |
| ... | ... | @@ -820,10 +827,10 @@ fn printStepStatus( |
| 820 | 827 | try stderr.writeAll(" cached"); |
| 821 | 828 | } else if (s.test_results.test_count > 0) { |
| 822 | 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 | 831 | if (s.test_results.skip_count > 0) { |
| 825 | 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 | 835 | } else { |
| 829 | 836 | try stderr.writeAll(" success"); |
| ... | ... | @@ -832,15 +839,15 @@ fn printStepStatus( |
| 832 | 839 | if (s.result_duration_ns) |ns| { |
| 833 | 840 | try ttyconf.setColor(stderr, .dim); |
| 834 | 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 | 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 | 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 | 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 | 849 | } else { |
| 843 | try stderr.writer().print(" {d}ns", .{ns}); | |
| 850 | try stderr.print(" {d}ns", .{ns}); | |
| 844 | 851 | } |
| 845 | 852 | try ttyconf.setColor(stderr, .reset); |
| 846 | 853 | } |
| ... | ... | @@ -848,13 +855,13 @@ fn printStepStatus( |
| 848 | 855 | const rss = s.result_peak_rss; |
| 849 | 856 | try ttyconf.setColor(stderr, .dim); |
| 850 | 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 | 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 | 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 | 863 | } else { |
| 857 | try stderr.writer().print(" MaxRSS:{d}B", .{rss}); | |
| 864 | try stderr.print(" MaxRSS:{d}B", .{rss}); | |
| 858 | 865 | } |
| 859 | 866 | try ttyconf.setColor(stderr, .reset); |
| 860 | 867 | } |
| ... | ... | @@ -866,7 +873,7 @@ fn printStepStatus( |
| 866 | 873 | if (skip == .skipped_oom) { |
| 867 | 874 | try stderr.writeAll(" (not enough memory)"); |
| 868 | 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 | 877 | try ttyconf.setColor(stderr, .yellow); |
| 871 | 878 | } |
| 872 | 879 | try stderr.writeAll("\n"); |
| ... | ... | @@ -878,23 +885,23 @@ fn printStepStatus( |
| 878 | 885 | |
| 879 | 886 | fn printStepFailure( |
| 880 | 887 | s: *Step, |
| 881 | stderr: File, | |
| 888 | stderr: *Writer, | |
| 882 | 889 | ttyconf: std.io.tty.Config, |
| 883 | 890 | ) !void { |
| 884 | 891 | if (s.result_error_bundle.errorMessageCount() > 0) { |
| 885 | 892 | try ttyconf.setColor(stderr, .red); |
| 886 | try stderr.writer().print(" {d} errors\n", .{ | |
| 893 | try stderr.print(" {d} errors\n", .{ | |
| 887 | 894 | s.result_error_bundle.errorMessageCount(), |
| 888 | 895 | }); |
| 889 | 896 | try ttyconf.setColor(stderr, .reset); |
| 890 | 897 | } else if (!s.test_results.isSuccess()) { |
| 891 | try stderr.writer().print(" {d}/{d} passed", .{ | |
| 898 | try stderr.print(" {d}/{d} passed", .{ | |
| 892 | 899 | s.test_results.passCount(), s.test_results.test_count, |
| 893 | 900 | }); |
| 894 | 901 | if (s.test_results.fail_count > 0) { |
| 895 | 902 | try stderr.writeAll(", "); |
| 896 | 903 | try ttyconf.setColor(stderr, .red); |
| 897 | try stderr.writer().print("{d} failed", .{ | |
| 904 | try stderr.print("{d} failed", .{ | |
| 898 | 905 | s.test_results.fail_count, |
| 899 | 906 | }); |
| 900 | 907 | try ttyconf.setColor(stderr, .reset); |
| ... | ... | @@ -902,7 +909,7 @@ fn printStepFailure( |
| 902 | 909 | if (s.test_results.skip_count > 0) { |
| 903 | 910 | try stderr.writeAll(", "); |
| 904 | 911 | try ttyconf.setColor(stderr, .yellow); |
| 905 | try stderr.writer().print("{d} skipped", .{ | |
| 912 | try stderr.print("{d} skipped", .{ | |
| 906 | 913 | s.test_results.skip_count, |
| 907 | 914 | }); |
| 908 | 915 | try ttyconf.setColor(stderr, .reset); |
| ... | ... | @@ -910,7 +917,7 @@ fn printStepFailure( |
| 910 | 917 | if (s.test_results.leak_count > 0) { |
| 911 | 918 | try stderr.writeAll(", "); |
| 912 | 919 | try ttyconf.setColor(stderr, .red); |
| 913 | try stderr.writer().print("{d} leaked", .{ | |
| 920 | try stderr.print("{d} leaked", .{ | |
| 914 | 921 | s.test_results.leak_count, |
| 915 | 922 | }); |
| 916 | 923 | try ttyconf.setColor(stderr, .reset); |
| ... | ... | @@ -932,7 +939,7 @@ fn printTreeStep( |
| 932 | 939 | b: *std.Build, |
| 933 | 940 | s: *Step, |
| 934 | 941 | run: *const Run, |
| 935 | stderr: File, | |
| 942 | stderr: *Writer, | |
| 936 | 943 | ttyconf: std.io.tty.Config, |
| 937 | 944 | parent_node: *PrintNode, |
| 938 | 945 | step_stack: *std.AutoArrayHashMapUnmanaged(*Step, void), |
| ... | ... | @@ -992,7 +999,7 @@ fn printTreeStep( |
| 992 | 999 | if (s.dependencies.items.len == 0) { |
| 993 | 1000 | try stderr.writeAll(" (reused)\n"); |
| 994 | 1001 | } else { |
| 995 | try stderr.writer().print(" (+{d} more reused dependencies)\n", .{ | |
| 1002 | try stderr.print(" (+{d} more reused dependencies)\n", .{ | |
| 996 | 1003 | s.dependencies.items.len, |
| 997 | 1004 | }); |
| 998 | 1005 | } |
| ... | ... | @@ -1129,11 +1136,11 @@ fn workerMakeOneStep( |
| 1129 | 1136 | const show_stderr = s.result_stderr.len > 0; |
| 1130 | 1137 | |
| 1131 | 1138 | if (show_error_msgs or show_compile_errors or show_stderr) { |
| 1132 | std.debug.lockStdErr(); | |
| 1133 | defer std.debug.unlockStdErr(); | |
| 1139 | const bw = std.debug.lockStderrWriter(&stdio_buffer_allocation); | |
| 1140 | defer std.debug.unlockStderrWriter(); | |
| 1134 | 1141 | |
| 1135 | 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 | } |
| 1138 | 1145 | |
| 1139 | 1146 | handle_result: { |
| ... | ... | @@ -1190,7 +1197,7 @@ pub fn printErrorMessages( |
| 1190 | 1197 | gpa: Allocator, |
| 1191 | 1198 | failing_step: *Step, |
| 1192 | 1199 | options: std.zig.ErrorBundle.RenderOptions, |
| 1193 | stderr: File, | |
| 1200 | stderr: *Writer, | |
| 1194 | 1201 | prominent_compile_errors: bool, |
| 1195 | 1202 | ) !void { |
| 1196 | 1203 | // Provide context for where these error messages are coming from by |
| ... | ... | @@ -1209,7 +1216,7 @@ pub fn printErrorMessages( |
| 1209 | 1216 | var indent: usize = 0; |
| 1210 | 1217 | while (step_stack.pop()) |s| : (indent += 1) { |
| 1211 | 1218 | if (indent > 0) { |
| 1212 | try stderr.writer().writeByteNTimes(' ', (indent - 1) * 3); | |
| 1219 | try stderr.splatByteAll(' ', (indent - 1) * 3); | |
| 1213 | 1220 | try printChildNodePrefix(stderr, ttyconf); |
| 1214 | 1221 | } |
| 1215 | 1222 | |
| ... | ... | @@ -1231,7 +1238,7 @@ pub fn printErrorMessages( |
| 1231 | 1238 | } |
| 1232 | 1239 | |
| 1233 | 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 | } |
| 1236 | 1243 | |
| 1237 | 1244 | for (failing_step.result_error_msgs.items) |msg| { |
| ... | ... | @@ -1243,27 +1250,27 @@ pub fn printErrorMessages( |
| 1243 | 1250 | } |
| 1244 | 1251 | } |
| 1245 | 1252 | |
| 1246 | fn steps(builder: *std.Build, out_stream: anytype) !void { | |
| 1253 | fn printSteps(builder: *std.Build, w: *Writer) !void { | |
| 1247 | 1254 | const allocator = builder.allocator; |
| 1248 | 1255 | for (builder.top_level_steps.values()) |top_level_step| { |
| 1249 | 1256 | const name = if (&top_level_step.step == builder.default_step) |
| 1250 | 1257 | try fmt.allocPrint(allocator, "{s} (default)", .{top_level_step.step.name}) |
| 1251 | 1258 | else |
| 1252 | 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 | } |
| 1256 | 1263 | |
| 1257 | fn usage(b: *std.Build, out_stream: anytype) !void { | |
| 1258 | try out_stream.print( | |
| 1264 | fn printUsage(b: *std.Build, w: *Writer) !void { | |
| 1265 | try w.print( | |
| 1259 | 1266 | \\Usage: {s} build [steps] [options] |
| 1260 | 1267 | \\ |
| 1261 | 1268 | \\Steps: |
| 1262 | 1269 | \\ |
| 1263 | 1270 | , .{b.graph.zig_exe}); |
| 1264 | try steps(b, out_stream); | |
| 1271 | try printSteps(b, w); | |
| 1265 | 1272 | |
| 1266 | try out_stream.writeAll( | |
| 1273 | try w.writeAll( | |
| 1267 | 1274 | \\ |
| 1268 | 1275 | \\General Options: |
| 1269 | 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 | 1326 | |
| 1320 | 1327 | const arena = b.allocator; |
| 1321 | 1328 | if (b.available_options_list.items.len == 0) { |
| 1322 | try out_stream.print(" (none)\n", .{}); | |
| 1329 | try w.print(" (none)\n", .{}); | |
| 1323 | 1330 | } else { |
| 1324 | 1331 | for (b.available_options_list.items) |option| { |
| 1325 | 1332 | const name = try fmt.allocPrint(arena, " -D{s}=[{s}]", .{ |
| 1326 | 1333 | option.name, |
| 1327 | 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 | 1337 | if (option.enum_options) |enum_options| { |
| 1331 | 1338 | const padding = " " ** 33; |
| 1332 | try out_stream.writeAll(padding ++ "Supported Values:\n"); | |
| 1339 | try w.writeAll(padding ++ "Supported Values:\n"); | |
| 1333 | 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 | } |
| 1339 | 1346 | |
| 1340 | try out_stream.writeAll( | |
| 1347 | try w.writeAll( | |
| 1341 | 1348 | \\ |
| 1342 | 1349 | \\System Integration Options: |
| 1343 | 1350 | \\ --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 | 1359 | \\ |
| 1353 | 1360 | ); |
| 1354 | 1361 | if (b.graph.system_library_options.entries.len == 0) { |
| 1355 | try out_stream.writeAll(" (none) -\n"); | |
| 1362 | try w.writeAll(" (none) -\n"); | |
| 1356 | 1363 | } else { |
| 1357 | 1364 | for (b.graph.system_library_options.keys(), b.graph.system_library_options.values()) |k, v| { |
| 1358 | 1365 | const status = switch (v) { |
| ... | ... | @@ -1360,11 +1367,11 @@ fn usage(b: *std.Build, out_stream: anytype) !void { |
| 1360 | 1367 | .declared_disabled => "no", |
| 1361 | 1368 | .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 | } |
| 1366 | 1373 | |
| 1367 | try out_stream.writeAll( | |
| 1374 | try w.writeAll( | |
| 1368 | 1375 | \\ |
| 1369 | 1376 | \\Advanced Options: |
| 1370 | 1377 | \\ -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 | 1551 | }; |
| 1545 | 1552 | } |
| 1546 | 1553 | } |
| 1554 | ||
| 1555 | var stdio_buffer_allocation: [256]u8 = undefined; | |
| 1556 | var stdout_writer_allocation: std.fs.File.Writer = undefined; | |
| 1557 | ||
| 1558 | fn 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 | 40 | const arg = args[i]; |
| 41 | 41 | if (mem.startsWith(u8, arg, "-")) { |
| 42 | 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 | 44 | try stdout.writeAll(usage_libc); |
| 45 | 45 | return std.process.cleanExit(); |
| 46 | 46 | } else if (mem.eql(u8, arg, "-target")) { |
| ... | ... | @@ -97,7 +97,7 @@ pub fn main() !void { |
| 97 | 97 | fatal("no include dirs detected for target {s}", .{zig_target}); |
| 98 | 98 | } |
| 99 | 99 | |
| 100 | var bw = std.io.bufferedWriter(std.io.getStdOut().writer()); | |
| 100 | var bw = std.io.bufferedWriter(std.fs.File.stdout().deprecatedWriter()); | |
| 101 | 101 | var writer = bw.writer(); |
| 102 | 102 | for (libc_dirs.libc_include_dir_list) |include_dir| { |
| 103 | 103 | try writer.writeAll(include_dir); |
| ... | ... | @@ -125,7 +125,7 @@ pub fn main() !void { |
| 125 | 125 | }; |
| 126 | 126 | defer libc.deinit(gpa); |
| 127 | 127 | |
| 128 | var bw = std.io.bufferedWriter(std.io.getStdOut().writer()); | |
| 128 | var bw = std.io.bufferedWriter(std.fs.File.stdout().deprecatedWriter()); | |
| 129 | 129 | try libc.render(bw.writer()); |
| 130 | 130 | try bw.flush(); |
| 131 | 131 | } |
lib/compiler/objcopy.zig+6-6| ... | ... | @@ -54,7 +54,7 @@ fn cmdObjCopy( |
| 54 | 54 | fatal("unexpected positional argument: '{s}'", .{arg}); |
| 55 | 55 | } |
| 56 | 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 | 58 | } else if (mem.eql(u8, arg, "-O") or mem.eql(u8, arg, "--output-target")) { |
| 59 | 59 | i += 1; |
| 60 | 60 | if (i >= args.len) fatal("expected another argument after '{s}'", .{arg}); |
| ... | ... | @@ -227,8 +227,8 @@ fn cmdObjCopy( |
| 227 | 227 | if (listen) { |
| 228 | 228 | var server = try Server.init(.{ |
| 229 | 229 | .gpa = gpa, |
| 230 | .in = std.io.getStdIn(), | |
| 231 | .out = std.io.getStdOut(), | |
| 230 | .in = .stdin(), | |
| 231 | .out = .stdout(), | |
| 232 | 232 | .zig_version = builtin.zig_version_string, |
| 233 | 233 | }); |
| 234 | 234 | defer server.deinit(); |
| ... | ... | @@ -635,11 +635,11 @@ const HexWriter = struct { |
| 635 | 635 | const payload_bytes = self.getPayloadBytes(); |
| 636 | 636 | assert(payload_bytes.len <= MAX_PAYLOAD_LEN); |
| 637 | 637 | |
| 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 | 639 | @as(u8, @intCast(payload_bytes.len)), |
| 640 | 640 | self.address, |
| 641 | 641 | @intFromEnum(self.payload), |
| 642 | std.fmt.fmtSliceHexUpper(payload_bytes), | |
| 642 | payload_bytes, | |
| 643 | 643 | self.checksum(), |
| 644 | 644 | }); |
| 645 | 645 | try file.writeAll(line); |
| ... | ... | @@ -1495,7 +1495,7 @@ const ElfFileHelper = struct { |
| 1495 | 1495 | if (size < prefix.len) return null; |
| 1496 | 1496 | |
| 1497 | 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); | |
| 1499 | 1499 | |
| 1500 | 1500 | // allocate as large as decompressed data. if the compression doesn't fit, keep the data uncompressed. |
| 1501 | 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 | 68 | const arg = args[i]; |
| 69 | 69 | if (mem.startsWith(u8, arg, "-")) { |
| 70 | 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 | 72 | try stdout.writeAll(usage); |
| 73 | 73 | return std.process.cleanExit(); |
| 74 | 74 | } else if (mem.eql(u8, arg, "--")) { |
lib/compiler/resinator/cli.zig+13-14| ... | ... | @@ -125,13 +125,12 @@ pub const Diagnostics = struct { |
| 125 | 125 | } |
| 126 | 126 | |
| 127 | 127 | pub fn renderToStdErr(self: *Diagnostics, args: []const []const u8, config: std.io.tty.Config) void { |
| 128 | std.debug.lockStdErr(); | |
| 129 | defer std.debug.unlockStdErr(); | |
| 130 | const stderr = std.io.getStdErr().writer(); | |
| 128 | const stderr = std.debug.lockStderrWriter(&.{}); | |
| 129 | defer std.debug.unlockStderrWriter(); | |
| 131 | 130 | self.renderToWriter(args, stderr, config) catch return; |
| 132 | 131 | } |
| 133 | 132 | |
| 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 | 134 | for (self.errors.items) |err_details| { |
| 136 | 135 | try renderErrorMessage(writer, config, err_details, args); |
| 137 | 136 | } |
| ... | ... | @@ -1403,7 +1402,7 @@ test parsePercent { |
| 1403 | 1402 | try std.testing.expectError(error.InvalidFormat, parsePercent("~1")); |
| 1404 | 1403 | } |
| 1405 | 1404 | |
| 1406 | pub fn renderErrorMessage(writer: anytype, config: std.io.tty.Config, err_details: Diagnostics.ErrorDetails, args: []const []const u8) !void { | |
| 1405 | pub fn renderErrorMessage(writer: *std.io.Writer, config: std.io.tty.Config, err_details: Diagnostics.ErrorDetails, args: []const []const u8) !void { | |
| 1407 | 1406 | try config.setColor(writer, .dim); |
| 1408 | 1407 | try writer.writeAll("<cli>"); |
| 1409 | 1408 | try config.setColor(writer, .reset); |
| ... | ... | @@ -1481,27 +1480,27 @@ pub fn renderErrorMessage(writer: anytype, config: std.io.tty.Config, err_detail |
| 1481 | 1480 | try writer.writeByte('\n'); |
| 1482 | 1481 | |
| 1483 | 1482 | try config.setColor(writer, .green); |
| 1484 | try writer.writeByteNTimes(' ', prefix.len); | |
| 1483 | try writer.splatByteAll(' ', prefix.len); | |
| 1485 | 1484 | // Special case for when the option is *only* a prefix (e.g. invalid option: -) |
| 1486 | 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 | 1487 | } else { |
| 1489 | try writer.writeByteNTimes('~', err_details.arg_span.prefix_len); | |
| 1490 | try writer.writeByteNTimes(' ', err_details.arg_span.name_offset - err_details.arg_span.prefix_len); | |
| 1488 | try writer.splatByteAll('~', err_details.arg_span.prefix_len); | |
| 1489 | try writer.splatByteAll(' ', err_details.arg_span.name_offset - err_details.arg_span.prefix_len); | |
| 1491 | 1490 | if (!err_details.arg_span.point_at_next_arg and err_details.arg_span.value_offset == 0) { |
| 1492 | 1491 | try writer.writeByte('^'); |
| 1493 | try writer.writeByteNTimes('~', name_slice.len - 1); | |
| 1492 | try writer.splatByteAll('~', name_slice.len - 1); | |
| 1494 | 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 | 1495 | try writer.writeByte('^'); |
| 1497 | 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 | 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 | 1501 | try writer.writeByte('^'); |
| 1503 | 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 | 570 | switch (predefined_type) { |
| 571 | 571 | .GROUP_ICON, .GROUP_CURSOR => { |
| 572 | 572 | // Check for animated icon first |
| 573 | if (ani.isAnimatedIcon(file.reader())) { | |
| 573 | if (ani.isAnimatedIcon(file.deprecatedReader())) { | |
| 574 | 574 | // Animated icons are just put into the resource unmodified, |
| 575 | 575 | // and the resource type changes to ANIICON/ANICURSOR |
| 576 | 576 | |
| ... | ... | @@ -586,14 +586,14 @@ pub const Compiler = struct { |
| 586 | 586 | |
| 587 | 587 | try header.write(writer, self.errContext(node.id)); |
| 588 | 588 | try file.seekTo(0); |
| 589 | try writeResourceData(writer, file.reader(), header.data_size); | |
| 589 | try writeResourceData(writer, file.deprecatedReader(), header.data_size); | |
| 590 | 590 | return; |
| 591 | 591 | } |
| 592 | 592 | |
| 593 | 593 | // isAnimatedIcon moved the file cursor so reset to the start |
| 594 | 594 | try file.seekTo(0); |
| 595 | 595 | |
| 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 | 597 | error.OutOfMemory => |e| return e, |
| 598 | 598 | else => |e| { |
| 599 | 599 | return self.iconReadError( |
| ... | ... | @@ -672,7 +672,7 @@ pub const Compiler = struct { |
| 672 | 672 | } |
| 673 | 673 | |
| 674 | 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 | 676 | return self.iconReadError( |
| 677 | 677 | error.UnexpectedEOF, |
| 678 | 678 | filename_utf8, |
| ... | ... | @@ -803,7 +803,7 @@ pub const Compiler = struct { |
| 803 | 803 | } |
| 804 | 804 | |
| 805 | 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 | 807 | try writeDataPadding(writer, full_data_size); |
| 808 | 808 | |
| 809 | 809 | if (self.state.icon_id == std.math.maxInt(u16)) { |
| ... | ... | @@ -859,7 +859,7 @@ pub const Compiler = struct { |
| 859 | 859 | header.applyMemoryFlags(node.common_resource_attributes, self.source); |
| 860 | 860 | const file_size = try file.getEndPos(); |
| 861 | 861 | |
| 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 | 863 | const filename_string_index = try self.diagnostics.putString(filename_utf8); |
| 864 | 864 | return self.addErrorDetailsAndFail(.{ |
| 865 | 865 | .err = .bmp_read_error, |
| ... | ... | @@ -922,7 +922,7 @@ pub const Compiler = struct { |
| 922 | 922 | header.data_size = bmp_bytes_to_write; |
| 923 | 923 | try header.write(writer, self.errContext(node.id)); |
| 924 | 924 | try file.seekTo(bmp.file_header_len); |
| 925 | const file_reader = file.reader(); | |
| 925 | const file_reader = file.deprecatedReader(); | |
| 926 | 926 | try writeResourceDataNoPadding(writer, file_reader, bitmap_info.dib_header_size); |
| 927 | 927 | if (bitmap_info.getBitmasksByteLen() > 0) { |
| 928 | 928 | try writeResourceDataNoPadding(writer, file_reader, bitmap_info.getBitmasksByteLen()); |
| ... | ... | @@ -968,7 +968,7 @@ pub const Compiler = struct { |
| 968 | 968 | header.data_size = @intCast(file_size); |
| 969 | 969 | try header.write(writer, self.errContext(node.id)); |
| 970 | 970 | |
| 971 | var header_slurping_reader = headerSlurpingReader(148, file.reader()); | |
| 971 | var header_slurping_reader = headerSlurpingReader(148, file.deprecatedReader()); | |
| 972 | 972 | try writeResourceData(writer, header_slurping_reader.reader(), header.data_size); |
| 973 | 973 | |
| 974 | 974 | try self.state.font_dir.add(self.arena, FontDir.Font{ |
| ... | ... | @@ -1002,7 +1002,7 @@ pub const Compiler = struct { |
| 1002 | 1002 | // We now know that the data size will fit in a u32 |
| 1003 | 1003 | header.data_size = @intCast(data_size); |
| 1004 | 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 | } |
| 1007 | 1007 | |
| 1008 | 1008 | fn iconReadError( |
| ... | ... | @@ -2949,7 +2949,7 @@ pub fn HeaderSlurpingReader(comptime size: usize, comptime ReaderType: anytype) |
| 2949 | 2949 | slurped_header: [size]u8 = [_]u8{0x00} ** size, |
| 2950 | 2950 | |
| 2951 | 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); | |
| 2953 | 2953 | |
| 2954 | 2954 | pub fn read(self: *@This(), buf: []u8) Error!usize { |
| 2955 | 2955 | const amt = try self.child_reader.read(buf); |
| ... | ... | @@ -2983,7 +2983,7 @@ pub fn LimitedWriter(comptime WriterType: type) type { |
| 2983 | 2983 | bytes_left: u64, |
| 2984 | 2984 | |
| 2985 | 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); | |
| 2987 | 2987 | |
| 2988 | 2988 | const Self = @This(); |
| 2989 | 2989 |
lib/compiler/resinator/errors.zig+29-33| ... | ... | @@ -1,4 +1,5 @@ |
| 1 | 1 | const std = @import("std"); |
| 2 | const assert = std.debug.assert; | |
| 2 | 3 | const Token = @import("lex.zig").Token; |
| 3 | 4 | const SourceMappings = @import("source_mapping.zig").SourceMappings; |
| 4 | 5 | const utils = @import("utils.zig"); |
| ... | ... | @@ -61,16 +62,15 @@ pub const Diagnostics = struct { |
| 61 | 62 | } |
| 62 | 63 | |
| 63 | 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 | defer std.debug.unlockStdErr(); | |
| 66 | const stderr = std.io.getStdErr().writer(); | |
| 65 | const stderr = std.debug.lockStderrWriter(&.{}); | |
| 66 | defer std.debug.unlockStderrWriter(); | |
| 67 | 67 | for (self.errors.items) |err_details| { |
| 68 | 68 | renderErrorMessage(stderr, tty_config, cwd, err_details, source, self.strings.items, source_mappings) catch return; |
| 69 | 69 | } |
| 70 | 70 | } |
| 71 | 71 | |
| 72 | 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 | 74 | return self.renderToStdErr(cwd, source, tty_config, source_mappings); |
| 75 | 75 | } |
| 76 | 76 | |
| ... | ... | @@ -409,15 +409,7 @@ pub const ErrorDetails = struct { |
| 409 | 409 | failed_to_open_cwd, |
| 410 | 410 | }; |
| 411 | 411 | |
| 412 | fn formatToken( | |
| 413 | ctx: TokenFormatContext, | |
| 414 | comptime fmt: []const u8, | |
| 415 | options: std.fmt.FormatOptions, | |
| 416 | writer: anytype, | |
| 417 | ) !void { | |
| 418 | _ = fmt; | |
| 419 | _ = options; | |
| 420 | ||
| 412 | fn formatToken(ctx: TokenFormatContext, writer: *std.io.Writer) std.io.Writer.Error!void { | |
| 421 | 413 | switch (ctx.token.id) { |
| 422 | 414 | .eof => return writer.writeAll(ctx.token.id.nameForErrorDisplay()), |
| 423 | 415 | else => {}, |
| ... | ... | @@ -441,7 +433,7 @@ pub const ErrorDetails = struct { |
| 441 | 433 | code_page: SupportedCodePage, |
| 442 | 434 | }; |
| 443 | 435 | |
| 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 | 437 | return .{ .data = .{ |
| 446 | 438 | .token = self.token, |
| 447 | 439 | .code_page = self.code_page, |
| ... | ... | @@ -452,7 +444,7 @@ pub const ErrorDetails = struct { |
| 452 | 444 | pub fn render(self: ErrorDetails, writer: anytype, source: []const u8, strings: []const []const u8) !void { |
| 453 | 445 | switch (self.err) { |
| 454 | 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 | 449 | .string_literal_too_long => { |
| 458 | 450 | return writer.print("string literal too long (max is currently {} characters)", .{self.extra.number}); |
| ... | ... | @@ -466,10 +458,14 @@ pub const ErrorDetails = struct { |
| 466 | 458 | .hint => return, |
| 467 | 459 | }, |
| 468 | 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 | 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 | 470 | .illegal_codepoint_outside_string_literals => { |
| 475 | 471 | // This is somewhat hacky, but we know that: |
| ... | ... | @@ -527,26 +523,26 @@ pub const ErrorDetails = struct { |
| 527 | 523 | return writer.print("unsupported code page '{s} (id={})' in #pragma code_page", .{ @tagName(code_page), number }); |
| 528 | 524 | }, |
| 529 | 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 | 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 | 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 | 534 | .expected_something_else => { |
| 539 | 535 | try writer.writeAll("expected "); |
| 540 | 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 | 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() }), | |
| 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)}), | |
| 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() }), | |
| 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 | 542 | .hint => return, |
| 547 | 543 | }, |
| 548 | 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 | 547 | .name_or_id_not_allowed => { |
| 552 | 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 | 558 | try writer.writeAll("ASCII character not equivalent to virtual key code"); |
| 563 | 559 | }, |
| 564 | 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 | 563 | .rc_would_miscompile_version_value_padding => switch (self.type) { |
| 568 | 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 | 623 | .string_already_defined => switch (self.type) { |
| 628 | 624 | .err, .warning => { |
| 629 | 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 | 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 | 629 | .hint => return, |
| ... | ... | @@ -642,7 +638,7 @@ pub const ErrorDetails = struct { |
| 642 | 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 | 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 | 643 | .accelerator_type_required => { |
| 648 | 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 | 894 | |
| 899 | 895 | const truncated_str = "<...truncated...>"; |
| 900 | 896 | |
| 901 | pub 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 { | |
| 897 | pub 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 | 898 | if (err_details.type == .hint) return; |
| 903 | 899 | |
| 904 | 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 | 977 | |
| 982 | 978 | try tty_config.setColor(writer, .green); |
| 983 | 979 | const num_spaces = truncated_visual_info.point_offset - truncated_visual_info.before_len; |
| 984 | try writer.writeByteNTimes(' ', num_spaces); | |
| 985 | try writer.writeByteNTimes('~', truncated_visual_info.before_len); | |
| 980 | try writer.splatByteAll(' ', num_spaces); | |
| 981 | try writer.splatByteAll('~', truncated_visual_info.before_len); | |
| 986 | 982 | try writer.writeByte('^'); |
| 987 | try writer.writeByteNTimes('~', truncated_visual_info.after_len); | |
| 983 | try writer.splatByteAll('~', truncated_visual_info.after_len); | |
| 988 | 984 | try writer.writeByte('\n'); |
| 989 | 985 | try tty_config.setColor(writer, .reset); |
| 990 | 986 | |
| ... | ... | @@ -1085,7 +1081,7 @@ const CorrespondingLines = struct { |
| 1085 | 1081 | buffered_reader: BufferedReaderType, |
| 1086 | 1082 | code_page: SupportedCodePage, |
| 1087 | 1083 | |
| 1088 | const BufferedReaderType = std.io.BufferedReader(512, std.fs.File.Reader); | |
| 1084 | const BufferedReaderType = std.io.BufferedReader(512, std.fs.File.DeprecatedReader); | |
| 1089 | 1085 | |
| 1090 | 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 | 1087 | // 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 | 1102 | .code_page = err_details.code_page, |
| 1107 | 1103 | }; |
| 1108 | 1104 | corresponding_lines.buffered_reader = BufferedReaderType{ |
| 1109 | .unbuffered_reader = corresponding_lines.file.reader(), | |
| 1105 | .unbuffered_reader = corresponding_lines.file.deprecatedReader(), | |
| 1110 | 1106 | }; |
| 1111 | 1107 | errdefer corresponding_lines.deinit(); |
| 1112 | 1108 |
lib/compiler/resinator/lex.zig+3-1| ... | ... | @@ -237,7 +237,9 @@ pub const Lexer = struct { |
| 237 | 237 | } |
| 238 | 238 | |
| 239 | 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 | } |
| 242 | 244 | |
| 243 | 245 | pub const LexMethod = enum { |
lib/compiler/resinator/main.zig+17-13| ... | ... | @@ -22,14 +22,14 @@ pub fn main() !void { |
| 22 | 22 | defer arena_state.deinit(); |
| 23 | 23 | const arena = arena_state.allocator(); |
| 24 | 24 | |
| 25 | const stderr = std.io.getStdErr(); | |
| 25 | const stderr = std.fs.File.stderr(); | |
| 26 | 26 | const stderr_config = std.io.tty.detectConfig(stderr); |
| 27 | 27 | |
| 28 | 28 | const args = try std.process.argsAlloc(allocator); |
| 29 | 29 | defer std.process.argsFree(allocator, args); |
| 30 | 30 | |
| 31 | 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 | 33 | std.process.exit(1); |
| 34 | 34 | } |
| 35 | 35 | const zig_lib_dir = args[1]; |
| ... | ... | @@ -44,7 +44,7 @@ pub fn main() !void { |
| 44 | 44 | var error_handler: ErrorHandler = switch (zig_integration) { |
| 45 | 45 | true => .{ |
| 46 | 46 | .server = .{ |
| 47 | .out = std.io.getStdOut(), | |
| 47 | .out = std.fs.File.stdout(), | |
| 48 | 48 | .in = undefined, // won't be receiving messages |
| 49 | 49 | .receive_fifo = undefined, // won't be receiving messages |
| 50 | 50 | }, |
| ... | ... | @@ -81,15 +81,15 @@ pub fn main() !void { |
| 81 | 81 | defer options.deinit(); |
| 82 | 82 | |
| 83 | 83 | if (options.print_help_and_exit) { |
| 84 | const stdout = std.io.getStdOut(); | |
| 85 | try cli.writeUsage(stdout.writer(), "zig rc"); | |
| 84 | const stdout = std.fs.File.stdout(); | |
| 85 | try cli.writeUsage(stdout.deprecatedWriter(), "zig rc"); | |
| 86 | 86 | return; |
| 87 | 87 | } |
| 88 | 88 | |
| 89 | 89 | // Don't allow verbose when integrating with Zig via stdout |
| 90 | 90 | options.verbose = false; |
| 91 | 91 | |
| 92 | const stdout_writer = std.io.getStdOut().writer(); | |
| 92 | const stdout_writer = std.fs.File.stdout().deprecatedWriter(); | |
| 93 | 93 | if (options.verbose) { |
| 94 | 94 | try options.dumpVerbose(stdout_writer); |
| 95 | 95 | try stdout_writer.writeByte('\n'); |
| ... | ... | @@ -290,7 +290,7 @@ pub fn main() !void { |
| 290 | 290 | }; |
| 291 | 291 | defer depfile.close(); |
| 292 | 292 | |
| 293 | const depfile_writer = depfile.writer(); | |
| 293 | const depfile_writer = depfile.deprecatedWriter(); | |
| 294 | 294 | var depfile_buffered_writer = std.io.bufferedWriter(depfile_writer); |
| 295 | 295 | switch (options.depfile_fmt) { |
| 296 | 296 | .json => { |
| ... | ... | @@ -343,7 +343,7 @@ pub fn main() !void { |
| 343 | 343 | switch (err) { |
| 344 | 344 | error.DuplicateResource => { |
| 345 | 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 | 347 | duplicate_resource.name_value, |
| 348 | 348 | fmtResourceType(duplicate_resource.type_value), |
| 349 | 349 | duplicate_resource.language, |
| ... | ... | @@ -352,7 +352,7 @@ pub fn main() !void { |
| 352 | 352 | error.ResourceDataTooLong => { |
| 353 | 353 | const overflow_resource = resources.list.items[cvtres_diagnostics.duplicate_resource]; |
| 354 | 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 | 356 | overflow_resource.name_value, |
| 357 | 357 | fmtResourceType(overflow_resource.type_value), |
| 358 | 358 | overflow_resource.language, |
| ... | ... | @@ -361,7 +361,7 @@ pub fn main() !void { |
| 361 | 361 | error.TotalResourceDataTooLong => { |
| 362 | 362 | const overflow_resource = resources.list.items[cvtres_diagnostics.duplicate_resource]; |
| 363 | 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 | 365 | overflow_resource.name_value, |
| 366 | 366 | fmtResourceType(overflow_resource.type_value), |
| 367 | 367 | overflow_resource.language, |
| ... | ... | @@ -471,7 +471,7 @@ const IoStream = struct { |
| 471 | 471 | allocator: std.mem.Allocator, |
| 472 | 472 | }; |
| 473 | 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); | |
| 475 | 475 | |
| 476 | 476 | pub fn write(ctx: WriterContext, bytes: []const u8) WriteError!usize { |
| 477 | 477 | switch (ctx.self.*) { |
| ... | ... | @@ -645,7 +645,9 @@ const ErrorHandler = union(enum) { |
| 645 | 645 | }, |
| 646 | 646 | .tty => { |
| 647 | 647 | // 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 | 651 | aro.Diagnostics.render(comp, self.tty); |
| 650 | 652 | }, |
| 651 | 653 | } |
| ... | ... | @@ -690,7 +692,9 @@ const ErrorHandler = union(enum) { |
| 690 | 692 | try server.serveErrorBundle(error_bundle); |
| 691 | 693 | }, |
| 692 | 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 | 1 | const std = @import("std"); |
| 2 | const assert = std.debug.assert; | |
| 2 | 3 | const rc = @import("rc.zig"); |
| 3 | 4 | const ResourceType = rc.ResourceType; |
| 4 | 5 | const CommonResourceAttributes = rc.CommonResourceAttributes; |
| ... | ... | @@ -163,14 +164,7 @@ pub const Language = packed struct(u16) { |
| 163 | 164 | return @bitCast(self); |
| 164 | 165 | } |
| 165 | 166 | |
| 166 | pub fn format( | |
| 167 | language: Language, | |
| 168 | comptime fmt: []const u8, | |
| 169 | options: std.fmt.FormatOptions, | |
| 170 | out_stream: anytype, | |
| 171 | ) !void { | |
| 172 | _ = fmt; | |
| 173 | _ = options; | |
| 167 | pub fn format(language: Language, w: *std.io.Writer) std.io.Writer.Error!void { | |
| 174 | 168 | const language_id = language.asInt(); |
| 175 | 169 | const language_name = language_name: { |
| 176 | 170 | if (std.enums.fromInt(lang.LanguageId, language_id)) |lang_enum_val| { |
| ... | ... | @@ -181,7 +175,7 @@ pub const Language = packed struct(u16) { |
| 181 | 175 | } |
| 182 | 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 | }; |
| 187 | 181 | |
| ... | ... | @@ -445,47 +439,33 @@ pub const NameOrOrdinal = union(enum) { |
| 445 | 439 | } |
| 446 | 440 | } |
| 447 | 441 | |
| 448 | pub fn format( | |
| 449 | self: NameOrOrdinal, | |
| 450 | comptime fmt: []const u8, | |
| 451 | options: std.fmt.FormatOptions, | |
| 452 | out_stream: anytype, | |
| 453 | ) !void { | |
| 454 | _ = fmt; | |
| 455 | _ = options; | |
| 442 | pub fn format(self: NameOrOrdinal, w: *std.io.Writer) !void { | |
| 456 | 443 | switch (self) { |
| 457 | 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 | 447 | .ordinal => |ordinal| { |
| 461 | try out_stream.print("{d}", .{ordinal}); | |
| 448 | try w.print("{d}", .{ordinal}); | |
| 462 | 449 | }, |
| 463 | 450 | } |
| 464 | 451 | } |
| 465 | 452 | |
| 466 | fn formatResourceType( | |
| 467 | self: NameOrOrdinal, | |
| 468 | comptime fmt: []const u8, | |
| 469 | options: std.fmt.FormatOptions, | |
| 470 | out_stream: anytype, | |
| 471 | ) !void { | |
| 472 | _ = fmt; | |
| 473 | _ = options; | |
| 453 | fn formatResourceType(self: NameOrOrdinal, w: *std.io.Writer) std.io.Writer.Error!void { | |
| 474 | 454 | switch (self) { |
| 475 | 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 | 458 | .ordinal => |ordinal| { |
| 479 | 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 | 461 | } else { |
| 482 | try out_stream.print("{d}", .{ordinal}); | |
| 462 | try w.print("{d}", .{ordinal}); | |
| 483 | 463 | } |
| 484 | 464 | }, |
| 485 | 465 | } |
| 486 | 466 | } |
| 487 | 467 | |
| 488 | pub fn fmtResourceType(type_value: NameOrOrdinal) std.fmt.Formatter(formatResourceType) { | |
| 468 | pub fn fmtResourceType(type_value: NameOrOrdinal) std.fmt.Formatter(NameOrOrdinal, formatResourceType) { | |
| 489 | 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 | 86 | |
| 87 | 87 | /// Used for generic colored errors/warnings/notes, more context-specific error messages |
| 88 | 88 | /// are handled elsewhere. |
| 89 | pub fn renderErrorMessage(writer: anytype, config: std.io.tty.Config, msg_type: ErrorMessageType, comptime format: []const u8, args: anytype) !void { | |
| 89 | pub fn renderErrorMessage(writer: *std.io.Writer, config: std.io.tty.Config, msg_type: ErrorMessageType, comptime format: []const u8, args: anytype) !void { | |
| 90 | 90 | switch (msg_type) { |
| 91 | 91 | .err => { |
| 92 | 92 | try config.setColor(writer, .bold); |
lib/compiler/std-docs.zig+2-2| ... | ... | @@ -7,7 +7,7 @@ const assert = std.debug.assert; |
| 7 | 7 | const Cache = std.Build.Cache; |
| 8 | 8 | |
| 9 | 9 | fn usage() noreturn { |
| 10 | io.getStdOut().writeAll( | |
| 10 | std.fs.File.stdout().writeAll( | |
| 11 | 11 | \\Usage: zig std [options] |
| 12 | 12 | \\ |
| 13 | 13 | \\Options: |
| ... | ... | @@ -63,7 +63,7 @@ pub fn main() !void { |
| 63 | 63 | var http_server = try address.listen(.{}); |
| 64 | 64 | const port = http_server.listen_address.in.getPort(); |
| 65 | 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 | 67 | if (should_open_browser) { |
| 68 | 68 | openBrowserTab(gpa, url_with_newline[0 .. url_with_newline.len - 1 :'\n']) catch |err| { |
| 69 | 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 | 69 | @disableInstrumentation(); |
| 70 | 70 | var server = try std.zig.Server.init(.{ |
| 71 | 71 | .gpa = fba.allocator(), |
| 72 | .in = std.io.getStdIn(), | |
| 73 | .out = std.io.getStdOut(), | |
| 72 | .in = .stdin(), | |
| 73 | .out = .stdout(), | |
| 74 | 74 | .zig_version = builtin.zig_version_string, |
| 75 | 75 | }); |
| 76 | 76 | defer server.deinit(); |
| ... | ... | @@ -191,7 +191,7 @@ fn mainTerminal() void { |
| 191 | 191 | .root_name = "Test", |
| 192 | 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(); | |
| 195 | 195 | |
| 196 | 196 | var async_frame_buffer: []align(builtin.target.stackAlignment()) u8 = undefined; |
| 197 | 197 | // TODO this is on the next line (using `undefined` above) because otherwise zig incorrectly |
| ... | ... | @@ -301,7 +301,7 @@ pub fn mainSimple() anyerror!void { |
| 301 | 301 | var failed: u64 = 0; |
| 302 | 302 | |
| 303 | 303 | // 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 {}; | |
| 305 | 305 | |
| 306 | 306 | for (builtin.test_functions) |test_fn| { |
| 307 | 307 | if (test_fn.func()) |_| { |
| ... | ... | @@ -328,7 +328,7 @@ pub fn mainSimple() anyerror!void { |
| 328 | 328 | passed += 1; |
| 329 | 329 | } |
| 330 | 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 | 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 | 440 | const err_loc = std.zig.findLineColumn(ast.source, err_offset); |
| 441 | 441 | rendered_err.clearRetainingCapacity(); |
| 442 | 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 | 445 | return Ast.parse(gpa, "", .zig); |
| 446 | 446 | } |
lib/docs/wasm/main.zig+2-2| ... | ... | @@ -717,9 +717,9 @@ fn render_docs( |
| 717 | 717 | try writer.writeAll("<a href=\"#"); |
| 718 | 718 | _ = missing_feature_url_escape; |
| 719 | 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 | 721 | } else { |
| 722 | try writer.print("{}", .{markdown.fmtHtml(content)}); | |
| 722 | try writer.print("{f}", .{markdown.fmtHtml(content)}); | |
| 723 | 723 | } |
| 724 | 724 | |
| 725 | 725 | try writer.writeAll("</code>"); |
lib/docs/wasm/markdown.zig+2-2| ... | ... | @@ -145,7 +145,7 @@ fn mainImpl() !void { |
| 145 | 145 | var parser = try Parser.init(gpa); |
| 146 | 146 | defer parser.deinit(); |
| 147 | 147 | |
| 148 | var stdin_buf = std.io.bufferedReader(std.io.getStdIn().reader()); | |
| 148 | var stdin_buf = std.io.bufferedReader(std.fs.File.stdin().deprecatedReader()); | |
| 149 | 149 | var line_buf = std.ArrayList(u8).init(gpa); |
| 150 | 150 | defer line_buf.deinit(); |
| 151 | 151 | while (stdin_buf.reader().streamUntilDelimiter(line_buf.writer(), '\n', null)) { |
| ... | ... | @@ -160,7 +160,7 @@ fn mainImpl() !void { |
| 160 | 160 | var doc = try parser.endInput(); |
| 161 | 161 | defer doc.deinit(gpa); |
| 162 | 162 | |
| 163 | var stdout_buf = std.io.bufferedWriter(std.io.getStdOut().writer()); | |
| 163 | var stdout_buf = std.io.bufferedWriter(std.fs.File.stdout().deprecatedWriter()); | |
| 164 | 164 | try doc.render(stdout_buf.writer()); |
| 165 | 165 | try stdout_buf.flush(); |
| 166 | 166 | } |
lib/docs/wasm/markdown/renderer.zig+13-19| ... | ... | @@ -1,6 +1,7 @@ |
| 1 | 1 | const std = @import("std"); |
| 2 | 2 | const Document = @import("Document.zig"); |
| 3 | 3 | const Node = Document.Node; |
| 4 | const assert = std.debug.assert; | |
| 4 | 5 | |
| 5 | 6 | /// A Markdown document renderer. |
| 6 | 7 | /// |
| ... | ... | @@ -41,7 +42,7 @@ pub fn Renderer(comptime Writer: type, comptime Context: type) type { |
| 41 | 42 | if (start == 1) { |
| 42 | 43 | try writer.writeAll("<ol>\n"); |
| 43 | 44 | } else { |
| 44 | try writer.print("<ol start=\"{}\">\n", .{start}); | |
| 45 | try writer.print("<ol start=\"{d}\">\n", .{start}); | |
| 45 | 46 | } |
| 46 | 47 | } else { |
| 47 | 48 | try writer.writeAll("<ul>\n"); |
| ... | ... | @@ -105,15 +106,15 @@ pub fn Renderer(comptime Writer: type, comptime Context: type) type { |
| 105 | 106 | } |
| 106 | 107 | }, |
| 107 | 108 | .heading => { |
| 108 | try writer.print("<h{}>", .{data.heading.level}); | |
| 109 | try writer.print("<h{d}>", .{data.heading.level}); | |
| 109 | 110 | for (doc.extraChildren(data.heading.children)) |child| { |
| 110 | 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 | 115 | .code_block => { |
| 115 | 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 | 119 | .blockquote => { |
| 119 | 120 | try writer.writeAll("<blockquote>\n"); |
| ... | ... | @@ -134,7 +135,7 @@ pub fn Renderer(comptime Writer: type, comptime Context: type) type { |
| 134 | 135 | }, |
| 135 | 136 | .link => { |
| 136 | 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 | 139 | for (doc.extraChildren(data.link.children)) |child| { |
| 139 | 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 | 143 | }, |
| 143 | 144 | .autolink => { |
| 144 | 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 | 148 | .image => { |
| 148 | 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 | 151 | for (doc.extraChildren(data.link.children)) |child| { |
| 151 | 152 | try renderInlineNodeText(doc, child, writer); |
| 152 | 153 | } |
| ... | ... | @@ -168,11 +169,11 @@ pub fn Renderer(comptime Writer: type, comptime Context: type) type { |
| 168 | 169 | }, |
| 169 | 170 | .code_span => { |
| 170 | 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 | 174 | .text => { |
| 174 | 175 | const content = doc.string(data.text.content); |
| 175 | try writer.print("{}", .{fmtHtml(content)}); | |
| 176 | try writer.print("{f}", .{fmtHtml(content)}); | |
| 176 | 177 | }, |
| 177 | 178 | .line_break => { |
| 178 | 179 | try writer.writeAll("<br />\n"); |
| ... | ... | @@ -221,7 +222,7 @@ pub fn renderInlineNodeText( |
| 221 | 222 | }, |
| 222 | 223 | .autolink, .code_span, .text => { |
| 223 | 224 | const content = doc.string(data.text.content); |
| 224 | try writer.print("{}", .{fmtHtml(content)}); | |
| 225 | try writer.print("{f}", .{fmtHtml(content)}); | |
| 225 | 226 | }, |
| 226 | 227 | .line_break => { |
| 227 | 228 | try writer.writeAll("\n"); |
| ... | ... | @@ -229,18 +230,11 @@ pub fn renderInlineNodeText( |
| 229 | 230 | } |
| 230 | 231 | } |
| 231 | 232 | |
| 232 | pub fn fmtHtml(bytes: []const u8) std.fmt.Formatter(formatHtml) { | |
| 233 | pub fn fmtHtml(bytes: []const u8) std.fmt.Formatter([]const u8, formatHtml) { | |
| 233 | 234 | return .{ .data = bytes }; |
| 234 | 235 | } |
| 235 | 236 | |
| 236 | fn formatHtml( | |
| 237 | bytes: []const u8, | |
| 238 | comptime fmt: []const u8, | |
| 239 | options: std.fmt.FormatOptions, | |
| 240 | writer: anytype, | |
| 241 | ) !void { | |
| 242 | _ = fmt; | |
| 243 | _ = options; | |
| 237 | fn formatHtml(bytes: []const u8, writer: *std.io.Writer) std.io.Writer.Error!void { | |
| 244 | 238 | for (bytes) |b| { |
| 245 | 239 | switch (b) { |
| 246 | 240 | '<' => try writer.writeAll("&lt;"), |
lib/fuzzer.zig+12-9| ... | ... | @@ -9,7 +9,8 @@ pub const std_options = std.Options{ |
| 9 | 9 | .logFn = logOverride, |
| 10 | 10 | }; |
| 11 | 11 | |
| 12 | var log_file: ?std.fs.File = null; | |
| 12 | var log_file_buffer: [256]u8 = undefined; | |
| 13 | var log_file_writer: ?std.fs.File.Writer = null; | |
| 13 | 14 | |
| 14 | 15 | fn logOverride( |
| 15 | 16 | comptime level: std.log.Level, |
| ... | ... | @@ -17,15 +18,17 @@ fn logOverride( |
| 17 | 18 | comptime format: []const u8, |
| 18 | 19 | args: anytype, |
| 19 | 20 | ) void { |
| 20 | const f = if (log_file) |f| f else f: { | |
| 21 | const fw = if (log_file_writer) |*f| f else f: { | |
| 21 | 22 | const f = fuzzer.cache_dir.createFile("tmp/libfuzzer.log", .{}) catch |
| 22 | 23 | @panic("failed to open fuzzer log file"); |
| 23 | log_file = f; | |
| 24 | break :f f; | |
| 24 | log_file_writer = f.writer(&log_file_buffer); | |
| 25 | break :f &log_file_writer.?; | |
| 25 | 26 | }; |
| 26 | 27 | const prefix1 = comptime level.asText(); |
| 27 | 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 | } |
| 30 | 33 | |
| 31 | 34 | /// Helps determine run uniqueness in the face of recursion. |
| ... | ... | @@ -226,18 +229,18 @@ const Fuzzer = struct { |
| 226 | 229 | .read = true, |
| 227 | 230 | }) catch |e| switch (e) { |
| 228 | 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 | 234 | errdefer input_file.close(); |
| 232 | 235 | // Initialize the mmap for the current input. |
| 233 | 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 | 238 | f.corpus_directory, i, @errorName(e), |
| 236 | 239 | }); |
| 237 | 240 | }; |
| 238 | 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 | 245 | errdefer gpa.free(input); |
| 243 | 246 | f.corpus.append(gpa, .{ |
| ... | ... | @@ -263,7 +266,7 @@ const Fuzzer = struct { |
| 263 | 266 | const sub_path = try std.fmt.allocPrint(gpa, "f/{s}", .{f.unit_test_name}); |
| 264 | 267 | f.corpus_directory = .{ |
| 265 | 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 | 270 | .path = sub_path, |
| 268 | 271 | }; |
| 269 | 272 | initNextInput(f); |
lib/init/src/root.zig+1-1| ... | ... | @@ -5,7 +5,7 @@ pub fn bufferedPrint() !void { |
| 5 | 5 | // Stdout is for the actual output of your application, for example if you |
| 6 | 6 | // are implementing gzip, then only the compressed bytes should be sent to |
| 7 | 7 | // stdout, not any debugging messages. |
| 8 | const stdout_file = std.io.getStdOut().writer(); | |
| 8 | const stdout_file = std.fs.File.stdout().deprecatedWriter(); | |
| 9 | 9 | // Buffering can improve performance significantly in print-heavy programs. |
| 10 | 10 | var bw = std.io.bufferedWriter(stdout_file); |
| 11 | 11 | const stdout = bw.writer(); |
lib/std/Build.zig+33-43| ... | ... | @@ -284,7 +284,7 @@ pub fn create( |
| 284 | 284 | .h_dir = undefined, |
| 285 | 285 | .dest_dir = graph.env_map.get("DESTDIR"), |
| 286 | 286 | .install_tls = .{ |
| 287 | .step = Step.init(.{ | |
| 287 | .step = .init(.{ | |
| 288 | 288 | .id = TopLevelStep.base_id, |
| 289 | 289 | .name = "install", |
| 290 | 290 | .owner = b, |
| ... | ... | @@ -292,7 +292,7 @@ pub fn create( |
| 292 | 292 | .description = "Copy build artifacts to prefix path", |
| 293 | 293 | }, |
| 294 | 294 | .uninstall_tls = .{ |
| 295 | .step = Step.init(.{ | |
| 295 | .step = .init(.{ | |
| 296 | 296 | .id = TopLevelStep.base_id, |
| 297 | 297 | .name = "uninstall", |
| 298 | 298 | .owner = b, |
| ... | ... | @@ -342,7 +342,7 @@ fn createChildOnly( |
| 342 | 342 | .graph = parent.graph, |
| 343 | 343 | .allocator = allocator, |
| 344 | 344 | .install_tls = .{ |
| 345 | .step = Step.init(.{ | |
| 345 | .step = .init(.{ | |
| 346 | 346 | .id = TopLevelStep.base_id, |
| 347 | 347 | .name = "install", |
| 348 | 348 | .owner = child, |
| ... | ... | @@ -350,7 +350,7 @@ fn createChildOnly( |
| 350 | 350 | .description = "Copy build artifacts to prefix path", |
| 351 | 351 | }, |
| 352 | 352 | .uninstall_tls = .{ |
| 353 | .step = Step.init(.{ | |
| 353 | .step = .init(.{ | |
| 354 | 354 | .id = TopLevelStep.base_id, |
| 355 | 355 | .name = "uninstall", |
| 356 | 356 | .owner = child, |
| ... | ... | @@ -1525,7 +1525,7 @@ pub fn option(b: *Build, comptime T: type, name_raw: []const u8, description_raw |
| 1525 | 1525 | pub fn step(b: *Build, name: []const u8, description: []const u8) *Step { |
| 1526 | 1526 | const step_info = b.allocator.create(TopLevelStep) catch @panic("OOM"); |
| 1527 | 1527 | step_info.* = .{ |
| 1528 | .step = Step.init(.{ | |
| 1528 | .step = .init(.{ | |
| 1529 | 1529 | .id = TopLevelStep.base_id, |
| 1530 | 1530 | .name = name, |
| 1531 | 1531 | .owner = b, |
| ... | ... | @@ -1745,7 +1745,7 @@ pub fn addUserInputOption(b: *Build, name_raw: []const u8, value_raw: []const u8 |
| 1745 | 1745 | return true; |
| 1746 | 1746 | }, |
| 1747 | 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 | 1749 | return true; |
| 1750 | 1750 | }, |
| 1751 | 1751 | } |
| ... | ... | @@ -1824,13 +1824,13 @@ pub fn validateUserInputDidItFail(b: *Build) bool { |
| 1824 | 1824 | return b.invalid_user_input; |
| 1825 | 1825 | } |
| 1826 | 1826 | |
| 1827 | fn allocPrintCmd(ally: Allocator, opt_cwd: ?[]const u8, argv: []const []const u8) error{OutOfMemory}![]u8 { | |
| 1828 | var buf = ArrayList(u8).init(ally); | |
| 1829 | if (opt_cwd) |cwd| try buf.writer().print("cd {s} && ", .{cwd}); | |
| 1827 | fn allocPrintCmd(gpa: Allocator, opt_cwd: ?[]const u8, argv: []const []const u8) error{OutOfMemory}![]u8 { | |
| 1828 | var buf: std.ArrayListUnmanaged(u8) = .empty; | |
| 1829 | if (opt_cwd) |cwd| try buf.print(gpa, "cd {s} && ", .{cwd}); | |
| 1830 | 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 | } |
| 1835 | 1835 | |
| 1836 | 1836 | fn printCmd(ally: Allocator, cwd: ?[]const u8, argv: []const []const u8) void { |
| ... | ... | @@ -2059,7 +2059,7 @@ pub fn runAllowFail( |
| 2059 | 2059 | try Step.handleVerbose2(b, null, child.env_map, argv); |
| 2060 | 2060 | try child.spawn(); |
| 2061 | 2061 | |
| 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 | 2063 | return error.ReadFailure; |
| 2064 | 2064 | }; |
| 2065 | 2065 | errdefer b.allocator.free(stdout); |
| ... | ... | @@ -2466,10 +2466,9 @@ pub const GeneratedFile = struct { |
| 2466 | 2466 | |
| 2467 | 2467 | pub fn getPath2(gen: GeneratedFile, src_builder: *Build, asking_step: ?*Step) []const u8 { |
| 2468 | 2468 | return gen.path orelse { |
| 2469 | std.debug.lockStdErr(); | |
| 2470 | const stderr = std.io.getStdErr(); | |
| 2471 | dumpBadGetPathHelp(gen.step, stderr, src_builder, asking_step) catch {}; | |
| 2472 | std.debug.unlockStdErr(); | |
| 2469 | const w = debug.lockStderrWriter(&.{}); | |
| 2470 | dumpBadGetPathHelp(gen.step, w, .detect(.stderr()), src_builder, asking_step) catch {}; | |
| 2471 | debug.unlockStderrWriter(); | |
| 2473 | 2472 | @panic("misconfigured build script"); |
| 2474 | 2473 | }; |
| 2475 | 2474 | } |
| ... | ... | @@ -2676,10 +2675,9 @@ pub const LazyPath = union(enum) { |
| 2676 | 2675 | var file_path: Cache.Path = .{ |
| 2677 | 2676 | .root_dir = Cache.Directory.cwd(), |
| 2678 | 2677 | .sub_path = gen.file.path orelse { |
| 2679 | std.debug.lockStdErr(); | |
| 2680 | const stderr = std.io.getStdErr(); | |
| 2681 | dumpBadGetPathHelp(gen.file.step, stderr, src_builder, asking_step) catch {}; | |
| 2682 | std.debug.unlockStdErr(); | |
| 2678 | const w = debug.lockStderrWriter(&.{}); | |
| 2679 | dumpBadGetPathHelp(gen.file.step, w, .detect(.stderr()), src_builder, asking_step) catch {}; | |
| 2680 | debug.unlockStderrWriter(); | |
| 2683 | 2681 | @panic("misconfigured build script"); |
| 2684 | 2682 | }, |
| 2685 | 2683 | }; |
| ... | ... | @@ -2766,44 +2764,42 @@ fn dumpBadDirnameHelp( |
| 2766 | 2764 | comptime msg: []const u8, |
| 2767 | 2765 | args: anytype, |
| 2768 | 2766 | ) anyerror!void { |
| 2769 | debug.lockStdErr(); | |
| 2770 | defer debug.unlockStdErr(); | |
| 2767 | const w = debug.lockStderrWriter(&.{}); | |
| 2768 | defer debug.unlockStderrWriter(); | |
| 2771 | 2769 | |
| 2772 | const stderr = io.getStdErr(); | |
| 2773 | const w = stderr.writer(); | |
| 2774 | 2770 | try w.print(msg, args); |
| 2775 | 2771 | |
| 2776 | const tty_config = std.io.tty.detectConfig(stderr); | |
| 2772 | const tty_config = std.io.tty.detectConfig(.stderr()); | |
| 2777 | 2773 | |
| 2778 | 2774 | if (fail_step) |s| { |
| 2779 | 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 | 2777 | tty_config.setColor(w, .reset) catch {}; |
| 2782 | 2778 | |
| 2783 | s.dump(stderr); | |
| 2779 | s.dump(w, tty_config); | |
| 2784 | 2780 | } |
| 2785 | 2781 | |
| 2786 | 2782 | if (asking_step) |as| { |
| 2787 | 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 | 2785 | tty_config.setColor(w, .reset) catch {}; |
| 2790 | 2786 | |
| 2791 | as.dump(stderr); | |
| 2787 | as.dump(w, tty_config); | |
| 2792 | 2788 | } |
| 2793 | 2789 | |
| 2794 | 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 | 2792 | tty_config.setColor(w, .reset) catch {}; |
| 2797 | 2793 | } |
| 2798 | 2794 | |
| 2799 | 2795 | /// In this function the stderr mutex has already been locked. |
| 2800 | 2796 | pub fn dumpBadGetPathHelp( |
| 2801 | 2797 | s: *Step, |
| 2802 | stderr: fs.File, | |
| 2798 | w: *std.io.Writer, | |
| 2799 | tty_config: std.io.tty.Config, | |
| 2803 | 2800 | src_builder: *Build, |
| 2804 | 2801 | asking_step: ?*Step, |
| 2805 | 2802 | ) anyerror!void { |
| 2806 | const w = stderr.writer(); | |
| 2807 | 2803 | try w.print( |
| 2808 | 2804 | \\getPath() was called on a GeneratedFile that wasn't built yet. |
| 2809 | 2805 | \\ source package path: {s} |
| ... | ... | @@ -2814,21 +2810,20 @@ pub fn dumpBadGetPathHelp( |
| 2814 | 2810 | s.name, |
| 2815 | 2811 | }); |
| 2816 | 2812 | |
| 2817 | const tty_config = std.io.tty.detectConfig(stderr); | |
| 2818 | 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 | 2815 | tty_config.setColor(w, .reset) catch {}; |
| 2821 | 2816 | |
| 2822 | s.dump(stderr); | |
| 2817 | s.dump(w, tty_config); | |
| 2823 | 2818 | if (asking_step) |as| { |
| 2824 | 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 | 2821 | tty_config.setColor(w, .reset) catch {}; |
| 2827 | 2822 | |
| 2828 | as.dump(stderr); | |
| 2823 | as.dump(w, tty_config); | |
| 2829 | 2824 | } |
| 2830 | 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 | 2827 | tty_config.setColor(w, .reset) catch {}; |
| 2833 | 2828 | } |
| 2834 | 2829 | |
| ... | ... | @@ -2866,11 +2861,6 @@ pub fn makeTempPath(b: *Build) []const u8 { |
| 2866 | 2861 | return result_path; |
| 2867 | 2862 | } |
| 2868 | 2863 | |
| 2869 | /// Deprecated; use `std.fmt.hex` instead. | |
| 2870 | pub fn hex64(x: u64) [16]u8 { | |
| 2871 | return std.fmt.hex(x); | |
| 2872 | } | |
| 2873 | ||
| 2874 | 2864 | /// A pair of target query and fully resolved target. |
| 2875 | 2865 | /// This type is generally required by build system API that need to be given a |
| 2876 | 2866 | /// 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 | 2 | //! This is not a general-purpose cache. It is designed to be fast and simple, |
| 3 | 3 | //! not to withstand attacks using specially-crafted input. |
| 4 | 4 | |
| 5 | const Cache = @This(); | |
| 6 | const std = @import("std"); | |
| 7 | const builtin = @import("builtin"); | |
| 8 | const crypto = std.crypto; | |
| 9 | const fs = std.fs; | |
| 10 | const assert = std.debug.assert; | |
| 11 | const testing = std.testing; | |
| 12 | const mem = std.mem; | |
| 13 | const fmt = std.fmt; | |
| 14 | const Allocator = std.mem.Allocator; | |
| 15 | const log = std.log.scoped(.cache); | |
| 16 | ||
| 5 | 17 | gpa: Allocator, |
| 6 | 18 | manifest_dir: fs.Dir, |
| 7 | 19 | hash: HashHelper = .{}, |
| ... | ... | @@ -21,18 +33,6 @@ pub const Path = @import("Cache/Path.zig"); |
| 21 | 33 | pub const Directory = @import("Cache/Directory.zig"); |
| 22 | 34 | pub const DepTokenizer = @import("Cache/DepTokenizer.zig"); |
| 23 | 35 | |
| 24 | const Cache = @This(); | |
| 25 | const std = @import("std"); | |
| 26 | const builtin = @import("builtin"); | |
| 27 | const crypto = std.crypto; | |
| 28 | const fs = std.fs; | |
| 29 | const assert = std.debug.assert; | |
| 30 | const testing = std.testing; | |
| 31 | const mem = std.mem; | |
| 32 | const fmt = std.fmt; | |
| 33 | const Allocator = std.mem.Allocator; | |
| 34 | const log = std.log.scoped(.cache); | |
| 35 | ||
| 36 | 36 | pub fn addPrefix(cache: *Cache, directory: Directory) void { |
| 37 | 37 | cache.prefixes_buffer[cache.prefixes_len] = directory; |
| 38 | 38 | cache.prefixes_len += 1; |
| ... | ... | @@ -68,7 +68,7 @@ const PrefixedPath = struct { |
| 68 | 68 | |
| 69 | 69 | fn findPrefix(cache: *const Cache, file_path: []const u8) !PrefixedPath { |
| 70 | 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 | 72 | errdefer gpa.free(resolved_path); |
| 73 | 73 | return findPrefixResolved(cache, resolved_path); |
| 74 | 74 | } |
| ... | ... | @@ -132,7 +132,7 @@ pub const Hasher = crypto.auth.siphash.SipHash128(1, 3); |
| 132 | 132 | /// Initial state with random bytes, that can be copied. |
| 133 | 133 | /// Refresh this with new random bytes when the manifest |
| 134 | 134 | /// format is modified in a non-backwards-compatible way. |
| 135 | pub const hasher_init: Hasher = Hasher.init(&[_]u8{ | |
| 135 | pub const hasher_init: Hasher = Hasher.init(&.{ | |
| 136 | 136 | 0x33, 0x52, 0xa2, 0x84, |
| 137 | 137 | 0xcf, 0x17, 0x56, 0x57, |
| 138 | 138 | 0x01, 0xbb, 0xcd, 0xe4, |
| ... | ... | @@ -286,11 +286,8 @@ pub const HashHelper = struct { |
| 286 | 286 | |
| 287 | 287 | pub fn binToHex(bin_digest: BinDigest) HexDigest { |
| 288 | 288 | var out_digest: HexDigest = undefined; |
| 289 | _ = fmt.bufPrint( | |
| 290 | &out_digest, | |
| 291 | "{s}", | |
| 292 | .{fmt.fmtSliceHexLower(&bin_digest)}, | |
| 293 | ) catch unreachable; | |
| 289 | var w: std.io.Writer = .fixed(&out_digest); | |
| 290 | w.printHex(&bin_digest, .lower) catch unreachable; | |
| 294 | 291 | return out_digest; |
| 295 | 292 | } |
| 296 | 293 | |
| ... | ... | @@ -337,7 +334,6 @@ pub const Manifest = struct { |
| 337 | 334 | manifest_create: fs.File.OpenError, |
| 338 | 335 | manifest_read: fs.File.ReadError, |
| 339 | 336 | manifest_lock: fs.File.LockError, |
| 340 | manifest_seek: fs.File.SeekError, | |
| 341 | 337 | file_open: FileOp, |
| 342 | 338 | file_stat: FileOp, |
| 343 | 339 | file_read: FileOp, |
| ... | ... | @@ -611,12 +607,6 @@ pub const Manifest = struct { |
| 611 | 607 | var file = self.files.pop().?; |
| 612 | 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 | 610 | switch (try self.hitWithCurrentLock()) { |
| 621 | 611 | .hit => break :hit, |
| 622 | 612 | .miss => |m| break :digests m.file_digests_populated, |
| ... | ... | @@ -661,9 +651,8 @@ pub const Manifest = struct { |
| 661 | 651 | return true; |
| 662 | 652 | } |
| 663 | 653 | |
| 664 | /// Assumes that `self.hash.hasher` has been updated only with the original digest, that | |
| 665 | /// `self.files` contains only the original input files, and that `self.manifest_file.?` is | |
| 666 | /// seeked to the start of the file. | |
| 654 | /// Assumes that `self.hash.hasher` has been updated only with the original digest and that | |
| 655 | /// `self.files` contains only the original input files. | |
| 667 | 656 | fn hitWithCurrentLock(self: *Manifest) HitError!union(enum) { |
| 668 | 657 | hit, |
| 669 | 658 | miss: struct { |
| ... | ... | @@ -672,12 +661,13 @@ pub const Manifest = struct { |
| 672 | 661 | } { |
| 673 | 662 | const gpa = self.cache.gpa; |
| 674 | 663 | const input_file_count = self.files.entries.len; |
| 675 | ||
| 676 | const file_contents = self.manifest_file.?.reader().readAllAlloc(gpa, manifest_file_size_max) catch |err| switch (err) { | |
| 664 | var manifest_reader = self.manifest_file.?.reader(&.{}); // Reads positionally from zero. | |
| 665 | const limit: std.io.Limit = .limited(manifest_file_size_max); | |
| 666 | const file_contents = manifest_reader.interface.allocRemaining(gpa, limit) catch |err| switch (err) { | |
| 677 | 667 | error.OutOfMemory => return error.OutOfMemory, |
| 678 | 668 | error.StreamTooLong => return error.OutOfMemory, |
| 679 | else => |e| { | |
| 680 | self.diagnostic = .{ .manifest_read = e }; | |
| 669 | error.ReadFailed => { | |
| 670 | self.diagnostic = .{ .manifest_read = manifest_reader.err.? }; | |
| 681 | 671 | return error.CacheCheckFailed; |
| 682 | 672 | }, |
| 683 | 673 | }; |
| ... | ... | @@ -1063,14 +1053,17 @@ pub const Manifest = struct { |
| 1063 | 1053 | } |
| 1064 | 1054 | |
| 1065 | 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); | |
| 1067 | defer self.cache.gpa.free(dep_file_contents); | |
| 1056 | const gpa = self.cache.gpa; | |
| 1057 | const dep_file_contents = try dir.readFileAlloc(gpa, dep_file_basename, manifest_file_size_max); | |
| 1058 | defer gpa.free(dep_file_contents); | |
| 1068 | 1059 | |
| 1069 | var error_buf = std.ArrayList(u8).init(self.cache.gpa); | |
| 1070 | defer error_buf.deinit(); | |
| 1060 | var error_buf: std.ArrayListUnmanaged(u8) = .empty; | |
| 1061 | defer error_buf.deinit(gpa); | |
| 1071 | 1062 | |
| 1072 | var it: DepTokenizer = .{ .bytes = dep_file_contents }; | |
| 1063 | var resolve_buf: std.ArrayListUnmanaged(u8) = .empty; | |
| 1064 | defer resolve_buf.deinit(gpa); | |
| 1073 | 1065 | |
| 1066 | var it: DepTokenizer = .{ .bytes = dep_file_contents }; | |
| 1074 | 1067 | while (it.next()) |token| { |
| 1075 | 1068 | switch (token) { |
| 1076 | 1069 | // We don't care about targets, we only want the prereqs |
| ... | ... | @@ -1080,16 +1073,14 @@ pub const Manifest = struct { |
| 1080 | 1073 | _ = try self.addFile(file_path, null); |
| 1081 | 1074 | } else try self.addFilePost(file_path), |
| 1082 | 1075 | .prereq_must_resolve => { |
| 1083 | var resolve_buf = std.ArrayList(u8).init(self.cache.gpa); | |
| 1084 | defer resolve_buf.deinit(); | |
| 1085 | ||
| 1086 | try token.resolve(resolve_buf.writer()); | |
| 1076 | resolve_buf.clearRetainingCapacity(); | |
| 1077 | try token.resolve(gpa, &resolve_buf); | |
| 1087 | 1078 | if (self.manifest_file == null) { |
| 1088 | 1079 | _ = try self.addFile(resolve_buf.items, null); |
| 1089 | 1080 | } else try self.addFilePost(resolve_buf.items); |
| 1090 | 1081 | }, |
| 1091 | 1082 | else => |err| { |
| 1092 | try err.printError(error_buf.writer()); | |
| 1083 | try err.printError(gpa, &error_buf); | |
| 1093 | 1084 | log.err("failed parsing {s}: {s}", .{ dep_file_basename, error_buf.items }); |
| 1094 | 1085 | return error.InvalidDepFile; |
| 1095 | 1086 | }, |
| ... | ... | @@ -1127,24 +1118,12 @@ pub const Manifest = struct { |
| 1127 | 1118 | if (self.manifest_dirty) { |
| 1128 | 1119 | self.manifest_dirty = false; |
| 1129 | 1120 | |
| 1130 | var contents = std.ArrayList(u8).init(self.cache.gpa); | |
| 1131 | defer contents.deinit(); | |
| 1132 | ||
| 1133 | const writer = contents.writer(); | |
| 1134 | try writer.writeAll(manifest_header ++ "\n"); | |
| 1135 | for (self.files.keys()) |file| { | |
| 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); | |
| 1121 | var buffer: [4000]u8 = undefined; | |
| 1122 | var fw = manifest_file.writer(&buffer); | |
| 1123 | writeDirtyManifestToStream(self, &fw) catch |err| switch (err) { | |
| 1124 | error.WriteFailed => return fw.err.?, | |
| 1125 | else => |e| return e, | |
| 1126 | }; | |
| 1148 | 1127 | } |
| 1149 | 1128 | |
| 1150 | 1129 | if (self.want_shared_lock) { |
| ... | ... | @@ -1152,6 +1131,21 @@ pub const Manifest = struct { |
| 1152 | 1131 | } |
| 1153 | 1132 | } |
| 1154 | 1133 | |
| 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 | 1149 | fn downgradeToSharedLock(self: *Manifest) !void { |
| 1156 | 1150 | if (!self.have_exclusive_lock) return; |
| 1157 | 1151 |
lib/std/Build/Cache/DepTokenizer.zig+43-158| ... | ... | @@ -7,6 +7,7 @@ state: State = .lhs, |
| 7 | 7 | const std = @import("std"); |
| 8 | 8 | const testing = std.testing; |
| 9 | 9 | const assert = std.debug.assert; |
| 10 | const Allocator = std.mem.Allocator; | |
| 10 | 11 | |
| 11 | 12 | pub fn next(self: *Tokenizer) ?Token { |
| 12 | 13 | var start = self.index; |
| ... | ... | @@ -362,7 +363,7 @@ pub const Token = union(enum) { |
| 362 | 363 | }; |
| 363 | 364 | |
| 364 | 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 | 367 | switch (self) { |
| 367 | 368 | .target_must_resolve => |bytes| { |
| 368 | 369 | var state: enum { start, escape, dollar } = .start; |
| ... | ... | @@ -372,27 +373,27 @@ pub const Token = union(enum) { |
| 372 | 373 | switch (c) { |
| 373 | 374 | '\\' => state = .escape, |
| 374 | 375 | '$' => state = .dollar, |
| 375 | else => try writer.writeByte(c), | |
| 376 | else => try list.append(gpa, c), | |
| 376 | 377 | } |
| 377 | 378 | }, |
| 378 | 379 | .escape => { |
| 379 | 380 | switch (c) { |
| 380 | 381 | ' ', '#', '\\' => {}, |
| 381 | 382 | '$' => { |
| 382 | try writer.writeByte('\\'); | |
| 383 | try list.append(gpa, '\\'); | |
| 383 | 384 | state = .dollar; |
| 384 | 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 | 390 | state = .start; |
| 390 | 391 | }, |
| 391 | 392 | .dollar => { |
| 392 | try writer.writeByte('$'); | |
| 393 | try list.append(gpa, '$'); | |
| 393 | 394 | switch (c) { |
| 394 | 395 | '$' => {}, |
| 395 | else => try writer.writeByte(c), | |
| 396 | else => try list.append(gpa, c), | |
| 396 | 397 | } |
| 397 | 398 | state = .start; |
| 398 | 399 | }, |
| ... | ... | @@ -406,19 +407,19 @@ pub const Token = union(enum) { |
| 406 | 407 | .start => { |
| 407 | 408 | switch (c) { |
| 408 | 409 | '\\' => state = .escape, |
| 409 | else => try writer.writeByte(c), | |
| 410 | else => try list.append(gpa, c), | |
| 410 | 411 | } |
| 411 | 412 | }, |
| 412 | 413 | .escape => { |
| 413 | 414 | switch (c) { |
| 414 | 415 | ' ' => {}, |
| 415 | 416 | '\\' => { |
| 416 | try writer.writeByte(c); | |
| 417 | try list.append(gpa, c); | |
| 417 | 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 | 423 | state = .start; |
| 423 | 424 | }, |
| 424 | 425 | } |
| ... | ... | @@ -428,20 +429,20 @@ pub const Token = union(enum) { |
| 428 | 429 | } |
| 429 | 430 | } |
| 430 | 431 | |
| 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 | 433 | switch (self) { |
| 433 | 434 | .target, .target_must_resolve, .prereq, .prereq_must_resolve => unreachable, // not an error |
| 434 | 435 | .incomplete_quoted_prerequisite, |
| 435 | 436 | .incomplete_target, |
| 436 | 437 | => |index_and_bytes| { |
| 437 | try writer.print("{s} '", .{self.errStr()}); | |
| 438 | try list.print(gpa, "{s} '", .{self.errStr()}); | |
| 438 | 439 | if (self == .incomplete_target) { |
| 439 | 440 | const tmp = Token{ .target_must_resolve = index_and_bytes.bytes }; |
| 440 | try tmp.resolve(writer); | |
| 441 | try tmp.resolve(gpa, list); | |
| 441 | 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 | 447 | .invalid_target, |
| 447 | 448 | .bad_target_escape, |
| ... | ... | @@ -450,9 +451,9 @@ pub const Token = union(enum) { |
| 450 | 451 | .incomplete_escape, |
| 451 | 452 | .expected_colon, |
| 452 | 453 | => |index_and_char| { |
| 453 | try writer.writeAll("illegal char "); | |
| 454 | try printUnderstandableChar(writer, index_and_char.char); | |
| 455 | try writer.print(" at position {d}: {s}", .{ index_and_char.index, self.errStr() }); | |
| 454 | try list.appendSlice(gpa, "illegal char "); | |
| 455 | try printUnderstandableChar(gpa, list, index_and_char.char); | |
| 456 | try list.print(gpa, " at position {d}: {s}", .{ index_and_char.index, self.errStr() }); | |
| 456 | 457 | }, |
| 457 | 458 | } |
| 458 | 459 | } |
| ... | ... | @@ -1026,41 +1027,41 @@ fn depTokenizer(input: []const u8, expect: []const u8) !void { |
| 1026 | 1027 | defer arena_allocator.deinit(); |
| 1027 | 1028 | |
| 1028 | 1029 | var it: Tokenizer = .{ .bytes = input }; |
| 1029 | var buffer = std.ArrayList(u8).init(arena); | |
| 1030 | var resolve_buf = std.ArrayList(u8).init(arena); | |
| 1030 | var buffer: std.ArrayListUnmanaged(u8) = .empty; | |
| 1031 | var resolve_buf: std.ArrayListUnmanaged(u8) = .empty; | |
| 1031 | 1032 | var i: usize = 0; |
| 1032 | 1033 | while (it.next()) |token| { |
| 1033 | if (i != 0) try buffer.appendSlice("\n"); | |
| 1034 | if (i != 0) try buffer.appendSlice(arena, "\n"); | |
| 1034 | 1035 | switch (token) { |
| 1035 | 1036 | .target, .prereq => |bytes| { |
| 1036 | try buffer.appendSlice(@tagName(token)); | |
| 1037 | try buffer.appendSlice(" = {"); | |
| 1037 | try buffer.appendSlice(arena, @tagName(token)); | |
| 1038 | try buffer.appendSlice(arena, " = {"); | |
| 1038 | 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 | 1044 | .target_must_resolve => { |
| 1044 | try buffer.appendSlice("target = {"); | |
| 1045 | try token.resolve(resolve_buf.writer()); | |
| 1045 | try buffer.appendSlice(arena, "target = {"); | |
| 1046 | try token.resolve(arena, &resolve_buf); | |
| 1046 | 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 | 1050 | resolve_buf.items.len = 0; |
| 1050 | try buffer.appendSlice("}"); | |
| 1051 | try buffer.appendSlice(arena, "}"); | |
| 1051 | 1052 | }, |
| 1052 | 1053 | .prereq_must_resolve => { |
| 1053 | try buffer.appendSlice("prereq = {"); | |
| 1054 | try token.resolve(resolve_buf.writer()); | |
| 1054 | try buffer.appendSlice(arena, "prereq = {"); | |
| 1055 | try token.resolve(arena, &resolve_buf); | |
| 1055 | 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 | 1059 | resolve_buf.items.len = 0; |
| 1059 | try buffer.appendSlice("}"); | |
| 1060 | try buffer.appendSlice(arena, "}"); | |
| 1060 | 1061 | }, |
| 1061 | 1062 | else => { |
| 1062 | try buffer.appendSlice("ERROR: "); | |
| 1063 | try token.printError(buffer.writer()); | |
| 1063 | try buffer.appendSlice(arena, "ERROR: "); | |
| 1064 | try token.printError(arena, &buffer); | |
| 1064 | 1065 | break; |
| 1065 | 1066 | }, |
| 1066 | 1067 | } |
| ... | ... | @@ -1072,134 +1073,18 @@ fn depTokenizer(input: []const u8, expect: []const u8) !void { |
| 1072 | 1073 | return; |
| 1073 | 1074 | } |
| 1074 | 1075 | |
| 1075 | const out = std.io.getStdErr().writer(); | |
| 1076 | ||
| 1077 | try out.writeAll("\n"); | |
| 1078 | try printSection(out, "<<<< input", input); | |
| 1079 | try printSection(out, "==== expect", expect); | |
| 1080 | try printSection(out, ">>>> got", buffer.items); | |
| 1081 | try printRuler(out); | |
| 1082 | ||
| 1083 | try testing.expect(false); | |
| 1084 | } | |
| 1085 | ||
| 1086 | fn 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 | ||
| 1094 | fn 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 | ||
| 1106 | fn 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 | ||
| 1115 | fn hexDump(out: anytype, bytes: []const u8) !void { | |
| 1116 | const n16 = bytes.len >> 4; | |
| 1117 | var line: usize = 0; | |
| 1118 | var offset: usize = 0; | |
| 1119 | while (line < n16) : (line += 1) { | |
| 1120 | try hexDump16(out, offset, bytes[offset..][0..16]); | |
| 1121 | offset += 16; | |
| 1122 | } | |
| 1123 | ||
| 1124 | const n = bytes.len & 0x0f; | |
| 1125 | if (n > 0) { | |
| 1126 | try printDecValue(out, offset, 8); | |
| 1127 | try out.writeAll(":"); | |
| 1128 | try out.writeAll(" "); | |
| 1129 | const end1 = @min(offset + n, offset + 8); | |
| 1130 | for (bytes[offset..end1]) |b| { | |
| 1131 | try out.writeAll(" "); | |
| 1132 | try printHexValue(out, b, 2); | |
| 1133 | } | |
| 1134 | const end2 = offset + n; | |
| 1135 | if (end2 > end1) { | |
| 1136 | try out.writeAll(" "); | |
| 1137 | for (bytes[end1..end2]) |b| { | |
| 1138 | try out.writeAll(" "); | |
| 1139 | try printHexValue(out, b, 2); | |
| 1140 | } | |
| 1141 | } | |
| 1142 | const short = 16 - n; | |
| 1143 | var i: usize = 0; | |
| 1144 | while (i < short) : (i += 1) { | |
| 1145 | try out.writeAll(" "); | |
| 1146 | } | |
| 1147 | if (end2 > end1) { | |
| 1148 | try out.writeAll(" |"); | |
| 1149 | } else { | |
| 1150 | try out.writeAll(" |"); | |
| 1151 | } | |
| 1152 | try printCharValues(out, bytes[offset..end2]); | |
| 1153 | try out.writeAll("|\n"); | |
| 1154 | offset += n; | |
| 1155 | } | |
| 1156 | ||
| 1157 | try printDecValue(out, offset, 8); | |
| 1158 | try out.writeAll(":"); | |
| 1159 | try out.writeAll("\n"); | |
| 1076 | try testing.expectEqualStrings(expect, buffer.items); | |
| 1160 | 1077 | } |
| 1161 | 1078 | |
| 1162 | fn hexDump16(out: anytype, offset: usize, bytes: []const u8) !void { | |
| 1163 | try printDecValue(out, offset, 8); | |
| 1164 | try out.writeAll(":"); | |
| 1165 | try out.writeAll(" "); | |
| 1166 | for (bytes[0..8]) |b| { | |
| 1167 | try out.writeAll(" "); | |
| 1168 | try printHexValue(out, b, 2); | |
| 1169 | } | |
| 1170 | try out.writeAll(" "); | |
| 1171 | for (bytes[8..16]) |b| { | |
| 1172 | try out.writeAll(" "); | |
| 1173 | try printHexValue(out, b, 2); | |
| 1174 | } | |
| 1175 | try out.writeAll(" |"); | |
| 1176 | try printCharValues(out, bytes); | |
| 1177 | try out.writeAll("|\n"); | |
| 1178 | } | |
| 1179 | ||
| 1180 | fn 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 | ||
| 1186 | fn 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 | ||
| 1192 | fn printCharValues(out: anytype, bytes: []const u8) !void { | |
| 1193 | for (bytes) |b| { | |
| 1194 | try out.writeAll(&[_]u8{printable_char_tab[b]}); | |
| 1195 | } | |
| 1079 | fn printCharValues(gpa: Allocator, list: *std.ArrayListUnmanaged(u8), bytes: []const u8) !void { | |
| 1080 | for (bytes) |b| try list.append(gpa, printable_char_tab[b]); | |
| 1196 | 1081 | } |
| 1197 | 1082 | |
| 1198 | fn printUnderstandableChar(out: anytype, char: u8) !void { | |
| 1083 | fn printUnderstandableChar(gpa: Allocator, list: *std.ArrayListUnmanaged(u8), char: u8) !void { | |
| 1199 | 1084 | if (std.ascii.isPrint(char)) { |
| 1200 | try out.print("'{c}'", .{char}); | |
| 1085 | try list.print(gpa, "'{c}'", .{char}); | |
| 1201 | 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 | } |
| 1205 | 1090 |
lib/std/Build/Cache/Directory.zig+2-8| ... | ... | @@ -1,5 +1,6 @@ |
| 1 | 1 | const Directory = @This(); |
| 2 | 2 | const std = @import("../../std.zig"); |
| 3 | const assert = std.debug.assert; | |
| 3 | 4 | const fs = std.fs; |
| 4 | 5 | const fmt = std.fmt; |
| 5 | 6 | const Allocator = std.mem.Allocator; |
| ... | ... | @@ -55,14 +56,7 @@ pub fn closeAndFree(self: *Directory, gpa: Allocator) void { |
| 55 | 56 | self.* = undefined; |
| 56 | 57 | } |
| 57 | 58 | |
| 58 | pub fn format( | |
| 59 | self: Directory, | |
| 60 | comptime fmt_string: []const u8, | |
| 61 | options: fmt.FormatOptions, | |
| 62 | writer: anytype, | |
| 63 | ) !void { | |
| 64 | _ = options; | |
| 65 | if (fmt_string.len != 0) fmt.invalidFmtError(fmt_string, self); | |
| 59 | pub fn format(self: Directory, writer: *std.io.Writer) std.io.Writer.Error!void { | |
| 66 | 60 | if (self.path) |p| { |
| 67 | 61 | try writer.writeAll(p); |
| 68 | 62 | try writer.writeAll(fs.path.sep_str); |
lib/std/Build/Cache/Path.zig+39-34| ... | ... | @@ -1,3 +1,10 @@ |
| 1 | const Path = @This(); | |
| 2 | const std = @import("../../std.zig"); | |
| 3 | const assert = std.debug.assert; | |
| 4 | const fs = std.fs; | |
| 5 | const Allocator = std.mem.Allocator; | |
| 6 | const Cache = std.Build.Cache; | |
| 7 | ||
| 1 | 8 | root_dir: Cache.Directory, |
| 2 | 9 | /// The path, relative to the root dir, that this `Path` represents. |
| 3 | 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 | 140 | } |
| 134 | 141 | |
| 135 | 142 | pub 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 | } |
| 138 | 145 | |
| 139 | 146 | pub fn toStringZ(p: Path, allocator: Allocator) Allocator.Error![:0]u8 { |
| 140 | return std.fmt.allocPrintZ(allocator, "{}", .{p}); | |
| 141 | } | |
| 142 | ||
| 143 | pub fn format( | |
| 144 | self: Path, | |
| 145 | comptime fmt_string: []const u8, | |
| 146 | options: std.fmt.FormatOptions, | |
| 147 | writer: anytype, | |
| 148 | ) !void { | |
| 149 | if (fmt_string.len == 1) { | |
| 150 | // Quote-escape the string. | |
| 151 | const stringEscape = std.zig.stringEscape; | |
| 152 | const f = switch (fmt_string[0]) { | |
| 153 | 'q' => "", | |
| 154 | '\'' => "\'", | |
| 155 | else => @compileError("unsupported format string: " ++ fmt_string), | |
| 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; | |
| 147 | return std.fmt.allocPrintSentinel(allocator, "{f}", .{p}, 0); | |
| 148 | } | |
| 149 | ||
| 150 | pub fn fmtEscapeString(path: Path) std.fmt.Formatter(Path, formatEscapeString) { | |
| 151 | return .{ .data = path }; | |
| 152 | } | |
| 153 | ||
| 154 | pub fn formatEscapeString(path: Path, writer: *std.io.Writer) std.io.Writer.Error!void { | |
| 155 | if (path.root_dir.path) |p| { | |
| 156 | try std.zig.stringEscape(p, writer); | |
| 157 | if (path.sub_path.len > 0) try std.zig.stringEscape(fs.path.sep_str, writer); | |
| 165 | 158 | } |
| 166 | if (fmt_string.len > 0) | |
| 167 | std.fmt.invalidFmtError(fmt_string, self); | |
| 159 | if (path.sub_path.len > 0) { | |
| 160 | try std.zig.stringEscape(path.sub_path, writer); | |
| 161 | } | |
| 162 | } | |
| 163 | ||
| 164 | pub fn fmtEscapeChar(path: Path) std.fmt.Formatter(Path, formatEscapeChar) { | |
| 165 | return .{ .data = path }; | |
| 166 | } | |
| 167 | ||
| 168 | pub 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 | ||
| 178 | pub fn format(self: Path, writer: *std.io.Writer) std.io.Writer.Error!void { | |
| 168 | 179 | if (std.fs.path.isAbsolute(self.sub_path)) { |
| 169 | 180 | try writer.writeAll(self.sub_path); |
| 170 | 181 | return; |
| ... | ... | @@ -223,9 +234,3 @@ pub const TableAdapter = struct { |
| 223 | 234 | return a.eql(b); |
| 224 | 235 | } |
| 225 | 236 | }; |
| 226 | ||
| 227 | const Path = @This(); | |
| 228 | const std = @import("../../std.zig"); | |
| 229 | const fs = std.fs; | |
| 230 | const Allocator = std.mem.Allocator; | |
| 231 | const 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 | 112 | |
| 113 | 113 | fn rebuildTestsWorkerRunFallible(run: *Step.Run, ttyconf: std.io.tty.Config, parent_prog_node: std.Progress.Node) !void { |
| 114 | 114 | const gpa = run.step.owner.allocator; |
| 115 | const stderr = std.io.getStdErr(); | |
| 116 | 115 | |
| 117 | 116 | const compile = run.producer.?; |
| 118 | 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 | 124 | const show_stderr = compile.step.result_stderr.len > 0; |
| 126 | 125 | |
| 127 | 126 | if (show_error_msgs or show_compile_errors or show_stderr) { |
| 128 | std.debug.lockStdErr(); | |
| 129 | defer std.debug.unlockStdErr(); | |
| 130 | build_runner.printErrorMessages(gpa, &compile.step, .{ .ttyconf = ttyconf }, stderr, false) catch {}; | |
| 127 | var buf: [256]u8 = undefined; | |
| 128 | const w = std.debug.lockStderrWriter(&buf); | |
| 129 | defer std.debug.unlockStderrWriter(); | |
| 130 | build_runner.printErrorMessages(gpa, &compile.step, .{ .ttyconf = ttyconf }, w, false) catch {}; | |
| 131 | 131 | } |
| 132 | 132 | |
| 133 | 133 | const rebuilt_bin_path = result catch |err| switch (err) { |
| ... | ... | @@ -152,10 +152,10 @@ fn fuzzWorkerRun( |
| 152 | 152 | |
| 153 | 153 | run.rerunInFuzzMode(web_server, unit_test_index, prog_node) catch |err| switch (err) { |
| 154 | 154 | error.MakeFailed => { |
| 155 | const stderr = std.io.getStdErr(); | |
| 156 | std.debug.lockStdErr(); | |
| 157 | defer std.debug.unlockStdErr(); | |
| 158 | build_runner.printErrorMessages(gpa, &run.step, .{ .ttyconf = ttyconf }, stderr, false) catch {}; | |
| 155 | var buf: [256]u8 = undefined; | |
| 156 | const w = std.debug.lockStderrWriter(&buf); | |
| 157 | defer std.debug.unlockStderrWriter(); | |
| 158 | build_runner.printErrorMessages(gpa, &run.step, .{ .ttyconf = ttyconf }, w, false) catch {}; | |
| 159 | 159 | return; |
| 160 | 160 | }, |
| 161 | 161 | else => { |
lib/std/Build/Fuzz/WebServer.zig+9-9| ... | ... | @@ -170,7 +170,7 @@ fn serveFile( |
| 170 | 170 | // We load the file with every request so that the user can make changes to the file |
| 171 | 171 | // and refresh the HTML page without restarting this server. |
| 172 | 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 | 174 | return error.AlreadyReported; |
| 175 | 175 | }; |
| 176 | 176 | defer gpa.free(file_contents); |
| ... | ... | @@ -251,10 +251,10 @@ fn buildWasmBinary( |
| 251 | 251 | "-fsingle-threaded", // |
| 252 | 252 | "--dep", "Walk", // |
| 253 | 253 | "--dep", "html_render", // |
| 254 | try std.fmt.allocPrint(arena, "-Mroot={}", .{main_src_path}), // | |
| 255 | try std.fmt.allocPrint(arena, "-MWalk={}", .{walk_src_path}), // | |
| 254 | try std.fmt.allocPrint(arena, "-Mroot={f}", .{main_src_path}), // | |
| 255 | try std.fmt.allocPrint(arena, "-MWalk={f}", .{walk_src_path}), // | |
| 256 | 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 | 258 | "--listen=-", |
| 259 | 259 | }); |
| 260 | 260 | |
| ... | ... | @@ -526,7 +526,7 @@ fn serveSourcesTar(ws: *WebServer, request: *std.http.Server.Request) !void { |
| 526 | 526 | |
| 527 | 527 | for (deduped_paths) |joined_path| { |
| 528 | 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 | 530 | continue; |
| 531 | 531 | }; |
| 532 | 532 | defer file.close(); |
| ... | ... | @@ -604,7 +604,7 @@ fn prepareTables( |
| 604 | 604 | |
| 605 | 605 | const rebuilt_exe_path = run_step.rebuilt_executable.?; |
| 606 | 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 | 608 | run_step.step.name, rebuilt_exe_path, @errorName(err), |
| 609 | 609 | }); |
| 610 | 610 | return error.AlreadyReported; |
| ... | ... | @@ -616,7 +616,7 @@ fn prepareTables( |
| 616 | 616 | .sub_path = "v/" ++ std.fmt.hex(coverage_id), |
| 617 | 617 | }; |
| 618 | 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 | 620 | run_step.step.name, coverage_file_path, @errorName(err), |
| 621 | 621 | }); |
| 622 | 622 | return error.AlreadyReported; |
| ... | ... | @@ -624,7 +624,7 @@ fn prepareTables( |
| 624 | 624 | defer coverage_file.close(); |
| 625 | 625 | |
| 626 | 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 | 628 | return error.AlreadyReported; |
| 629 | 629 | }; |
| 630 | 630 | |
| ... | ... | @@ -636,7 +636,7 @@ fn prepareTables( |
| 636 | 636 | coverage_file.handle, |
| 637 | 637 | 0, |
| 638 | 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 | 640 | return error.AlreadyReported; |
| 641 | 641 | }; |
| 642 | 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 | 186 | .embed_path => |lazy_path| { |
| 187 | 187 | // Special case: this is a single arg. |
| 188 | 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 | 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 | 286 | } |
| 287 | 287 | |
| 288 | 288 | /// For debugging purposes, prints identifying information about this Step. |
| 289 | pub fn dump(step: *Step, file: std.fs.File) void { | |
| 290 | const w = file.writer(); | |
| 291 | const tty_config = std.io.tty.detectConfig(file); | |
| 289 | pub fn dump(step: *Step, w: *std.io.Writer, tty_config: std.io.tty.Config) void { | |
| 292 | 290 | const debug_info = std.debug.getSelfDebugInfo() catch |err| { |
| 293 | 291 | w.print("Unable to dump stack trace: Unable to open debug info: {s}\n", .{ |
| 294 | 292 | @errorName(err), |
| ... | ... | @@ -482,9 +480,9 @@ pub fn evalZigProcess( |
| 482 | 480 | pub fn installFile(s: *Step, src_lazy_path: Build.LazyPath, dest_path: []const u8) !std.fs.Dir.PrevStatus { |
| 483 | 481 | const b = s.owner; |
| 484 | 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 | 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 | 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 | 819 | switch (err) { |
| 822 | 820 | error.CacheCheckFailed => switch (man.diagnostic) { |
| 823 | 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 | 823 | @tagName(man.diagnostic), @errorName(e), |
| 826 | 824 | }), |
| 827 | 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 | const math = std.math; |
| 7 | 7 | const mem = std.mem; |
| 8 | 8 | const testing = std.testing; |
| 9 | const Writer = std.io.Writer; | |
| 9 | 10 | |
| 10 | 11 | const CheckObject = @This(); |
| 11 | 12 | |
| ... | ... | @@ -28,7 +29,7 @@ pub fn create( |
| 28 | 29 | const gpa = owner.allocator; |
| 29 | 30 | const check_object = gpa.create(CheckObject) catch @panic("OOM"); |
| 30 | 31 | check_object.* = .{ |
| 31 | .step = Step.init(.{ | |
| 32 | .step = .init(.{ | |
| 32 | 33 | .id = base_id, |
| 33 | 34 | .name = "CheckObject", |
| 34 | 35 | .owner = owner, |
| ... | ... | @@ -80,7 +81,7 @@ const Action = struct { |
| 80 | 81 | const hay = mem.trim(u8, haystack, " "); |
| 81 | 82 | const phrase = mem.trim(u8, act.phrase.resolve(b, step), " "); |
| 82 | 83 | |
| 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 | 85 | var hay_it = mem.tokenizeScalar(u8, hay, ' '); |
| 85 | 86 | var needle_it = mem.tokenizeScalar(u8, phrase, ' '); |
| 86 | 87 | |
| ... | ... | @@ -229,18 +230,11 @@ const ComputeCompareExpected = struct { |
| 229 | 230 | literal: u64, |
| 230 | 231 | }, |
| 231 | 232 | |
| 232 | pub fn format( | |
| 233 | value: @This(), | |
| 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)}); | |
| 233 | pub fn format(value: ComputeCompareExpected, w: *Writer) Writer.Error!void { | |
| 234 | try w.print("{t} ", .{value.op}); | |
| 241 | 235 | switch (value.value) { |
| 242 | .variable => |name| try writer.writeAll(name), | |
| 243 | .literal => |x| try writer.print("{x}", .{x}), | |
| 236 | .variable => |name| try w.writeAll(name), | |
| 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 | 559 | null, |
| 566 | 560 | .of(u64), |
| 567 | 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 | }); | |
| 569 | 565 | |
| 570 | var vars = std.StringHashMap(u64).init(gpa); | |
| 566 | var vars: std.StringHashMap(u64) = .init(gpa); | |
| 571 | 567 | for (check_object.checks.items) |chk| { |
| 572 | 568 | if (chk.kind == .compute_compare) { |
| 573 | 569 | assert(chk.actions.items.len == 1); |
| ... | ... | @@ -581,7 +577,7 @@ fn make(step: *Step, make_options: Step.MakeOptions) !void { |
| 581 | 577 | return step.fail( |
| 582 | 578 | \\ |
| 583 | 579 | \\========= comparison failed for action: =========== |
| 584 | \\{s} {} | |
| 580 | \\{s} {f} | |
| 585 | 581 | \\=================================================== |
| 586 | 582 | , .{ act.phrase.resolve(b, step), act.expected.? }); |
| 587 | 583 | } |
| ... | ... | @@ -600,7 +596,7 @@ fn make(step: *Step, make_options: Step.MakeOptions) !void { |
| 600 | 596 | // we either format message string with escaped codes, or not to aid debugging |
| 601 | 597 | // the failed test. |
| 602 | 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 | 600 | return .{ .data = .{ |
| 605 | 601 | .kind = kind, |
| 606 | 602 | .msg = msg, |
| ... | ... | @@ -612,17 +608,10 @@ fn make(step: *Step, make_options: Step.MakeOptions) !void { |
| 612 | 608 | msg: []const u8, |
| 613 | 609 | }; |
| 614 | 610 | |
| 615 | fn formatMessageString( | |
| 616 | ctx: Ctx, | |
| 617 | comptime unused_fmt_string: []const u8, | |
| 618 | options: std.fmt.FormatOptions, | |
| 619 | writer: anytype, | |
| 620 | ) !void { | |
| 621 | _ = unused_fmt_string; | |
| 622 | _ = options; | |
| 611 | fn formatMessageString(ctx: Ctx, w: *Writer) !void { | |
| 623 | 612 | switch (ctx.kind) { |
| 624 | .dump_section => try writer.print("{s}", .{std.fmt.fmtSliceEscapeLower(ctx.msg)}), | |
| 625 | else => try writer.writeAll(ctx.msg), | |
| 613 | .dump_section => try w.print("{f}", .{std.ascii.hexEscape(ctx.msg, .lower)}), | |
| 614 | else => try w.writeAll(ctx.msg), | |
| 626 | 615 | } |
| 627 | 616 | } |
| 628 | 617 | }.fmtMessageString; |
| ... | ... | @@ -637,11 +626,11 @@ fn make(step: *Step, make_options: Step.MakeOptions) !void { |
| 637 | 626 | return step.fail( |
| 638 | 627 | \\ |
| 639 | 628 | \\========= expected to find: ========================== |
| 640 | \\{s} | |
| 629 | \\{f} | |
| 641 | 630 | \\========= but parsed file does not contain it: ======= |
| 642 | \\{s} | |
| 631 | \\{f} | |
| 643 | 632 | \\========= file path: ================================= |
| 644 | \\{} | |
| 633 | \\{f} | |
| 645 | 634 | , .{ |
| 646 | 635 | fmtMessageString(chk.kind, act.phrase.resolve(b, step)), |
| 647 | 636 | fmtMessageString(chk.kind, output), |
| ... | ... | @@ -657,11 +646,11 @@ fn make(step: *Step, make_options: Step.MakeOptions) !void { |
| 657 | 646 | return step.fail( |
| 658 | 647 | \\ |
| 659 | 648 | \\========= expected to find: ========================== |
| 660 | \\*{s}* | |
| 649 | \\*{f}* | |
| 661 | 650 | \\========= but parsed file does not contain it: ======= |
| 662 | \\{s} | |
| 651 | \\{f} | |
| 663 | 652 | \\========= file path: ================================= |
| 664 | \\{} | |
| 653 | \\{f} | |
| 665 | 654 | , .{ |
| 666 | 655 | fmtMessageString(chk.kind, act.phrase.resolve(b, step)), |
| 667 | 656 | fmtMessageString(chk.kind, output), |
| ... | ... | @@ -676,11 +665,11 @@ fn make(step: *Step, make_options: Step.MakeOptions) !void { |
| 676 | 665 | return step.fail( |
| 677 | 666 | \\ |
| 678 | 667 | \\========= expected not to find: =================== |
| 679 | \\{s} | |
| 668 | \\{f} | |
| 680 | 669 | \\========= but parsed file does contain it: ======== |
| 681 | \\{s} | |
| 670 | \\{f} | |
| 682 | 671 | \\========= file path: ============================== |
| 683 | \\{} | |
| 672 | \\{f} | |
| 684 | 673 | , .{ |
| 685 | 674 | fmtMessageString(chk.kind, act.phrase.resolve(b, step)), |
| 686 | 675 | fmtMessageString(chk.kind, output), |
| ... | ... | @@ -696,13 +685,13 @@ fn make(step: *Step, make_options: Step.MakeOptions) !void { |
| 696 | 685 | return step.fail( |
| 697 | 686 | \\ |
| 698 | 687 | \\========= expected to find and extract: ============== |
| 699 | \\{s} | |
| 688 | \\{f} | |
| 700 | 689 | \\========= but parsed file does not contain it: ======= |
| 701 | \\{s} | |
| 690 | \\{f} | |
| 702 | 691 | \\========= file path: ============================== |
| 703 | \\{} | |
| 692 | \\{f} | |
| 704 | 693 | , .{ |
| 705 | act.phrase.resolve(b, step), | |
| 694 | fmtMessageString(chk.kind, act.phrase.resolve(b, step)), | |
| 706 | 695 | fmtMessageString(chk.kind, output), |
| 707 | 696 | src_path, |
| 708 | 697 | }); |
| ... | ... | @@ -963,7 +952,7 @@ const MachODumper = struct { |
| 963 | 952 | .UUID => { |
| 964 | 953 | const uuid = lc.cast(macho.uuid_command).?; |
| 965 | 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 | }, |
| 968 | 957 | |
| 969 | 958 | .DATA_IN_CODE, |
| ... | ... | @@ -2012,7 +2001,7 @@ const ElfDumper = struct { |
| 2012 | 2001 | |
| 2013 | 2002 | for (ctx.phdrs, 0..) |phdr, phndx| { |
| 2014 | 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 | 2005 | try writer.print("vaddr {x}\n", .{phdr.p_vaddr}); |
| 2017 | 2006 | try writer.print("paddr {x}\n", .{phdr.p_paddr}); |
| 2018 | 2007 | try writer.print("offset {x}\n", .{phdr.p_offset}); |
| ... | ... | @@ -2052,7 +2041,7 @@ const ElfDumper = struct { |
| 2052 | 2041 | for (ctx.shdrs, 0..) |shdr, shndx| { |
| 2053 | 2042 | try writer.print("shdr {d}\n", .{shndx}); |
| 2054 | 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 | 2045 | try writer.print("addr {x}\n", .{shdr.sh_addr}); |
| 2057 | 2046 | try writer.print("offset {x}\n", .{shdr.sh_offset}); |
| 2058 | 2047 | try writer.print("size {x}\n", .{shdr.sh_size}); |
| ... | ... | @@ -2325,18 +2314,11 @@ const ElfDumper = struct { |
| 2325 | 2314 | return mem.sliceTo(@as([*:0]const u8, @ptrCast(strtab.ptr + off)), 0); |
| 2326 | 2315 | } |
| 2327 | 2316 | |
| 2328 | fn fmtShType(sh_type: u32) std.fmt.Formatter(formatShType) { | |
| 2317 | fn fmtShType(sh_type: u32) std.fmt.Formatter(u32, formatShType) { | |
| 2329 | 2318 | return .{ .data = sh_type }; |
| 2330 | 2319 | } |
| 2331 | 2320 | |
| 2332 | fn formatShType( | |
| 2333 | sh_type: u32, | |
| 2334 | comptime unused_fmt_string: []const u8, | |
| 2335 | options: std.fmt.FormatOptions, | |
| 2336 | writer: anytype, | |
| 2337 | ) !void { | |
| 2338 | _ = unused_fmt_string; | |
| 2339 | _ = options; | |
| 2321 | fn formatShType(sh_type: u32, writer: *Writer) Writer.Error!void { | |
| 2340 | 2322 | const name = switch (sh_type) { |
| 2341 | 2323 | elf.SHT_NULL => "NULL", |
| 2342 | 2324 | elf.SHT_PROGBITS => "PROGBITS", |
| ... | ... | @@ -2372,18 +2354,11 @@ const ElfDumper = struct { |
| 2372 | 2354 | try writer.writeAll(name); |
| 2373 | 2355 | } |
| 2374 | 2356 | |
| 2375 | fn fmtPhType(ph_type: u32) std.fmt.Formatter(formatPhType) { | |
| 2357 | fn fmtPhType(ph_type: u32) std.fmt.Formatter(u32, formatPhType) { | |
| 2376 | 2358 | return .{ .data = ph_type }; |
| 2377 | 2359 | } |
| 2378 | 2360 | |
| 2379 | fn formatPhType( | |
| 2380 | ph_type: u32, | |
| 2381 | comptime unused_fmt_string: []const u8, | |
| 2382 | options: std.fmt.FormatOptions, | |
| 2383 | writer: anytype, | |
| 2384 | ) !void { | |
| 2385 | _ = unused_fmt_string; | |
| 2386 | _ = options; | |
| 2361 | fn formatPhType(ph_type: u32, writer: *Writer) Writer.Error!void { | |
| 2387 | 2362 | const p_type = switch (ph_type) { |
| 2388 | 2363 | elf.PT_NULL => "NULL", |
| 2389 | 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 | 409 | .linkage = options.linkage, |
| 410 | 410 | .kind = options.kind, |
| 411 | 411 | .name = name, |
| 412 | .step = Step.init(.{ | |
| 412 | .step = .init(.{ | |
| 413 | 413 | .id = base_id, |
| 414 | 414 | .name = step_name, |
| 415 | 415 | .owner = owner, |
| ... | ... | @@ -1017,20 +1017,16 @@ fn getGeneratedFilePath(compile: *Compile, comptime tag_name: []const u8, asking |
| 1017 | 1017 | const maybe_path: ?*GeneratedFile = @field(compile, tag_name); |
| 1018 | 1018 | |
| 1019 | 1019 | const generated_file = maybe_path orelse { |
| 1020 | std.debug.lockStdErr(); | |
| 1021 | const stderr = std.io.getStdErr(); | |
| 1022 | ||
| 1023 | std.Build.dumpBadGetPathHelp(&compile.step, stderr, compile.step.owner, asking_step) catch {}; | |
| 1024 | ||
| 1020 | const w = std.debug.lockStderrWriter(&.{}); | |
| 1021 | std.Build.dumpBadGetPathHelp(&compile.step, w, .detect(.stderr()), compile.step.owner, asking_step) catch {}; | |
| 1022 | std.debug.unlockStderrWriter(); | |
| 1025 | 1023 | @panic("missing emit option for " ++ tag_name); |
| 1026 | 1024 | }; |
| 1027 | 1025 | |
| 1028 | 1026 | const path = generated_file.path orelse { |
| 1029 | std.debug.lockStdErr(); | |
| 1030 | const stderr = std.io.getStdErr(); | |
| 1031 | ||
| 1032 | std.Build.dumpBadGetPathHelp(&compile.step, stderr, compile.step.owner, asking_step) catch {}; | |
| 1033 | ||
| 1027 | const w = std.debug.lockStderrWriter(&.{}); | |
| 1028 | std.Build.dumpBadGetPathHelp(&compile.step, w, .detect(.stderr()), compile.step.owner, asking_step) catch {}; | |
| 1029 | std.debug.unlockStderrWriter(); | |
| 1034 | 1030 | @panic(tag_name ++ " is null. Is there a missing step dependency?"); |
| 1035 | 1031 | }; |
| 1036 | 1032 | |
| ... | ... | @@ -1542,7 +1538,7 @@ fn getZigArgs(compile: *Compile, fuzz: bool) ![][]const u8 { |
| 1542 | 1538 | if (compile.kind == .lib and compile.linkage != null and compile.linkage.? == .dynamic) { |
| 1543 | 1539 | if (compile.version) |version| { |
| 1544 | 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 | } |
| 1547 | 1543 | |
| 1548 | 1544 | if (compile.rootModuleTarget().os.tag.isDarwin()) { |
| ... | ... | @@ -1696,9 +1692,7 @@ fn getZigArgs(compile: *Compile, fuzz: bool) ![][]const u8 { |
| 1696 | 1692 | |
| 1697 | 1693 | if (compile.build_id orelse b.build_id) |build_id| { |
| 1698 | 1694 | try zig_args.append(switch (build_id) { |
| 1699 | .hexstring => |hs| b.fmt("--build-id=0x{s}", .{ | |
| 1700 | std.fmt.fmtSliceHexLower(hs.toSlice()), | |
| 1701 | }), | |
| 1695 | .hexstring => |hs| b.fmt("--build-id=0x{x}", .{hs.toSlice()}), | |
| 1702 | 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 | 1700 | const opt_zig_lib_dir = if (compile.zig_lib_dir) |dir| |
| 1707 | 1701 | dir.getPath2(b, step) |
| 1708 | 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 | 1704 | else |
| 1711 | 1705 | null; |
| 1712 | 1706 | |
| ... | ... | @@ -1746,8 +1740,7 @@ fn getZigArgs(compile: *Compile, fuzz: bool) ![][]const u8 { |
| 1746 | 1740 | } |
| 1747 | 1741 | |
| 1748 | 1742 | if (compile.error_limit) |err_limit| try zig_args.appendSlice(&.{ |
| 1749 | "--error-limit", | |
| 1750 | b.fmt("{}", .{err_limit}), | |
| 1743 | "--error-limit", b.fmt("{d}", .{err_limit}), | |
| 1751 | 1744 | }); |
| 1752 | 1745 | |
| 1753 | 1746 | try addFlag(&zig_args, "incremental", b.graph.incremental); |
| ... | ... | @@ -1771,12 +1764,12 @@ fn getZigArgs(compile: *Compile, fuzz: bool) ![][]const u8 { |
| 1771 | 1764 | for (arg, 0..) |c, arg_idx| { |
| 1772 | 1765 | if (c == '\\' or c == '"') { |
| 1773 | 1766 | // 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); | |
| 1775 | const writer = escaped.writer(); | |
| 1776 | try writer.writeAll(arg[0..arg_idx]); | |
| 1767 | var escaped: std.ArrayListUnmanaged(u8) = .empty; | |
| 1768 | try escaped.ensureTotalCapacityPrecise(arena, arg.len + 1); | |
| 1769 | try escaped.appendSlice(arena, arg[0..arg_idx]); | |
| 1777 | 1770 | for (arg[arg_idx..]) |to_escape| { |
| 1778 | if (to_escape == '\\' or to_escape == '"') try writer.writeByte('\\'); | |
| 1779 | try writer.writeByte(to_escape); | |
| 1771 | if (to_escape == '\\' or to_escape == '"') try escaped.append(arena, '\\'); | |
| 1772 | try escaped.append(arena, to_escape); | |
| 1780 | 1773 | } |
| 1781 | 1774 | escaped_args.appendAssumeCapacity(escaped.items); |
| 1782 | 1775 | continue :arg_blk; |
| ... | ... | @@ -1793,11 +1786,7 @@ fn getZigArgs(compile: *Compile, fuzz: bool) ![][]const u8 { |
| 1793 | 1786 | var args_hash: [Sha256.digest_length]u8 = undefined; |
| 1794 | 1787 | Sha256.hash(args, &args_hash, .{}); |
| 1795 | 1788 | var args_hex_hash: [Sha256.digest_length * 2]u8 = undefined; |
| 1796 | _ = try std.fmt.bufPrint( | |
| 1797 | &args_hex_hash, | |
| 1798 | "{s}", | |
| 1799 | .{std.fmt.fmtSliceHexLower(&args_hash)}, | |
| 1800 | ); | |
| 1789 | _ = try std.fmt.bufPrint(&args_hex_hash, "{x}", .{&args_hash}); | |
| 1801 | 1790 | |
| 1802 | 1791 | const args_file = "args" ++ fs.path.sep_str ++ args_hex_hash; |
| 1803 | 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 | 1825 | // Update generated files |
| 1837 | 1826 | if (maybe_output_dir) |output_dir| { |
| 1838 | 1827 | if (compile.emit_directory) |lp| { |
| 1839 | lp.path = b.fmt("{}", .{output_dir}); | |
| 1828 | lp.path = b.fmt("{f}", .{output_dir}); | |
| 1840 | 1829 | } |
| 1841 | 1830 | |
| 1842 | 1831 | // zig fmt: off |
| ... | ... | @@ -1970,20 +1959,23 @@ fn addFlag(args: *ArrayList([]const u8), comptime name: []const u8, opt: ?bool) |
| 1970 | 1959 | fn checkCompileErrors(compile: *Compile) !void { |
| 1971 | 1960 | // Clear this field so that it does not get printed by the build runner. |
| 1972 | 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; | |
| 1974 | 1963 | |
| 1975 | 1964 | const arena = compile.step.owner.allocator; |
| 1976 | 1965 | |
| 1977 | var actual_errors_list = std.ArrayList(u8).init(arena); | |
| 1978 | try actual_eb.renderToWriter(.{ | |
| 1979 | .ttyconf = .no_color, | |
| 1980 | .include_reference_trace = false, | |
| 1981 | .include_source_line = false, | |
| 1982 | }, actual_errors_list.writer()); | |
| 1983 | const actual_errors = try actual_errors_list.toOwnedSlice(); | |
| 1966 | const actual_errors = ae: { | |
| 1967 | var aw: std.io.Writer.Allocating = .init(arena); | |
| 1968 | defer aw.deinit(); | |
| 1969 | try actual_eb.renderToWriter(.{ | |
| 1970 | .ttyconf = .no_color, | |
| 1971 | .include_reference_trace = false, | |
| 1972 | .include_source_line = false, | |
| 1973 | }, &aw.writer); | |
| 1974 | break :ae try aw.toOwnedSlice(); | |
| 1975 | }; | |
| 1984 | 1976 | |
| 1985 | 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 | 1979 | const expect_errors = compile.expect_errors.?; |
| 1988 | 1980 | |
| 1989 | 1981 | var actual_line_it = mem.splitScalar(u8, actual_errors, '\n'); |
| ... | ... | @@ -2042,17 +2034,17 @@ fn checkCompileErrors(compile: *Compile) !void { |
| 2042 | 2034 | .exact => |expect_lines| { |
| 2043 | 2035 | for (expect_lines) |expect_line| { |
| 2044 | 2036 | const actual_line = actual_line_it.next() orelse { |
| 2045 | try expected_generated.appendSlice(expect_line); | |
| 2046 | try expected_generated.append('\n'); | |
| 2037 | try expected_generated.appendSlice(arena, expect_line); | |
| 2038 | try expected_generated.append(arena, '\n'); | |
| 2047 | 2039 | continue; |
| 2048 | 2040 | }; |
| 2049 | 2041 | if (matchCompileError(actual_line, expect_line)) { |
| 2050 | try expected_generated.appendSlice(actual_line); | |
| 2051 | try expected_generated.append('\n'); | |
| 2042 | try expected_generated.appendSlice(arena, actual_line); | |
| 2043 | try expected_generated.append(arena, '\n'); | |
| 2052 | 2044 | continue; |
| 2053 | 2045 | } |
| 2054 | try expected_generated.appendSlice(expect_line); | |
| 2055 | try expected_generated.append('\n'); | |
| 2046 | try expected_generated.appendSlice(arena, expect_line); | |
| 2047 | try expected_generated.append(arena, '\n'); | |
| 2056 | 2048 | } |
| 2057 | 2049 | |
| 2058 | 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 | 2 | const ConfigHeader = @This(); |
| 3 | 3 | const Step = std.Build.Step; |
| 4 | 4 | const Allocator = std.mem.Allocator; |
| 5 | const Writer = std.io.Writer; | |
| 5 | 6 | |
| 6 | 7 | pub const Style = union(enum) { |
| 7 | 8 | /// 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 | 88 | owner.fmt("configure {s} header to {s}", .{ @tagName(options.style), include_path }); |
| 88 | 89 | |
| 89 | 90 | config_header.* = .{ |
| 90 | .step = Step.init(.{ | |
| 91 | .step = .init(.{ | |
| 91 | 92 | .id = base_id, |
| 92 | 93 | .name = name, |
| 93 | 94 | .owner = owner, |
| ... | ... | @@ -95,7 +96,7 @@ pub fn create(owner: *std.Build, options: Options) *ConfigHeader { |
| 95 | 96 | .first_ret_addr = options.first_ret_addr orelse @returnAddress(), |
| 96 | 97 | }), |
| 97 | 98 | .style = options.style, |
| 98 | .values = std.StringArrayHashMap(Value).init(owner.allocator), | |
| 99 | .values = .init(owner.allocator), | |
| 99 | 100 | |
| 100 | 101 | .max_bytes = options.max_bytes, |
| 101 | 102 | .include_path = include_path, |
| ... | ... | @@ -195,8 +196,9 @@ fn make(step: *Step, options: Step.MakeOptions) !void { |
| 195 | 196 | man.hash.addBytes(config_header.include_path); |
| 196 | 197 | man.hash.addOptionalBytes(config_header.include_guard_override); |
| 197 | 198 | |
| 198 | var output = std.ArrayList(u8).init(gpa); | |
| 199 | defer output.deinit(); | |
| 199 | var aw: std.io.Writer.Allocating = .init(gpa); | |
| 200 | defer aw.deinit(); | |
| 201 | const bw = &aw.writer; | |
| 200 | 202 | |
| 201 | 203 | const header_text = "This file was generated by ConfigHeader using the Zig Build System."; |
| 202 | 204 | const c_generated_line = "/* " ++ header_text ++ " */\n"; |
| ... | ... | @@ -204,7 +206,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void { |
| 204 | 206 | |
| 205 | 207 | switch (config_header.style) { |
| 206 | 208 | .autoconf_undef, .autoconf, .autoconf_at => |file_source| { |
| 207 | try output.appendSlice(c_generated_line); | |
| 209 | try bw.writeAll(c_generated_line); | |
| 208 | 210 | const src_path = file_source.getPath2(b, step); |
| 209 | 211 | const contents = std.fs.cwd().readFileAlloc(arena, src_path, config_header.max_bytes) catch |err| { |
| 210 | 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 | 214 | }); |
| 213 | 215 | }; |
| 214 | 216 | switch (config_header.style) { |
| 215 | .autoconf_undef, .autoconf => try render_autoconf_undef(step, contents, &output, config_header.values, src_path), | |
| 216 | .autoconf_at => try render_autoconf_at(step, contents, &output, config_header.values, src_path), | |
| 217 | .autoconf_undef, .autoconf => try render_autoconf_undef(step, contents, bw, config_header.values, src_path), | |
| 218 | .autoconf_at => try render_autoconf_at(step, contents, &aw, config_header.values, src_path), | |
| 217 | 219 | else => unreachable, |
| 218 | 220 | } |
| 219 | 221 | }, |
| 220 | 222 | .cmake => |file_source| { |
| 221 | try output.appendSlice(c_generated_line); | |
| 223 | try bw.writeAll(c_generated_line); | |
| 222 | 224 | const src_path = file_source.getPath2(b, step); |
| 223 | 225 | const contents = std.fs.cwd().readFileAlloc(arena, src_path, config_header.max_bytes) catch |err| { |
| 224 | 226 | return step.fail("unable to read cmake input file '{s}': {s}", .{ |
| 225 | 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 | 232 | .blank => { |
| 231 | try output.appendSlice(c_generated_line); | |
| 232 | try render_blank(&output, config_header.values, config_header.include_path, config_header.include_guard_override); | |
| 233 | try bw.writeAll(c_generated_line); | |
| 234 | try render_blank(gpa, bw, config_header.values, config_header.include_path, config_header.include_guard_override); | |
| 233 | 235 | }, |
| 234 | 236 | .nasm => { |
| 235 | try output.appendSlice(asm_generated_line); | |
| 236 | try render_nasm(&output, config_header.values); | |
| 237 | try bw.writeAll(asm_generated_line); | |
| 238 | try render_nasm(bw, config_header.values); | |
| 237 | 239 | }, |
| 238 | 240 | } |
| 239 | 241 | |
| 240 | man.hash.addBytes(output.items); | |
| 242 | const output = aw.getWritten(); | |
| 243 | man.hash.addBytes(output); | |
| 241 | 244 | |
| 242 | 245 | if (try step.cacheHit(&man)) { |
| 243 | 246 | const digest = man.final(); |
| ... | ... | @@ -256,13 +259,13 @@ fn make(step: *Step, options: Step.MakeOptions) !void { |
| 256 | 259 | const sub_path_dirname = std.fs.path.dirname(sub_path).?; |
| 257 | 260 | |
| 258 | 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 | 263 | b.cache_root, sub_path_dirname, @errorName(err), |
| 261 | 264 | }); |
| 262 | 265 | }; |
| 263 | 266 | |
| 264 | b.cache_root.handle.writeFile(.{ .sub_path = sub_path, .data = output.items }) catch |err| { | |
| 265 | return step.fail("unable to write file '{}{s}': {s}", .{ | |
| 267 | b.cache_root.handle.writeFile(.{ .sub_path = sub_path, .data = output }) catch |err| { | |
| 268 | return step.fail("unable to write file '{f}{s}': {s}", .{ | |
| 266 | 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 | 277 | fn render_autoconf_undef( |
| 275 | 278 | step: *Step, |
| 276 | 279 | contents: []const u8, |
| 277 | output: *std.ArrayList(u8), | |
| 280 | bw: *Writer, | |
| 278 | 281 | values: std.StringArrayHashMap(Value), |
| 279 | 282 | src_path: []const u8, |
| 280 | 283 | ) !void { |
| ... | ... | @@ -289,15 +292,15 @@ fn render_autoconf_undef( |
| 289 | 292 | var line_it = std.mem.splitScalar(u8, contents, '\n'); |
| 290 | 293 | while (line_it.next()) |line| : (line_index += 1) { |
| 291 | 294 | if (!std.mem.startsWith(u8, line, "#")) { |
| 292 | try output.appendSlice(line); | |
| 293 | try output.appendSlice("\n"); | |
| 295 | try bw.writeAll(line); | |
| 296 | try bw.writeByte('\n'); | |
| 294 | 297 | continue; |
| 295 | 298 | } |
| 296 | 299 | var it = std.mem.tokenizeAny(u8, line[1..], " \t\r"); |
| 297 | 300 | const undef = it.next().?; |
| 298 | 301 | if (!std.mem.eql(u8, undef, "undef")) { |
| 299 | try output.appendSlice(line); | |
| 300 | try output.appendSlice("\n"); | |
| 302 | try bw.writeAll(line); | |
| 303 | try bw.writeByte('\n'); | |
| 301 | 304 | continue; |
| 302 | 305 | } |
| 303 | 306 | const name = it.next().?; |
| ... | ... | @@ -309,7 +312,7 @@ fn render_autoconf_undef( |
| 309 | 312 | continue; |
| 310 | 313 | }; |
| 311 | 314 | is_used.set(index); |
| 312 | try renderValueC(output, name, values.values()[index]); | |
| 315 | try renderValueC(bw, name, values.values()[index]); | |
| 313 | 316 | } |
| 314 | 317 | |
| 315 | 318 | var unused_value_it = is_used.iterator(.{ .kind = .unset }); |
| ... | ... | @@ -326,12 +329,13 @@ fn render_autoconf_undef( |
| 326 | 329 | fn render_autoconf_at( |
| 327 | 330 | step: *Step, |
| 328 | 331 | contents: []const u8, |
| 329 | output: *std.ArrayList(u8), | |
| 332 | aw: *std.io.Writer.Allocating, | |
| 330 | 333 | values: std.StringArrayHashMap(Value), |
| 331 | 334 | src_path: []const u8, |
| 332 | 335 | ) !void { |
| 333 | 336 | const build = step.owner; |
| 334 | 337 | const allocator = build.allocator; |
| 338 | const bw = &aw.writer; | |
| 335 | 339 | |
| 336 | 340 | const used = allocator.alloc(bool, values.count()) catch @panic("OOM"); |
| 337 | 341 | for (used) |*u| u.* = false; |
| ... | ... | @@ -343,11 +347,11 @@ fn render_autoconf_at( |
| 343 | 347 | while (line_it.next()) |line| : (line_index += 1) { |
| 344 | 348 | const last_line = line_it.index == line_it.buffer.len; |
| 345 | 349 | |
| 346 | const old_len = output.items.len; | |
| 347 | expand_variables_autoconf_at(output, line, values, used) catch |err| switch (err) { | |
| 350 | const old_len = aw.getWritten().len; | |
| 351 | expand_variables_autoconf_at(bw, line, values, used) catch |err| switch (err) { | |
| 348 | 352 | error.MissingValue => { |
| 349 | const name = output.items[old_len..]; | |
| 350 | defer output.shrinkRetainingCapacity(old_len); | |
| 353 | const name = aw.getWritten()[old_len..]; | |
| 354 | defer aw.shrinkRetainingCapacity(old_len); | |
| 351 | 355 | try step.addError("{s}:{d}: error: unspecified config header value: '{s}'", .{ |
| 352 | 356 | src_path, line_index + 1, name, |
| 353 | 357 | }); |
| ... | ... | @@ -362,9 +366,7 @@ fn render_autoconf_at( |
| 362 | 366 | continue; |
| 363 | 367 | }, |
| 364 | 368 | }; |
| 365 | if (!last_line) { | |
| 366 | try output.append('\n'); | |
| 367 | } | |
| 369 | if (!last_line) try bw.writeByte('\n'); | |
| 368 | 370 | } |
| 369 | 371 | |
| 370 | 372 | for (values.unmanaged.entries.slice().items(.key), used) |name, u| { |
| ... | ... | @@ -374,15 +376,13 @@ fn render_autoconf_at( |
| 374 | 376 | } |
| 375 | 377 | } |
| 376 | 378 | |
| 377 | if (any_errors) { | |
| 378 | return error.MakeFailed; | |
| 379 | } | |
| 379 | if (any_errors) return error.MakeFailed; | |
| 380 | 380 | } |
| 381 | 381 | |
| 382 | 382 | fn render_cmake( |
| 383 | 383 | step: *Step, |
| 384 | 384 | contents: []const u8, |
| 385 | output: *std.ArrayList(u8), | |
| 385 | bw: *Writer, | |
| 386 | 386 | values: std.StringArrayHashMap(Value), |
| 387 | 387 | src_path: []const u8, |
| 388 | 388 | ) !void { |
| ... | ... | @@ -417,10 +417,8 @@ fn render_cmake( |
| 417 | 417 | defer allocator.free(line); |
| 418 | 418 | |
| 419 | 419 | if (!std.mem.startsWith(u8, line, "#")) { |
| 420 | try output.appendSlice(line); | |
| 421 | if (!last_line) { | |
| 422 | try output.appendSlice("\n"); | |
| 423 | } | |
| 420 | try bw.writeAll(line); | |
| 421 | if (!last_line) try bw.writeByte('\n'); | |
| 424 | 422 | continue; |
| 425 | 423 | } |
| 426 | 424 | var it = std.mem.tokenizeAny(u8, line[1..], " \t\r"); |
| ... | ... | @@ -428,10 +426,8 @@ fn render_cmake( |
| 428 | 426 | if (!std.mem.eql(u8, cmakedefine, "cmakedefine") and |
| 429 | 427 | !std.mem.eql(u8, cmakedefine, "cmakedefine01")) |
| 430 | 428 | { |
| 431 | try output.appendSlice(line); | |
| 432 | if (!last_line) { | |
| 433 | try output.appendSlice("\n"); | |
| 434 | } | |
| 429 | try bw.writeAll(line); | |
| 430 | if (!last_line) try bw.writeByte('\n'); | |
| 435 | 431 | continue; |
| 436 | 432 | } |
| 437 | 433 | |
| ... | ... | @@ -502,7 +498,7 @@ fn render_cmake( |
| 502 | 498 | value = Value{ .ident = it.rest() }; |
| 503 | 499 | } |
| 504 | 500 | |
| 505 | try renderValueC(output, name, value); | |
| 501 | try renderValueC(bw, name, value); | |
| 506 | 502 | } |
| 507 | 503 | |
| 508 | 504 | if (any_errors) { |
| ... | ... | @@ -511,13 +507,14 @@ fn render_cmake( |
| 511 | 507 | } |
| 512 | 508 | |
| 513 | 509 | fn render_blank( |
| 514 | output: *std.ArrayList(u8), | |
| 510 | gpa: std.mem.Allocator, | |
| 511 | bw: *Writer, | |
| 515 | 512 | defines: std.StringArrayHashMap(Value), |
| 516 | 513 | include_path: []const u8, |
| 517 | 514 | include_guard_override: ?[]const u8, |
| 518 | 515 | ) !void { |
| 519 | 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 | 518 | for (name) |*byte| { |
| 522 | 519 | switch (byte.*) { |
| 523 | 520 | 'a'...'z' => byte.* = byte.* - 'a' + 'A', |
| ... | ... | @@ -527,92 +524,53 @@ fn render_blank( |
| 527 | 524 | } |
| 528 | 525 | break :blk name; |
| 529 | 526 | }; |
| 527 | defer if (include_guard_override == null) gpa.free(include_guard_name); | |
| 530 | 528 | |
| 531 | try output.appendSlice("#ifndef "); | |
| 532 | try output.appendSlice(include_guard_name); | |
| 533 | try output.appendSlice("\n#define "); | |
| 534 | try output.appendSlice(include_guard_name); | |
| 535 | try output.appendSlice("\n"); | |
| 529 | try bw.print( | |
| 530 | \\#ifndef {[0]s} | |
| 531 | \\#define {[0]s} | |
| 532 | \\ | |
| 533 | , .{include_guard_name}); | |
| 536 | 534 | |
| 537 | 535 | const values = defines.values(); |
| 538 | for (defines.keys(), 0..) |name, i| { | |
| 539 | try renderValueC(output, name, values[i]); | |
| 540 | } | |
| 536 | for (defines.keys(), 0..) |name, i| try renderValueC(bw, name, values[i]); | |
| 541 | 537 | |
| 542 | try output.appendSlice("#endif /* "); | |
| 543 | try output.appendSlice(include_guard_name); | |
| 544 | try output.appendSlice(" */\n"); | |
| 538 | try bw.print( | |
| 539 | \\#endif /* {s} */ | |
| 540 | \\ | |
| 541 | , .{include_guard_name}); | |
| 545 | 542 | } |
| 546 | 543 | |
| 547 | fn render_nasm(output: *std.ArrayList(u8), defines: std.StringArrayHashMap(Value)) !void { | |
| 548 | const values = defines.values(); | |
| 549 | for (defines.keys(), 0..) |name, i| { | |
| 550 | try renderValueNasm(output, name, values[i]); | |
| 551 | } | |
| 544 | fn render_nasm(bw: *Writer, defines: std.StringArrayHashMap(Value)) !void { | |
| 545 | for (defines.keys(), defines.values()) |name, value| try renderValueNasm(bw, name, value); | |
| 552 | 546 | } |
| 553 | 547 | |
| 554 | fn renderValueC(output: *std.ArrayList(u8), name: []const u8, value: Value) !void { | |
| 548 | fn renderValueC(bw: *Writer, name: []const u8, value: Value) !void { | |
| 555 | 549 | switch (value) { |
| 556 | .undef => { | |
| 557 | try output.appendSlice("/* #undef "); | |
| 558 | try output.appendSlice(name); | |
| 559 | try output.appendSlice(" */\n"); | |
| 560 | }, | |
| 561 | .defined => { | |
| 562 | try output.appendSlice("#define "); | |
| 563 | try output.appendSlice(name); | |
| 564 | try output.appendSlice("\n"); | |
| 565 | }, | |
| 566 | .boolean => |b| { | |
| 567 | try output.appendSlice("#define "); | |
| 568 | try output.appendSlice(name); | |
| 569 | try output.appendSlice(if (b) " 1\n" else " 0\n"); | |
| 570 | }, | |
| 571 | .int => |i| { | |
| 572 | try output.writer().print("#define {s} {d}\n", .{ name, i }); | |
| 573 | }, | |
| 574 | .ident => |ident| { | |
| 575 | try output.writer().print("#define {s} {s}\n", .{ name, ident }); | |
| 576 | }, | |
| 577 | .string => |string| { | |
| 578 | // TODO: use C-specific escaping instead of zig string literals | |
| 579 | try output.writer().print("#define {s} \"{}\"\n", .{ name, std.zig.fmtEscapes(string) }); | |
| 580 | }, | |
| 550 | .undef => try bw.print("/* #undef {s} */\n", .{name}), | |
| 551 | .defined => try bw.print("#define {s}\n", .{name}), | |
| 552 | .boolean => |b| try bw.print("#define {s} {c}\n", .{ name, @as(u8, '0') + @intFromBool(b) }), | |
| 553 | .int => |i| try bw.print("#define {s} {d}\n", .{ name, i }), | |
| 554 | .ident => |ident| try bw.print("#define {s} {s}\n", .{ name, ident }), | |
| 555 | // TODO: use C-specific escaping instead of zig string literals | |
| 556 | .string => |string| try bw.print("#define {s} \"{f}\"\n", .{ name, std.zig.fmtString(string) }), | |
| 581 | 557 | } |
| 582 | 558 | } |
| 583 | 559 | |
| 584 | fn renderValueNasm(output: *std.ArrayList(u8), name: []const u8, value: Value) !void { | |
| 560 | fn renderValueNasm(bw: *Writer, name: []const u8, value: Value) !void { | |
| 585 | 561 | switch (value) { |
| 586 | .undef => { | |
| 587 | try output.appendSlice("; %undef "); | |
| 588 | try output.appendSlice(name); | |
| 589 | try output.appendSlice("\n"); | |
| 590 | }, | |
| 591 | .defined => { | |
| 592 | try output.appendSlice("%define "); | |
| 593 | try output.appendSlice(name); | |
| 594 | try output.appendSlice("\n"); | |
| 595 | }, | |
| 596 | .boolean => |b| { | |
| 597 | try output.appendSlice("%define "); | |
| 598 | try output.appendSlice(name); | |
| 599 | try output.appendSlice(if (b) " 1\n" else " 0\n"); | |
| 600 | }, | |
| 601 | .int => |i| { | |
| 602 | try output.writer().print("%define {s} {d}\n", .{ name, i }); | |
| 603 | }, | |
| 604 | .ident => |ident| { | |
| 605 | try output.writer().print("%define {s} {s}\n", .{ name, ident }); | |
| 606 | }, | |
| 607 | .string => |string| { | |
| 608 | // TODO: use nasm-specific escaping instead of zig string literals | |
| 609 | try output.writer().print("%define {s} \"{}\"\n", .{ name, std.zig.fmtEscapes(string) }); | |
| 610 | }, | |
| 562 | .undef => try bw.print("; %undef {s}\n", .{name}), | |
| 563 | .defined => try bw.print("%define {s}\n", .{name}), | |
| 564 | .boolean => |b| try bw.print("%define {s} {c}\n", .{ name, @as(u8, '0') + @intFromBool(b) }), | |
| 565 | .int => |i| try bw.print("%define {s} {d}\n", .{ name, i }), | |
| 566 | .ident => |ident| try bw.print("%define {s} {s}\n", .{ name, ident }), | |
| 567 | // TODO: use nasm-specific escaping instead of zig string literals | |
| 568 | .string => |string| try bw.print("%define {s} \"{f}\"\n", .{ name, std.zig.fmtString(string) }), | |
| 611 | 569 | } |
| 612 | 570 | } |
| 613 | 571 | |
| 614 | 572 | fn expand_variables_autoconf_at( |
| 615 | output: *std.ArrayList(u8), | |
| 573 | bw: *Writer, | |
| 616 | 574 | contents: []const u8, |
| 617 | 575 | values: std.StringArrayHashMap(Value), |
| 618 | 576 | used: []bool, |
| ... | ... | @@ -637,23 +595,17 @@ fn expand_variables_autoconf_at( |
| 637 | 595 | const key = contents[curr + 1 .. close_pos]; |
| 638 | 596 | const index = values.getIndex(key) orelse { |
| 639 | 597 | // Report the missing key to the caller. |
| 640 | try output.appendSlice(key); | |
| 598 | try bw.writeAll(key); | |
| 641 | 599 | return error.MissingValue; |
| 642 | 600 | }; |
| 643 | 601 | const value = values.unmanaged.entries.slice().items(.value)[index]; |
| 644 | 602 | used[index] = true; |
| 645 | try output.appendSlice(contents[source_offset..curr]); | |
| 603 | try bw.writeAll(contents[source_offset..curr]); | |
| 646 | 604 | switch (value) { |
| 647 | 605 | .undef, .defined => {}, |
| 648 | .boolean => |b| { | |
| 649 | try output.append(if (b) '1' else '0'); | |
| 650 | }, | |
| 651 | .int => |i| { | |
| 652 | try output.writer().print("{d}", .{i}); | |
| 653 | }, | |
| 654 | .ident, .string => |s| { | |
| 655 | try output.appendSlice(s); | |
| 656 | }, | |
| 606 | .boolean => |b| try bw.writeByte(@as(u8, '0') + @intFromBool(b)), | |
| 607 | .int => |i| try bw.print("{d}", .{i}), | |
| 608 | .ident, .string => |s| try bw.writeAll(s), | |
| 657 | 609 | } |
| 658 | 610 | |
| 659 | 611 | curr = close_pos; |
| ... | ... | @@ -661,7 +613,7 @@ fn expand_variables_autoconf_at( |
| 661 | 613 | } |
| 662 | 614 | } |
| 663 | 615 | |
| 664 | try output.appendSlice(contents[source_offset..]); | |
| 616 | try bw.writeAll(contents[source_offset..]); | |
| 665 | 617 | } |
| 666 | 618 | |
| 667 | 619 | fn expand_variables_cmake( |
| ... | ... | @@ -669,7 +621,7 @@ fn expand_variables_cmake( |
| 669 | 621 | contents: []const u8, |
| 670 | 622 | values: std.StringArrayHashMap(Value), |
| 671 | 623 | ) ![]const u8 { |
| 672 | var result = std.ArrayList(u8).init(allocator); | |
| 624 | var result: std.ArrayList(u8) = .init(allocator); | |
| 673 | 625 | errdefer result.deinit(); |
| 674 | 626 | |
| 675 | 627 | const valid_varname_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789/_.+-"; |
| ... | ... | @@ -681,7 +633,7 @@ fn expand_variables_cmake( |
| 681 | 633 | source: usize, |
| 682 | 634 | target: usize, |
| 683 | 635 | }; |
| 684 | var var_stack = std.ArrayList(Position).init(allocator); | |
| 636 | var var_stack: std.ArrayList(Position) = .init(allocator); | |
| 685 | 637 | defer var_stack.deinit(); |
| 686 | 638 | loop: while (curr < contents.len) : (curr += 1) { |
| 687 | 639 | switch (contents[curr]) { |
| ... | ... | @@ -707,7 +659,7 @@ fn expand_variables_cmake( |
| 707 | 659 | try result.append(if (b) '1' else '0'); |
| 708 | 660 | }, |
| 709 | 661 | .int => |i| { |
| 710 | try result.writer().print("{d}", .{i}); | |
| 662 | try result.print("{d}", .{i}); | |
| 711 | 663 | }, |
| 712 | 664 | .ident, .string => |s| { |
| 713 | 665 | try result.appendSlice(s); |
| ... | ... | @@ -764,7 +716,7 @@ fn expand_variables_cmake( |
| 764 | 716 | try result.append(if (b) '1' else '0'); |
| 765 | 717 | }, |
| 766 | 718 | .int => |i| { |
| 767 | try result.writer().print("{d}", .{i}); | |
| 719 | try result.print("{d}", .{i}); | |
| 768 | 720 | }, |
| 769 | 721 | .ident, .string => |s| { |
| 770 | 722 | try result.appendSlice(s); |
| ... | ... | @@ -801,17 +753,17 @@ fn testReplaceVariablesAutoconfAt( |
| 801 | 753 | expected: []const u8, |
| 802 | 754 | values: std.StringArrayHashMap(Value), |
| 803 | 755 | ) !void { |
| 804 | var output = std.ArrayList(u8).init(allocator); | |
| 805 | defer output.deinit(); | |
| 756 | var aw: std.io.Writer.Allocating = .init(allocator); | |
| 757 | defer aw.deinit(); | |
| 806 | 758 | |
| 807 | 759 | const used = try allocator.alloc(bool, values.count()); |
| 808 | 760 | for (used) |*u| u.* = false; |
| 809 | 761 | defer allocator.free(used); |
| 810 | 762 | |
| 811 | try expand_variables_autoconf_at(&output, contents, values, used); | |
| 763 | try expand_variables_autoconf_at(&aw.writer, contents, values, used); | |
| 812 | 764 | |
| 813 | 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 | } |
| 816 | 768 | |
| 817 | 769 | fn testReplaceVariablesCMake( |
| ... | ... | @@ -828,7 +780,7 @@ fn testReplaceVariablesCMake( |
| 828 | 780 | |
| 829 | 781 | test "expand_variables_autoconf_at simple cases" { |
| 830 | 782 | const allocator = std.testing.allocator; |
| 831 | var values = std.StringArrayHashMap(Value).init(allocator); | |
| 783 | var values: std.StringArrayHashMap(Value) = .init(allocator); | |
| 832 | 784 | defer values.deinit(); |
| 833 | 785 | |
| 834 | 786 | // empty strings are preserved |
| ... | ... | @@ -924,7 +876,7 @@ test "expand_variables_autoconf_at simple cases" { |
| 924 | 876 | |
| 925 | 877 | test "expand_variables_autoconf_at edge cases" { |
| 926 | 878 | const allocator = std.testing.allocator; |
| 927 | var values = std.StringArrayHashMap(Value).init(allocator); | |
| 879 | var values: std.StringArrayHashMap(Value) = .init(allocator); | |
| 928 | 880 | defer values.deinit(); |
| 929 | 881 | |
| 930 | 882 | // @-vars resolved only when they wrap valid characters, otherwise considered literals |
| ... | ... | @@ -940,7 +892,7 @@ test "expand_variables_autoconf_at edge cases" { |
| 940 | 892 | |
| 941 | 893 | test "expand_variables_cmake simple cases" { |
| 942 | 894 | const allocator = std.testing.allocator; |
| 943 | var values = std.StringArrayHashMap(Value).init(allocator); | |
| 895 | var values: std.StringArrayHashMap(Value) = .init(allocator); | |
| 944 | 896 | defer values.deinit(); |
| 945 | 897 | |
| 946 | 898 | try values.putNoClobber("undef", .undef); |
| ... | ... | @@ -1028,7 +980,7 @@ test "expand_variables_cmake simple cases" { |
| 1028 | 980 | |
| 1029 | 981 | test "expand_variables_cmake edge cases" { |
| 1030 | 982 | const allocator = std.testing.allocator; |
| 1031 | var values = std.StringArrayHashMap(Value).init(allocator); | |
| 983 | var values: std.StringArrayHashMap(Value) = .init(allocator); | |
| 1032 | 984 | defer values.deinit(); |
| 1033 | 985 | |
| 1034 | 986 | // special symbols |
| ... | ... | @@ -1089,7 +1041,7 @@ test "expand_variables_cmake edge cases" { |
| 1089 | 1041 | |
| 1090 | 1042 | test "expand_variables_cmake escaped characters" { |
| 1091 | 1043 | const allocator = std.testing.allocator; |
| 1092 | var values = std.StringArrayHashMap(Value).init(allocator); | |
| 1044 | var values: std.StringArrayHashMap(Value) = .init(allocator); | |
| 1093 | 1045 | defer values.deinit(); |
| 1094 | 1046 | |
| 1095 | 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 | 164 | const full_h_prefix = b.getInstallPath(h_dir, dir.dest_rel_path); |
| 165 | 165 | |
| 166 | 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 | 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 | 65 | const src_dir_path = install_dir.options.source_dir.getPath3(b, step); |
| 66 | 66 | const need_derived_inputs = try step.addDirectoryWatchInput(install_dir.options.source_dir); |
| 67 | 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 | 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 | 12 | step: Step, |
| 13 | 13 | generated_file: GeneratedFile, |
| 14 | 14 | |
| 15 | contents: std.ArrayList(u8), | |
| 16 | args: std.ArrayList(Arg), | |
| 17 | encountered_types: std.StringHashMap(void), | |
| 15 | contents: std.ArrayListUnmanaged(u8), | |
| 16 | args: std.ArrayListUnmanaged(Arg), | |
| 17 | encountered_types: std.StringHashMapUnmanaged(void), | |
| 18 | 18 | |
| 19 | 19 | pub fn create(owner: *std.Build) *Options { |
| 20 | 20 | const options = owner.allocator.create(Options) catch @panic("OOM"); |
| 21 | 21 | options.* = .{ |
| 22 | .step = Step.init(.{ | |
| 22 | .step = .init(.{ | |
| 23 | 23 | .id = base_id, |
| 24 | 24 | .name = "options", |
| 25 | 25 | .owner = owner, |
| 26 | 26 | .makeFn = make, |
| 27 | 27 | }), |
| 28 | 28 | .generated_file = undefined, |
| 29 | .contents = std.ArrayList(u8).init(owner.allocator), | |
| 30 | .args = std.ArrayList(Arg).init(owner.allocator), | |
| 31 | .encountered_types = std.StringHashMap(void).init(owner.allocator), | |
| 29 | .contents = .empty, | |
| 30 | .args = .empty, | |
| 31 | .encountered_types = .empty, | |
| 32 | 32 | }; |
| 33 | 33 | options.generated_file = .{ .step = &options.step }; |
| 34 | 34 | |
| ... | ... | @@ -40,110 +40,119 @@ pub fn addOption(options: *Options, comptime T: type, name: []const u8, value: T |
| 40 | 40 | } |
| 41 | 41 | |
| 42 | 42 | fn addOptionFallible(options: *Options, comptime T: type, name: []const u8, value: T) !void { |
| 43 | const out = options.contents.writer(); | |
| 44 | try printType(options, out, T, value, 0, name); | |
| 43 | try printType(options, &options.contents, T, value, 0, name); | |
| 45 | 44 | } |
| 46 | 45 | |
| 47 | fn printType(options: *Options, out: anytype, comptime T: type, value: T, indent: u8, name: ?[]const u8) !void { | |
| 46 | fn 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 | 55 | switch (T) { |
| 49 | 56 | []const []const u8 => { |
| 50 | 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 | } |
| 53 | 60 | |
| 54 | try out.writeAll("&[_][]const u8{\n"); | |
| 61 | try out.appendSlice(gpa, "&[_][]const u8{\n"); | |
| 55 | 62 | |
| 56 | 63 | for (value) |slice| { |
| 57 | try out.writeByteNTimes(' ', indent); | |
| 58 | try out.print(" \"{}\",\n", .{std.zig.fmtEscapes(slice)}); | |
| 64 | try out.appendNTimes(gpa, ' ', indent); | |
| 65 | try out.print(gpa, " \"{f}\",\n", .{std.zig.fmtString(slice)}); | |
| 59 | 66 | } |
| 60 | 67 | |
| 61 | 68 | if (name != null) { |
| 62 | try out.writeAll("};\n"); | |
| 69 | try out.appendSlice(gpa, "};\n"); | |
| 63 | 70 | } else { |
| 64 | try out.writeAll("},\n"); | |
| 71 | try out.appendSlice(gpa, "},\n"); | |
| 65 | 72 | } |
| 66 | 73 | |
| 67 | 74 | return; |
| 68 | 75 | }, |
| 69 | 76 | []const u8 => { |
| 70 | 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 | 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 | 86 | [:0]const u8 => { |
| 78 | 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 | 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 | 94 | ?[]const u8 => { |
| 86 | 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 | } |
| 89 | 98 | |
| 90 | 99 | if (value) |payload| { |
| 91 | try out.print("\"{}\"", .{std.zig.fmtEscapes(payload)}); | |
| 100 | try out.print(gpa, "\"{f}\"", .{std.zig.fmtString(payload)}); | |
| 92 | 101 | } else { |
| 93 | try out.writeAll("null"); | |
| 102 | try out.appendSlice(gpa, "null"); | |
| 94 | 103 | } |
| 95 | 104 | |
| 96 | 105 | if (name != null) { |
| 97 | try out.writeAll(";\n"); | |
| 106 | try out.appendSlice(gpa, ";\n"); | |
| 98 | 107 | } else { |
| 99 | try out.writeAll(",\n"); | |
| 108 | try out.appendSlice(gpa, ",\n"); | |
| 100 | 109 | } |
| 101 | 110 | return; |
| 102 | 111 | }, |
| 103 | 112 | ?[:0]const u8 => { |
| 104 | 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 | } |
| 107 | 116 | |
| 108 | 117 | if (value) |payload| { |
| 109 | try out.print("\"{}\"", .{std.zig.fmtEscapes(payload)}); | |
| 118 | try out.print(gpa, "\"{f}\"", .{std.zig.fmtString(payload)}); | |
| 110 | 119 | } else { |
| 111 | try out.writeAll("null"); | |
| 120 | try out.appendSlice(gpa, "null"); | |
| 112 | 121 | } |
| 113 | 122 | |
| 114 | 123 | if (name != null) { |
| 115 | try out.writeAll(";\n"); | |
| 124 | try out.appendSlice(gpa, ";\n"); | |
| 116 | 125 | } else { |
| 117 | try out.writeAll(",\n"); | |
| 126 | try out.appendSlice(gpa, ",\n"); | |
| 118 | 127 | } |
| 119 | 128 | return; |
| 120 | 129 | }, |
| 121 | 130 | std.SemanticVersion => { |
| 122 | 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 | } |
| 125 | 134 | |
| 126 | try out.writeAll(".{\n"); | |
| 127 | try out.writeByteNTimes(' ', indent); | |
| 128 | try out.print(" .major = {d},\n", .{value.major}); | |
| 129 | try out.writeByteNTimes(' ', indent); | |
| 130 | try out.print(" .minor = {d},\n", .{value.minor}); | |
| 131 | try out.writeByteNTimes(' ', indent); | |
| 132 | try out.print(" .patch = {d},\n", .{value.patch}); | |
| 135 | try out.appendSlice(gpa, ".{\n"); | |
| 136 | try out.appendNTimes(gpa, ' ', indent); | |
| 137 | try out.print(gpa, " .major = {d},\n", .{value.major}); | |
| 138 | try out.appendNTimes(gpa, ' ', indent); | |
| 139 | try out.print(gpa, " .minor = {d},\n", .{value.minor}); | |
| 140 | try out.appendNTimes(gpa, ' ', indent); | |
| 141 | try out.print(gpa, " .patch = {d},\n", .{value.patch}); | |
| 133 | 142 | |
| 134 | 143 | if (value.pre) |some| { |
| 135 | try out.writeByteNTimes(' ', indent); | |
| 136 | try out.print(" .pre = \"{}\",\n", .{std.zig.fmtEscapes(some)}); | |
| 144 | try out.appendNTimes(gpa, ' ', indent); | |
| 145 | try out.print(gpa, " .pre = \"{f}\",\n", .{std.zig.fmtString(some)}); | |
| 137 | 146 | } |
| 138 | 147 | if (value.build) |some| { |
| 139 | try out.writeByteNTimes(' ', indent); | |
| 140 | try out.print(" .build = \"{}\",\n", .{std.zig.fmtEscapes(some)}); | |
| 148 | try out.appendNTimes(gpa, ' ', indent); | |
| 149 | try out.print(gpa, " .build = \"{f}\",\n", .{std.zig.fmtString(some)}); | |
| 141 | 150 | } |
| 142 | 151 | |
| 143 | 152 | if (name != null) { |
| 144 | try out.writeAll("};\n"); | |
| 153 | try out.appendSlice(gpa, "};\n"); | |
| 145 | 154 | } else { |
| 146 | try out.writeAll("},\n"); | |
| 155 | try out.appendSlice(gpa, "},\n"); | |
| 147 | 156 | } |
| 148 | 157 | return; |
| 149 | 158 | }, |
| ... | ... | @@ -153,21 +162,21 @@ fn printType(options: *Options, out: anytype, comptime T: type, value: T, indent |
| 153 | 162 | switch (@typeInfo(T)) { |
| 154 | 163 | .array => { |
| 155 | 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 | } |
| 158 | 167 | |
| 159 | try out.print("{s} {{\n", .{@typeName(T)}); | |
| 168 | try out.print(gpa, "{s} {{\n", .{@typeName(T)}); | |
| 160 | 169 | for (value) |item| { |
| 161 | try out.writeByteNTimes(' ', indent + 4); | |
| 170 | try out.appendNTimes(gpa, ' ', indent + 4); | |
| 162 | 171 | try printType(options, out, @TypeOf(item), item, indent + 4, null); |
| 163 | 172 | } |
| 164 | try out.writeByteNTimes(' ', indent); | |
| 165 | try out.writeAll("}"); | |
| 173 | try out.appendNTimes(gpa, ' ', indent); | |
| 174 | try out.appendSlice(gpa, "}"); | |
| 166 | 175 | |
| 167 | 176 | if (name != null) { |
| 168 | try out.writeAll(";\n"); | |
| 177 | try out.appendSlice(gpa, ";\n"); | |
| 169 | 178 | } else { |
| 170 | try out.writeAll(",\n"); | |
| 179 | try out.appendSlice(gpa, ",\n"); | |
| 171 | 180 | } |
| 172 | 181 | return; |
| 173 | 182 | }, |
| ... | ... | @@ -177,27 +186,27 @@ fn printType(options: *Options, out: anytype, comptime T: type, value: T, indent |
| 177 | 186 | } |
| 178 | 187 | |
| 179 | 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 | } |
| 182 | 191 | |
| 183 | try out.print("&[_]{s} {{\n", .{@typeName(p.child)}); | |
| 192 | try out.print(gpa, "&[_]{s} {{\n", .{@typeName(p.child)}); | |
| 184 | 193 | for (value) |item| { |
| 185 | try out.writeByteNTimes(' ', indent + 4); | |
| 194 | try out.appendNTimes(gpa, ' ', indent + 4); | |
| 186 | 195 | try printType(options, out, @TypeOf(item), item, indent + 4, null); |
| 187 | 196 | } |
| 188 | try out.writeByteNTimes(' ', indent); | |
| 189 | try out.writeAll("}"); | |
| 197 | try out.appendNTimes(gpa, ' ', indent); | |
| 198 | try out.appendSlice(gpa, "}"); | |
| 190 | 199 | |
| 191 | 200 | if (name != null) { |
| 192 | try out.writeAll(";\n"); | |
| 201 | try out.appendSlice(gpa, ";\n"); | |
| 193 | 202 | } else { |
| 194 | try out.writeAll(",\n"); | |
| 203 | try out.appendSlice(gpa, ",\n"); | |
| 195 | 204 | } |
| 196 | 205 | return; |
| 197 | 206 | }, |
| 198 | 207 | .optional => { |
| 199 | 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 | } |
| 202 | 211 | |
| 203 | 212 | if (value) |inner| { |
| ... | ... | @@ -206,13 +215,13 @@ fn printType(options: *Options, out: anytype, comptime T: type, value: T, indent |
| 206 | 215 | _ = options.contents.pop(); |
| 207 | 216 | _ = options.contents.pop(); |
| 208 | 217 | } else { |
| 209 | try out.writeAll("null"); | |
| 218 | try out.appendSlice(gpa, "null"); | |
| 210 | 219 | } |
| 211 | 220 | |
| 212 | 221 | if (name != null) { |
| 213 | try out.writeAll(";\n"); | |
| 222 | try out.appendSlice(gpa, ";\n"); | |
| 214 | 223 | } else { |
| 215 | try out.writeAll(",\n"); | |
| 224 | try out.appendSlice(gpa, ",\n"); | |
| 216 | 225 | } |
| 217 | 226 | return; |
| 218 | 227 | }, |
| ... | ... | @@ -224,9 +233,9 @@ fn printType(options: *Options, out: anytype, comptime T: type, value: T, indent |
| 224 | 233 | .null, |
| 225 | 234 | => { |
| 226 | 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 | 237 | } else { |
| 229 | try out.print("{any},\n", .{value}); | |
| 238 | try out.print(gpa, "{any},\n", .{value}); | |
| 230 | 239 | } |
| 231 | 240 | return; |
| 232 | 241 | }, |
| ... | ... | @@ -234,10 +243,10 @@ fn printType(options: *Options, out: anytype, comptime T: type, value: T, indent |
| 234 | 243 | try printEnum(options, out, T, info, indent); |
| 235 | 244 | |
| 236 | 245 | if (name) |some| { |
| 237 | try out.print("pub const {}: {} = .{p_};\n", .{ | |
| 246 | try out.print(gpa, "pub const {f}: {f} = .{f};\n", .{ | |
| 238 | 247 | std.zig.fmtId(some), |
| 239 | 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 | 252 | return; |
| ... | ... | @@ -246,7 +255,7 @@ fn printType(options: *Options, out: anytype, comptime T: type, value: T, indent |
| 246 | 255 | try printStruct(options, out, T, info, indent); |
| 247 | 256 | |
| 248 | 257 | if (name) |some| { |
| 249 | try out.print("pub const {}: {} = ", .{ | |
| 258 | try out.print(gpa, "pub const {f}: {f} = ", .{ | |
| 250 | 259 | std.zig.fmtId(some), |
| 251 | 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 | 267 | } |
| 259 | 268 | } |
| 260 | 269 | |
| 261 | fn printUserDefinedType(options: *Options, out: anytype, comptime T: type, indent: u8) !void { | |
| 270 | fn printUserDefinedType(options: *Options, out: *std.ArrayListUnmanaged(u8), comptime T: type, indent: u8) !void { | |
| 262 | 271 | switch (@typeInfo(T)) { |
| 263 | 272 | .@"enum" => |info| { |
| 264 | 273 | return try printEnum(options, out, T, info, indent); |
| ... | ... | @@ -270,94 +279,119 @@ fn printUserDefinedType(options: *Options, out: anytype, comptime T: type, inden |
| 270 | 279 | } |
| 271 | 280 | } |
| 272 | 281 | |
| 273 | fn printEnum(options: *Options, out: anytype, comptime T: type, comptime val: std.builtin.Type.Enum, indent: u8) !void { | |
| 274 | const gop = try options.encountered_types.getOrPut(@typeName(T)); | |
| 282 | fn printEnum( | |
| 283 | options: *Options, | |
| 284 | out: *std.ArrayListUnmanaged(u8), | |
| 285 | comptime T: type, | |
| 286 | comptime val: std.builtin.Type.Enum, | |
| 287 | indent: u8, | |
| 288 | ) !void { | |
| 289 | const gpa = options.step.owner.allocator; | |
| 290 | const gop = try options.encountered_types.getOrPut(gpa, @typeName(T)); | |
| 275 | 291 | if (gop.found_existing) return; |
| 276 | 292 | |
| 277 | try out.writeByteNTimes(' ', indent); | |
| 278 | try out.print("pub const {} = enum ({s}) {{\n", .{ std.zig.fmtId(@typeName(T)), @typeName(val.tag_type) }); | |
| 293 | try out.appendNTimes(gpa, ' ', indent); | |
| 294 | try out.print(gpa, "pub const {f} = enum ({s}) {{\n", .{ std.zig.fmtId(@typeName(T)), @typeName(val.tag_type) }); | |
| 279 | 295 | |
| 280 | 296 | inline for (val.fields) |field| { |
| 281 | try out.writeByteNTimes(' ', indent); | |
| 282 | try out.print(" {p} = {d},\n", .{ std.zig.fmtId(field.name), field.value }); | |
| 297 | try out.appendNTimes(gpa, ' ', indent); | |
| 298 | try out.print(gpa, " {f} = {d},\n", .{ | |
| 299 | std.zig.fmtIdFlags(field.name, .{ .allow_primitive = true }), field.value, | |
| 300 | }); | |
| 283 | 301 | } |
| 284 | 302 | |
| 285 | 303 | if (!val.is_exhaustive) { |
| 286 | try out.writeByteNTimes(' ', indent); | |
| 287 | try out.writeAll(" _,\n"); | |
| 304 | try out.appendNTimes(gpa, ' ', indent); | |
| 305 | try out.appendSlice(gpa, " _,\n"); | |
| 288 | 306 | } |
| 289 | 307 | |
| 290 | try out.writeByteNTimes(' ', indent); | |
| 291 | try out.writeAll("};\n"); | |
| 308 | try out.appendNTimes(gpa, ' ', indent); | |
| 309 | try out.appendSlice(gpa, "};\n"); | |
| 292 | 310 | } |
| 293 | 311 | |
| 294 | fn printStruct(options: *Options, out: anytype, comptime T: type, comptime val: std.builtin.Type.Struct, indent: u8) !void { | |
| 295 | const gop = try options.encountered_types.getOrPut(@typeName(T)); | |
| 312 | fn printStruct(options: *Options, out: *std.ArrayListUnmanaged(u8), comptime T: type, comptime val: std.builtin.Type.Struct, indent: u8) !void { | |
| 313 | const gpa = options.step.owner.allocator; | |
| 314 | const gop = try options.encountered_types.getOrPut(gpa, @typeName(T)); | |
| 296 | 315 | if (gop.found_existing) return; |
| 297 | 316 | |
| 298 | try out.writeByteNTimes(' ', indent); | |
| 299 | try out.print("pub const {} = ", .{std.zig.fmtId(@typeName(T))}); | |
| 317 | try out.appendNTimes(gpa, ' ', indent); | |
| 318 | try out.print(gpa, "pub const {f} = ", .{std.zig.fmtId(@typeName(T))}); | |
| 300 | 319 | |
| 301 | 320 | switch (val.layout) { |
| 302 | .@"extern" => try out.writeAll("extern struct"), | |
| 303 | .@"packed" => try out.writeAll("packed struct"), | |
| 304 | else => try out.writeAll("struct"), | |
| 321 | .@"extern" => try out.appendSlice(gpa, "extern struct"), | |
| 322 | .@"packed" => try out.appendSlice(gpa, "packed struct"), | |
| 323 | else => try out.appendSlice(gpa, "struct"), | |
| 305 | 324 | } |
| 306 | 325 | |
| 307 | try out.writeAll(" {\n"); | |
| 326 | try out.appendSlice(gpa, " {\n"); | |
| 308 | 327 | |
| 309 | 328 | inline for (val.fields) |field| { |
| 310 | try out.writeByteNTimes(' ', indent); | |
| 329 | try out.appendNTimes(gpa, ' ', indent); | |
| 311 | 330 | |
| 312 | 331 | const type_name = @typeName(field.type); |
| 313 | 332 | |
| 314 | 333 | // If the type name doesn't contains a '.' the type is from zig builtins. |
| 315 | 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 | 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 | } |
| 320 | 345 | |
| 321 | 346 | if (field.defaultValue()) |default_value| { |
| 322 | try out.writeAll(" = "); | |
| 347 | try out.appendSlice(gpa, " = "); | |
| 323 | 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 | 350 | .@"struct" => |info| { |
| 326 | 351 | try printStructValue(options, out, info, default_value, indent + 4); |
| 327 | 352 | }, |
| 328 | 353 | else => try printType(options, out, @TypeOf(default_value), default_value, indent, null), |
| 329 | 354 | } |
| 330 | 355 | } else { |
| 331 | try out.writeAll(",\n"); | |
| 356 | try out.appendSlice(gpa, ",\n"); | |
| 332 | 357 | } |
| 333 | 358 | } |
| 334 | 359 | |
| 335 | 360 | // TODO: write declarations |
| 336 | 361 | |
| 337 | try out.writeByteNTimes(' ', indent); | |
| 338 | try out.writeAll("};\n"); | |
| 362 | try out.appendNTimes(gpa, ' ', indent); | |
| 363 | try out.appendSlice(gpa, "};\n"); | |
| 339 | 364 | |
| 340 | 365 | inline for (val.fields) |field| { |
| 341 | 366 | try printUserDefinedType(options, out, field.type, 0); |
| 342 | 367 | } |
| 343 | 368 | } |
| 344 | 369 | |
| 345 | fn printStructValue(options: *Options, out: anytype, comptime struct_val: std.builtin.Type.Struct, val: anytype, indent: u8) !void { | |
| 346 | try out.writeAll(".{\n"); | |
| 370 | fn printStructValue( | |
| 371 | options: *Options, | |
| 372 | out: *std.ArrayListUnmanaged(u8), | |
| 373 | comptime struct_val: std.builtin.Type.Struct, | |
| 374 | val: anytype, | |
| 375 | indent: u8, | |
| 376 | ) !void { | |
| 377 | const gpa = options.step.owner.allocator; | |
| 378 | try out.appendSlice(gpa, ".{\n"); | |
| 347 | 379 | |
| 348 | 380 | if (struct_val.is_tuple) { |
| 349 | 381 | inline for (struct_val.fields) |field| { |
| 350 | try out.writeByteNTimes(' ', indent); | |
| 382 | try out.appendNTimes(gpa, ' ', indent); | |
| 351 | 383 | try printType(options, out, @TypeOf(@field(val, field.name)), @field(val, field.name), indent, null); |
| 352 | 384 | } |
| 353 | 385 | } else { |
| 354 | 386 | inline for (struct_val.fields) |field| { |
| 355 | try out.writeByteNTimes(' ', indent); | |
| 356 | try out.print(" .{p_} = ", .{std.zig.fmtId(field.name)}); | |
| 387 | try out.appendNTimes(gpa, ' ', indent); | |
| 388 | try out.print(gpa, " .{f} = ", .{ | |
| 389 | std.zig.fmtIdFlags(field.name, .{ .allow_primitive = true, .allow_underscore = true }), | |
| 390 | }); | |
| 357 | 391 | |
| 358 | 392 | const field_name = @field(val, field.name); |
| 359 | 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 | 395 | .@"struct" => |struct_info| { |
| 362 | 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 | 401 | } |
| 368 | 402 | |
| 369 | 403 | if (indent == 0) { |
| 370 | try out.writeAll("};\n"); | |
| 404 | try out.appendSlice(gpa, "};\n"); | |
| 371 | 405 | } else { |
| 372 | try out.writeByteNTimes(' ', indent); | |
| 373 | try out.writeAll("},\n"); | |
| 406 | try out.appendNTimes(gpa, ' ', indent); | |
| 407 | try out.appendSlice(gpa, "},\n"); | |
| 374 | 408 | } |
| 375 | 409 | } |
| 376 | 410 | |
| ... | ... | @@ -381,7 +415,8 @@ pub fn addOptionPath( |
| 381 | 415 | name: []const u8, |
| 382 | 416 | path: LazyPath, |
| 383 | 417 | ) void { |
| 384 | options.args.append(.{ | |
| 418 | const arena = options.step.owner.allocator; | |
| 419 | options.args.append(arena, .{ | |
| 385 | 420 | .name = options.step.owner.dupe(name), |
| 386 | 421 | .path = path.dupe(options.step.owner), |
| 387 | 422 | }) catch @panic("OOM"); |
| ... | ... | @@ -440,7 +475,7 @@ fn make(step: *Step, make_options: Step.MakeOptions) !void { |
| 440 | 475 | error.FileNotFound => { |
| 441 | 476 | const sub_dirname = fs.path.dirname(sub_path).?; |
| 442 | 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 | 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 | 487 | const tmp_sub_path_dirname = fs.path.dirname(tmp_sub_path).?; |
| 453 | 488 | |
| 454 | 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 | 491 | b.cache_root, tmp_sub_path_dirname, @errorName(err), |
| 457 | 492 | }); |
| 458 | 493 | }; |
| 459 | 494 | |
| 460 | 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 | 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 | 502 | error.PathAlreadyExists => { |
| 468 | 503 | // Other process beat us to it. Clean up the temp file. |
| 469 | 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 | 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 | 510 | return; |
| 476 | 511 | }, |
| 477 | 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 | 514 | b.cache_root, tmp_sub_path, |
| 480 | 515 | b.cache_root, sub_path, |
| 481 | 516 | @errorName(err), |
| ... | ... | @@ -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 | 522 | b.cache_root, sub_path, @errorName(e), |
| 488 | 523 | }), |
| 489 | 524 | } |
| ... | ... | @@ -643,5 +678,5 @@ test Options { |
| 643 | 678 | \\ |
| 644 | 679 | , options.contents.items); |
| 645 | 680 | |
| 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 | 832 | else => unreachable, |
| 833 | 833 | }; |
| 834 | 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 | 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 | 864 | else => unreachable, |
| 865 | 865 | }; |
| 866 | 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 | 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 | 903 | b.cache_root.handle.rename(tmp_dir_path, o_sub_path) catch |err| { |
| 904 | 904 | if (err == error.PathAlreadyExists) { |
| 905 | 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 | 907 | b.cache_root, |
| 908 | 908 | tmp_dir_path, |
| 909 | 909 | @errorName(del_err), |
| 910 | 910 | }); |
| 911 | 911 | }; |
| 912 | 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 | 914 | b.cache_root, tmp_dir_path, |
| 915 | 915 | b.cache_root, o_sub_path, |
| 916 | 916 | @errorName(retry_err), |
| 917 | 917 | }); |
| 918 | 918 | }; |
| 919 | 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 | 921 | b.cache_root, tmp_dir_path, |
| 922 | 922 | b.cache_root, o_sub_path, |
| 923 | 923 | @errorName(err), |
| ... | ... | @@ -964,7 +964,7 @@ pub fn rerunInFuzzMode( |
| 964 | 964 | .artifact => |pa| { |
| 965 | 965 | const artifact = pa.artifact; |
| 966 | 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 | 968 | break :p artifact.installed_path orelse artifact.generated_bin.?.path.?; |
| 969 | 969 | }; |
| 970 | 970 | try argv_list.append(arena, b.fmt("{s}{s}", .{ |
| ... | ... | @@ -1011,24 +1011,17 @@ fn populateGeneratedPaths( |
| 1011 | 1011 | } |
| 1012 | 1012 | } |
| 1013 | 1013 | |
| 1014 | fn formatTerm( | |
| 1015 | term: ?std.process.Child.Term, | |
| 1016 | comptime fmt: []const u8, | |
| 1017 | options: std.fmt.FormatOptions, | |
| 1018 | writer: anytype, | |
| 1019 | ) !void { | |
| 1020 | _ = fmt; | |
| 1021 | _ = options; | |
| 1014 | fn formatTerm(term: ?std.process.Child.Term, w: *std.io.Writer) std.io.Writer.Error!void { | |
| 1022 | 1015 | if (term) |t| switch (t) { |
| 1023 | .Exited => |code| try writer.print("exited with code {}", .{code}), | |
| 1024 | .Signal => |sig| try writer.print("terminated with signal {}", .{sig}), | |
| 1025 | .Stopped => |sig| try writer.print("stopped with signal {}", .{sig}), | |
| 1026 | .Unknown => |code| try writer.print("terminated for unknown reason with code {}", .{code}), | |
| 1016 | .Exited => |code| try w.print("exited with code {d}", .{code}), | |
| 1017 | .Signal => |sig| try w.print("terminated with signal {d}", .{sig}), | |
| 1018 | .Stopped => |sig| try w.print("stopped with signal {d}", .{sig}), | |
| 1019 | .Unknown => |code| try w.print("terminated for unknown reason with code {d}", .{code}), | |
| 1027 | 1020 | } else { |
| 1028 | try writer.writeAll("exited with any code"); | |
| 1021 | try w.writeAll("exited with any code"); | |
| 1029 | 1022 | } |
| 1030 | 1023 | } |
| 1031 | fn fmtTerm(term: ?std.process.Child.Term) std.fmt.Formatter(formatTerm) { | |
| 1024 | fn fmtTerm(term: ?std.process.Child.Term) std.fmt.Formatter(?std.process.Child.Term, formatTerm) { | |
| 1032 | 1025 | return .{ .data = term }; |
| 1033 | 1026 | } |
| 1034 | 1027 | |
| ... | ... | @@ -1262,12 +1255,12 @@ fn runCommand( |
| 1262 | 1255 | const sub_path = b.pathJoin(&output_components); |
| 1263 | 1256 | const sub_path_dirname = fs.path.dirname(sub_path).?; |
| 1264 | 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 | 1259 | b.cache_root, sub_path_dirname, @errorName(err), |
| 1267 | 1260 | }); |
| 1268 | 1261 | }; |
| 1269 | 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 | 1264 | b.cache_root, sub_path, @errorName(err), |
| 1272 | 1265 | }); |
| 1273 | 1266 | }; |
| ... | ... | @@ -1346,7 +1339,7 @@ fn runCommand( |
| 1346 | 1339 | }, |
| 1347 | 1340 | .expect_term => |expected_term| { |
| 1348 | 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 | 1343 | fmtTerm(result.term), |
| 1351 | 1344 | fmtTerm(expected_term), |
| 1352 | 1345 | try Step.allocPrintCmd(arena, cwd, final_argv), |
| ... | ... | @@ -1366,7 +1359,7 @@ fn runCommand( |
| 1366 | 1359 | }; |
| 1367 | 1360 | const expected_term: std.process.Child.Term = .{ .Exited = 0 }; |
| 1368 | 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 | 1363 | prefix, |
| 1371 | 1364 | fmtTerm(result.term), |
| 1372 | 1365 | fmtTerm(expected_term), |
| ... | ... | @@ -1797,10 +1790,10 @@ fn evalGeneric(run: *Run, child: *std.process.Child) !StdIoResult { |
| 1797 | 1790 | stdout_bytes = try poller.fifo(.stdout).toOwnedSlice(); |
| 1798 | 1791 | stderr_bytes = try poller.fifo(.stderr).toOwnedSlice(); |
| 1799 | 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 | 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 | } |
| 1805 | 1798 | |
| 1806 | 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 | 76 | for (usf.output_source_files.items) |output_source_file| { |
| 77 | 77 | if (fs.path.dirname(output_source_file.sub_path)) |dirname| { |
| 78 | 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 | 80 | b.build_root, dirname, @errorName(err), |
| 81 | 81 | }); |
| 82 | 82 | }; |
| ... | ... | @@ -84,7 +84,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void { |
| 84 | 84 | switch (output_source_file.contents) { |
| 85 | 85 | .bytes => |bytes| { |
| 86 | 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 | 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 | 101 | output_source_file.sub_path, |
| 102 | 102 | .{}, |
| 103 | 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 | 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 | 217 | const src_dir_path = dir.source.getPath3(b, step); |
| 218 | 218 | |
| 219 | 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 | 221 | src_dir_path, @errorName(err), |
| 222 | 222 | }); |
| 223 | 223 | }; |
| ... | ... | @@ -258,7 +258,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void { |
| 258 | 258 | write_file.generated_directory.path = try b.cache_root.join(arena, &.{ "o", &digest }); |
| 259 | 259 | |
| 260 | 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 | 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 | 269 | for (write_file.files.items) |file| { |
| 270 | 270 | if (fs.path.dirname(file.sub_path)) |dirname| { |
| 271 | 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 | 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 | 277 | switch (file.contents) { |
| 278 | 278 | .bytes => |bytes| { |
| 279 | 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 | 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 | 291 | file.sub_path, |
| 292 | 292 | .{}, |
| 293 | 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 | 295 | source_path, |
| 296 | 296 | b.cache_root, |
| 297 | 297 | cache_path, |
| ... | ... | @@ -315,7 +315,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void { |
| 315 | 315 | |
| 316 | 316 | if (dest_dirname.len != 0) { |
| 317 | 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 | 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 | 338 | dest_path, |
| 339 | 339 | .{}, |
| 340 | 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 | 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 | 211 | .ADD = true, |
| 212 | 212 | .ONLYDIR = true, |
| 213 | 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 | 217 | break :rs &dh_gop.value_ptr.reaction_set; |
| ... | ... | @@ -265,7 +265,7 @@ const Os = switch (builtin.os.tag) { |
| 265 | 265 | .ONLYDIR = true, |
| 266 | 266 | }, fan_mask, path.root_dir.handle.fd, path.subPathOrDot()) catch |err| switch (err) { |
| 267 | 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 | }; |
| 270 | 270 | |
| 271 | 271 | w.dir_table.swapRemoveAt(i); |
| ... | ... | @@ -659,7 +659,7 @@ const Os = switch (builtin.os.tag) { |
| 659 | 659 | path.root_dir.handle.fd |
| 660 | 660 | else |
| 661 | 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 | 664 | // Empirically the dir has to stay open or else no events are triggered. |
| 665 | 665 | errdefer if (!skip_open_dir) posix.close(dir_fd); |
lib/std/Progress.zig+32-1| ... | ... | @@ -9,6 +9,7 @@ const Progress = @This(); |
| 9 | 9 | const posix = std.posix; |
| 10 | 10 | const is_big_endian = builtin.cpu.arch.endian() == .big; |
| 11 | 11 | const is_windows = builtin.os.tag == .windows; |
| 12 | const Writer = std.io.Writer; | |
| 12 | 13 | |
| 13 | 14 | /// `null` if the current node (and its children) should |
| 14 | 15 | /// not print on update() |
| ... | ... | @@ -451,7 +452,7 @@ pub fn start(options: Options) Node { |
| 451 | 452 | if (options.disable_printing) { |
| 452 | 453 | return Node.none; |
| 453 | 454 | } |
| 454 | const stderr = std.io.getStdErr(); | |
| 455 | const stderr: std.fs.File = .stderr(); | |
| 455 | 456 | global_progress.terminal = stderr; |
| 456 | 457 | if (stderr.getOrEnableAnsiEscapeSupport()) { |
| 457 | 458 | global_progress.terminal_mode = .ansi_escape_codes; |
| ... | ... | @@ -606,6 +607,36 @@ pub fn unlockStdErr() void { |
| 606 | 607 | stderr_mutex.unlock(); |
| 607 | 608 | } |
| 608 | 609 | |
| 610 | /// Protected by `stderr_mutex`. | |
| 611 | const stderr_writer: *Writer = &stderr_file_writer.interface; | |
| 612 | /// Protected by `stderr_mutex`. | |
| 613 | var 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. | |
| 625 | pub 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 | ||
| 634 | pub fn unlockStderrWriter() void { | |
| 635 | stderr_writer.flush() catch {}; | |
| 636 | stderr_writer.buffer = &.{}; | |
| 637 | stderr_mutex.unlock(); | |
| 638 | } | |
| 639 | ||
| 609 | 640 | fn ipcThreadRun(fd: posix.fd_t) anyerror!void { |
| 610 | 641 | // Store this data in the thread so that it does not need to be part of the |
| 611 | 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 | 122 | } |
| 123 | 123 | |
| 124 | 124 | pub fn main() !void { |
| 125 | const stdout = std.io.getStdOut().writer(); | |
| 125 | const stdout = std.fs.File.stdout().deprecatedWriter(); | |
| 126 | 126 | |
| 127 | 127 | var buffer: [1024]u8 = undefined; |
| 128 | 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 | 150 | }; |
| 151 | 151 | } |
| 152 | 152 | |
| 153 | pub fn format( | |
| 154 | self: Version, | |
| 155 | comptime fmt: []const u8, | |
| 156 | options: std.fmt.FormatOptions, | |
| 157 | out_stream: anytype, | |
| 158 | ) !void { | |
| 159 | _ = options; | |
| 160 | if (fmt.len != 0) std.fmt.invalidFmtError(fmt, self); | |
| 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}); | |
| 153 | pub fn format(self: Version, w: *std.io.Writer) std.io.Writer.Error!void { | |
| 154 | try w.print("{d}.{d}.{d}", .{ self.major, self.minor, self.patch }); | |
| 155 | if (self.pre) |pre| try w.print("-{s}", .{pre}); | |
| 156 | if (self.build) |build| try w.print("+{s}", .{build}); | |
| 164 | 157 | } |
| 165 | 158 | |
| 166 | 159 | const expect = std.testing.expect; |
| ... | ... | @@ -202,7 +195,7 @@ test format { |
| 202 | 195 | "1.0.0+0.build.1-rc.10000aaa-kk-0.1", |
| 203 | 196 | "5.4.0-1018-raspi", |
| 204 | 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)}); | |
| 206 | 199 | |
| 207 | 200 | // Invalid version strings should be rejected. |
| 208 | 201 | for ([_][]const u8{ |
| ... | ... | @@ -269,12 +262,12 @@ test format { |
| 269 | 262 | // Valid version string that may overflow. |
| 270 | 263 | const big_valid = "99999999999999999999999.999999999999999999.99999999999999999"; |
| 271 | 264 | if (parse(big_valid)) |ver| { |
| 272 | try std.testing.expectFmt(big_valid, "{}", .{ver}); | |
| 265 | try std.testing.expectFmt(big_valid, "{f}", .{ver}); | |
| 273 | 266 | } else |err| try expect(err == error.Overflow); |
| 274 | 267 | |
| 275 | 268 | // Invalid version string that may overflow. |
| 276 | 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 | } |
| 279 | 272 | |
| 280 | 273 | test "precedence" { |
lib/std/Target.zig+7-23| ... | ... | @@ -301,29 +301,13 @@ pub const Os = struct { |
| 301 | 301 | |
| 302 | 302 | /// This function is defined to serialize a Zig source code representation of this |
| 303 | 303 | /// type, that, when parsed, will deserialize into the same data. |
| 304 | pub fn format( | |
| 305 | ver: WindowsVersion, | |
| 306 | comptime fmt_str: []const u8, | |
| 307 | _: std.fmt.FormatOptions, | |
| 308 | writer: anytype, | |
| 309 | ) @TypeOf(writer).Error!void { | |
| 310 | const maybe_name = std.enums.tagName(WindowsVersion, ver); | |
| 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); | |
| 304 | pub fn format(wv: WindowsVersion, w: *std.io.Writer) std.io.Writer.Error!void { | |
| 305 | if (std.enums.tagName(WindowsVersion, wv)) |name| { | |
| 306 | var vecs: [2][]const u8 = .{ ".", name }; | |
| 307 | return w.writeVecAll(&vecs); | |
| 308 | } else { | |
| 309 | return w.print("@enumFromInt(0x{X:0>8})", .{wv}); | |
| 310 | } | |
| 327 | 311 | } |
| 328 | 312 | }; |
| 329 | 313 |
lib/std/Target/Query.zig+20-21| ... | ... | @@ -394,25 +394,24 @@ pub fn canDetectLibC(self: Query) bool { |
| 394 | 394 | |
| 395 | 395 | /// Formats a version with the patch component omitted if it is zero, |
| 396 | 396 | /// unlike SemanticVersion.format which formats all its version components regardless. |
| 397 | fn formatVersion(version: SemanticVersion, writer: anytype) !void { | |
| 397 | fn formatVersion(version: SemanticVersion, gpa: Allocator, list: *std.ArrayListUnmanaged(u8)) !void { | |
| 398 | 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 | 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 | } |
| 404 | 404 | |
| 405 | pub fn zigTriple(self: Query, allocator: Allocator) Allocator.Error![]u8 { | |
| 406 | if (self.isNativeTriple()) | |
| 407 | return allocator.dupe(u8, "native"); | |
| 405 | pub fn zigTriple(self: Query, gpa: Allocator) Allocator.Error![]u8 { | |
| 406 | if (self.isNativeTriple()) return gpa.dupe(u8, "native"); | |
| 408 | 407 | |
| 409 | 408 | const arch_name = if (self.cpu_arch) |arch| @tagName(arch) else "native"; |
| 410 | 409 | const os_name = if (self.os_tag) |os_tag| @tagName(os_tag) else "native"; |
| 411 | 410 | |
| 412 | var result = std.ArrayList(u8).init(allocator); | |
| 413 | defer result.deinit(); | |
| 411 | var result: std.ArrayListUnmanaged(u8) = .empty; | |
| 412 | defer result.deinit(gpa); | |
| 414 | 413 | |
| 415 | try result.writer().print("{s}-{s}", .{ arch_name, os_name }); | |
| 414 | try result.print(gpa, "{s}-{s}", .{ arch_name, os_name }); | |
| 416 | 415 | |
| 417 | 416 | // The zig target syntax does not allow specifying a max os version with no min, so |
| 418 | 417 | // if either are present, we need the min. |
| ... | ... | @@ -420,11 +419,11 @@ pub fn zigTriple(self: Query, allocator: Allocator) Allocator.Error![]u8 { |
| 420 | 419 | switch (min) { |
| 421 | 420 | .none => {}, |
| 422 | 421 | .semver => |v| { |
| 423 | try result.writer().writeAll("."); | |
| 424 | try formatVersion(v, result.writer()); | |
| 422 | try result.appendSlice(gpa, "."); | |
| 423 | try formatVersion(v, gpa, &result); | |
| 425 | 424 | }, |
| 426 | 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 | 431 | switch (max) { |
| 433 | 432 | .none => {}, |
| 434 | 433 | .semver => |v| { |
| 435 | try result.writer().writeAll("..."); | |
| 436 | try formatVersion(v, result.writer()); | |
| 434 | try result.appendSlice(gpa, "..."); | |
| 435 | try formatVersion(v, gpa, &result); | |
| 437 | 436 | }, |
| 438 | 437 | .windows => |v| { |
| 439 | 438 | // This is counting on a custom format() function defined on `WindowsVersion` |
| 440 | 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 | } |
| 445 | 444 | |
| 446 | 445 | if (self.glibc_version) |v| { |
| 447 | 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 | 448 | result.appendAssumeCapacity('-'); |
| 450 | 449 | result.appendSliceAssumeCapacity(name); |
| 451 | 450 | result.appendAssumeCapacity('.'); |
| 452 | try formatVersion(v, result.writer()); | |
| 451 | try formatVersion(v, gpa, &result); | |
| 453 | 452 | } else if (self.android_api_level) |lvl| { |
| 454 | 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 | 455 | result.appendAssumeCapacity('-'); |
| 457 | 456 | result.appendSliceAssumeCapacity(name); |
| 458 | 457 | result.appendAssumeCapacity('.'); |
| 459 | try result.writer().print("{d}", .{lvl}); | |
| 458 | try result.print(gpa, "{d}", .{lvl}); | |
| 460 | 459 | } else if (self.abi) |abi| { |
| 461 | 460 | const name = @tagName(abi); |
| 462 | try result.ensureUnusedCapacity(name.len + 1); | |
| 461 | try result.ensureUnusedCapacity(gpa, name.len + 1); | |
| 463 | 462 | result.appendAssumeCapacity('-'); |
| 464 | 463 | result.appendSliceAssumeCapacity(name); |
| 465 | 464 | } |
| 466 | 465 | |
| 467 | return result.toOwnedSlice(); | |
| 466 | return result.toOwnedSlice(gpa); | |
| 468 | 467 | } |
| 469 | 468 | |
| 470 | 469 | /// 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 | 167 | const file = try std.fs.cwd().openFile(path, .{ .mode = .write_only }); |
| 168 | 168 | defer file.close(); |
| 169 | 169 | |
| 170 | try file.writer().writeAll(name); | |
| 170 | try file.deprecatedWriter().writeAll(name); | |
| 171 | 171 | return; |
| 172 | 172 | }, |
| 173 | 173 | .windows => { |
| ... | ... | @@ -281,7 +281,7 @@ pub fn getName(self: Thread, buffer_ptr: *[max_name_len:0]u8) GetNameError!?[]co |
| 281 | 281 | const file = try std.fs.cwd().openFile(path, .{}); |
| 282 | 282 | defer file.close(); |
| 283 | 283 | |
| 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]); | |
| 285 | 285 | |
| 286 | 286 | return if (data_len >= 1) buffer[0 .. data_len - 1] else null; |
| 287 | 287 | }, |
| ... | ... | @@ -1163,7 +1163,7 @@ const LinuxThreadImpl = struct { |
| 1163 | 1163 | |
| 1164 | 1164 | fn getCurrentId() Id { |
| 1165 | 1165 | return tls_thread_id orelse { |
| 1166 | const tid = @as(u32, @bitCast(linux.gettid())); | |
| 1166 | const tid: u32 = @bitCast(linux.gettid()); | |
| 1167 | 1167 | tls_thread_id = tid; |
| 1168 | 1168 | return tid; |
| 1169 | 1169 | }; |
lib/std/Uri.zig+153-129| ... | ... | @@ -1,6 +1,10 @@ |
| 1 | 1 | //! Uniform Resource Identifier (URI) parsing roughly adhering to <https://tools.ietf.org/html/rfc3986>. |
| 2 | 2 | //! Does not do perfect grammar and character class checking, but should be robust against URIs in the wild. |
| 3 | 3 | |
| 4 | const std = @import("std.zig"); | |
| 5 | const testing = std.testing; | |
| 6 | const Uri = @This(); | |
| 7 | ||
| 4 | 8 | scheme: []const u8, |
| 5 | 9 | user: ?Component = null, |
| 6 | 10 | password: ?Component = null, |
| ... | ... | @@ -34,27 +38,15 @@ pub const Component = union(enum) { |
| 34 | 38 | return switch (component) { |
| 35 | 39 | .raw => |raw| raw, |
| 36 | 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 | 42 | else |
| 39 | 43 | percent_encoded, |
| 40 | 44 | }; |
| 41 | 45 | } |
| 42 | 46 | |
| 43 | pub fn format( | |
| 44 | component: Component, | |
| 45 | comptime fmt_str: []const u8, | |
| 46 | _: std.fmt.FormatOptions, | |
| 47 | writer: anytype, | |
| 48 | ) @TypeOf(writer).Error!void { | |
| 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), | |
| 47 | pub fn formatRaw(component: Component, w: *std.io.Writer) std.io.Writer.Error!void { | |
| 48 | switch (component) { | |
| 49 | .raw => |raw| try w.writeAll(raw), | |
| 58 | 50 | .percent_encoded => |percent_encoded| { |
| 59 | 51 | var start: usize = 0; |
| 60 | 52 | var index: usize = 0; |
| ... | ... | @@ -63,51 +55,75 @@ pub const Component = union(enum) { |
| 63 | 55 | if (percent_encoded.len - index < 2) continue; |
| 64 | 56 | const percent_encoded_char = |
| 65 | 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 | 59 | percent_encoded[start..percent], |
| 68 | 60 | percent_encoded_char, |
| 69 | 61 | }); |
| 70 | 62 | start = percent + 3; |
| 71 | 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) { | |
| 76 | .raw => |raw| try percentEncode(writer, raw, isUnreserved), | |
| 77 | .percent_encoded => |percent_encoded| try writer.writeAll(percent_encoded), | |
| 78 | } else if (comptime std.mem.eql(u8, fmt_str, "user")) switch (component) { | |
| 79 | .raw => |raw| try percentEncode(writer, raw, isUserChar), | |
| 80 | .percent_encoded => |percent_encoded| try writer.writeAll(percent_encoded), | |
| 81 | } else if (comptime std.mem.eql(u8, fmt_str, "password")) switch (component) { | |
| 82 | .raw => |raw| try percentEncode(writer, raw, isPasswordChar), | |
| 83 | .percent_encoded => |percent_encoded| try writer.writeAll(percent_encoded), | |
| 84 | } else if (comptime std.mem.eql(u8, fmt_str, "host")) switch (component) { | |
| 85 | .raw => |raw| try percentEncode(writer, raw, isHostChar), | |
| 86 | .percent_encoded => |percent_encoded| try writer.writeAll(percent_encoded), | |
| 87 | } else if (comptime std.mem.eql(u8, fmt_str, "path")) switch (component) { | |
| 88 | .raw => |raw| try percentEncode(writer, raw, isPathChar), | |
| 89 | .percent_encoded => |percent_encoded| try writer.writeAll(percent_encoded), | |
| 90 | } else if (comptime std.mem.eql(u8, fmt_str, "query")) switch (component) { | |
| 91 | .raw => |raw| try percentEncode(writer, raw, isQueryChar), | |
| 92 | .percent_encoded => |percent_encoded| try writer.writeAll(percent_encoded), | |
| 93 | } else if (comptime std.mem.eql(u8, fmt_str, "fragment")) switch (component) { | |
| 94 | .raw => |raw| try percentEncode(writer, raw, isFragmentChar), | |
| 95 | .percent_encoded => |percent_encoded| try writer.writeAll(percent_encoded), | |
| 96 | } else @compileError("invalid format string '" ++ fmt_str ++ "'"); | |
| 97 | } | |
| 98 | ||
| 99 | pub fn percentEncode( | |
| 100 | writer: anytype, | |
| 101 | raw: []const u8, | |
| 102 | comptime isValidChar: fn (u8) bool, | |
| 103 | ) @TypeOf(writer).Error!void { | |
| 67 | } | |
| 68 | } | |
| 69 | ||
| 70 | pub fn formatEscaped(component: Component, w: *std.io.Writer) std.io.Writer.Error!void { | |
| 71 | switch (component) { | |
| 72 | .raw => |raw| try percentEncode(w, raw, isUnreserved), | |
| 73 | .percent_encoded => |percent_encoded| try w.writeAll(percent_encoded), | |
| 74 | } | |
| 75 | } | |
| 76 | ||
| 77 | pub fn formatUser(component: Component, w: *std.io.Writer) std.io.Writer.Error!void { | |
| 78 | switch (component) { | |
| 79 | .raw => |raw| try percentEncode(w, raw, isUserChar), | |
| 80 | .percent_encoded => |percent_encoded| try w.writeAll(percent_encoded), | |
| 81 | } | |
| 82 | } | |
| 83 | ||
| 84 | pub fn formatPassword(component: Component, w: *std.io.Writer) std.io.Writer.Error!void { | |
| 85 | switch (component) { | |
| 86 | .raw => |raw| try percentEncode(w, raw, isPasswordChar), | |
| 87 | .percent_encoded => |percent_encoded| try w.writeAll(percent_encoded), | |
| 88 | } | |
| 89 | } | |
| 90 | ||
| 91 | pub fn formatHost(component: Component, w: *std.io.Writer) std.io.Writer.Error!void { | |
| 92 | switch (component) { | |
| 93 | .raw => |raw| try percentEncode(w, raw, isHostChar), | |
| 94 | .percent_encoded => |percent_encoded| try w.writeAll(percent_encoded), | |
| 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 | 120 | var start: usize = 0; |
| 105 | 121 | for (raw, 0..) |char, index| { |
| 106 | 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 | 124 | start = index + 1; |
| 109 | 125 | } |
| 110 | try writer.writeAll(raw[start..]); | |
| 126 | try w.writeAll(raw[start..]); | |
| 111 | 127 | } |
| 112 | 128 | }; |
| 113 | 129 | |
| ... | ... | @@ -224,91 +240,91 @@ pub fn parseAfterScheme(scheme: []const u8, text: []const u8) ParseError!Uri { |
| 224 | 240 | return uri; |
| 225 | 241 | } |
| 226 | 242 | |
| 227 | pub const WriteToStreamOptions = struct { | |
| 228 | /// When true, include the scheme part of the URI. | |
| 229 | scheme: bool = false, | |
| 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 | }; | |
| 243 | pub fn format(uri: *const Uri, writer: *std.io.Writer) std.io.Writer.Error!void { | |
| 244 | return writeToStream(uri, writer, .all); | |
| 245 | } | |
| 249 | 246 | |
| 250 | pub fn writeToStream( | |
| 251 | uri: Uri, | |
| 252 | options: WriteToStreamOptions, | |
| 253 | writer: anytype, | |
| 254 | ) @TypeOf(writer).Error!void { | |
| 255 | if (options.scheme) { | |
| 247 | pub fn writeToStream(uri: *const Uri, writer: *std.io.Writer, flags: Format.Flags) std.io.Writer.Error!void { | |
| 248 | if (flags.scheme) { | |
| 256 | 249 | try writer.print("{s}:", .{uri.scheme}); |
| 257 | if (options.authority and uri.host != null) { | |
| 250 | if (flags.authority and uri.host != null) { | |
| 258 | 251 | try writer.writeAll("//"); |
| 259 | 252 | } |
| 260 | 253 | } |
| 261 | if (options.authority) { | |
| 262 | if (options.authentication and uri.host != null) { | |
| 254 | if (flags.authority) { | |
| 255 | if (flags.authentication and uri.host != null) { | |
| 263 | 256 | if (uri.user) |user| { |
| 264 | try writer.print("{user}", .{user}); | |
| 257 | try user.formatUser(writer); | |
| 265 | 258 | if (uri.password) |password| { |
| 266 | try writer.print(":{password}", .{password}); | |
| 259 | try writer.writeByte(':'); | |
| 260 | try password.formatPassword(writer); | |
| 267 | 261 | } |
| 268 | 262 | try writer.writeByte('@'); |
| 269 | 263 | } |
| 270 | 264 | } |
| 271 | 265 | if (uri.host) |host| { |
| 272 | try writer.print("{host}", .{host}); | |
| 273 | if (options.port) { | |
| 266 | try host.formatHost(writer); | |
| 267 | if (flags.port) { | |
| 274 | 268 | if (uri.port) |port| try writer.print(":{d}", .{port}); |
| 275 | 269 | } |
| 276 | 270 | } |
| 277 | 271 | } |
| 278 | if (options.path) { | |
| 279 | try writer.print("{path}", .{ | |
| 280 | if (uri.path.isEmpty()) Uri.Component{ .percent_encoded = "/" } else uri.path, | |
| 281 | }); | |
| 282 | if (options.query) { | |
| 283 | if (uri.query) |query| try writer.print("?{query}", .{query}); | |
| 272 | if (flags.path) { | |
| 273 | const uri_path: Component = if (uri.path.isEmpty()) .{ .percent_encoded = "/" } else uri.path; | |
| 274 | try uri_path.formatPath(writer); | |
| 275 | if (flags.query) { | |
| 276 | if (uri.query) |query| { | |
| 277 | try writer.writeByte('?'); | |
| 278 | try query.formatQuery(writer); | |
| 279 | } | |
| 284 | 280 | } |
| 285 | if (options.fragment) { | |
| 286 | if (uri.fragment) |fragment| try writer.print("#{fragment}", .{fragment}); | |
| 281 | if (flags.fragment) { | |
| 282 | if (uri.fragment) |fragment| { | |
| 283 | try writer.writeByte('#'); | |
| 284 | try fragment.formatFragment(writer); | |
| 285 | } | |
| 287 | 286 | } |
| 288 | 287 | } |
| 289 | 288 | } |
| 290 | 289 | |
| 291 | pub fn format( | |
| 292 | uri: Uri, | |
| 293 | comptime fmt_str: []const u8, | |
| 294 | _: std.fmt.FormatOptions, | |
| 295 | writer: anytype, | |
| 296 | ) @TypeOf(writer).Error!void { | |
| 297 | const scheme = comptime std.mem.indexOfScalar(u8, fmt_str, ';') != null or fmt_str.len == 0; | |
| 298 | const authentication = comptime std.mem.indexOfScalar(u8, fmt_str, '@') != null or fmt_str.len == 0; | |
| 299 | const authority = comptime std.mem.indexOfScalar(u8, fmt_str, '+') != null or fmt_str.len == 0; | |
| 300 | const path = comptime std.mem.indexOfScalar(u8, fmt_str, '/') != null or fmt_str.len == 0; | |
| 301 | const query = comptime std.mem.indexOfScalar(u8, fmt_str, '?') != null or fmt_str.len == 0; | |
| 302 | const fragment = comptime std.mem.indexOfScalar(u8, fmt_str, '#') != null or fmt_str.len == 0; | |
| 303 | ||
| 304 | return writeToStream(uri, .{ | |
| 305 | .scheme = scheme, | |
| 306 | .authentication = authentication, | |
| 307 | .authority = authority, | |
| 308 | .path = path, | |
| 309 | .query = query, | |
| 310 | .fragment = fragment, | |
| 311 | }, writer); | |
| 290 | pub const Format = struct { | |
| 291 | uri: *const Uri, | |
| 292 | flags: Flags = .{}, | |
| 293 | ||
| 294 | pub const Flags = struct { | |
| 295 | /// When true, include the scheme part of the URI. | |
| 296 | scheme: bool = false, | |
| 297 | /// When true, include the user and password part of the URI. Ignored if `authority` is false. | |
| 298 | authentication: bool = false, | |
| 299 | /// When true, include the authority part of the URI. | |
| 300 | authority: bool = false, | |
| 301 | /// When true, include the path part of the URI. | |
| 302 | path: bool = false, | |
| 303 | /// When true, include the query part of the URI. Ignored when `path` is false. | |
| 304 | query: bool = false, | |
| 305 | /// When true, include the fragment part of the URI. Ignored when `path` is false. | |
| 306 | fragment: bool = false, | |
| 307 | /// When true, include the port part of the URI. Ignored when `port` is null. | |
| 308 | port: bool = true, | |
| 309 | ||
| 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 | ||
| 326 | pub fn fmt(uri: *const Uri, flags: Format.Flags) std.fmt.Formatter(Format, Format.default) { | |
| 327 | return .{ .data = .{ .uri = uri, .flags = flags } }; | |
| 312 | 328 | } |
| 313 | 329 | |
| 314 | 330 | /// Parses the URI or returns an error. |
| ... | ... | @@ -445,14 +461,13 @@ test remove_dot_segments { |
| 445 | 461 | |
| 446 | 462 | /// 5.2.3. Merge Paths |
| 447 | 463 | fn 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 | 465 | if (!base.isEmpty()) { |
| 450 | try aux.writer().print("{path}", .{base}); | |
| 451 | aux.pos = std.mem.lastIndexOfScalar(u8, aux.getWritten(), '/') orelse | |
| 452 | return remove_dot_segments(new); | |
| 466 | base.formatPath(&aux) catch return error.NoSpaceLeft; | |
| 467 | aux.end = std.mem.lastIndexOfScalar(u8, aux.buffered(), '/') orelse return remove_dot_segments(new); | |
| 453 | 468 | } |
| 454 | try aux.writer().print("/{s}", .{new}); | |
| 455 | const merged_path = remove_dot_segments(aux.getWritten()); | |
| 469 | aux.print("/{s}", .{new}) catch return error.NoSpaceLeft; | |
| 470 | const merged_path = remove_dot_segments(aux.buffered()); | |
| 456 | 471 | aux_buf.* = aux_buf.*[merged_path.percent_encoded.len..]; |
| 457 | 472 | return merged_path; |
| 458 | 473 | } |
| ... | ... | @@ -812,8 +827,11 @@ test "Special test" { |
| 812 | 827 | test "URI percent encoding" { |
| 813 | 828 | try std.testing.expectFmt( |
| 814 | 829 | "%5C%C3%B6%2F%20%C3%A4%C3%B6%C3%9F%20~~.adas-https%3A%2F%2Fcanvas%3A123%2F%23ads%26%26sad", |
| 815 | "{%}", | |
| 816 | .{Component{ .raw = "\\ö/ äöß ~~.adas-https://canvas:123/#ads&&sad" }}, | |
| 830 | "{f}", | |
| 831 | .{std.fmt.alt( | |
| 832 | @as(Component, .{ .raw = "\\ö/ äöß ~~.adas-https://canvas:123/#ads&&sad" }), | |
| 833 | .formatEscaped, | |
| 834 | )}, | |
| 817 | 835 | ); |
| 818 | 836 | } |
| 819 | 837 | |
| ... | ... | @@ -822,7 +840,10 @@ test "URI percent decoding" { |
| 822 | 840 | const expected = "\\ö/ äöß ~~.adas-https://canvas:123/#ads&&sad"; |
| 823 | 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".*; |
| 824 | 842 | |
| 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 | )}); | |
| 826 | 847 | |
| 827 | 848 | var output: [expected.len]u8 = undefined; |
| 828 | 849 | try std.testing.expectEqualStrings(percentDecodeBackwards(&output, &input), expected); |
| ... | ... | @@ -834,7 +855,10 @@ test "URI percent decoding" { |
| 834 | 855 | const expected = "/abc%"; |
| 835 | 856 | var input = expected.*; |
| 836 | 857 | |
| 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 | )}); | |
| 838 | 862 | |
| 839 | 863 | var output: [expected.len]u8 = undefined; |
| 840 | 864 | try std.testing.expectEqualStrings(percentDecodeBackwards(&output, &input), expected); |
| ... | ... | @@ -848,7 +872,9 @@ test "URI query encoding" { |
| 848 | 872 | const parsed = try Uri.parse(address); |
| 849 | 873 | |
| 850 | 874 | // 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 | } |
| 853 | 879 | |
| 854 | 880 | test "format" { |
| ... | ... | @@ -862,7 +888,9 @@ test "format" { |
| 862 | 888 | .query = null, |
| 863 | 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 | } |
| 867 | 895 | |
| 868 | 896 | test "URI malformed input" { |
| ... | ... | @@ -870,7 +898,3 @@ test "URI malformed input" { |
| 870 | 898 | try std.testing.expectError(error.InvalidFormat, std.Uri.parse("http://]@[")); |
| 871 | 899 | try std.testing.expectError(error.InvalidFormat, std.Uri.parse("http://lo]s\x85hc@[/8\x10?0Q")); |
| 872 | 900 | } |
| 873 | ||
| 874 | const std = @import("std.zig"); | |
| 875 | const testing = std.testing; | |
| 876 | const 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 | 338 | @memcpy(self.items[old_len..][0..items.len], items); |
| 339 | 339 | } |
| 340 | 340 | |
| 341 | pub const Writer = if (T != u8) | |
| 342 | @compileError("The Writer interface is only defined for ArrayList(u8) " ++ | |
| 343 | "but the given type is ArrayList(" ++ @typeName(T) ++ ")") | |
| 344 | else | |
| 345 | std.io.Writer(*Self, Allocator.Error, appendWrite); | |
| 341 | pub fn print(self: *Self, comptime fmt: []const u8, args: anytype) error{OutOfMemory}!void { | |
| 342 | const gpa = self.allocator; | |
| 343 | var unmanaged = self.moveToUnmanaged(); | |
| 344 | defer self.* = unmanaged.toManaged(gpa); | |
| 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); | |
| 346 | 349 | |
| 347 | 350 | /// Initializes a Writer which will append to the list. |
| 348 | 351 | pub fn writer(self: *Self) Writer { |
| ... | ... | @@ -350,14 +353,14 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?mem.Alignment) ty |
| 350 | 353 | } |
| 351 | 354 | |
| 352 | 355 | /// 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 | 357 | /// Invalidates element pointers if additional memory is needed. |
| 355 | 358 | fn appendWrite(self: *Self, m: []const u8) Allocator.Error!usize { |
| 356 | 359 | try self.appendSlice(m); |
| 357 | 360 | return m.len; |
| 358 | 361 | } |
| 359 | 362 | |
| 360 | pub const FixedWriter = std.io.Writer(*Self, Allocator.Error, appendWriteFixed); | |
| 363 | pub const FixedWriter = std.io.GenericWriter(*Self, Allocator.Error, appendWriteFixed); | |
| 361 | 364 | |
| 362 | 365 | /// Initializes a Writer which will append to the list but will return |
| 363 | 366 | /// `error.OutOfMemory` rather than increasing capacity. |
| ... | ... | @@ -365,7 +368,7 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?mem.Alignment) ty |
| 365 | 368 | return .{ .context = self }; |
| 366 | 369 | } |
| 367 | 370 | |
| 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 | 372 | fn appendWriteFixed(self: *Self, m: []const u8) error{OutOfMemory}!usize { |
| 370 | 373 | const available_capacity = self.capacity - self.items.len; |
| 371 | 374 | if (m.len > available_capacity) |
| ... | ... | @@ -933,40 +936,56 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?mem.Alig |
| 933 | 936 | @memcpy(self.items[old_len..][0..items.len], items); |
| 934 | 937 | } |
| 935 | 938 | |
| 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 | 957 | pub const WriterContext = struct { |
| 937 | 958 | self: *Self, |
| 938 | 959 | allocator: Allocator, |
| 939 | 960 | }; |
| 940 | 961 | |
| 962 | /// Deprecated in favor of `print` or `std.io.Writer.Allocating`. | |
| 941 | 963 | pub const Writer = if (T != u8) |
| 942 | 964 | @compileError("The Writer interface is only defined for ArrayList(u8) " ++ |
| 943 | 965 | "but the given type is ArrayList(" ++ @typeName(T) ++ ")") |
| 944 | 966 | else |
| 945 | std.io.Writer(WriterContext, Allocator.Error, appendWrite); | |
| 967 | std.io.GenericWriter(WriterContext, Allocator.Error, appendWrite); | |
| 946 | 968 | |
| 947 | /// Initializes a Writer which will append to the list. | |
| 969 | /// Deprecated in favor of `print` or `std.io.Writer.Allocating`. | |
| 948 | 970 | pub fn writer(self: *Self, gpa: Allocator) Writer { |
| 949 | 971 | return .{ .context = .{ .self = self, .allocator = gpa } }; |
| 950 | 972 | } |
| 951 | 973 | |
| 952 | /// Same as `append` except it returns the number of bytes written, | |
| 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. | |
| 974 | /// Deprecated in favor of `print` or `std.io.Writer.Allocating`. | |
| 956 | 975 | fn appendWrite(context: WriterContext, m: []const u8) Allocator.Error!usize { |
| 957 | 976 | try context.self.appendSlice(context.allocator, m); |
| 958 | 977 | return m.len; |
| 959 | 978 | } |
| 960 | 979 | |
| 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); | |
| 962 | 982 | |
| 963 | /// Initializes a Writer which will append to the list but will return | |
| 964 | /// `error.OutOfMemory` rather than increasing capacity. | |
| 983 | /// Deprecated in favor of `print` or `std.io.Writer.Allocating`. | |
| 965 | 984 | pub fn fixedWriter(self: *Self) FixedWriter { |
| 966 | 985 | return .{ .context = self }; |
| 967 | 986 | } |
| 968 | 987 | |
| 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 | 989 | fn appendWriteFixed(self: *Self, m: []const u8) error{OutOfMemory}!usize { |
| 971 | 990 | const available_capacity = self.capacity - self.items.len; |
| 972 | 991 | if (m.len > available_capacity) |
lib/std/ascii.zig+45| ... | ... | @@ -10,6 +10,10 @@ |
| 10 | 10 | |
| 11 | 11 | const std = @import("std"); |
| 12 | 12 | |
| 13 | pub const lowercase = "abcdefghijklmnopqrstuvwxyz"; | |
| 14 | pub const uppercase = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; | |
| 15 | pub const letters = lowercase ++ uppercase; | |
| 16 | ||
| 13 | 17 | /// The C0 control codes of the ASCII encoding. |
| 14 | 18 | /// |
| 15 | 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 | 439 | pub fn lessThanIgnoreCase(lhs: []const u8, rhs: []const u8) bool { |
| 436 | 440 | return orderIgnoreCase(lhs, rhs) == .lt; |
| 437 | 441 | } |
| 442 | ||
| 443 | pub 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. | |
| 470 | pub 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 | ||
| 477 | test 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 | 108 | } |
| 109 | 109 | } |
| 110 | 110 | |
| 111 | // dest must be compatible with std.io.Writer's writeAll interface | |
| 111 | // dest must be compatible with std.io.GenericWriter's writeAll interface | |
| 112 | 112 | pub fn encodeWriter(encoder: *const Base64Encoder, dest: anytype, source: []const u8) !void { |
| 113 | 113 | var chunker = window(u8, source, 3, 3); |
| 114 | 114 | while (chunker.next()) |chunk| { |
| ... | ... | @@ -118,8 +118,8 @@ pub const Base64Encoder = struct { |
| 118 | 118 | } |
| 119 | 119 | } |
| 120 | 120 | |
| 121 | // destWriter must be compatible with std.io.Writer's writeAll interface | |
| 122 | // sourceReader must be compatible with std.io.Reader's read interface | |
| 121 | // destWriter must be compatible with std.io.GenericWriter's writeAll interface | |
| 122 | // sourceReader must be compatible with `std.io.GenericReader` read interface | |
| 123 | 123 | pub fn encodeFromReaderToWriter(encoder: *const Base64Encoder, destWriter: anytype, sourceReader: anytype) !void { |
| 124 | 124 | while (true) { |
| 125 | 125 | var tempSource: [3]u8 = undefined; |
lib/std/bounded_array.zig+2-2| ... | ... | @@ -277,7 +277,7 @@ pub fn BoundedArrayAligned( |
| 277 | 277 | @compileError("The Writer interface is only defined for BoundedArray(u8, ...) " ++ |
| 278 | 278 | "but the given type is BoundedArray(" ++ @typeName(T) ++ ", ...)") |
| 279 | 279 | else |
| 280 | std.io.Writer(*Self, error{Overflow}, appendWrite); | |
| 280 | std.io.GenericWriter(*Self, error{Overflow}, appendWrite); | |
| 281 | 281 | |
| 282 | 282 | /// Initializes a writer which will write into the array. |
| 283 | 283 | pub fn writer(self: *Self) Writer { |
| ... | ... | @@ -285,7 +285,7 @@ pub fn BoundedArrayAligned( |
| 285 | 285 | } |
| 286 | 286 | |
| 287 | 287 | /// 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 | 289 | fn appendWrite(self: *Self, m: []const u8) error{Overflow}!usize { |
| 290 | 290 | try self.appendSlice(m); |
| 291 | 291 | return m.len; |
lib/std/builtin.zig+2-10| ... | ... | @@ -34,24 +34,16 @@ pub const StackTrace = struct { |
| 34 | 34 | index: usize, |
| 35 | 35 | instruction_addresses: []usize, |
| 36 | 36 | |
| 37 | pub fn format( | |
| 38 | self: StackTrace, | |
| 39 | comptime fmt: []const u8, | |
| 40 | options: std.fmt.FormatOptions, | |
| 41 | writer: anytype, | |
| 42 | ) !void { | |
| 43 | if (fmt.len != 0) std.fmt.invalidFmtError(fmt, self); | |
| 44 | ||
| 37 | pub fn format(self: StackTrace, writer: *std.io.Writer) std.io.Writer.Error!void { | |
| 45 | 38 | // TODO: re-evaluate whether to use format() methods at all. |
| 46 | 39 | // Until then, avoid an error when using GeneralPurposeAllocator with WebAssembly |
| 47 | 40 | // where it tries to call detectTTYConfig here. |
| 48 | 41 | if (builtin.os.tag == .freestanding) return; |
| 49 | 42 | |
| 50 | _ = options; | |
| 51 | 43 | const debug_info = std.debug.getSelfDebugInfo() catch |err| { |
| 52 | 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 | 47 | try writer.writeAll("\n"); |
| 56 | 48 | std.debug.writeStackTrace(self, writer, debug_info, tty_config) catch |err| { |
| 57 | 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 | 16 | hasher: HasherType, |
| 17 | 17 | |
| 18 | 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); | |
| 20 | 20 | |
| 21 | 21 | pub fn read(self: *@This(), buf: []u8) Error!usize { |
| 22 | 22 | const amt = try self.child_reader.read(buf); |
| ... | ... | @@ -43,7 +43,7 @@ pub fn HashedWriter(WriterType: type, HasherType: type) type { |
| 43 | 43 | hasher: HasherType, |
| 44 | 44 | |
| 45 | 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); | |
| 47 | 47 | |
| 48 | 48 | pub fn write(self: *@This(), buf: []const u8) Error!usize { |
| 49 | 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 | 355 | |
| 356 | 356 | // Writer interface |
| 357 | 357 | |
| 358 | pub const Writer = io.Writer(*Self, Error, write); | |
| 358 | pub const Writer = io.GenericWriter(*Self, Error, write); | |
| 359 | 359 | pub const Error = BlockWriterType.Error; |
| 360 | 360 | |
| 361 | 361 | /// Write `input` of uncompressed data. |
| ... | ... | @@ -512,7 +512,7 @@ fn SimpleCompressor( |
| 512 | 512 | |
| 513 | 513 | // Writer interface |
| 514 | 514 | |
| 515 | pub const Writer = io.Writer(*Self, Error, write); | |
| 515 | pub const Writer = io.GenericWriter(*Self, Error, write); | |
| 516 | 516 | pub const Error = BlockWriterType.Error; |
| 517 | 517 | |
| 518 | 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 | 341 | |
| 342 | 342 | // Reader interface |
| 343 | 343 | |
| 344 | pub const Reader = std.io.Reader(*Self, Error, read); | |
| 344 | pub const Reader = std.io.GenericReader(*Self, Error, read); | |
| 345 | 345 | |
| 346 | 346 | /// Returns the number of bytes read. It may be less than buffer.len. |
| 347 | 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 | 30 | Allocator.Error || |
| 31 | 31 | error{ CorruptInput, EndOfStream, Overflow }; |
| 32 | 32 | |
| 33 | pub const Reader = std.io.Reader(*Self, Error, read); | |
| 33 | pub const Reader = std.io.GenericReader(*Self, Error, read); | |
| 34 | 34 | |
| 35 | 35 | allocator: Allocator, |
| 36 | 36 | in_reader: ReaderType, |
lib/std/compress/xz.zig+1-1| ... | ... | @@ -34,7 +34,7 @@ pub fn Decompress(comptime ReaderType: type) type { |
| 34 | 34 | const Self = @This(); |
| 35 | 35 | |
| 36 | 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); | |
| 38 | 38 | |
| 39 | 39 | allocator: Allocator, |
| 40 | 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 | 27 | ReaderType.Error || |
| 28 | 28 | DecodeError || |
| 29 | 29 | Allocator.Error; |
| 30 | pub const Reader = std.io.Reader(*Self, Error, read); | |
| 30 | pub const Reader = std.io.GenericReader(*Self, Error, read); | |
| 31 | 31 | |
| 32 | 32 | allocator: Allocator, |
| 33 | 33 | inner_reader: ReaderType, |
lib/std/compress/zstandard.zig+1-1| ... | ... | @@ -50,7 +50,7 @@ pub fn Decompressor(comptime ReaderType: type) type { |
| 50 | 50 | OutOfMemory, |
| 51 | 51 | }; |
| 52 | 52 | |
| 53 | pub const Reader = std.io.Reader(*Self, Error, read); | |
| 53 | pub const Reader = std.io.GenericReader(*Self, Error, read); | |
| 54 | 54 | |
| 55 | 55 | pub fn init(source: ReaderType, options: DecompressorOptions) Self { |
| 56 | 56 | return .{ |
lib/std/compress/zstandard/readers.zig+1-1| ... | ... | @@ -4,7 +4,7 @@ pub const ReversedByteReader = struct { |
| 4 | 4 | remaining_bytes: usize, |
| 5 | 5 | bytes: []const u8, |
| 6 | 6 | |
| 7 | const Reader = std.io.Reader(*ReversedByteReader, error{}, readFn); | |
| 7 | const Reader = std.io.GenericReader(*ReversedByteReader, error{}, readFn); | |
| 8 | 8 | |
| 9 | 9 | pub fn init(bytes: []const u8) ReversedByteReader { |
| 10 | 10 | return .{ |
lib/std/crypto/25519/curve25519.zig+2-2| ... | ... | @@ -124,9 +124,9 @@ test "curve25519" { |
| 124 | 124 | const p = try Curve25519.basePoint.clampedMul(s); |
| 125 | 125 | try p.rejectIdentity(); |
| 126 | 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 | 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"); | |
| 130 | 130 | |
| 131 | 131 | try Curve25519.rejectNonCanonical(s); |
| 132 | 132 | s[31] |= 0x80; |
lib/std/crypto/25519/ed25519.zig+3-3| ... | ... | @@ -509,8 +509,8 @@ test "key pair creation" { |
| 509 | 509 | _ = try fmt.hexToBytes(seed[0..], "8052030376d47112be7f73ed7a019293dd12ad910b654455798b4667d73de166"); |
| 510 | 510 | const key_pair = try Ed25519.KeyPair.generateDeterministic(seed); |
| 511 | 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"); | |
| 513 | try std.testing.expectEqualStrings(try std.fmt.bufPrint(&buf, "{s}", .{std.fmt.fmtSliceHexUpper(&key_pair.public_key.toBytes())}), "2D6F7455D97B4A3A10D7293909D1A4F2058CB9A370E43FA8154BB280DB839083"); | |
| 512 | try std.testing.expectEqualStrings(try std.fmt.bufPrint(&buf, "{X}", .{&key_pair.secret_key.toBytes()}), "8052030376D47112BE7F73ED7A019293DD12AD910B654455798B4667D73DE1662D6F7455D97B4A3A10D7293909D1A4F2058CB9A370E43FA8154BB280DB839083"); | |
| 513 | try std.testing.expectEqualStrings(try std.fmt.bufPrint(&buf, "{X}", .{&key_pair.public_key.toBytes()}), "2D6F7455D97B4A3A10D7293909D1A4F2058CB9A370E43FA8154BB280DB839083"); | |
| 514 | 514 | } |
| 515 | 515 | |
| 516 | 516 | test "signature" { |
| ... | ... | @@ -520,7 +520,7 @@ test "signature" { |
| 520 | 520 | |
| 521 | 521 | const sig = try key_pair.sign("test", null); |
| 522 | 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 | 524 | try sig.verify("test", key_pair.public_key); |
| 525 | 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 | 546 | var b = Edwards25519.basePoint; |
| 547 | 547 | const pk = try b.mul(s); |
| 548 | 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"); | |
| 550 | 550 | |
| 551 | 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 | 175 | test "ristretto255" { |
| 176 | 176 | const p = Ristretto255.basePoint; |
| 177 | 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"); | |
| 179 | 179 | |
| 180 | 180 | var r: [Ristretto255.encoded_length]u8 = undefined; |
| 181 | 181 | _ = try fmt.hexToBytes(r[0..], "6a493210f7499cd17fecb510ae0cea23a110e8d5b901f8acadd3095c73a3b919"); |
| 182 | 182 | var q = try Ristretto255.fromBytes(r); |
| 183 | 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"); | |
| 185 | 185 | |
| 186 | 186 | const s = [_]u8{15} ++ [_]u8{0} ** 31; |
| 187 | 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"); | |
| 189 | 189 | |
| 190 | 190 | try std.testing.expect(p.dbl().dbl().dbl().dbl().equivalent(w.add(p))); |
| 191 | 191 | |
| 192 | 192 | const h = [_]u8{69} ** 32 ++ [_]u8{42} ** 32; |
| 193 | 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 | 850 | var y = x.toBytes(); |
| 851 | 851 | try rejectNonCanonical(y); |
| 852 | 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"); | |
| 854 | 854 | |
| 855 | 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 | } |
| 858 | 858 | |
| 859 | 859 | test "non-canonical scalar25519" { |
| ... | ... | @@ -867,7 +867,7 @@ test "mulAdd overflow check" { |
| 867 | 867 | const c: [32]u8 = [_]u8{0xff} ** 32; |
| 868 | 868 | const x = mulAdd(a, b, c); |
| 869 | 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 | } |
| 872 | 872 | |
| 873 | 873 | test "scalar field inversion" { |
lib/std/crypto/aegis.zig+1-1| ... | ... | @@ -803,7 +803,7 @@ fn AegisMac(comptime T: type) type { |
| 803 | 803 | } |
| 804 | 804 | |
| 805 | 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); | |
| 807 | 807 | |
| 808 | 808 | fn write(self: *Mac, bytes: []const u8) Error!usize { |
| 809 | 809 | self.update(bytes); |
lib/std/crypto/benchmark.zig+1-1| ... | ... | @@ -458,7 +458,7 @@ fn mode(comptime x: comptime_int) comptime_int { |
| 458 | 458 | } |
| 459 | 459 | |
| 460 | 460 | pub fn main() !void { |
| 461 | const stdout = std.io.getStdOut().writer(); | |
| 461 | const stdout = std.fs.File.stdout().deprecatedWriter(); | |
| 462 | 462 | |
| 463 | 463 | var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator); |
| 464 | 464 | defer arena.deinit(); |
lib/std/crypto/blake2.zig+1-1| ... | ... | @@ -187,7 +187,7 @@ pub fn Blake2s(comptime out_bits: usize) type { |
| 187 | 187 | } |
| 188 | 188 | |
| 189 | 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); | |
| 191 | 191 | |
| 192 | 192 | fn write(self: *Self, bytes: []const u8) Error!usize { |
| 193 | 193 | self.update(bytes); |
lib/std/crypto/blake3.zig+1-1| ... | ... | @@ -476,7 +476,7 @@ pub const Blake3 = struct { |
| 476 | 476 | } |
| 477 | 477 | |
| 478 | 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); | |
| 480 | 480 | |
| 481 | 481 | fn write(self: *Blake3, bytes: []const u8) Error!usize { |
| 482 | 482 | self.update(bytes); |
lib/std/crypto/chacha20.zig+2-2| ... | ... | @@ -1145,7 +1145,7 @@ test "xchacha20" { |
| 1145 | 1145 | var c: [m.len]u8 = undefined; |
| 1146 | 1146 | XChaCha20IETF.xor(c[0..], m[0..], 0, key, nonce); |
| 1147 | 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 | 1151 | const ad = "Additional data"; |
| ... | ... | @@ -1154,7 +1154,7 @@ test "xchacha20" { |
| 1154 | 1154 | var out: [m.len]u8 = undefined; |
| 1155 | 1155 | try XChaCha20Poly1305.decrypt(out[0..], c[0..m.len], c[m.len..].*, ad, nonce, key); |
| 1156 | 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 | 1158 | try testing.expectEqualSlices(u8, out[0..], m); |
| 1159 | 1159 | c[0] +%= 1; |
| 1160 | 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 | 45 | self.data.ptr = begin; |
| 46 | 46 | } |
| 47 | 47 | |
| 48 | pub const Writer = std.io.Writer(*ArrayListReverse, Error, prependSliceSize); | |
| 48 | pub const Writer = std.io.GenericWriter(*ArrayListReverse, Error, prependSliceSize); | |
| 49 | 49 | /// Warning: This writer writes backwards. `fn print` will NOT work as expected. |
| 50 | 50 | pub fn writer(self: *ArrayListReverse) Writer { |
| 51 | 51 | return .{ .context = self }; |
lib/std/crypto/ml_kem.zig+6-6| ... | ... | @@ -1741,7 +1741,7 @@ test "NIST KAT test" { |
| 1741 | 1741 | for (0..100) |i| { |
| 1742 | 1742 | g.fill(&seed); |
| 1743 | 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 | 1745 | var g2 = NistDRBG.init(seed); |
| 1746 | 1746 | |
| 1747 | 1747 | // This is not equivalent to g2.fill(kseed[:]). As the reference |
| ... | ... | @@ -1756,16 +1756,16 @@ test "NIST KAT test" { |
| 1756 | 1756 | const e = kp.public_key.encaps(eseed); |
| 1757 | 1757 | const ss2 = try kp.secret_key.decaps(&e.ciphertext); |
| 1758 | 1758 | try testing.expectEqual(ss2, e.shared_secret); |
| 1759 | try std.fmt.format(fw, "pk = {s}\n", .{std.fmt.fmtSliceHexUpper(&kp.public_key.toBytes())}); | |
| 1760 | try std.fmt.format(fw, "sk = {s}\n", .{std.fmt.fmtSliceHexUpper(&kp.secret_key.toBytes())}); | |
| 1761 | try std.fmt.format(fw, "ct = {s}\n", .{std.fmt.fmtSliceHexUpper(&e.ciphertext)}); | |
| 1762 | try std.fmt.format(fw, "ss = {s}\n\n", .{std.fmt.fmtSliceHexUpper(&e.shared_secret)}); | |
| 1759 | try std.fmt.format(fw, "pk = {X}\n", .{&kp.public_key.toBytes()}); | |
| 1760 | try std.fmt.format(fw, "sk = {X}\n", .{&kp.secret_key.toBytes()}); | |
| 1761 | try std.fmt.format(fw, "ct = {X}\n", .{&e.ciphertext}); | |
| 1762 | try std.fmt.format(fw, "ss = {X}\n\n", .{&e.shared_secret}); | |
| 1763 | 1763 | } |
| 1764 | 1764 | |
| 1765 | 1765 | var out: [32]u8 = undefined; |
| 1766 | 1766 | f.final(&out); |
| 1767 | 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 | 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 | 269 | } |
| 270 | 270 | |
| 271 | 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); | |
| 273 | 273 | |
| 274 | 274 | fn write(self: *Self, bytes: []const u8) Error!usize { |
| 275 | 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 | 376 | } |
| 377 | 377 | |
| 378 | 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); | |
| 380 | 380 | |
| 381 | 381 | fn write(self: *Self, bytes: []const u8) Error!usize { |
| 382 | 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 | 82 | } |
| 83 | 83 | |
| 84 | 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); | |
| 86 | 86 | |
| 87 | 87 | fn write(self: *Self, bytes: []const u8) Error!usize { |
| 88 | 88 | self.update(bytes); |
| ... | ... | @@ -193,7 +193,7 @@ fn ShakeLike(comptime security_level: u11, comptime default_delim: u8, comptime |
| 193 | 193 | } |
| 194 | 194 | |
| 195 | 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); | |
| 197 | 197 | |
| 198 | 198 | fn write(self: *Self, bytes: []const u8) Error!usize { |
| 199 | 199 | self.update(bytes); |
| ... | ... | @@ -286,7 +286,7 @@ fn CShakeLike(comptime security_level: u11, comptime default_delim: u8, comptime |
| 286 | 286 | } |
| 287 | 287 | |
| 288 | 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); | |
| 290 | 290 | |
| 291 | 291 | fn write(self: *Self, bytes: []const u8) Error!usize { |
| 292 | 292 | self.update(bytes); |
| ... | ... | @@ -392,7 +392,7 @@ fn KMacLike(comptime security_level: u11, comptime default_delim: u8, comptime r |
| 392 | 392 | } |
| 393 | 393 | |
| 394 | 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); | |
| 396 | 396 | |
| 397 | 397 | fn write(self: *Self, bytes: []const u8) Error!usize { |
| 398 | 398 | self.update(bytes); |
| ... | ... | @@ -484,7 +484,7 @@ fn TupleHashLike(comptime security_level: u11, comptime default_delim: u8, compt |
| 484 | 484 | } |
| 485 | 485 | |
| 486 | 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); | |
| 488 | 488 | |
| 489 | 489 | fn write(self: *Self, bytes: []const u8) Error!usize { |
| 490 | 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 | 240 | } |
| 241 | 241 | |
| 242 | 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); | |
| 244 | 244 | |
| 245 | 245 | fn write(self: *Self, bytes: []const u8) Error!usize { |
| 246 | 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 | 1512 | const locked = if (key_log_file.lock(.exclusive)) |_| true else |_| false; |
| 1513 | 1513 | defer if (locked) key_log_file.unlock(); |
| 1514 | 1514 | key_log_file.seekFromEnd(0) catch {}; |
| 1515 | inline for (@typeInfo(@TypeOf(secrets)).@"struct".fields) |field| key_log_file.writer().print("{s}" ++ | |
| 1516 | (if (@hasField(@TypeOf(context), "counter")) "_{d}" else "") ++ " {} {}\n", .{field.name} ++ | |
| 1515 | inline for (@typeInfo(@TypeOf(secrets)).@"struct".fields) |field| key_log_file.deprecatedWriter().print("{s}" ++ | |
| 1516 | (if (@hasField(@TypeOf(context), "counter")) "_{d}" else "") ++ " {x} {x}\n", .{field.name} ++ | |
| 1517 | 1517 | (if (@hasField(@TypeOf(context), "counter")) .{context.counter} else .{}) ++ .{ |
| 1518 | std.fmt.fmtSliceHexLower(context.client_random), | |
| 1519 | std.fmt.fmtSliceHexLower(@field(secrets, field.name)), | |
| 1518 | context.client_random, | |
| 1519 | @field(secrets, field.name), | |
| 1520 | 1520 | }) catch {}; |
| 1521 | 1521 | } |
| 1522 | 1522 |
lib/std/debug.zig+186-170| ... | ... | @@ -12,6 +12,7 @@ const windows = std.os.windows; |
| 12 | 12 | const native_arch = builtin.cpu.arch; |
| 13 | 13 | const native_os = builtin.os.tag; |
| 14 | 14 | const native_endian = native_arch.endian(); |
| 15 | const Writer = std.io.Writer; | |
| 15 | 16 | |
| 16 | 17 | pub const MemoryAccessor = @import("debug/MemoryAccessor.zig"); |
| 17 | 18 | pub const FixedBufferReader = @import("debug/FixedBufferReader.zig"); |
| ... | ... | @@ -204,13 +205,26 @@ pub fn unlockStdErr() void { |
| 204 | 205 | std.Progress.unlockStdErr(); |
| 205 | 206 | } |
| 206 | 207 | |
| 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. | |
| 214 | pub fn lockStderrWriter(buffer: []u8) *Writer { | |
| 215 | return std.Progress.lockStderrWriter(buffer); | |
| 216 | } | |
| 217 | ||
| 218 | pub fn unlockStderrWriter() void { | |
| 219 | std.Progress.unlockStderrWriter(); | |
| 220 | } | |
| 221 | ||
| 207 | 222 | /// 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. | |
| 209 | 224 | pub fn print(comptime fmt: []const u8, args: anytype) void { |
| 210 | lockStdErr(); | |
| 211 | defer unlockStdErr(); | |
| 212 | const stderr = io.getStdErr().writer(); | |
| 213 | nosuspend stderr.print(fmt, args) catch return; | |
| 225 | const bw = lockStderrWriter(&.{}); | |
| 226 | defer unlockStderrWriter(); | |
| 227 | nosuspend bw.print(fmt, args) catch return; | |
| 214 | 228 | } |
| 215 | 229 | |
| 216 | 230 | pub fn getStderrMutex() *std.Thread.Mutex { |
| ... | ... | @@ -232,50 +246,44 @@ pub fn getSelfDebugInfo() !*SelfInfo { |
| 232 | 246 | /// Tries to print a hexadecimal view of the bytes, unbuffered, and ignores any error returned. |
| 233 | 247 | /// Obtains the stderr mutex while dumping. |
| 234 | 248 | pub fn dumpHex(bytes: []const u8) void { |
| 235 | lockStdErr(); | |
| 236 | defer unlockStdErr(); | |
| 237 | dumpHexFallible(bytes) catch {}; | |
| 238 | } | |
| 239 | ||
| 240 | /// Prints a hexadecimal view of the bytes, unbuffered, returning any error that occurs. | |
| 241 | pub 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); | |
| 249 | const bw = lockStderrWriter(&.{}); | |
| 250 | defer unlockStderrWriter(); | |
| 251 | const ttyconf = std.io.tty.detectConfig(.stderr()); | |
| 252 | dumpHexFallible(bw, ttyconf, bytes) catch {}; | |
| 246 | 253 | } |
| 247 | 254 | |
| 248 | fn 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. | |
| 256 | pub fn dumpHexFallible(bw: *Writer, ttyconf: std.io.tty.Config, bytes: []const u8) !void { | |
| 249 | 257 | var chunks = mem.window(u8, bytes, 16, 16); |
| 250 | 258 | while (chunks.next()) |window| { |
| 251 | 259 | // 1. Print the address. |
| 252 | 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 | 262 | // We print the address in lowercase and the bytes in uppercase hexadecimal to distinguish them more. |
| 255 | 263 | // Also, make sure all lines are aligned by padding the address. |
| 256 | try writer.print("{x:0>[1]} ", .{ address, @sizeOf(usize) * 2 }); | |
| 257 | try ttyconf.setColor(writer, .reset); | |
| 264 | try bw.print("{x:0>[1]} ", .{ address, @sizeOf(usize) * 2 }); | |
| 265 | try ttyconf.setColor(bw, .reset); | |
| 258 | 266 | |
| 259 | 267 | // 2. Print the bytes. |
| 260 | 268 | for (window, 0..) |byte, index| { |
| 261 | try writer.print("{X:0>2} ", .{byte}); | |
| 262 | if (index == 7) try writer.writeByte(' '); | |
| 269 | try bw.print("{X:0>2} ", .{byte}); | |
| 270 | if (index == 7) try bw.writeByte(' '); | |
| 263 | 271 | } |
| 264 | try writer.writeByte(' '); | |
| 272 | try bw.writeByte(' '); | |
| 265 | 273 | if (window.len < 16) { |
| 266 | 274 | var missing_columns = (16 - window.len) * 3; |
| 267 | 275 | if (window.len < 8) missing_columns += 1; |
| 268 | try writer.writeByteNTimes(' ', missing_columns); | |
| 276 | try bw.splatByteAll(' ', missing_columns); | |
| 269 | 277 | } |
| 270 | 278 | |
| 271 | 279 | // 3. Print the characters. |
| 272 | 280 | for (window) |byte| { |
| 273 | 281 | if (std.ascii.isPrint(byte)) { |
| 274 | try writer.writeByte(byte); | |
| 282 | try bw.writeByte(byte); | |
| 275 | 283 | } else { |
| 276 | 284 | // Related: https://github.com/ziglang/zig/issues/7600 |
| 277 | 285 | if (ttyconf == .windows_api) { |
| 278 | try writer.writeByte('.'); | |
| 286 | try bw.writeByte('.'); | |
| 279 | 287 | continue; |
| 280 | 288 | } |
| 281 | 289 | |
| ... | ... | @@ -283,22 +291,23 @@ fn dumpHexInternal(bytes: []const u8, ttyconf: std.io.tty.Config, writer: anytyp |
| 283 | 291 | // We don't want to do this for all control codes because most control codes apart from |
| 284 | 292 | // the ones that Zig has escape sequences for are likely not very useful to print as symbols. |
| 285 | 293 | switch (byte) { |
| 286 | '\n' => try writer.writeAll("␊"), | |
| 287 | '\r' => try writer.writeAll("␍"), | |
| 288 | '\t' => try writer.writeAll("␉"), | |
| 289 | else => try writer.writeByte('.'), | |
| 294 | '\n' => try bw.writeAll("␊"), | |
| 295 | '\r' => try bw.writeAll("␍"), | |
| 296 | '\t' => try bw.writeAll("␉"), | |
| 297 | else => try bw.writeByte('.'), | |
| 290 | 298 | } |
| 291 | 299 | } |
| 292 | 300 | } |
| 293 | try writer.writeByte('\n'); | |
| 301 | try bw.writeByte('\n'); | |
| 294 | 302 | } |
| 295 | 303 | } |
| 296 | 304 | |
| 297 | test dumpHexInternal { | |
| 305 | test dumpHexFallible { | |
| 298 | 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); | |
| 300 | defer output.deinit(); | |
| 301 | try dumpHexInternal(bytes, .no_color, output.writer()); | |
| 307 | var aw: std.io.Writer.Allocating = .init(std.testing.allocator); | |
| 308 | defer aw.deinit(); | |
| 309 | ||
| 310 | try dumpHexFallible(&aw.writer, .no_color, bytes); | |
| 302 | 311 | const expected = try std.fmt.allocPrint(std.testing.allocator, |
| 303 | 312 | \\{x:0>[2]} 00 11 22 33 44 55 66 77 88 99 AA BB CC DD EE FF .."3DUfw........ |
| 304 | 313 | \\{x:0>[2]} 01 12 13 ... |
| ... | ... | @@ -309,34 +318,36 @@ test dumpHexInternal { |
| 309 | 318 | @sizeOf(usize) * 2, |
| 310 | 319 | }); |
| 311 | 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 | } |
| 314 | 323 | |
| 315 | 324 | /// Tries to print the current stack trace to stderr, unbuffered, and ignores any error returned. |
| 316 | /// TODO multithreaded awareness | |
| 317 | 325 | pub fn dumpCurrentStackTrace(start_addr: ?usize) void { |
| 318 | nosuspend { | |
| 319 | if (builtin.target.cpu.arch.isWasm()) { | |
| 320 | if (native_os == .wasi) { | |
| 321 | const stderr = io.getStdErr().writer(); | |
| 322 | stderr.print("Unable to dump stack trace: not implemented for Wasm\n", .{}) catch return; | |
| 323 | } | |
| 324 | return; | |
| 325 | } | |
| 326 | const stderr = io.getStdErr().writer(); | |
| 327 | if (builtin.strip_debug_info) { | |
| 328 | stderr.print("Unable to dump stack trace: debug info stripped\n", .{}) catch return; | |
| 329 | return; | |
| 326 | const stderr = lockStderrWriter(&.{}); | |
| 327 | defer unlockStderrWriter(); | |
| 328 | nosuspend dumpCurrentStackTraceToWriter(start_addr, stderr) catch return; | |
| 329 | } | |
| 330 | ||
| 331 | /// Prints the current stack trace to the provided writer. | |
| 332 | pub fn dumpCurrentStackTraceToWriter(start_addr: ?usize, writer: *Writer) !void { | |
| 333 | if (builtin.target.cpu.arch.isWasm()) { | |
| 334 | if (native_os == .wasi) { | |
| 335 | try writer.writeAll("Unable to dump stack trace: not implemented for Wasm\n"); | |
| 330 | 336 | } |
| 331 | const debug_info = getSelfDebugInfo() catch |err| { | |
| 332 | stderr.print("Unable to dump stack trace: Unable to open debug info: {s}\n", .{@errorName(err)}) catch return; | |
| 333 | return; | |
| 334 | }; | |
| 335 | writeCurrentStackTrace(stderr, debug_info, io.tty.detectConfig(io.getStdErr()), start_addr) catch |err| { | |
| 336 | stderr.print("Unable to dump stack trace: {s}\n", .{@errorName(err)}) catch return; | |
| 337 | return; | |
| 338 | }; | |
| 337 | return; | |
| 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 | } |
| 341 | 352 | |
| 342 | 353 | pub const have_ucontext = posix.ucontext_t != void; |
| ... | ... | @@ -402,16 +413,14 @@ pub inline fn getContext(context: *ThreadContext) bool { |
| 402 | 413 | /// Tries to print the stack trace starting from the supplied base pointer to stderr, |
| 403 | 414 | /// unbuffered, and ignores any error returned. |
| 404 | 415 | /// TODO multithreaded awareness |
| 405 | pub fn dumpStackTraceFromBase(context: *ThreadContext) void { | |
| 416 | pub fn dumpStackTraceFromBase(context: *ThreadContext, stderr: *Writer) void { | |
| 406 | 417 | nosuspend { |
| 407 | 418 | if (builtin.target.cpu.arch.isWasm()) { |
| 408 | 419 | if (native_os == .wasi) { |
| 409 | const stderr = io.getStdErr().writer(); | |
| 410 | 420 | stderr.print("Unable to dump stack trace: not implemented for Wasm\n", .{}) catch return; |
| 411 | 421 | } |
| 412 | 422 | return; |
| 413 | 423 | } |
| 414 | const stderr = io.getStdErr().writer(); | |
| 415 | 424 | if (builtin.strip_debug_info) { |
| 416 | 425 | stderr.print("Unable to dump stack trace: debug info stripped\n", .{}) catch return; |
| 417 | 426 | return; |
| ... | ... | @@ -420,7 +429,7 @@ pub fn dumpStackTraceFromBase(context: *ThreadContext) void { |
| 420 | 429 | stderr.print("Unable to dump stack trace: Unable to open debug info: {s}\n", .{@errorName(err)}) catch return; |
| 421 | 430 | return; |
| 422 | 431 | }; |
| 423 | const tty_config = io.tty.detectConfig(io.getStdErr()); | |
| 432 | const tty_config = io.tty.detectConfig(.stderr()); | |
| 424 | 433 | if (native_os == .windows) { |
| 425 | 434 | // On x86_64 and aarch64, the stack will be unwound using RtlVirtualUnwind using the context |
| 426 | 435 | // 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 | 519 | nosuspend { |
| 511 | 520 | if (builtin.target.cpu.arch.isWasm()) { |
| 512 | 521 | if (native_os == .wasi) { |
| 513 | const stderr = io.getStdErr().writer(); | |
| 514 | stderr.print("Unable to dump stack trace: not implemented for Wasm\n", .{}) catch return; | |
| 522 | const stderr = lockStderrWriter(&.{}); | |
| 523 | defer unlockStderrWriter(); | |
| 524 | stderr.writeAll("Unable to dump stack trace: not implemented for Wasm\n") catch return; | |
| 515 | 525 | } |
| 516 | 526 | return; |
| 517 | 527 | } |
| 518 | const stderr = io.getStdErr().writer(); | |
| 528 | const stderr = lockStderrWriter(&.{}); | |
| 529 | defer unlockStderrWriter(); | |
| 519 | 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 | 532 | return; |
| 522 | 533 | } |
| 523 | 534 | const debug_info = getSelfDebugInfo() catch |err| { |
| 524 | 535 | stderr.print("Unable to dump stack trace: Unable to open debug info: {s}\n", .{@errorName(err)}) catch return; |
| 525 | 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 | 539 | stderr.print("Unable to dump stack trace: {s}\n", .{@errorName(err)}) catch return; |
| 529 | 540 | return; |
| 530 | 541 | }; |
| ... | ... | @@ -573,14 +584,13 @@ pub fn panicExtra( |
| 573 | 584 | const size = 0x1000; |
| 574 | 585 | const trunc_msg = "(msg truncated)"; |
| 575 | 586 | var buf: [size + trunc_msg.len]u8 = undefined; |
| 587 | var bw: Writer = .fixed(buf[0..size]); | |
| 576 | 588 | // a minor annoyance with this is that it will result in the NoSpaceLeft |
| 577 | 589 | // error being part of the @panic stack trace (but that error should |
| 578 | 590 | // only happen rarely) |
| 579 | const msg = std.fmt.bufPrint(buf[0..size], format, args) catch |err| switch (err) { | |
| 580 | error.NoSpaceLeft => blk: { | |
| 581 | @memcpy(buf[size..], trunc_msg); | |
| 582 | break :blk &buf; | |
| 583 | }, | |
| 591 | const msg = if (bw.print(format, args)) |_| bw.buffered() else |_| blk: { | |
| 592 | @memcpy(buf[size..], trunc_msg); | |
| 593 | break :blk &buf; | |
| 584 | 594 | }; |
| 585 | 595 | std.builtin.panic.call(msg, ret_addr); |
| 586 | 596 | } |
| ... | ... | @@ -675,10 +685,9 @@ pub fn defaultPanic( |
| 675 | 685 | _ = panicking.fetchAdd(1, .seq_cst); |
| 676 | 686 | |
| 677 | 687 | { |
| 678 | lockStdErr(); | |
| 679 | defer unlockStdErr(); | |
| 688 | const stderr = lockStderrWriter(&.{}); | |
| 689 | defer unlockStderrWriter(); | |
| 680 | 690 | |
| 681 | const stderr = io.getStdErr().writer(); | |
| 682 | 691 | if (builtin.single_threaded) { |
| 683 | 692 | stderr.print("panic: ", .{}) catch posix.abort(); |
| 684 | 693 | } else { |
| ... | ... | @@ -688,7 +697,7 @@ pub fn defaultPanic( |
| 688 | 697 | stderr.print("{s}\n", .{msg}) catch posix.abort(); |
| 689 | 698 | |
| 690 | 699 | if (@errorReturnTrace()) |t| dumpStackTrace(t.*); |
| 691 | dumpCurrentStackTrace(first_trace_addr orelse @returnAddress()); | |
| 700 | dumpCurrentStackTraceToWriter(first_trace_addr orelse @returnAddress(), stderr) catch {}; | |
| 692 | 701 | } |
| 693 | 702 | |
| 694 | 703 | waitForOtherThreadToFinishPanicking(); |
| ... | ... | @@ -699,7 +708,7 @@ pub fn defaultPanic( |
| 699 | 708 | // A panic happened while trying to print a previous panic message. |
| 700 | 709 | // We're still holding the mutex but that's fine as we're going to |
| 701 | 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 | 713 | else => {}, // Panicked while printing the recursive panic message. |
| 705 | 714 | }; |
| ... | ... | @@ -723,7 +732,7 @@ fn waitForOtherThreadToFinishPanicking() void { |
| 723 | 732 | |
| 724 | 733 | pub fn writeStackTrace( |
| 725 | 734 | stack_trace: std.builtin.StackTrace, |
| 726 | out_stream: anytype, | |
| 735 | writer: *Writer, | |
| 727 | 736 | debug_info: *SelfInfo, |
| 728 | 737 | tty_config: io.tty.Config, |
| 729 | 738 | ) !void { |
| ... | ... | @@ -736,15 +745,15 @@ pub fn writeStackTrace( |
| 736 | 745 | frame_index = (frame_index + 1) % stack_trace.instruction_addresses.len; |
| 737 | 746 | }) { |
| 738 | 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 | } |
| 741 | 750 | |
| 742 | 751 | if (stack_trace.index > stack_trace.instruction_addresses.len) { |
| 743 | 752 | const dropped_frames = stack_trace.index - stack_trace.instruction_addresses.len; |
| 744 | 753 | |
| 745 | tty_config.setColor(out_stream, .bold) catch {}; | |
| 746 | try out_stream.print("({d} additional stack frames skipped...)\n", .{dropped_frames}); | |
| 747 | tty_config.setColor(out_stream, .reset) catch {}; | |
| 754 | tty_config.setColor(writer, .bold) catch {}; | |
| 755 | try writer.print("({d} additional stack frames skipped...)\n", .{dropped_frames}); | |
| 756 | tty_config.setColor(writer, .reset) catch {}; | |
| 748 | 757 | } |
| 749 | 758 | } |
| 750 | 759 | |
| ... | ... | @@ -954,7 +963,7 @@ pub const StackIterator = struct { |
| 954 | 963 | }; |
| 955 | 964 | |
| 956 | 965 | pub fn writeCurrentStackTrace( |
| 957 | out_stream: anytype, | |
| 966 | writer: *Writer, | |
| 958 | 967 | debug_info: *SelfInfo, |
| 959 | 968 | tty_config: io.tty.Config, |
| 960 | 969 | start_addr: ?usize, |
| ... | ... | @@ -962,7 +971,7 @@ pub fn writeCurrentStackTrace( |
| 962 | 971 | if (native_os == .windows) { |
| 963 | 972 | var context: ThreadContext = undefined; |
| 964 | 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 | 976 | var context: ThreadContext = undefined; |
| 968 | 977 | const has_context = getContext(&context); |
| ... | ... | @@ -973,7 +982,7 @@ pub fn writeCurrentStackTrace( |
| 973 | 982 | defer it.deinit(); |
| 974 | 983 | |
| 975 | 984 | while (it.next()) |return_address| { |
| 976 | printLastUnwindError(&it, debug_info, out_stream, tty_config); | |
| 985 | printLastUnwindError(&it, debug_info, writer, tty_config); | |
| 977 | 986 | |
| 978 | 987 | // On arm64 macOS, the address of the last frame is 0x0 rather than 0x1 as on x86_64 macOS, |
| 979 | 988 | // therefore, we do a check for `return_address == 0` before subtracting 1 from it to avoid |
| ... | ... | @@ -981,8 +990,8 @@ pub fn writeCurrentStackTrace( |
| 981 | 990 | // condition on the subsequent iteration and return `null` thus terminating the loop. |
| 982 | 991 | // same behaviour for x86-windows-msvc |
| 983 | 992 | const address = return_address -| 1; |
| 984 | try printSourceAtAddress(debug_info, out_stream, address, tty_config); | |
| 985 | } else printLastUnwindError(&it, debug_info, out_stream, tty_config); | |
| 993 | try printSourceAtAddress(debug_info, writer, address, tty_config); | |
| 994 | } else printLastUnwindError(&it, debug_info, writer, tty_config); | |
| 986 | 995 | } |
| 987 | 996 | |
| 988 | 997 | pub 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 | 1051 | } |
| 1043 | 1052 | |
| 1044 | 1053 | pub fn writeStackTraceWindows( |
| 1045 | out_stream: anytype, | |
| 1054 | writer: *Writer, | |
| 1046 | 1055 | debug_info: *SelfInfo, |
| 1047 | 1056 | tty_config: io.tty.Config, |
| 1048 | 1057 | context: *const windows.CONTEXT, |
| ... | ... | @@ -1058,14 +1067,14 @@ pub fn writeStackTraceWindows( |
| 1058 | 1067 | return; |
| 1059 | 1068 | } else 0; |
| 1060 | 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 | } |
| 1064 | 1073 | |
| 1065 | fn printUnknownSource(debug_info: *SelfInfo, out_stream: anytype, address: usize, tty_config: io.tty.Config) !void { | |
| 1074 | fn printUnknownSource(debug_info: *SelfInfo, writer: *Writer, address: usize, tty_config: io.tty.Config) !void { | |
| 1066 | 1075 | const module_name = debug_info.getModuleNameForAddress(address); |
| 1067 | 1076 | return printLineInfo( |
| 1068 | out_stream, | |
| 1077 | writer, | |
| 1069 | 1078 | null, |
| 1070 | 1079 | address, |
| 1071 | 1080 | "???", |
| ... | ... | @@ -1075,38 +1084,38 @@ fn printUnknownSource(debug_info: *SelfInfo, out_stream: anytype, address: usize |
| 1075 | 1084 | ); |
| 1076 | 1085 | } |
| 1077 | 1086 | |
| 1078 | fn printLastUnwindError(it: *StackIterator, debug_info: *SelfInfo, out_stream: anytype, tty_config: io.tty.Config) void { | |
| 1087 | fn printLastUnwindError(it: *StackIterator, debug_info: *SelfInfo, writer: *Writer, tty_config: io.tty.Config) void { | |
| 1079 | 1088 | if (!have_ucontext) return; |
| 1080 | 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 | } |
| 1084 | 1093 | |
| 1085 | fn printUnwindError(debug_info: *SelfInfo, out_stream: anytype, address: usize, err: UnwindError, tty_config: io.tty.Config) !void { | |
| 1094 | fn printUnwindError(debug_info: *SelfInfo, writer: *Writer, address: usize, err: UnwindError, tty_config: io.tty.Config) !void { | |
| 1086 | 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 | 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 | 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 | } |
| 1095 | 1104 | |
| 1096 | pub fn printSourceAtAddress(debug_info: *SelfInfo, out_stream: anytype, address: usize, tty_config: io.tty.Config) !void { | |
| 1105 | pub fn printSourceAtAddress(debug_info: *SelfInfo, writer: *Writer, address: usize, tty_config: io.tty.Config) !void { | |
| 1097 | 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 | 1108 | else => return err, |
| 1100 | 1109 | }; |
| 1101 | 1110 | |
| 1102 | 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 | 1113 | else => return err, |
| 1105 | 1114 | }; |
| 1106 | 1115 | defer if (symbol_info.source_location) |sl| debug_info.allocator.free(sl.file_name); |
| 1107 | 1116 | |
| 1108 | 1117 | return printLineInfo( |
| 1109 | out_stream, | |
| 1118 | writer, | |
| 1110 | 1119 | symbol_info.source_location, |
| 1111 | 1120 | address, |
| 1112 | 1121 | symbol_info.name, |
| ... | ... | @@ -1117,7 +1126,7 @@ pub fn printSourceAtAddress(debug_info: *SelfInfo, out_stream: anytype, address: |
| 1117 | 1126 | } |
| 1118 | 1127 | |
| 1119 | 1128 | fn printLineInfo( |
| 1120 | out_stream: anytype, | |
| 1129 | writer: *Writer, | |
| 1121 | 1130 | source_location: ?SourceLocation, |
| 1122 | 1131 | address: usize, |
| 1123 | 1132 | symbol_name: []const u8, |
| ... | ... | @@ -1126,34 +1135,34 @@ fn printLineInfo( |
| 1126 | 1135 | comptime printLineFromFile: anytype, |
| 1127 | 1136 | ) !void { |
| 1128 | 1137 | nosuspend { |
| 1129 | try tty_config.setColor(out_stream, .bold); | |
| 1138 | try tty_config.setColor(writer, .bold); | |
| 1130 | 1139 | |
| 1131 | 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 | 1142 | } else { |
| 1134 | try out_stream.writeAll("???:?:?"); | |
| 1143 | try writer.writeAll("???:?:?"); | |
| 1135 | 1144 | } |
| 1136 | 1145 | |
| 1137 | try tty_config.setColor(out_stream, .reset); | |
| 1138 | try out_stream.writeAll(": "); | |
| 1139 | try tty_config.setColor(out_stream, .dim); | |
| 1140 | try out_stream.print("0x{x} in {s} ({s})", .{ address, symbol_name, compile_unit_name }); | |
| 1141 | try tty_config.setColor(out_stream, .reset); | |
| 1142 | try out_stream.writeAll("\n"); | |
| 1146 | try tty_config.setColor(writer, .reset); | |
| 1147 | try writer.writeAll(": "); | |
| 1148 | try tty_config.setColor(writer, .dim); | |
| 1149 | try writer.print("0x{x} in {s} ({s})", .{ address, symbol_name, compile_unit_name }); | |
| 1150 | try tty_config.setColor(writer, .reset); | |
| 1151 | try writer.writeAll("\n"); | |
| 1143 | 1152 | |
| 1144 | 1153 | // Show the matching source code line if possible |
| 1145 | 1154 | if (source_location) |sl| { |
| 1146 | if (printLineFromFile(out_stream, sl)) { | |
| 1155 | if (printLineFromFile(writer, sl)) { | |
| 1147 | 1156 | if (sl.column > 0) { |
| 1148 | 1157 | // The caret already takes one char |
| 1149 | 1158 | const space_needed = @as(usize, @intCast(sl.column - 1)); |
| 1150 | 1159 | |
| 1151 | try out_stream.writeByteNTimes(' ', space_needed); | |
| 1152 | try tty_config.setColor(out_stream, .green); | |
| 1153 | try out_stream.writeAll("^"); | |
| 1154 | try tty_config.setColor(out_stream, .reset); | |
| 1160 | try writer.splatByteAll(' ', space_needed); | |
| 1161 | try tty_config.setColor(writer, .green); | |
| 1162 | try writer.writeAll("^"); | |
| 1163 | try tty_config.setColor(writer, .reset); | |
| 1155 | 1164 | } |
| 1156 | try out_stream.writeAll("\n"); | |
| 1165 | try writer.writeAll("\n"); | |
| 1157 | 1166 | } else |err| switch (err) { |
| 1158 | 1167 | error.EndOfFile, error.FileNotFound => {}, |
| 1159 | 1168 | error.BadPathName => {}, |
| ... | ... | @@ -1164,7 +1173,7 @@ fn printLineInfo( |
| 1164 | 1173 | } |
| 1165 | 1174 | } |
| 1166 | 1175 | |
| 1167 | fn printLineFromFileAnyOs(out_stream: anytype, source_location: SourceLocation) !void { | |
| 1176 | fn printLineFromFileAnyOs(writer: *Writer, source_location: SourceLocation) !void { | |
| 1168 | 1177 | // Need this to always block even in async I/O mode, because this could potentially |
| 1169 | 1178 | // be called from e.g. the event loop code crashing. |
| 1170 | 1179 | var f = try fs.cwd().openFile(source_location.file_name, .{}); |
| ... | ... | @@ -1197,31 +1206,31 @@ fn printLineFromFileAnyOs(out_stream: anytype, source_location: SourceLocation) |
| 1197 | 1206 | if (mem.indexOfScalar(u8, slice, '\n')) |pos| { |
| 1198 | 1207 | const line = slice[0 .. pos + 1]; |
| 1199 | 1208 | mem.replaceScalar(u8, line, '\t', ' '); |
| 1200 | return out_stream.writeAll(line); | |
| 1209 | return writer.writeAll(line); | |
| 1201 | 1210 | } else { // Line is the last inside the buffer, and requires another read to find delimiter. Alternatively the file ends. |
| 1202 | 1211 | mem.replaceScalar(u8, slice, '\t', ' '); |
| 1203 | try out_stream.writeAll(slice); | |
| 1212 | try writer.writeAll(slice); | |
| 1204 | 1213 | while (amt_read == buf.len) { |
| 1205 | 1214 | amt_read = try f.read(buf[0..]); |
| 1206 | 1215 | if (mem.indexOfScalar(u8, buf[0..amt_read], '\n')) |pos| { |
| 1207 | 1216 | const line = buf[0 .. pos + 1]; |
| 1208 | 1217 | mem.replaceScalar(u8, line, '\t', ' '); |
| 1209 | return out_stream.writeAll(line); | |
| 1218 | return writer.writeAll(line); | |
| 1210 | 1219 | } else { |
| 1211 | 1220 | const line = buf[0..amt_read]; |
| 1212 | 1221 | mem.replaceScalar(u8, line, '\t', ' '); |
| 1213 | try out_stream.writeAll(line); | |
| 1222 | try writer.writeAll(line); | |
| 1214 | 1223 | } |
| 1215 | 1224 | } |
| 1216 | 1225 | // 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 | } |
| 1220 | 1229 | |
| 1221 | 1230 | test printLineFromFileAnyOs { |
| 1222 | var output = std.ArrayList(u8).init(std.testing.allocator); | |
| 1223 | defer output.deinit(); | |
| 1224 | const output_stream = output.writer(); | |
| 1231 | var aw: Writer.Allocating = .init(std.testing.allocator); | |
| 1232 | defer aw.deinit(); | |
| 1233 | const output_stream = &aw.writer; | |
| 1225 | 1234 | |
| 1226 | 1235 | const allocator = std.testing.allocator; |
| 1227 | 1236 | const join = std.fs.path.join; |
| ... | ... | @@ -1243,8 +1252,8 @@ test printLineFromFileAnyOs { |
| 1243 | 1252 | try expectError(error.EndOfFile, printLineFromFileAnyOs(output_stream, .{ .file_name = path, .line = 2, .column = 0 })); |
| 1244 | 1253 | |
| 1245 | 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); | |
| 1247 | output.clearRetainingCapacity(); | |
| 1255 | try expectEqualStrings("no new lines in this file, but one is printed anyway\n", aw.getWritten()); | |
| 1256 | aw.clearRetainingCapacity(); | |
| 1248 | 1257 | } |
| 1249 | 1258 | { |
| 1250 | 1259 | const path = try fs.path.join(allocator, &.{ test_dir_path, "three_lines.zig" }); |
| ... | ... | @@ -1259,12 +1268,12 @@ test printLineFromFileAnyOs { |
| 1259 | 1268 | }); |
| 1260 | 1269 | |
| 1261 | 1270 | try printLineFromFileAnyOs(output_stream, .{ .file_name = path, .line = 1, .column = 0 }); |
| 1262 | try expectEqualStrings("1\n", output.items); | |
| 1263 | output.clearRetainingCapacity(); | |
| 1271 | try expectEqualStrings("1\n", aw.getWritten()); | |
| 1272 | aw.clearRetainingCapacity(); | |
| 1264 | 1273 | |
| 1265 | 1274 | try printLineFromFileAnyOs(output_stream, .{ .file_name = path, .line = 3, .column = 0 }); |
| 1266 | try expectEqualStrings("3\n", output.items); | |
| 1267 | output.clearRetainingCapacity(); | |
| 1275 | try expectEqualStrings("3\n", aw.getWritten()); | |
| 1276 | aw.clearRetainingCapacity(); | |
| 1268 | 1277 | } |
| 1269 | 1278 | { |
| 1270 | 1279 | const file = try test_dir.dir.createFile("line_overlaps_page_boundary.zig", .{}); |
| ... | ... | @@ -1273,14 +1282,17 @@ test printLineFromFileAnyOs { |
| 1273 | 1282 | defer allocator.free(path); |
| 1274 | 1283 | |
| 1275 | 1284 | const overlap = 10; |
| 1276 | var writer = file.writer(); | |
| 1277 | try writer.writeByteNTimes('a', std.heap.page_size_min - overlap); | |
| 1285 | var buf: [16]u8 = undefined; | |
| 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 | 1289 | try writer.writeByte('\n'); |
| 1279 | try writer.writeByteNTimes('a', overlap); | |
| 1290 | try writer.splatByteAll('a', overlap); | |
| 1291 | try writer.flush(); | |
| 1280 | 1292 | |
| 1281 | 1293 | try printLineFromFileAnyOs(output_stream, .{ .file_name = path, .line = 2, .column = 0 }); |
| 1282 | try expectEqualStrings(("a" ** overlap) ++ "\n", output.items); | |
| 1283 | output.clearRetainingCapacity(); | |
| 1294 | try expectEqualStrings(("a" ** overlap) ++ "\n", aw.getWritten()); | |
| 1295 | aw.clearRetainingCapacity(); | |
| 1284 | 1296 | } |
| 1285 | 1297 | { |
| 1286 | 1298 | const file = try test_dir.dir.createFile("file_ends_on_page_boundary.zig", .{}); |
| ... | ... | @@ -1288,12 +1300,13 @@ test printLineFromFileAnyOs { |
| 1288 | 1300 | const path = try fs.path.join(allocator, &.{ test_dir_path, "file_ends_on_page_boundary.zig" }); |
| 1289 | 1301 | defer allocator.free(path); |
| 1290 | 1302 | |
| 1291 | var writer = file.writer(); | |
| 1292 | try writer.writeByteNTimes('a', std.heap.page_size_max); | |
| 1303 | var file_writer = file.writer(&.{}); | |
| 1304 | const writer = &file_writer.interface; | |
| 1305 | try writer.splatByteAll('a', std.heap.page_size_max); | |
| 1293 | 1306 | |
| 1294 | 1307 | try printLineFromFileAnyOs(output_stream, .{ .file_name = path, .line = 1, .column = 0 }); |
| 1295 | try expectEqualStrings(("a" ** std.heap.page_size_max) ++ "\n", output.items); | |
| 1296 | output.clearRetainingCapacity(); | |
| 1308 | try expectEqualStrings(("a" ** std.heap.page_size_max) ++ "\n", aw.getWritten()); | |
| 1309 | aw.clearRetainingCapacity(); | |
| 1297 | 1310 | } |
| 1298 | 1311 | { |
| 1299 | 1312 | const file = try test_dir.dir.createFile("very_long_first_line_spanning_multiple_pages.zig", .{}); |
| ... | ... | @@ -1301,24 +1314,25 @@ test printLineFromFileAnyOs { |
| 1301 | 1314 | const path = try fs.path.join(allocator, &.{ test_dir_path, "very_long_first_line_spanning_multiple_pages.zig" }); |
| 1302 | 1315 | defer allocator.free(path); |
| 1303 | 1316 | |
| 1304 | var writer = file.writer(); | |
| 1305 | try writer.writeByteNTimes('a', 3 * std.heap.page_size_max); | |
| 1317 | var file_writer = file.writer(&.{}); | |
| 1318 | const writer = &file_writer.interface; | |
| 1319 | try writer.splatByteAll('a', 3 * std.heap.page_size_max); | |
| 1306 | 1320 | |
| 1307 | 1321 | try expectError(error.EndOfFile, printLineFromFileAnyOs(output_stream, .{ .file_name = path, .line = 2, .column = 0 })); |
| 1308 | 1322 | |
| 1309 | 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); | |
| 1311 | output.clearRetainingCapacity(); | |
| 1324 | try expectEqualStrings(("a" ** (3 * std.heap.page_size_max)) ++ "\n", aw.getWritten()); | |
| 1325 | aw.clearRetainingCapacity(); | |
| 1312 | 1326 | |
| 1313 | 1327 | try writer.writeAll("a\na"); |
| 1314 | 1328 | |
| 1315 | 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); | |
| 1317 | output.clearRetainingCapacity(); | |
| 1330 | try expectEqualStrings(("a" ** (3 * std.heap.page_size_max)) ++ "a\n", aw.getWritten()); | |
| 1331 | aw.clearRetainingCapacity(); | |
| 1318 | 1332 | |
| 1319 | 1333 | try printLineFromFileAnyOs(output_stream, .{ .file_name = path, .line = 2, .column = 0 }); |
| 1320 | try expectEqualStrings("a\n", output.items); | |
| 1321 | output.clearRetainingCapacity(); | |
| 1334 | try expectEqualStrings("a\n", aw.getWritten()); | |
| 1335 | aw.clearRetainingCapacity(); | |
| 1322 | 1336 | } |
| 1323 | 1337 | { |
| 1324 | 1338 | const file = try test_dir.dir.createFile("file_of_newlines.zig", .{}); |
| ... | ... | @@ -1326,18 +1340,19 @@ test printLineFromFileAnyOs { |
| 1326 | 1340 | const path = try fs.path.join(allocator, &.{ test_dir_path, "file_of_newlines.zig" }); |
| 1327 | 1341 | defer allocator.free(path); |
| 1328 | 1342 | |
| 1329 | var writer = file.writer(); | |
| 1343 | var file_writer = file.writer(&.{}); | |
| 1344 | const writer = &file_writer.interface; | |
| 1330 | 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 | 1347 | try writer.writeAll("abc\ndef"); |
| 1333 | 1348 | |
| 1334 | 1349 | try printLineFromFileAnyOs(output_stream, .{ .file_name = path, .line = real_file_start + 1, .column = 0 }); |
| 1335 | try expectEqualStrings("abc\n", output.items); | |
| 1336 | output.clearRetainingCapacity(); | |
| 1350 | try expectEqualStrings("abc\n", aw.getWritten()); | |
| 1351 | aw.clearRetainingCapacity(); | |
| 1337 | 1352 | |
| 1338 | 1353 | try printLineFromFileAnyOs(output_stream, .{ .file_name = path, .line = real_file_start + 2, .column = 0 }); |
| 1339 | try expectEqualStrings("def\n", output.items); | |
| 1340 | output.clearRetainingCapacity(); | |
| 1354 | try expectEqualStrings("def\n", aw.getWritten()); | |
| 1355 | aw.clearRetainingCapacity(); | |
| 1341 | 1356 | } |
| 1342 | 1357 | } |
| 1343 | 1358 | |
| ... | ... | @@ -1461,7 +1476,8 @@ fn handleSegfaultPosix(sig: i32, info: *const posix.siginfo_t, ctx_ptr: ?*anyopa |
| 1461 | 1476 | } |
| 1462 | 1477 | |
| 1463 | 1478 | fn 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 | 1481 | _ = switch (sig) { |
| 1466 | 1482 | posix.SIG.SEGV => if (native_arch == .x86_64 and native_os == .linux and code == 128) // SI_KERNEL |
| 1467 | 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 | 1487 | // but can also happen when no addressable memory is involved; |
| 1472 | 1488 | // for example when reading/writing model-specific registers |
| 1473 | 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 | 1491 | else |
| 1476 | 1492 | stderr.print("Segmentation fault at address 0x{x}\n", .{addr}), |
| 1477 | 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 | 1525 | }, @ptrCast(ctx)).__mcontext_data; |
| 1510 | 1526 | } |
| 1511 | 1527 | relocateContext(&new_ctx); |
| 1512 | dumpStackTraceFromBase(&new_ctx); | |
| 1528 | dumpStackTraceFromBase(&new_ctx, stderr); | |
| 1513 | 1529 | }, |
| 1514 | 1530 | else => {}, |
| 1515 | 1531 | } |
| ... | ... | @@ -1539,25 +1555,24 @@ fn handleSegfaultWindowsExtra(info: *windows.EXCEPTION_POINTERS, msg: u8, label: |
| 1539 | 1555 | _ = panicking.fetchAdd(1, .seq_cst); |
| 1540 | 1556 | |
| 1541 | 1557 | { |
| 1542 | lockStdErr(); | |
| 1543 | defer unlockStdErr(); | |
| 1558 | const stderr = lockStderrWriter(&.{}); | |
| 1559 | defer unlockStderrWriter(); | |
| 1544 | 1560 | |
| 1545 | dumpSegfaultInfoWindows(info, msg, label); | |
| 1561 | dumpSegfaultInfoWindows(info, msg, label, stderr); | |
| 1546 | 1562 | } |
| 1547 | 1563 | |
| 1548 | 1564 | waitForOtherThreadToFinishPanicking(); |
| 1549 | 1565 | }, |
| 1550 | 1566 | 1 => { |
| 1551 | 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 | 1570 | else => {}, |
| 1555 | 1571 | }; |
| 1556 | 1572 | posix.abort(); |
| 1557 | 1573 | } |
| 1558 | 1574 | |
| 1559 | fn dumpSegfaultInfoWindows(info: *windows.EXCEPTION_POINTERS, msg: u8, label: ?[]const u8) void { | |
| 1560 | const stderr = io.getStdErr().writer(); | |
| 1575 | fn dumpSegfaultInfoWindows(info: *windows.EXCEPTION_POINTERS, msg: u8, label: ?[]const u8, stderr: *Writer) void { | |
| 1561 | 1576 | _ = switch (msg) { |
| 1562 | 1577 | 0 => stderr.print("{s}\n", .{label.?}), |
| 1563 | 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 | 1580 | else => unreachable, |
| 1566 | 1581 | } catch posix.abort(); |
| 1567 | 1582 | |
| 1568 | dumpStackTraceFromBase(info.ContextRecord); | |
| 1583 | dumpStackTraceFromBase(info.ContextRecord, stderr); | |
| 1569 | 1584 | } |
| 1570 | 1585 | |
| 1571 | 1586 | pub fn dumpStackPointerAddr(prefix: []const u8) void { |
| ... | ... | @@ -1588,10 +1603,10 @@ test "manage resources correctly" { |
| 1588 | 1603 | // self-hosted debug info is still too buggy |
| 1589 | 1604 | if (builtin.zig_backend != .stage2_llvm) return error.SkipZigTest; |
| 1590 | 1605 | |
| 1591 | const writer = std.io.null_writer; | |
| 1606 | var discarding: std.io.Writer.Discarding = .init(&.{}); | |
| 1592 | 1607 | var di = try SelfInfo.open(testing.allocator); |
| 1593 | 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 | } |
| 1596 | 1611 | |
| 1597 | 1612 | noinline fn showMyTrace() usize { |
| ... | ... | @@ -1657,8 +1672,9 @@ pub fn ConfigurableTrace(comptime size: usize, comptime stack_frame_count: usize |
| 1657 | 1672 | pub fn dump(t: @This()) void { |
| 1658 | 1673 | if (!enabled) return; |
| 1659 | 1674 | |
| 1660 | const tty_config = io.tty.detectConfig(std.io.getStdErr()); | |
| 1661 | const stderr = io.getStdErr().writer(); | |
| 1675 | const tty_config = io.tty.detectConfig(.stderr()); | |
| 1676 | const stderr = lockStderrWriter(&.{}); | |
| 1677 | defer unlockStderrWriter(); | |
| 1662 | 1678 | const end = @min(t.index, size); |
| 1663 | 1679 | const debug_info = getSelfDebugInfo() catch |err| { |
| 1664 | 1680 | stderr.print( |
| ... | ... | @@ -1688,7 +1704,7 @@ pub fn ConfigurableTrace(comptime size: usize, comptime stack_frame_count: usize |
| 1688 | 1704 | t: @This(), |
| 1689 | 1705 | comptime fmt: []const u8, |
| 1690 | 1706 | options: std.fmt.FormatOptions, |
| 1691 | writer: anytype, | |
| 1707 | writer: *Writer, | |
| 1692 | 1708 | ) !void { |
| 1693 | 1709 | if (fmt.len != 0) std.fmt.invalidFmtError(fmt, t); |
| 1694 | 1710 | _ = options; |
lib/std/debug/Dwarf.zig+3-11| ... | ... | @@ -2302,11 +2302,7 @@ pub const ElfModule = struct { |
| 2302 | 2302 | }; |
| 2303 | 2303 | defer debuginfod_dir.close(); |
| 2304 | 2304 | |
| 2305 | const filename = std.fmt.allocPrint( | |
| 2306 | gpa, | |
| 2307 | "{s}/debuginfo", | |
| 2308 | .{std.fmt.fmtSliceHexLower(id)}, | |
| 2309 | ) catch break :blk; | |
| 2305 | const filename = std.fmt.allocPrint(gpa, "{x}/debuginfo", .{id}) catch break :blk; | |
| 2310 | 2306 | defer gpa.free(filename); |
| 2311 | 2307 | |
| 2312 | 2308 | const path: Path = .{ |
| ... | ... | @@ -2330,12 +2326,8 @@ pub const ElfModule = struct { |
| 2330 | 2326 | var id_prefix_buf: [2]u8 = undefined; |
| 2331 | 2327 | var filename_buf: [38 + extension.len]u8 = undefined; |
| 2332 | 2328 | |
| 2333 | _ = std.fmt.bufPrint(&id_prefix_buf, "{s}", .{std.fmt.fmtSliceHexLower(id[0..1])}) catch unreachable; | |
| 2334 | const filename = std.fmt.bufPrint( | |
| 2335 | &filename_buf, | |
| 2336 | "{s}" ++ extension, | |
| 2337 | .{std.fmt.fmtSliceHexLower(id[1..])}, | |
| 2338 | ) catch break :blk; | |
| 2329 | _ = std.fmt.bufPrint(&id_prefix_buf, "{x}", .{id[0..1]}) catch unreachable; | |
| 2330 | const filename = std.fmt.bufPrint(&filename_buf, "{x}" ++ extension, .{id[1..]}) catch break :blk; | |
| 2339 | 2331 | |
| 2340 | 2332 | for (global_debug_directories) |global_directory| { |
| 2341 | 2333 | const path: Path = .{ |
lib/std/debug/Pdb.zig+3-3| ... | ... | @@ -395,7 +395,7 @@ const Msf = struct { |
| 395 | 395 | streams: []MsfStream, |
| 396 | 396 | |
| 397 | 397 | fn init(allocator: Allocator, file: File) !Msf { |
| 398 | const in = file.reader(); | |
| 398 | const in = file.deprecatedReader(); | |
| 399 | 399 | |
| 400 | 400 | const superblock = try in.readStruct(pdb.SuperBlock); |
| 401 | 401 | |
| ... | ... | @@ -514,7 +514,7 @@ const MsfStream = struct { |
| 514 | 514 | var offset = self.pos % self.block_size; |
| 515 | 515 | |
| 516 | 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(); | |
| 518 | 518 | |
| 519 | 519 | var size: usize = 0; |
| 520 | 520 | var rem_buffer = buffer; |
| ... | ... | @@ -562,7 +562,7 @@ const MsfStream = struct { |
| 562 | 562 | return block * self.block_size + offset; |
| 563 | 563 | } |
| 564 | 564 | |
| 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 | 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 | 15 | @branchHint(.cold); |
| 16 | 16 | _ = ra; |
| 17 | 17 | std.debug.lockStdErr(); |
| 18 | const stderr = std.io.getStdErr(); | |
| 18 | const stderr: std.fs.File = .stderr(); | |
| 19 | 19 | stderr.writeAll(msg) catch {}; |
| 20 | 20 | @trap(); |
| 21 | 21 | } |
lib/std/elf.zig+5-5| ... | ... | @@ -511,7 +511,7 @@ pub const Header = struct { |
| 511 | 511 | pub fn read(parse_source: anytype) !Header { |
| 512 | 512 | var hdr_buf: [@sizeOf(Elf64_Ehdr)]u8 align(@alignOf(Elf64_Ehdr)) = undefined; |
| 513 | 513 | try parse_source.seekableStream().seekTo(0); |
| 514 | try parse_source.reader().readNoEof(&hdr_buf); | |
| 514 | try parse_source.deprecatedReader().readNoEof(&hdr_buf); | |
| 515 | 515 | return Header.parse(&hdr_buf); |
| 516 | 516 | } |
| 517 | 517 | |
| ... | ... | @@ -586,7 +586,7 @@ pub fn ProgramHeaderIterator(comptime ParseSource: anytype) type { |
| 586 | 586 | var phdr: Elf64_Phdr = undefined; |
| 587 | 587 | const offset = self.elf_header.phoff + @sizeOf(@TypeOf(phdr)) * self.index; |
| 588 | 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)); | |
| 590 | 590 | |
| 591 | 591 | // ELF endianness matches native endianness. |
| 592 | 592 | if (self.elf_header.endian == native_endian) return phdr; |
| ... | ... | @@ -599,7 +599,7 @@ pub fn ProgramHeaderIterator(comptime ParseSource: anytype) type { |
| 599 | 599 | var phdr: Elf32_Phdr = undefined; |
| 600 | 600 | const offset = self.elf_header.phoff + @sizeOf(@TypeOf(phdr)) * self.index; |
| 601 | 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)); | |
| 603 | 603 | |
| 604 | 604 | // ELF endianness does NOT match native endianness. |
| 605 | 605 | if (self.elf_header.endian != native_endian) { |
| ... | ... | @@ -636,7 +636,7 @@ pub fn SectionHeaderIterator(comptime ParseSource: anytype) type { |
| 636 | 636 | var shdr: Elf64_Shdr = undefined; |
| 637 | 637 | const offset = self.elf_header.shoff + @sizeOf(@TypeOf(shdr)) * self.index; |
| 638 | 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)); | |
| 640 | 640 | |
| 641 | 641 | // ELF endianness matches native endianness. |
| 642 | 642 | if (self.elf_header.endian == native_endian) return shdr; |
| ... | ... | @@ -649,7 +649,7 @@ pub fn SectionHeaderIterator(comptime ParseSource: anytype) type { |
| 649 | 649 | var shdr: Elf32_Shdr = undefined; |
| 650 | 650 | const offset = self.elf_header.shoff + @sizeOf(@TypeOf(shdr)) * self.index; |
| 651 | 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)); | |
| 653 | 653 | |
| 654 | 654 | // ELF endianness does NOT match native endianness. |
| 655 | 655 | if (self.elf_header.endian != native_endian) { |
lib/std/fifo.zig+4-4| ... | ... | @@ -38,8 +38,8 @@ pub fn LinearFifo( |
| 38 | 38 | count: usize, |
| 39 | 39 | |
| 40 | 40 | const Self = @This(); |
| 41 | pub const Reader = std.io.Reader(*Self, error{}, readFn); | |
| 42 | pub const Writer = std.io.Writer(*Self, error{OutOfMemory}, appendWrite); | |
| 41 | pub const Reader = std.io.GenericReader(*Self, error{}, readFn); | |
| 42 | pub const Writer = std.io.GenericWriter(*Self, error{OutOfMemory}, appendWrite); | |
| 43 | 43 | |
| 44 | 44 | // Type of Self argument for slice operations. |
| 45 | 45 | // If buffer is inline (Static) then we need to ensure we haven't |
| ... | ... | @@ -231,7 +231,7 @@ pub fn LinearFifo( |
| 231 | 231 | } |
| 232 | 232 | |
| 233 | 233 | /// 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 | 235 | fn readFn(self: *Self, dest: []u8) error{}!usize { |
| 236 | 236 | return self.read(dest); |
| 237 | 237 | } |
| ... | ... | @@ -320,7 +320,7 @@ pub fn LinearFifo( |
| 320 | 320 | } |
| 321 | 321 | |
| 322 | 322 | /// 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 | 324 | fn appendWrite(self: *Self, bytes: []const u8) error{OutOfMemory}!usize { |
| 325 | 325 | try self.write(bytes); |
| 326 | 326 | return bytes.len; |
lib/std/fmt.zig+290-1715| ... | ... | @@ -1,17 +1,20 @@ |
| 1 | 1 | //! String formatting and parsing. |
| 2 | 2 | |
| 3 | const std = @import("std.zig"); | |
| 4 | 3 | const builtin = @import("builtin"); |
| 5 | 4 | |
| 5 | const std = @import("std.zig"); | |
| 6 | 6 | const io = std.io; |
| 7 | 7 | const math = std.math; |
| 8 | 8 | const assert = std.debug.assert; |
| 9 | 9 | const mem = std.mem; |
| 10 | const unicode = std.unicode; | |
| 11 | 10 | const meta = std.meta; |
| 12 | 11 | const lossyCast = math.lossyCast; |
| 13 | 12 | const expectFmt = std.testing.expectFmt; |
| 14 | 13 | const testing = std.testing; |
| 14 | const Allocator = std.mem.Allocator; | |
| 15 | const Writer = std.io.Writer; | |
| 16 | ||
| 17 | pub const float = @import("fmt/float.zig"); | |
| 15 | 18 | |
| 16 | 19 | pub const default_max_depth = 3; |
| 17 | 20 | |
| ... | ... | @@ -21,237 +24,91 @@ pub const Alignment = enum { |
| 21 | 24 | right, |
| 22 | 25 | }; |
| 23 | 26 | |
| 27 | pub const Case = enum { lower, upper }; | |
| 28 | ||
| 24 | 29 | const default_alignment = .right; |
| 25 | 30 | const default_fill_char = ' '; |
| 26 | 31 | |
| 27 | pub const FormatOptions = struct { | |
| 32 | /// Deprecated in favor of `Options`. | |
| 33 | pub const FormatOptions = Options; | |
| 34 | ||
| 35 | pub const Options = struct { | |
| 28 | 36 | precision: ?usize = null, |
| 29 | 37 | width: ?usize = null, |
| 30 | 38 | alignment: Alignment = default_alignment, |
| 31 | fill: u21 = default_fill_char, | |
| 32 | }; | |
| 33 | ||
| 34 | /// Renders fmt string with args, calling `writer` with slices of bytes. | |
| 35 | /// If `writer` returns an error, the error is returned from `format` and | |
| 36 | /// `writer` is not called again. | |
| 37 | /// | |
| 38 | /// The format string must be comptime-known and may contain placeholders following | |
| 39 | /// this format: | |
| 40 | /// `{[argument][specifier]:[fill][alignment][width].[precision]}` | |
| 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 `}}`. | |
| 84 | pub 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 | }, | |
| 39 | fill: u8 = default_fill_char, | |
| 40 | ||
| 41 | pub fn toNumber(o: Options, mode: Number.Mode, case: Case) Number { | |
| 42 | return .{ | |
| 43 | .mode = mode, | |
| 44 | .case = case, | |
| 45 | .precision = o.precision, | |
| 46 | .width = o.width, | |
| 47 | .alignment = o.alignment, | |
| 48 | .fill = o.fill, | |
| 188 | 49 | }; |
| 50 | } | |
| 51 | }; | |
| 189 | 52 | |
| 190 | const arg_to_print = comptime arg_state.nextArg(arg_pos) orelse | |
| 191 | @compileError("too few arguments"); | |
| 192 | ||
| 193 | try formatType( | |
| 194 | @field(args, fields_info[arg_to_print].name), | |
| 195 | placeholder.specifier_arg, | |
| 196 | FormatOptions{ | |
| 197 | .fill = placeholder.fill, | |
| 198 | .alignment = placeholder.alignment, | |
| 199 | .width = width, | |
| 200 | .precision = precision, | |
| 201 | }, | |
| 202 | writer, | |
| 203 | std.options.fmt_max_depth, | |
| 204 | ); | |
| 205 | } | |
| 206 | ||
| 207 | if (comptime arg_state.hasUnusedArgs()) { | |
| 208 | const missing_count = arg_state.args_len - @popCount(arg_state.used_args); | |
| 209 | switch (missing_count) { | |
| 210 | 0 => unreachable, | |
| 211 | 1 => @compileError("unused argument in '" ++ fmt ++ "'"), | |
| 212 | else => @compileError(comptimePrint("{d}", .{missing_count}) ++ " unused arguments in '" ++ fmt ++ "'"), | |
| 53 | pub const Number = struct { | |
| 54 | mode: Mode = .decimal, | |
| 55 | /// Affects hex digits as well as floating point "inf"/"INF". | |
| 56 | case: Case = .lower, | |
| 57 | precision: ?usize = null, | |
| 58 | width: ?usize = null, | |
| 59 | alignment: Alignment = default_alignment, | |
| 60 | fill: u8 = default_fill_char, | |
| 61 | ||
| 62 | pub const Mode = enum { | |
| 63 | decimal, | |
| 64 | binary, | |
| 65 | octal, | |
| 66 | hex, | |
| 67 | scientific, | |
| 68 | ||
| 69 | pub fn base(mode: Mode) ?u8 { | |
| 70 | return switch (mode) { | |
| 71 | .decimal => 10, | |
| 72 | .binary => 2, | |
| 73 | .octal => 8, | |
| 74 | .hex => 16, | |
| 75 | .scientific => null, | |
| 76 | }; | |
| 213 | 77 | } |
| 214 | } | |
| 215 | } | |
| 78 | }; | |
| 79 | }; | |
| 216 | 80 | |
| 217 | fn cacheString(str: anytype) []const u8 { | |
| 218 | return &str; | |
| 81 | /// Deprecated in favor of `Writer.print`. | |
| 82 | pub 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 | } |
| 220 | 88 | |
| 221 | 89 | pub const Placeholder = struct { |
| 222 | 90 | specifier_arg: []const u8, |
| 223 | fill: u21, | |
| 91 | fill: u8, | |
| 224 | 92 | alignment: Alignment, |
| 225 | 93 | arg: Specifier, |
| 226 | 94 | width: Specifier, |
| 227 | 95 | precision: Specifier, |
| 228 | 96 | |
| 229 | pub fn parse(comptime str: anytype) Placeholder { | |
| 230 | const view = std.unicode.Utf8View.initComptime(&str); | |
| 231 | comptime var parser = Parser{ | |
| 232 | .iter = view.iterator(), | |
| 233 | }; | |
| 234 | ||
| 235 | // Parse the positional argument number | |
| 236 | const arg = comptime parser.specifier() catch |err| | |
| 237 | @compileError(@errorName(err)); | |
| 238 | ||
| 239 | // Parse the format specifier | |
| 240 | const specifier_arg = comptime parser.until(':'); | |
| 241 | ||
| 242 | // Skip the colon, if present | |
| 243 | if (comptime parser.char()) |ch| { | |
| 244 | if (ch != ':') { | |
| 245 | @compileError("expected : or }, found '" ++ unicode.utf8EncodeComptime(ch) ++ "'"); | |
| 246 | } | |
| 97 | pub fn parse(comptime bytes: []const u8) Placeholder { | |
| 98 | var parser: Parser = .{ .bytes = bytes, .i = 0 }; | |
| 99 | const arg = parser.specifier() catch |err| @compileError(@errorName(err)); | |
| 100 | const specifier_arg = parser.until(':'); | |
| 101 | if (parser.char()) |b| { | |
| 102 | if (b != ':') @compileError("expected : or }, found '" ++ &[1]u8{b} ++ "'"); | |
| 247 | 103 | } |
| 248 | 104 | |
| 249 | // Parse the fill character, if present. | |
| 250 | // When the width field is also specified, the fill character must | |
| 105 | // Parse the fill byte, if present. | |
| 106 | // | |
| 107 | // When the width field is also specified, the fill byte must | |
| 251 | 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) | |
| 253 | var fill: ?u21 = comptime if (parser.peek(1)) |ch| | |
| 254 | switch (ch) { | |
| 109 | // (in which case it's handled as part of the width specifier). | |
| 110 | var fill: ?u8 = if (parser.peek(1)) |b| | |
| 111 | switch (b) { | |
| 255 | 112 | '<', '^', '>' => parser.char(), |
| 256 | 113 | else => null, |
| 257 | 114 | } |
| ... | ... | @@ -259,8 +116,8 @@ pub const Placeholder = struct { |
| 259 | 116 | null; |
| 260 | 117 | |
| 261 | 118 | // Parse the alignment parameter |
| 262 | const alignment: ?Alignment = comptime if (parser.peek(0)) |ch| init: { | |
| 263 | switch (ch) { | |
| 119 | const alignment: ?Alignment = if (parser.peek(0)) |b| init: { | |
| 120 | switch (b) { | |
| 264 | 121 | '<', '^', '>' => { |
| 265 | 122 | // consume the character |
| 266 | 123 | break :init switch (parser.char().?) { |
| ... | ... | @@ -276,30 +133,26 @@ pub const Placeholder = struct { |
| 276 | 133 | // When none of the fill character and the alignment specifier have |
| 277 | 134 | // been provided, check whether the width starts with a zero. |
| 278 | 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 | } |
| 281 | 138 | |
| 282 | 139 | // Parse the width parameter |
| 283 | const width = comptime parser.specifier() catch |err| | |
| 284 | @compileError(@errorName(err)); | |
| 140 | const width = parser.specifier() catch |err| @compileError(@errorName(err)); | |
| 285 | 141 | |
| 286 | 142 | // Skip the dot, if present |
| 287 | if (comptime parser.char()) |ch| { | |
| 288 | if (ch != '.') { | |
| 289 | @compileError("expected . or }, found '" ++ unicode.utf8EncodeComptime(ch) ++ "'"); | |
| 290 | } | |
| 143 | if (parser.char()) |b| { | |
| 144 | if (b != '.') @compileError("expected . or }, found '" ++ &[1]u8{b} ++ "'"); | |
| 291 | 145 | } |
| 292 | 146 | |
| 293 | 147 | // Parse the precision parameter |
| 294 | const precision = comptime parser.specifier() catch |err| | |
| 295 | @compileError(@errorName(err)); | |
| 148 | const precision = parser.specifier() catch |err| @compileError(@errorName(err)); | |
| 296 | 149 | |
| 297 | if (comptime parser.char()) |ch| { | |
| 298 | @compileError("extraneous trailing character '" ++ unicode.utf8EncodeComptime(ch) ++ "'"); | |
| 299 | } | |
| 150 | if (parser.char()) |b| @compileError("extraneous trailing character '" ++ &[1]u8{b} ++ "'"); | |
| 151 | ||
| 152 | const specifier_array = specifier_arg[0..specifier_arg.len].*; | |
| 300 | 153 | |
| 301 | return Placeholder{ | |
| 302 | .specifier_arg = cacheString(specifier_arg[0..specifier_arg.len].*), | |
| 154 | return .{ | |
| 155 | .specifier_arg = &specifier_array, | |
| 303 | 156 | .fill = fill orelse default_fill_char, |
| 304 | 157 | .alignment = alignment orelse default_alignment, |
| 305 | 158 | .arg = arg, |
| ... | ... | @@ -320,93 +173,64 @@ pub const Specifier = union(enum) { |
| 320 | 173 | /// Allows to implement formatters compatible with std.fmt without replicating |
| 321 | 174 | /// the standard library behavior. |
| 322 | 175 | pub const Parser = struct { |
| 323 | iter: std.unicode.Utf8Iterator, | |
| 176 | bytes: []const u8, | |
| 177 | i: usize, | |
| 324 | 178 | |
| 325 | // Returns a decimal number or null if the current character is not a | |
| 326 | // digit | |
| 327 | 179 | pub fn number(self: *@This()) ?usize { |
| 328 | 180 | var r: ?usize = null; |
| 329 | ||
| 330 | while (self.peek(0)) |code_point| { | |
| 331 | switch (code_point) { | |
| 181 | while (self.peek(0)) |byte| { | |
| 182 | switch (byte) { | |
| 332 | 183 | '0'...'9' => { |
| 333 | 184 | if (r == null) r = 0; |
| 334 | 185 | r.? *= 10; |
| 335 | r.? += code_point - '0'; | |
| 186 | r.? += byte - '0'; | |
| 336 | 187 | }, |
| 337 | 188 | else => break, |
| 338 | 189 | } |
| 339 | _ = self.iter.nextCodepoint(); | |
| 190 | self.i += 1; | |
| 340 | 191 | } |
| 341 | ||
| 342 | 192 | return r; |
| 343 | 193 | } |
| 344 | 194 | |
| 345 | // Returns a substring of the input starting from the current position | |
| 346 | // and ending where `ch` is found or until the end if not found | |
| 347 | pub fn until(self: *@This(), ch: u21) []const u8 { | |
| 348 | const start = self.iter.i; | |
| 349 | while (self.peek(0)) |code_point| { | |
| 350 | if (code_point == ch) | |
| 351 | break; | |
| 352 | _ = self.iter.nextCodepoint(); | |
| 353 | } | |
| 354 | return self.iter.bytes[start..self.iter.i]; | |
| 195 | pub fn until(self: *@This(), delimiter: u8) []const u8 { | |
| 196 | const start = self.i; | |
| 197 | self.i = std.mem.indexOfScalarPos(u8, self.bytes, self.i, delimiter) orelse self.bytes.len; | |
| 198 | return self.bytes[start..self.i]; | |
| 355 | 199 | } |
| 356 | 200 | |
| 357 | // Returns the character pointed to by the iterator if available, or | |
| 358 | // null otherwise | |
| 359 | pub fn char(self: *@This()) ?u21 { | |
| 360 | if (self.iter.nextCodepoint()) |code_point| { | |
| 361 | return code_point; | |
| 362 | } | |
| 363 | return null; | |
| 201 | pub fn char(self: *@This()) ?u8 { | |
| 202 | const i = self.i; | |
| 203 | if (self.bytes.len - i == 0) return null; | |
| 204 | self.i = i + 1; | |
| 205 | return self.bytes[i]; | |
| 364 | 206 | } |
| 365 | 207 | |
| 366 | // Returns true if the iterator points to an existing character and | |
| 367 | // false otherwise | |
| 368 | pub fn maybe(self: *@This(), val: u21) bool { | |
| 369 | if (self.peek(0) == val) { | |
| 370 | _ = self.iter.nextCodepoint(); | |
| 208 | pub fn maybe(self: *@This(), byte: u8) bool { | |
| 209 | if (self.peek(0) == byte) { | |
| 210 | self.i += 1; | |
| 371 | 211 | return true; |
| 372 | 212 | } |
| 373 | 213 | return false; |
| 374 | 214 | } |
| 375 | 215 | |
| 376 | // Returns a decimal number or null if the current character is not a | |
| 377 | // digit | |
| 378 | 216 | pub fn specifier(self: *@This()) !Specifier { |
| 379 | 217 | if (self.maybe('[')) { |
| 380 | 218 | const arg_name = self.until(']'); |
| 381 | ||
| 382 | if (!self.maybe(']')) | |
| 383 | return @field(anyerror, "Expected closing ]"); | |
| 384 | ||
| 385 | return Specifier{ .named = arg_name }; | |
| 219 | if (!self.maybe(']')) return error.@"Expected closing ]"; | |
| 220 | return .{ .named = arg_name }; | |
| 386 | 221 | } |
| 387 | if (self.number()) |i| | |
| 388 | return Specifier{ .number = i }; | |
| 389 | ||
| 390 | return Specifier{ .none = {} }; | |
| 222 | if (self.number()) |i| return .{ .number = i }; | |
| 223 | return .{ .none = {} }; | |
| 391 | 224 | } |
| 392 | 225 | |
| 393 | // Returns the n-th next character or null if that's past the end | |
| 394 | pub fn peek(self: *@This(), n: usize) ?u21 { | |
| 395 | const original_i = self.iter.i; | |
| 396 | defer self.iter.i = original_i; | |
| 397 | ||
| 398 | var i: usize = 0; | |
| 399 | var code_point: ?u21 = null; | |
| 400 | while (i <= n) : (i += 1) { | |
| 401 | code_point = self.iter.nextCodepoint(); | |
| 402 | if (code_point == null) return null; | |
| 403 | } | |
| 404 | return code_point; | |
| 226 | pub fn peek(self: *@This(), i: usize) ?u8 { | |
| 227 | const peek_index = self.i + i; | |
| 228 | if (peek_index >= self.bytes.len) return null; | |
| 229 | return self.bytes[peek_index]; | |
| 405 | 230 | } |
| 406 | 231 | }; |
| 407 | 232 | |
| 408 | 233 | pub const ArgSetType = u32; |
| 409 | const max_format_args = @typeInfo(ArgSetType).int.bits; | |
| 410 | 234 | |
| 411 | 235 | pub const ArgState = struct { |
| 412 | 236 | next_arg: usize = 0, |
| ... | ... | @@ -434,1075 +258,66 @@ pub const ArgState = struct { |
| 434 | 258 | } |
| 435 | 259 | }; |
| 436 | 260 | |
| 437 | pub fn formatAddress(value: anytype, options: FormatOptions, writer: anytype) @TypeOf(writer).Error!void { | |
| 438 | _ = options; | |
| 439 | const T = @TypeOf(value); | |
| 440 | ||
| 441 | switch (@typeInfo(T)) { | |
| 442 | .pointer => |info| { | |
| 443 | try writer.writeAll(@typeName(info.child) ++ "@"); | |
| 444 | if (info.size == .slice) | |
| 445 | try formatInt(@intFromPtr(value.ptr), 16, .lower, FormatOptions{}, writer) | |
| 446 | else | |
| 447 | try formatInt(@intFromPtr(value), 16, .lower, FormatOptions{}, writer); | |
| 448 | return; | |
| 449 | }, | |
| 450 | .optional => |info| { | |
| 451 | if (@typeInfo(info.child) == .pointer) { | |
| 452 | try writer.writeAll(@typeName(info.child) ++ "@"); | |
| 453 | try formatInt(@intFromPtr(value), 16, .lower, FormatOptions{}, writer); | |
| 454 | return; | |
| 455 | } | |
| 456 | }, | |
| 457 | else => {}, | |
| 458 | } | |
| 459 | ||
| 460 | @compileError("cannot format non-pointer type " ++ @typeName(T) ++ " with * specifier"); | |
| 261 | /// Asserts the rendered integer value fits in `buffer`. | |
| 262 | /// Returns the end index within `buffer`. | |
| 263 | pub fn printInt(buffer: []u8, value: anytype, base: u8, case: Case, options: Options) usize { | |
| 264 | var w: Writer = .fixed(buffer); | |
| 265 | w.printInt(value, base, case, options) catch unreachable; | |
| 266 | return w.end; | |
| 461 | 267 | } |
| 462 | 268 | |
| 463 | // This ANY const is a workaround for: https://github.com/ziglang/zig/issues/7948 | |
| 464 | const ANY = "any"; | |
| 465 | ||
| 466 | pub fn defaultSpec(comptime T: type) [:0]const u8 { | |
| 467 | switch (@typeInfo(T)) { | |
| 468 | .array, .vector => return ANY, | |
| 469 | .pointer => |ptr_info| switch (ptr_info.size) { | |
| 470 | .one => switch (@typeInfo(ptr_info.child)) { | |
| 471 | .array => return ANY, | |
| 472 | else => {}, | |
| 473 | }, | |
| 474 | .many, .c => return "*", | |
| 475 | .slice => return ANY, | |
| 476 | }, | |
| 477 | .optional => |info| return "?" ++ defaultSpec(info.child), | |
| 478 | .error_union => |info| return "!" ++ defaultSpec(info.payload), | |
| 479 | else => {}, | |
| 480 | } | |
| 481 | return ""; | |
| 482 | } | |
| 483 | ||
| 484 | fn 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 | ||
| 491 | pub fn invalidFmtError(comptime fmt: []const u8, value: anytype) void { | |
| 492 | @compileError("invalid format string '" ++ fmt ++ "' for type '" ++ @typeName(@TypeOf(value)) ++ "'"); | |
| 493 | } | |
| 494 | ||
| 495 | pub 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 | ||
| 720 | fn 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 | ||
| 735 | pub 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 | ||
| 783 | pub const format_float = @import("fmt/format_float.zig"); | |
| 784 | pub const formatFloat = format_float.formatFloat; | |
| 785 | pub const FormatFloatError = format_float.FormatError; | |
| 786 | ||
| 787 | fn 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); | |
| 269 | /// Converts values in the range [0, 100) to a base 10 string. | |
| 270 | pub fn digits2(value: u8) [2]u8 { | |
| 271 | if (builtin.mode == .ReleaseSmall) { | |
| 272 | return .{ @intCast('0' + value / 10), @intCast('0' + value % 10) }; | |
| 811 | 273 | } else { |
| 812 | invalidFmtError(fmt, value); | |
| 274 | return "00010203040506070809101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899"[value * 2 ..][0..2].*; | |
| 813 | 275 | } |
| 814 | 276 | } |
| 815 | 277 | |
| 816 | test { | |
| 817 | _ = &format_float; | |
| 818 | } | |
| 819 | ||
| 820 | pub const Case = enum { lower, upper }; | |
| 821 | ||
| 822 | fn 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 | ||
| 845 | const formatSliceHexLower = SliceHex(.lower).format; | |
| 846 | const 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. | |
| 850 | pub 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. | |
| 856 | pub fn fmtSliceHexUpper(bytes: []const u8) std.fmt.Formatter(formatSliceHexUpper) { | |
| 857 | return .{ .data = bytes }; | |
| 858 | } | |
| 859 | ||
| 860 | fn SliceEscape(comptime case: Case) type { | |
| 861 | const charset = "0123456789" ++ if (case == .upper) "ABCDEF" else "abcdef"; | |
| 278 | /// Deprecated in favor of `Alt`. | |
| 279 | pub const Formatter = Alt; | |
| 862 | 280 | |
| 281 | /// Creates a type suitable for instantiating and passing to a "{f}" placeholder. | |
| 282 | pub fn Alt( | |
| 283 | comptime Data: type, | |
| 284 | comptime formatFn: fn (data: Data, writer: *Writer) Writer.Error!void, | |
| 285 | ) type { | |
| 863 | 286 | return struct { |
| 864 | pub fn format( | |
| 865 | bytes: []const u8, | |
| 866 | comptime fmt: []const u8, | |
| 867 | options: std.fmt.FormatOptions, | |
| 868 | writer: anytype, | |
| 869 | ) !void { | |
| 870 | _ = fmt; | |
| 871 | _ = options; | |
| 872 | var buf: [4]u8 = undefined; | |
| 873 | ||
| 874 | buf[0] = '\\'; | |
| 875 | buf[1] = 'x'; | |
| 876 | ||
| 877 | for (bytes) |c| { | |
| 878 | if (std.ascii.isPrint(c)) { | |
| 879 | try writer.writeByte(c); | |
| 880 | } else { | |
| 881 | buf[2] = charset[c >> 4]; | |
| 882 | buf[3] = charset[c & 15]; | |
| 883 | try writer.writeAll(&buf); | |
| 884 | } | |
| 885 | } | |
| 287 | data: Data, | |
| 288 | pub inline fn format(self: @This(), writer: *Writer) Writer.Error!void { | |
| 289 | try formatFn(self.data, writer); | |
| 886 | 290 | } |
| 887 | 291 | }; |
| 888 | 292 | } |
| 889 | 293 | |
| 890 | const formatSliceEscapeLower = SliceEscape(.lower).format; | |
| 891 | const formatSliceEscapeUpper = SliceEscape(.upper).format; | |
| 892 | ||
| 893 | /// Return a Formatter for a []const u8 where every non-printable ASCII | |
| 894 | /// character is escaped as \xNN, where NN is the character in lowercase | |
| 895 | /// hexadecimal notation. | |
| 896 | pub fn fmtSliceEscapeLower(bytes: []const u8) std.fmt.Formatter(formatSliceEscapeLower) { | |
| 897 | return .{ .data = bytes }; | |
| 294 | /// Helper for calling alternate format methods besides one named "format". | |
| 295 | pub fn alt( | |
| 296 | context: anytype, | |
| 297 | comptime func_name: @TypeOf(.enum_literal), | |
| 298 | ) Formatter(@TypeOf(context), @field(@TypeOf(context), @tagName(func_name))) { | |
| 299 | return .{ .data = context }; | |
| 898 | 300 | } |
| 899 | 301 | |
| 900 | /// Return a Formatter for a []const u8 where every non-printable ASCII | |
| 901 | /// character is escaped as \xNN, where NN is the character in uppercase | |
| 902 | /// hexadecimal notation. | |
| 903 | pub fn fmtSliceEscapeUpper(bytes: []const u8) std.fmt.Formatter(formatSliceEscapeUpper) { | |
| 904 | return .{ .data = bytes }; | |
| 905 | } | |
| 906 | ||
| 907 | fn 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"; | |
| 302 | test alt { | |
| 303 | const Example = struct { | |
| 304 | number: u8, | |
| 924 | 305 | |
| 925 | const log2 = math.log2(value); | |
| 926 | const magnitude = switch (base) { | |
| 927 | 1000 => @min(log2 / comptime math.log2(1000), mags_si.len - 1), | |
| 928 | 1024 => @min(log2 / 10, mags_iec.len - 1), | |
| 929 | else => unreachable, | |
| 930 | }; | |
| 931 | const new_value = lossyCast(f64, value) / math.pow(f64, lossyCast(f64, base), lossyCast(f64, magnitude)); | |
| 932 | const suffix = switch (base) { | |
| 933 | 1000 => mags_si[magnitude], | |
| 934 | 1024 => mags_iec[magnitude], | |
| 935 | else => unreachable, | |
| 936 | }; | |
| 937 | ||
| 938 | const s = switch (magnitude) { | |
| 939 | 0 => buf[0..formatIntBuf(&buf, value, 10, .lower, .{})], | |
| 940 | else => formatFloat(&buf, new_value, .{ .mode = .decimal, .precision = options.precision }) catch |err| switch (err) { | |
| 941 | error.BufferTooSmall => unreachable, | |
| 942 | }, | |
| 943 | }; | |
| 944 | ||
| 945 | var i: usize = s.len; | |
| 946 | if (suffix == ' ') { | |
| 947 | buf[i] = 'B'; | |
| 948 | i += 1; | |
| 949 | } else switch (base) { | |
| 950 | 1000 => { | |
| 951 | buf[i..][0..2].* = [_]u8{ suffix, 'B' }; | |
| 952 | i += 2; | |
| 953 | }, | |
| 954 | 1024 => { | |
| 955 | buf[i..][0..3].* = [_]u8{ suffix, 'i', 'B' }; | |
| 956 | i += 3; | |
| 957 | }, | |
| 958 | else => unreachable, | |
| 959 | } | |
| 960 | ||
| 961 | return formatBuf(buf[0..i], options, writer); | |
| 306 | pub fn other(ex: @This(), w: *Writer) Writer.Error!void { | |
| 307 | try w.writeByte(ex.number); | |
| 962 | 308 | } |
| 963 | 309 | }; |
| 964 | } | |
| 965 | const formatSizeDec = Size(1000).format; | |
| 966 | const 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 | |
| 972 | pub 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 | |
| 980 | pub fn fmtIntSizeBin(value: u64) std.fmt.Formatter(formatSizeBin) { | |
| 981 | return .{ .data = value }; | |
| 982 | } | |
| 983 | ||
| 984 | fn 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 | ||
| 996 | pub 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 | ||
| 1006 | pub 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 | ||
| 1014 | pub 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 | ||
| 1028 | pub 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 | ||
| 1072 | pub 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 | ||
| 1181 | pub 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 | ||
| 1249 | pub 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. | |
| 1256 | pub 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 | ||
| 1264 | const FormatDurationData = struct { | |
| 1265 | ns: u64, | |
| 1266 | negative: bool = false, | |
| 1267 | }; | |
| 1268 | ||
| 1269 | fn 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 | |
| 1329 | pub fn fmtDuration(ns: u64) Formatter(formatDuration) { | |
| 1330 | const data = FormatDurationData{ .ns = ns }; | |
| 1331 | return .{ .data = data }; | |
| 1332 | } | |
| 1333 | ||
| 1334 | test 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 | ||
| 1382 | fn 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 | |
| 1389 | pub fn fmtDurationSigned(ns: i64) Formatter(formatDurationSigned) { | |
| 1390 | return .{ .data = ns }; | |
| 1391 | } | |
| 1392 | ||
| 1393 | test 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 | } | |
| 310 | const ex: Example = .{ .number = 'a' }; | |
| 311 | try expectFmt("a", "{f}", .{alt(ex, .other)}); | |
| 1470 | 312 | } |
| 1471 | 313 | |
| 1472 | 314 | pub const ParseIntError = error{ |
| 1473 | /// The result cannot fit in the type specified | |
| 315 | /// The result cannot fit in the type specified. | |
| 1474 | 316 | Overflow, |
| 1475 | ||
| 1476 | /// The input was empty or contained an invalid character | |
| 317 | /// The input was empty or contained an invalid character. | |
| 1477 | 318 | InvalidCharacter, |
| 1478 | 319 | }; |
| 1479 | 320 | |
| 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 | /// | |
| 1491 | pub 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 | 321 | /// Parses the string `buf` as signed or unsigned representation in the |
| 1507 | 322 | /// specified base of an integral value of type `T`. |
| 1508 | 323 | /// |
| ... | ... | @@ -1793,15 +608,13 @@ pub const BufPrintError = error{ |
| 1793 | 608 | NoSpaceLeft, |
| 1794 | 609 | }; |
| 1795 | 610 | |
| 1796 | /// Print a Formatter string into `buf`. Actually just a thin wrapper around `format` and `fixedBufferStream`. | |
| 1797 | /// Returns a slice of the bytes printed to. | |
| 611 | /// Print a Formatter string into `buf`. Returns a slice of the bytes printed. | |
| 1798 | 612 | pub fn bufPrint(buf: []u8, comptime fmt: []const u8, args: anytype) BufPrintError![]u8 { |
| 1799 | var fbs = std.io.fixedBufferStream(buf); | |
| 1800 | format(fbs.writer().any(), fmt, args) catch |err| switch (err) { | |
| 1801 | error.NoSpaceLeft => return error.NoSpaceLeft, | |
| 1802 | else => unreachable, | |
| 613 | var w: Writer = .fixed(buf); | |
| 614 | w.print(fmt, args) catch |err| switch (err) { | |
| 615 | error.WriteFailed => return error.NoSpaceLeft, | |
| 1803 | 616 | }; |
| 1804 | return fbs.getWritten(); | |
| 617 | return w.buffered(); | |
| 1805 | 618 | } |
| 1806 | 619 | |
| 1807 | 620 | pub 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 | 622 | return result[0 .. result.len - 1 :0]; |
| 1810 | 623 | } |
| 1811 | 624 | |
| 1812 | /// Count the characters needed for format. Useful for preallocating memory | |
| 1813 | pub fn count(comptime fmt: []const u8, args: anytype) u64 { | |
| 1814 | var counting_writer = std.io.countingWriter(std.io.null_writer); | |
| 1815 | format(counting_writer.writer().any(), fmt, args) catch unreachable; | |
| 1816 | return counting_writer.bytes_written; | |
| 1817 | } | |
| 1818 | ||
| 1819 | pub const AllocPrintError = error{OutOfMemory}; | |
| 1820 | ||
| 1821 | pub 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 | |
| 625 | /// Count the characters needed for format. | |
| 626 | pub fn count(comptime fmt: []const u8, args: anytype) usize { | |
| 627 | var trash_buffer: [64]u8 = undefined; | |
| 628 | var dw: Writer.Discarding = .init(&trash_buffer); | |
| 629 | dw.writer.print(fmt, args) catch |err| switch (err) { | |
| 630 | error.WriteFailed => unreachable, | |
| 1826 | 631 | }; |
| 632 | return @intCast(dw.count + dw.writer.end); | |
| 1827 | 633 | } |
| 1828 | 634 | |
| 1829 | pub fn allocPrintZ(allocator: mem.Allocator, comptime fmt: []const u8, args: anytype) AllocPrintError![:0]u8 { | |
| 1830 | const result = try allocPrint(allocator, fmt ++ "\x00", args); | |
| 1831 | return result[0 .. result.len - 1 :0]; | |
| 1832 | } | |
| 1833 | ||
| 1834 | test bufPrintIntToSlice { | |
| 1835 | var buffer: [100]u8 = undefined; | |
| 1836 | const buf = buffer[0..]; | |
| 1837 | ||
| 1838 | try std.testing.expectEqualSlices(u8, "-1", bufPrintIntToSlice(buf, @as(i1, -1), 10, .lower, FormatOptions{})); | |
| 1839 | ||
| 1840 | try std.testing.expectEqualSlices(u8, "-101111000110000101001110", bufPrintIntToSlice(buf, @as(i32, -12345678), 2, .lower, FormatOptions{})); | |
| 1841 | try std.testing.expectEqualSlices(u8, "-12345678", bufPrintIntToSlice(buf, @as(i32, -12345678), 10, .lower, FormatOptions{})); | |
| 1842 | try std.testing.expectEqualSlices(u8, "-bc614e", bufPrintIntToSlice(buf, @as(i32, -12345678), 16, .lower, FormatOptions{})); | |
| 1843 | try std.testing.expectEqualSlices(u8, "-BC614E", bufPrintIntToSlice(buf, @as(i32, -12345678), 16, .upper, FormatOptions{})); | |
| 1844 | ||
| 1845 | try std.testing.expectEqualSlices(u8, "12345678", bufPrintIntToSlice(buf, @as(u32, 12345678), 10, .upper, FormatOptions{})); | |
| 1846 | ||
| 1847 | try std.testing.expectEqualSlices(u8, " 666", bufPrintIntToSlice(buf, @as(u32, 666), 10, .lower, FormatOptions{ .width = 6 })); | |
| 1848 | try std.testing.expectEqualSlices(u8, " 1234", bufPrintIntToSlice(buf, @as(u32, 0x1234), 16, .lower, FormatOptions{ .width = 6 })); | |
| 1849 | try std.testing.expectEqualSlices(u8, "1234", bufPrintIntToSlice(buf, @as(u32, 0x1234), 16, .lower, FormatOptions{ .width = 1 })); | |
| 1850 | ||
| 1851 | try std.testing.expectEqualSlices(u8, "+42", bufPrintIntToSlice(buf, @as(i32, 42), 10, .lower, FormatOptions{ .width = 3 })); | |
| 1852 | try std.testing.expectEqualSlices(u8, "-42", bufPrintIntToSlice(buf, @as(i32, -42), 10, .lower, FormatOptions{ .width = 3 })); | |
| 635 | pub fn allocPrint(gpa: Allocator, comptime fmt: []const u8, args: anytype) Allocator.Error![]u8 { | |
| 636 | var aw = try Writer.Allocating.initCapacity(gpa, fmt.len); | |
| 637 | defer aw.deinit(); | |
| 638 | aw.writer.print(fmt, args) catch |err| switch (err) { | |
| 639 | error.WriteFailed => return error.OutOfMemory, | |
| 640 | }; | |
| 641 | return aw.toOwnedSlice(); | |
| 1853 | 642 | } |
| 1854 | 643 | |
| 1855 | pub fn bufPrintIntToSlice(buf: []u8, value: anytype, base: u8, case: Case, options: FormatOptions) []u8 { | |
| 1856 | return buf[0..formatIntBuf(buf, value, base, case, options)]; | |
| 644 | pub fn allocPrintSentinel( | |
| 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 | } |
| 1858 | 657 | |
| 1859 | 658 | pub inline fn comptimePrint(comptime fmt: []const u8, args: anytype) *const [count(fmt, args):0]u8 { |
| ... | ... | @@ -1984,26 +783,22 @@ test "int.padded" { |
| 1984 | 783 | try expectFmt("i16: '-12345'", "i16: '{:4}'", .{@as(i16, -12345)}); |
| 1985 | 784 | try expectFmt("i16: '+12345'", "i16: '{:4}'", .{@as(i16, 12345)}); |
| 1986 | 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 | } |
| 1992 | 787 | |
| 1993 | 788 | test "buffer" { |
| 1994 | 789 | { |
| 1995 | 790 | var buf1: [32]u8 = undefined; |
| 1996 | var fbs = std.io.fixedBufferStream(&buf1); | |
| 1997 | try formatType(1234, "", FormatOptions{}, fbs.writer(), std.options.fmt_max_depth); | |
| 1998 | try std.testing.expectEqualStrings("1234", fbs.getWritten()); | |
| 791 | var w: Writer = .fixed(&buf1); | |
| 792 | try w.printValue("", .{}, 1234, std.options.fmt_max_depth); | |
| 793 | try std.testing.expectEqualStrings("1234", w.buffered()); | |
| 1999 | 794 | |
| 2000 | fbs.reset(); | |
| 2001 | try formatType('a', "c", FormatOptions{}, fbs.writer(), std.options.fmt_max_depth); | |
| 2002 | try std.testing.expectEqualStrings("a", fbs.getWritten()); | |
| 795 | w = .fixed(&buf1); | |
| 796 | try w.printValue("c", .{}, 'a', std.options.fmt_max_depth); | |
| 797 | try std.testing.expectEqualStrings("a", w.buffered()); | |
| 2003 | 798 | |
| 2004 | fbs.reset(); | |
| 2005 | try formatType(0b1100, "b", FormatOptions{}, fbs.writer(), std.options.fmt_max_depth); | |
| 2006 | try std.testing.expectEqualStrings("1100", fbs.getWritten()); | |
| 799 | w = .fixed(&buf1); | |
| 800 | try w.printValue("b", .{}, 0b1100, std.options.fmt_max_depth); | |
| 801 | try std.testing.expectEqualStrings("1100", w.buffered()); | |
| 2007 | 802 | } |
| 2008 | 803 | } |
| 2009 | 804 | |
| ... | ... | @@ -2017,36 +812,24 @@ fn expectArrayFmt(expected: []const u8, comptime template: []const u8, comptime |
| 2017 | 812 | } |
| 2018 | 813 | |
| 2019 | 814 | test "array" { |
| 2020 | { | |
| 2021 | const value: [3]u8 = "abc".*; | |
| 2022 | try expectArrayFmt("array: abc\n", "array: {s}\n", value); | |
| 2023 | try expectArrayFmt("array: { 97, 98, 99 }\n", "array: {d}\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".* }; | |
| 815 | const value: [3]u8 = "abc".*; | |
| 816 | try expectArrayFmt("array: abc\n", "array: {s}\n", value); | |
| 817 | try expectArrayFmt("array: 616263\n", "array: {x}\n", value); | |
| 818 | try expectArrayFmt("array: { 97, 98, 99 }\n", "array: {any}\n", value); | |
| 2037 | 819 | |
| 2038 | try expectArrayFmt("array: { abc, def }\n", "array: {s}\n", value); | |
| 2039 | try expectArrayFmt("array: { { 97, 98, 99 }, { 100, 101, 102 } }\n", "array: {d}\n", value); | |
| 2040 | try expectArrayFmt("array: { { 61, 62, 63 }, { 64, 65, 66 } }\n", "array: {x}\n", value); | |
| 2041 | } | |
| 820 | var buf: [100]u8 = undefined; | |
| 821 | try expectFmt( | |
| 822 | try bufPrint(buf[0..], "array: [3]u8@{x}\n", .{@intFromPtr(&value)}), | |
| 823 | "array: {*}\n", | |
| 824 | .{&value}, | |
| 825 | ); | |
| 2042 | 826 | } |
| 2043 | 827 | |
| 2044 | 828 | test "slice" { |
| 2045 | 829 | { |
| 2046 | 830 | const value: []const u8 = "abc"; |
| 2047 | 831 | try expectFmt("slice: abc\n", "slice: {s}\n", .{value}); |
| 2048 | try expectFmt("slice: { 97, 98, 99 }\n", "slice: {d}\n", .{value}); | |
| 2049 | try expectFmt("slice: { 61, 62, 63 }\n", "slice: {x}\n", .{value}); | |
| 832 | try expectFmt("slice: 616263\n", "slice: {x}\n", .{value}); | |
| 2050 | 833 | try expectFmt("slice: { 97, 98, 99 }\n", "slice: {any}\n", .{value}); |
| 2051 | 834 | } |
| 2052 | 835 | { |
| ... | ... | @@ -2060,45 +843,33 @@ test "slice" { |
| 2060 | 843 | try expectFmt("buf: \x00hello\x00\n", "buf: {s}\n", .{null_term_slice}); |
| 2061 | 844 | } |
| 2062 | 845 | |
| 2063 | try expectFmt("buf: Test\n", "buf: {s:5}\n", .{"Test"}); | |
| 2064 | 846 | try expectFmt("buf: Test\n Other text", "buf: {s}\n Other text", .{"Test"}); |
| 2065 | 847 | |
| 2066 | 848 | { |
| 2067 | 849 | var int_slice = [_]u32{ 1, 4096, 391891, 1111111111 }; |
| 2068 | var runtime_zero: usize = 0; | |
| 2069 | _ = &runtime_zero; | |
| 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..]}); | |
| 850 | const input: []const u32 = &int_slice; | |
| 851 | try expectFmt("int: { 1, 4096, 391891, 1111111111 }", "int: {any}", .{input}); | |
| 2074 | 852 | } |
| 2075 | 853 | { |
| 2076 | 854 | const S1 = struct { |
| 2077 | 855 | x: u8, |
| 2078 | 856 | }; |
| 2079 | 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 | 861 | const S2 = struct { |
| 2084 | 862 | x: u8, |
| 2085 | 863 | |
| 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 | 865 | try writer.print("S2({})", .{s.x}); |
| 2088 | 866 | } |
| 2089 | 867 | }; |
| 2090 | 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 | } |
| 2094 | 872 | |
| 2095 | test "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 | ||
| 2102 | 873 | test "pointer" { |
| 2103 | 874 | { |
| 2104 | 875 | const value = @as(*align(1) i32, @ptrFromInt(0xdeadbeef)); |
| ... | ... | @@ -2122,26 +893,6 @@ test "cstr" { |
| 2122 | 893 | "cstr: {s}\n", |
| 2123 | 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 | ||
| 2132 | test "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 | } |
| 2146 | 897 | |
| 2147 | 898 | test "struct" { |
| ... | ... | @@ -2150,8 +901,8 @@ test "struct" { |
| 2150 | 901 | field: u8, |
| 2151 | 902 | }; |
| 2152 | 903 | const value = Struct{ .field = 42 }; |
| 2153 | try expectFmt("struct: fmt.test.struct.Struct{ .field = 42 }\n", "struct: {}\n", .{value}); | |
| 2154 | try expectFmt("struct: fmt.test.struct.Struct{ .field = 42 }\n", "struct: {}\n", .{&value}); | |
| 904 | try expectFmt("struct: .{ .field = 42 }\n", "struct: {}\n", .{value}); | |
| 905 | try expectFmt("struct: .{ .field = 42 }\n", "struct: {}\n", .{&value}); | |
| 2155 | 906 | } |
| 2156 | 907 | { |
| 2157 | 908 | const Struct = struct { |
| ... | ... | @@ -2159,7 +910,7 @@ test "struct" { |
| 2159 | 910 | b: u1, |
| 2160 | 911 | }; |
| 2161 | 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 | } |
| 2164 | 915 | |
| 2165 | 916 | const S = struct { |
| ... | ... | @@ -2172,11 +923,11 @@ test "struct" { |
| 2172 | 923 | .b = error.Unused, |
| 2173 | 924 | }; |
| 2174 | 925 | |
| 2175 | try expectFmt("fmt.test.struct.S{ .a = 456, .b = error.Unused }", "{}", .{inst}); | |
| 926 | try expectFmt(".{ .a = 456, .b = error.Unused }", "{}", .{inst}); | |
| 2176 | 927 | // Tuples |
| 2177 | try expectFmt("{ }", "{}", .{.{}}); | |
| 2178 | try expectFmt("{ -1 }", "{}", .{.{-1}}); | |
| 2179 | try expectFmt("{ -1, 42, 2.5e4 }", "{}", .{.{ -1, 42, 0.25e5 }}); | |
| 928 | try expectFmt(".{ }", "{}", .{.{}}); | |
| 929 | try expectFmt(".{ -1 }", "{}", .{.{-1}}); | |
| 930 | try expectFmt(".{ -1, 42, 25000 }", "{}", .{.{ -1, 42, 0.25e5 }}); | |
| 2180 | 931 | } |
| 2181 | 932 | |
| 2182 | 933 | test "enum" { |
| ... | ... | @@ -2185,15 +936,15 @@ test "enum" { |
| 2185 | 936 | Two, |
| 2186 | 937 | }; |
| 2187 | 938 | const value = Enum.Two; |
| 2188 | try expectFmt("enum: fmt.test.enum.Enum.Two\n", "enum: {}\n", .{value}); | |
| 2189 | try expectFmt("enum: fmt.test.enum.Enum.Two\n", "enum: {}\n", .{&value}); | |
| 2190 | try expectFmt("enum: fmt.test.enum.Enum.One\n", "enum: {}\n", .{Enum.One}); | |
| 2191 | try expectFmt("enum: fmt.test.enum.Enum.Two\n", "enum: {}\n", .{Enum.Two}); | |
| 939 | try expectFmt("enum: .Two\n", "enum: {}\n", .{value}); | |
| 940 | try expectFmt("enum: .Two\n", "enum: {}\n", .{&value}); | |
| 941 | try expectFmt("enum: .One\n", "enum: {}\n", .{Enum.One}); | |
| 942 | try expectFmt("enum: .Two\n", "enum: {}\n", .{Enum.Two}); | |
| 2192 | 943 | |
| 2193 | 944 | // test very large enum to verify ct branch quota is large enough |
| 2194 | 945 | // TODO: https://github.com/ziglang/zig/issues/15609 |
| 2195 | 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 | } |
| 2198 | 949 | |
| 2199 | 950 | const E = enum { |
| ... | ... | @@ -2204,7 +955,7 @@ test "enum" { |
| 2204 | 955 | |
| 2205 | 956 | const inst = E.Two; |
| 2206 | 957 | |
| 2207 | try expectFmt("fmt.test.enum.E.Two", "{}", .{inst}); | |
| 958 | try expectFmt(".Two", "{}", .{inst}); | |
| 2208 | 959 | } |
| 2209 | 960 | |
| 2210 | 961 | test "non-exhaustive enum" { |
| ... | ... | @@ -2213,13 +964,17 @@ test "non-exhaustive enum" { |
| 2213 | 964 | Two = 0xbeef, |
| 2214 | 965 | _, |
| 2215 | 966 | }; |
| 2216 | try expectFmt("enum: fmt.test.non-exhaustive enum.Enum.One\n", "enum: {}\n", .{Enum.One}); | |
| 2217 | try expectFmt("enum: fmt.test.non-exhaustive enum.Enum.Two\n", "enum: {}\n", .{Enum.Two}); | |
| 2218 | try expectFmt("enum: fmt.test.non-exhaustive enum.Enum(4660)\n", "enum: {}\n", .{@as(Enum, @enumFromInt(0x1234))}); | |
| 2219 | try expectFmt("enum: fmt.test.non-exhaustive enum.Enum.One\n", "enum: {x}\n", .{Enum.One}); | |
| 2220 | try expectFmt("enum: fmt.test.non-exhaustive enum.Enum.Two\n", "enum: {x}\n", .{Enum.Two}); | |
| 2221 | try expectFmt("enum: fmt.test.non-exhaustive enum.Enum.Two\n", "enum: {X}\n", .{Enum.Two}); | |
| 2222 | try expectFmt("enum: fmt.test.non-exhaustive enum.Enum(1234)\n", "enum: {x}\n", .{@as(Enum, @enumFromInt(0x1234))}); | |
| 967 | try expectFmt("enum: .One\n", "enum: {}\n", .{Enum.One}); | |
| 968 | try expectFmt("enum: .Two\n", "enum: {}\n", .{Enum.Two}); | |
| 969 | try expectFmt("enum: @enumFromInt(4660)\n", "enum: {}\n", .{@as(Enum, @enumFromInt(0x1234))}); | |
| 970 | try expectFmt("enum: f\n", "enum: {x}\n", .{Enum.One}); | |
| 971 | try expectFmt("enum: beef\n", "enum: {x}\n", .{Enum.Two}); | |
| 972 | try expectFmt("enum: BEEF\n", "enum: {X}\n", .{Enum.Two}); | |
| 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 | } |
| 2224 | 979 | |
| 2225 | 980 | test "float.scientific" { |
| ... | ... | @@ -2345,41 +1100,6 @@ test "float.libc.sanity" { |
| 2345 | 1100 | try expectFmt("f64: 18014400656965630.00000", "f64: {d:.5}", .{@as(f64, @as(f32, @bitCast(@as(u32, 1518338049))))}); |
| 2346 | 1101 | } |
| 2347 | 1102 | |
| 2348 | test "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 | ||
| 2383 | 1103 | test "union" { |
| 2384 | 1104 | const TU = union(enum) { |
| 2385 | 1105 | float: f32, |
| ... | ... | @@ -2396,18 +1116,13 @@ test "union" { |
| 2396 | 1116 | int: u32, |
| 2397 | 1117 | }; |
| 2398 | 1118 | |
| 2399 | const tu_inst = TU{ .int = 123 }; | |
| 2400 | const uu_inst = UU{ .int = 456 }; | |
| 2401 | const eu_inst = EU{ .float = 321.123 }; | |
| 2402 | ||
| 2403 | try expectFmt("fmt.test.union.TU{ .int = 123 }", "{}", .{tu_inst}); | |
| 1119 | const tu_inst: TU = .{ .int = 123 }; | |
| 1120 | const uu_inst: UU = .{ .int = 456 }; | |
| 1121 | const eu_inst: EU = .{ .float = 321.123 }; | |
| 2404 | 1122 | |
| 2405 | var buf: [100]u8 = undefined; | |
| 2406 | const uu_result = try bufPrint(buf[0..], "{}", .{uu_inst}); | |
| 2407 | try std.testing.expectEqualStrings("fmt.test.union.UU@", uu_result[0..18]); | |
| 2408 | ||
| 2409 | const eu_result = try bufPrint(buf[0..], "{}", .{eu_inst}); | |
| 2410 | try std.testing.expectEqualStrings("fmt.test.union.EU@", eu_result[0..18]); | |
| 1123 | try expectFmt(".{ .int = 123 }", "{}", .{tu_inst}); | |
| 1124 | try expectFmt(".{ ... }", "{}", .{uu_inst}); | |
| 1125 | try expectFmt(".{ .float = 321.123, .int = 1134596030 }", "{}", .{eu_inst}); | |
| 2411 | 1126 | } |
| 2412 | 1127 | |
| 2413 | 1128 | test "struct.self-referential" { |
| ... | ... | @@ -2421,7 +1136,7 @@ test "struct.self-referential" { |
| 2421 | 1136 | }; |
| 2422 | 1137 | inst.a = &inst; |
| 2423 | 1138 | |
| 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 | } |
| 2426 | 1141 | |
| 2427 | 1142 | test "struct.zero-size" { |
| ... | ... | @@ -2436,18 +1151,7 @@ test "struct.zero-size" { |
| 2436 | 1151 | const a = A{}; |
| 2437 | 1152 | const b = B{ .a = a, .c = 0 }; |
| 2438 | 1153 | |
| 2439 | try expectFmt("fmt.test.struct.zero-size.B{ .a = fmt.test.struct.zero-size.A{ }, .c = 0 }", "{}", .{b}); | |
| 2440 | } | |
| 2441 | ||
| 2442 | test "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)}); | |
| 1154 | try expectFmt(".{ .a = .{ }, .c = 0 }", "{}", .{b}); | |
| 2451 | 1155 | } |
| 2452 | 1156 | |
| 2453 | 1157 | /// Encodes a sequence of bytes as hexadecimal digits. |
| ... | ... | @@ -2494,110 +1198,14 @@ test bytesToHex { |
| 2494 | 1198 | |
| 2495 | 1199 | test hexToBytes { |
| 2496 | 1200 | var buf: [32]u8 = undefined; |
| 2497 | try expectFmt("90" ** 32, "{s}", .{fmtSliceHexUpper(try hexToBytes(&buf, "90" ** 32))}); | |
| 2498 | try expectFmt("ABCD", "{s}", .{fmtSliceHexUpper(try hexToBytes(&buf, "ABCD"))}); | |
| 2499 | try expectFmt("", "{s}", .{fmtSliceHexUpper(try hexToBytes(&buf, ""))}); | |
| 1201 | try expectFmt("90" ** 32, "{X}", .{try hexToBytes(&buf, "90" ** 32)}); | |
| 1202 | try expectFmt("ABCD", "{X}", .{try hexToBytes(&buf, "ABCD")}); | |
| 1203 | try expectFmt("", "{X}", .{try hexToBytes(&buf, "")}); | |
| 2500 | 1204 | try std.testing.expectError(error.InvalidCharacter, hexToBytes(&buf, "012Z")); |
| 2501 | 1205 | try std.testing.expectError(error.InvalidLength, hexToBytes(&buf, "AAA")); |
| 2502 | 1206 | try std.testing.expectError(error.NoSpaceLeft, hexToBytes(buf[0..1], "ABAB")); |
| 2503 | 1207 | } |
| 2504 | 1208 | |
| 2505 | test "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 | ||
| 2514 | test "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 | ||
| 2526 | test "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 | ||
| 2601 | 1209 | test "positional" { |
| 2602 | 1210 | try expectFmt("2 1 0", "{2} {1} {0}", .{ @as(usize, 0), @as(usize, 1), @as(usize, 2) }); |
| 2603 | 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 | 1262 | |
| 2655 | 1263 | test "padding" { |
| 2656 | 1264 | try expectFmt("Simple", "{s}", .{"Simple"}); |
| 2657 | try expectFmt(" true", "{:10}", .{true}); | |
| 2658 | try expectFmt(" true", "{:>10}", .{true}); | |
| 2659 | try expectFmt("======true", "{:=>10}", .{true}); | |
| 2660 | try expectFmt("true======", "{:=<10}", .{true}); | |
| 2661 | try expectFmt(" true ", "{:^10}", .{true}); | |
| 2662 | try expectFmt("===true===", "{:=^10}", .{true}); | |
| 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"}); | |
| 1265 | try expectFmt(" 1234", "{:10}", .{1234}); | |
| 1266 | try expectFmt(" 1234", "{:>10}", .{1234}); | |
| 1267 | try expectFmt("======1234", "{:=>10}", .{1234}); | |
| 1268 | try expectFmt("1234======", "{:=<10}", .{1234}); | |
| 1269 | try expectFmt(" 1234 ", "{:^10}", .{1234}); | |
| 1270 | try expectFmt("===1234===", "{:=^10}", .{1234}); | |
| 2670 | 1271 | try expectFmt("====a", "{c:=>5}", .{'a'}); |
| 2671 | 1272 | try expectFmt("==a==", "{c:=^5}", .{'a'}); |
| 2672 | 1273 | try expectFmt("a====", "{c:=<5}", .{'a'}); |
| 2673 | 1274 | } |
| 2674 | 1275 | |
| 2675 | test "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 | ||
| 2684 | 1276 | test "decimal float padding" { |
| 2685 | 1277 | const number: f32 = 3.1415; |
| 2686 | 1278 | try expectFmt("left-pad: **3.142\n", "left-pad: {d:*>7.3}\n", .{number}); |
| ... | ... | @@ -2723,17 +1315,17 @@ test "named arguments" { |
| 2723 | 1315 | |
| 2724 | 1316 | test "runtime width specifier" { |
| 2725 | 1317 | const width: usize = 9; |
| 2726 | try expectFmt("~~hello~~", "{s:~^[1]}", .{ "hello", width }); | |
| 2727 | try expectFmt("~~hello~~", "{s:~^[width]}", .{ .string = "hello", .width = width }); | |
| 2728 | try expectFmt(" hello", "{s:[1]}", .{ "hello", width }); | |
| 2729 | try expectFmt("42 hello", "{d} {s:[2]}", .{ 42, "hello", width }); | |
| 1318 | try expectFmt("~~12345~~", "{d:~^[1]}", .{ 12345, width }); | |
| 1319 | try expectFmt("~~12345~~", "{d:~^[width]}", .{ .string = 12345, .width = width }); | |
| 1320 | try expectFmt(" 12345", "{d:[1]}", .{ 12345, width }); | |
| 1321 | try expectFmt("42 12345", "{d} {d:[2]}", .{ 42, 12345, width }); | |
| 2730 | 1322 | } |
| 2731 | 1323 | |
| 2732 | 1324 | test "runtime precision specifier" { |
| 2733 | 1325 | const number: f32 = 3.1415; |
| 2734 | 1326 | const precision: usize = 2; |
| 2735 | try expectFmt("3.14e0", "{:1.[1]}", .{ number, precision }); | |
| 2736 | try expectFmt("3.14e0", "{:1.[precision]}", .{ .number = number, .precision = precision }); | |
| 1327 | try expectFmt("3.14e0", "{e:1.[1]}", .{ number, precision }); | |
| 1328 | try expectFmt("3.14e0", "{e:1.[precision]}", .{ .number = number, .precision = precision }); | |
| 2737 | 1329 | } |
| 2738 | 1330 | |
| 2739 | 1331 | test "recursive format function" { |
| ... | ... | @@ -2742,16 +1334,16 @@ test "recursive format function" { |
| 2742 | 1334 | Leaf: i32, |
| 2743 | 1335 | Branch: struct { left: *const R, right: *const R }, |
| 2744 | 1336 | |
| 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 | 1338 | return switch (self) { |
| 2747 | .Leaf => |n| std.fmt.format(writer, "Leaf({})", .{n}), | |
| 2748 | .Branch => |b| std.fmt.format(writer, "Branch({}, {})", .{ b.left, b.right }), | |
| 1339 | .Leaf => |n| writer.print("Leaf({})", .{n}), | |
| 1340 | .Branch => |b| writer.print("Branch({f}, {f})", .{ b.left, b.right }), | |
| 2749 | 1341 | }; |
| 2750 | 1342 | } |
| 2751 | 1343 | }; |
| 2752 | 1344 | |
| 2753 | var r = R{ .Leaf = 1 }; | |
| 2754 | try expectFmt("Leaf(1)\n", "{}\n", .{&r}); | |
| 1345 | var r: R = .{ .Leaf = 1 }; | |
| 1346 | try expectFmt("Leaf(1)\n", "{f}\n", .{&r}); | |
| 2755 | 1347 | } |
| 2756 | 1348 | |
| 2757 | 1349 | pub const hex_charset = "0123456789abcdef"; |
| ... | ... | @@ -2785,54 +1377,39 @@ test hex { |
| 2785 | 1377 | |
| 2786 | 1378 | test "parser until" { |
| 2787 | 1379 | { // return substring till ':' |
| 2788 | var parser: Parser = .{ | |
| 2789 | .iter = .{ .bytes = "abc:1234", .i = 0 }, | |
| 2790 | }; | |
| 1380 | var parser: Parser = .{ .bytes = "abc:1234", .i = 0 }; | |
| 2791 | 1381 | try testing.expectEqualStrings("abc", parser.until(':')); |
| 2792 | 1382 | } |
| 2793 | 1383 | |
| 2794 | 1384 | { // return the entire string - `ch` not found |
| 2795 | var parser: Parser = .{ | |
| 2796 | .iter = .{ .bytes = "abc1234", .i = 0 }, | |
| 2797 | }; | |
| 1385 | var parser: Parser = .{ .bytes = "abc1234", .i = 0 }; | |
| 2798 | 1386 | try testing.expectEqualStrings("abc1234", parser.until(':')); |
| 2799 | 1387 | } |
| 2800 | 1388 | |
| 2801 | 1389 | { // substring is empty - `ch` is the only character |
| 2802 | var parser: Parser = .{ | |
| 2803 | .iter = .{ .bytes = ":", .i = 0 }, | |
| 2804 | }; | |
| 1390 | var parser: Parser = .{ .bytes = ":", .i = 0 }; | |
| 2805 | 1391 | try testing.expectEqualStrings("", parser.until(':')); |
| 2806 | 1392 | } |
| 2807 | 1393 | |
| 2808 | 1394 | { // empty string and `ch` not found |
| 2809 | var parser: Parser = .{ | |
| 2810 | .iter = .{ .bytes = "", .i = 0 }, | |
| 2811 | }; | |
| 1395 | var parser: Parser = .{ .bytes = "", .i = 0 }; | |
| 2812 | 1396 | try testing.expectEqualStrings("", parser.until(':')); |
| 2813 | 1397 | } |
| 2814 | 1398 | |
| 2815 | 1399 | { // substring starts at index 2 and goes upto `ch` |
| 2816 | var parser: Parser = .{ | |
| 2817 | .iter = .{ .bytes = "abc:1234", .i = 2 }, | |
| 2818 | }; | |
| 1400 | var parser: Parser = .{ .bytes = "abc:1234", .i = 2 }; | |
| 2819 | 1401 | try testing.expectEqualStrings("c", parser.until(':')); |
| 2820 | 1402 | } |
| 2821 | 1403 | |
| 2822 | 1404 | { // substring starts at index 4 and goes upto the end - `ch` not found |
| 2823 | var parser: Parser = .{ | |
| 2824 | .iter = .{ .bytes = "abc1234", .i = 4 }, | |
| 2825 | }; | |
| 1405 | var parser: Parser = .{ .bytes = "abc1234", .i = 4 }; | |
| 2826 | 1406 | try testing.expectEqualStrings("234", parser.until(':')); |
| 2827 | 1407 | } |
| 2828 | 1408 | } |
| 2829 | 1409 | |
| 2830 | 1410 | test "parser peek" { |
| 2831 | 1411 | { // start iteration from the first index |
| 2832 | var parser: Parser = .{ | |
| 2833 | .iter = .{ .bytes = "hello world", .i = 0 }, | |
| 2834 | }; | |
| 2835 | ||
| 1412 | var parser: Parser = .{ .bytes = "hello world", .i = 0 }; | |
| 2836 | 1413 | try testing.expectEqual('h', parser.peek(0)); |
| 2837 | 1414 | try testing.expectEqual('e', parser.peek(1)); |
| 2838 | 1415 | try testing.expectEqual(' ', parser.peek(5)); |
| ... | ... | @@ -2841,9 +1418,7 @@ test "parser peek" { |
| 2841 | 1418 | } |
| 2842 | 1419 | |
| 2843 | 1420 | { // start iteration from the second last index |
| 2844 | var parser: Parser = .{ | |
| 2845 | .iter = .{ .bytes = "hello world!", .i = 10 }, | |
| 2846 | }; | |
| 1421 | var parser: Parser = .{ .bytes = "hello world!", .i = 10 }; | |
| 2847 | 1422 | |
| 2848 | 1423 | try testing.expectEqual('d', parser.peek(0)); |
| 2849 | 1424 | try testing.expectEqual('!', parser.peek(1)); |
| ... | ... | @@ -2851,18 +1426,14 @@ test "parser peek" { |
| 2851 | 1426 | } |
| 2852 | 1427 | |
| 2853 | 1428 | { // start iteration beyond the length of the string |
| 2854 | var parser: Parser = .{ | |
| 2855 | .iter = .{ .bytes = "hello", .i = 5 }, | |
| 2856 | }; | |
| 1429 | var parser: Parser = .{ .bytes = "hello", .i = 5 }; | |
| 2857 | 1430 | |
| 2858 | 1431 | try testing.expectEqual(null, parser.peek(0)); |
| 2859 | 1432 | try testing.expectEqual(null, parser.peek(1)); |
| 2860 | 1433 | } |
| 2861 | 1434 | |
| 2862 | 1435 | { // empty string |
| 2863 | var parser: Parser = .{ | |
| 2864 | .iter = .{ .bytes = "", .i = 0 }, | |
| 2865 | }; | |
| 1436 | var parser: Parser = .{ .bytes = "", .i = 0 }; | |
| 2866 | 1437 | |
| 2867 | 1438 | try testing.expectEqual(null, parser.peek(0)); |
| 2868 | 1439 | try testing.expectEqual(null, parser.peek(2)); |
| ... | ... | @@ -2871,78 +1442,78 @@ test "parser peek" { |
| 2871 | 1442 | |
| 2872 | 1443 | test "parser char" { |
| 2873 | 1444 | // character exists - iterator at 0 |
| 2874 | var parser: Parser = .{ .iter = .{ .bytes = "~~hello", .i = 0 } }; | |
| 1445 | var parser: Parser = .{ .bytes = "~~hello", .i = 0 }; | |
| 2875 | 1446 | try testing.expectEqual('~', parser.char()); |
| 2876 | 1447 | |
| 2877 | 1448 | // character exists - iterator in the middle |
| 2878 | parser = .{ .iter = .{ .bytes = "~~hello", .i = 3 } }; | |
| 1449 | parser = .{ .bytes = "~~hello", .i = 3 }; | |
| 2879 | 1450 | try testing.expectEqual('e', parser.char()); |
| 2880 | 1451 | |
| 2881 | 1452 | // character exists - iterator at the end |
| 2882 | parser = .{ .iter = .{ .bytes = "~~hello", .i = 6 } }; | |
| 1453 | parser = .{ .bytes = "~~hello", .i = 6 }; | |
| 2883 | 1454 | try testing.expectEqual('o', parser.char()); |
| 2884 | 1455 | |
| 2885 | 1456 | // 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 | 1458 | try testing.expectEqual(null, parser.char()); |
| 2888 | 1459 | } |
| 2889 | 1460 | |
| 2890 | 1461 | test "parser maybe" { |
| 2891 | 1462 | // 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 | 1464 | try testing.expect(parser.maybe('h')); |
| 2894 | 1465 | |
| 2895 | 1466 | // character exists - iterator at space |
| 2896 | parser = .{ .iter = .{ .bytes = "hello world", .i = 5 } }; | |
| 1467 | parser = .{ .bytes = "hello world", .i = 5 }; | |
| 2897 | 1468 | try testing.expect(parser.maybe(' ')); |
| 2898 | 1469 | |
| 2899 | 1470 | // character exists - iterator at the end |
| 2900 | parser = .{ .iter = .{ .bytes = "hello world", .i = 10 } }; | |
| 1471 | parser = .{ .bytes = "hello world", .i = 10 }; | |
| 2901 | 1472 | try testing.expect(parser.maybe('d')); |
| 2902 | 1473 | |
| 2903 | 1474 | // 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 | 1476 | try testing.expect(!parser.maybe('e')); |
| 2906 | 1477 | } |
| 2907 | 1478 | |
| 2908 | 1479 | test "parser number" { |
| 2909 | 1480 | // 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 | 1482 | try testing.expect(7 == parser.number()); |
| 2912 | 1483 | |
| 2913 | 1484 | // input is a two digit natural number - iterator at 1 |
| 2914 | parser = .{ .iter = .{ .bytes = "29", .i = 1 } }; | |
| 1485 | parser = .{ .bytes = "29", .i = 1 }; | |
| 2915 | 1486 | try testing.expect(9 == parser.number()); |
| 2916 | 1487 | |
| 2917 | 1488 | // 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 | 1490 | try testing.expectEqual(null, parser.number()); |
| 2920 | 1491 | |
| 2921 | 1492 | // input is an integer |
| 2922 | parser = .{ .iter = .{ .bytes = "0", .i = 0 } }; | |
| 1493 | parser = .{ .bytes = "0", .i = 0 }; | |
| 2923 | 1494 | try testing.expect(0 == parser.number()); |
| 2924 | 1495 | |
| 2925 | 1496 | // input is a negative integer |
| 2926 | parser = .{ .iter = .{ .bytes = "-2", .i = 0 } }; | |
| 1497 | parser = .{ .bytes = "-2", .i = 0 }; | |
| 2927 | 1498 | try testing.expectEqual(null, parser.number()); |
| 2928 | 1499 | |
| 2929 | 1500 | // input is a string |
| 2930 | parser = .{ .iter = .{ .bytes = "no_number", .i = 2 } }; | |
| 1501 | parser = .{ .bytes = "no_number", .i = 2 }; | |
| 2931 | 1502 | try testing.expectEqual(null, parser.number()); |
| 2932 | 1503 | |
| 2933 | 1504 | // input is a single character string |
| 2934 | parser = .{ .iter = .{ .bytes = "n", .i = 0 } }; | |
| 1505 | parser = .{ .bytes = "n", .i = 0 }; | |
| 2935 | 1506 | try testing.expectEqual(null, parser.number()); |
| 2936 | 1507 | |
| 2937 | 1508 | // input is an empty string |
| 2938 | parser = .{ .iter = .{ .bytes = "", .i = 0 } }; | |
| 1509 | parser = .{ .bytes = "", .i = 0 }; | |
| 2939 | 1510 | try testing.expectEqual(null, parser.number()); |
| 2940 | 1511 | } |
| 2941 | 1512 | |
| 2942 | 1513 | test "parser specifier" { |
| 2943 | 1514 | { // input string is a digit; iterator at 0 |
| 2944 | 1515 | const expected: Specifier = Specifier{ .number = 1 }; |
| 2945 | var parser: Parser = .{ .iter = .{ .bytes = "1", .i = 0 } }; | |
| 1516 | var parser: Parser = .{ .bytes = "1", .i = 0 }; | |
| 2946 | 1517 | |
| 2947 | 1518 | const result = try parser.specifier(); |
| 2948 | 1519 | try testing.expect(expected.number == result.number); |
| ... | ... | @@ -2950,7 +1521,7 @@ test "parser specifier" { |
| 2950 | 1521 | |
| 2951 | 1522 | { // input string is a two digit number; iterator at 0 |
| 2952 | 1523 | const digit: Specifier = Specifier{ .number = 42 }; |
| 2953 | var parser: Parser = .{ .iter = .{ .bytes = "42", .i = 0 } }; | |
| 1524 | var parser: Parser = .{ .bytes = "42", .i = 0 }; | |
| 2954 | 1525 | |
| 2955 | 1526 | const result = try parser.specifier(); |
| 2956 | 1527 | try testing.expect(digit.number == result.number); |
| ... | ... | @@ -2958,7 +1529,7 @@ test "parser specifier" { |
| 2958 | 1529 | |
| 2959 | 1530 | { // input string is a two digit number digit; iterator at 1 |
| 2960 | 1531 | const digit: Specifier = Specifier{ .number = 8 }; |
| 2961 | var parser: Parser = .{ .iter = .{ .bytes = "28", .i = 1 } }; | |
| 1532 | var parser: Parser = .{ .bytes = "28", .i = 1 }; | |
| 2962 | 1533 | |
| 2963 | 1534 | const result = try parser.specifier(); |
| 2964 | 1535 | try testing.expect(digit.number == result.number); |
| ... | ... | @@ -2966,7 +1537,7 @@ test "parser specifier" { |
| 2966 | 1537 | |
| 2967 | 1538 | { // input string is a two digit number with square brackets; iterator at 0 |
| 2968 | 1539 | const digit: Specifier = Specifier{ .named = "15" }; |
| 2969 | var parser: Parser = .{ .iter = .{ .bytes = "[15]", .i = 0 } }; | |
| 1540 | var parser: Parser = .{ .bytes = "[15]", .i = 0 }; | |
| 2970 | 1541 | |
| 2971 | 1542 | const result = try parser.specifier(); |
| 2972 | 1543 | try testing.expectEqualStrings(digit.named, result.named); |
| ... | ... | @@ -2974,21 +1545,21 @@ test "parser specifier" { |
| 2974 | 1545 | |
| 2975 | 1546 | { // input string is not a number and contains square brackets; iterator at 0 |
| 2976 | 1547 | const digit: Specifier = Specifier{ .named = "hello" }; |
| 2977 | var parser: Parser = .{ .iter = .{ .bytes = "[hello]", .i = 0 } }; | |
| 1548 | var parser: Parser = .{ .bytes = "[hello]", .i = 0 }; | |
| 2978 | 1549 | |
| 2979 | 1550 | const result = try parser.specifier(); |
| 2980 | 1551 | try testing.expectEqualStrings(digit.named, result.named); |
| 2981 | 1552 | } |
| 2982 | 1553 | |
| 2983 | 1554 | { // 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 }; | |
| 2985 | 1556 | |
| 2986 | 1557 | const result = parser.specifier(); |
| 2987 | 1558 | try testing.expectError(@field(anyerror, "Expected closing ]"), result); |
| 2988 | 1559 | } |
| 2989 | 1560 | |
| 2990 | 1561 | { // 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 }; | |
| 2992 | 1563 | |
| 2993 | 1564 | const result = parser.specifier(); |
| 2994 | 1565 | try testing.expectError(@field(anyerror, "Expected closing ]"), result); |
| ... | ... | @@ -2996,7 +1567,7 @@ test "parser specifier" { |
| 2996 | 1567 | |
| 2997 | 1568 | { // input string is not a number and contains unbalanced square brackets; iterator at 0 |
| 2998 | 1569 | const digit: Specifier = Specifier{ .named = "[[hello" }; |
| 2999 | var parser: Parser = .{ .iter = .{ .bytes = "[[[hello]", .i = 0 } }; | |
| 1570 | var parser: Parser = .{ .bytes = "[[[hello]", .i = 0 }; | |
| 3000 | 1571 | |
| 3001 | 1572 | const result = try parser.specifier(); |
| 3002 | 1573 | try testing.expectEqualStrings(digit.named, result.named); |
| ... | ... | @@ -3004,7 +1575,7 @@ test "parser specifier" { |
| 3004 | 1575 | |
| 3005 | 1576 | { // input string is not a number and contains unbalanced square brackets; iterator at 1 |
| 3006 | 1577 | const digit: Specifier = Specifier{ .named = "[[hello" }; |
| 3007 | var parser: Parser = .{ .iter = .{ .bytes = "[[[[hello]]]]]", .i = 1 } }; | |
| 1578 | var parser: Parser = .{ .bytes = "[[[[hello]]]]]", .i = 1 }; | |
| 3008 | 1579 | |
| 3009 | 1580 | const result = try parser.specifier(); |
| 3010 | 1581 | try testing.expectEqualStrings(digit.named, result.named); |
| ... | ... | @@ -3012,9 +1583,13 @@ test "parser specifier" { |
| 3012 | 1583 | |
| 3013 | 1584 | { // input string is neither a digit nor a named argument |
| 3014 | 1585 | const char: Specifier = Specifier{ .none = {} }; |
| 3015 | var parser: Parser = .{ .iter = .{ .bytes = "hello", .i = 0 } }; | |
| 1586 | var parser: Parser = .{ .bytes = "hello", .i = 0 }; | |
| 3016 | 1587 | |
| 3017 | 1588 | const result = try parser.specifier(); |
| 3018 | 1589 | try testing.expectEqual(char.none, result.none); |
| 3019 | 1590 | } |
| 3020 | 1591 | } |
| 1592 | ||
| 1593 | test { | |
| 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 | ||
| 4 | const std = @import("std"); | |
| 5 | const expectFmt = std.testing.expectFmt; | |
| 6 | ||
| 7 | const 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. | |
| 11 | pub const min_buffer_size = 53; | |
| 12 | ||
| 13 | /// Returns the minimum buffer size needed to print every float of a specific type and format. | |
| 14 | pub 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 | ||
| 30 | pub const Error = error{ | |
| 31 | BufferTooSmall, | |
| 32 | }; | |
| 33 | ||
| 34 | pub const Mode = enum { | |
| 35 | scientific, | |
| 36 | decimal, | |
| 37 | }; | |
| 38 | ||
| 39 | pub 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. | |
| 55 | pub 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 | ||
| 82 | pub 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 | ||
| 91 | fn 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 | ||
| 104 | fn 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 | ||
| 122 | fn 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 | ||
| 130 | const RoundMode = enum { | |
| 131 | /// 1234.56 = precision 2 | |
| 132 | decimal, | |
| 133 | /// 1.23456e3 = precision 5 | |
| 134 | scientific, | |
| 135 | }; | |
| 136 | ||
| 137 | fn 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. | |
| 195 | pub 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. | |
| 266 | pub 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 | ||
| 356 | fn cast_i32(v: anytype) i32 { | |
| 357 | return @intCast(v); | |
| 358 | } | |
| 359 | ||
| 360 | /// Convert a binary float representation to decimal. | |
| 361 | pub 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 | ||
| 498 | fn 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)) | |
| 535 | fn 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)) | |
| 541 | fn 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)) | |
| 547 | fn pow5Bits(e: u32) u32 { | |
| 548 | std.debug.assert(e <= 1 << 15); | |
| 549 | return @intCast(((@as(u64, @intCast(e)) * 163391164108059) >> 46) + 1); | |
| 550 | } | |
| 551 | ||
| 552 | fn 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 | ||
| 564 | fn 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 | ||
| 570 | fn 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 | ||
| 576 | fn 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 | ||
| 583 | fn 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 | ||
| 632 | pub 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 | ||
| 677 | fn 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 | ||
| 690 | pub 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 | ||
| 709 | pub 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 | ||
| 756 | const FLOAT64_POW5_INV_BITCOUNT = 125; | |
| 757 | const FLOAT64_POW5_BITCOUNT = 125; | |
| 758 | ||
| 759 | // zig fmt: off | |
| 760 | // | |
| 761 | // f64 small tables: 816 bytes | |
| 762 | ||
| 763 | const FLOAT64_POW5_TABLE_SIZE: comptime_int = FLOAT64_POW5_TABLE.len; | |
| 764 | ||
| 765 | const 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 | ||
| 781 | const 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 | ||
| 797 | const 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 | ||
| 806 | const 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 | ||
| 824 | const 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 | ||
| 837 | const 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 | ||
| 1003 | const 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 | ||
| 1181 | const FLOAT128_POW5_INV_BITCOUNT = 249; | |
| 1182 | const FLOAT128_POW5_BITCOUNT = 249; | |
| 1183 | const FLOAT128_POW5_TABLE_SIZE: comptime_int = FLOAT128_POW5_TABLE.len; | |
| 1184 | ||
| 1185 | const 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 | ||
| 1244 | const 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. | |
| 1338 | const 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 | ||
| 1380 | const 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 | ||
| 1472 | const 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 | ||
| 1516 | const builtin = @import("builtin"); | |
| 1517 | ||
| 1518 | fn 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 | ||
| 1538 | test "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 | ||
| 1599 | test "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 | ||
| 1648 | test "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 | ||
| 1669 | test "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 | ||
| 1690 | test "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 | ||
| 4 | const std = @import("std"); | |
| 5 | const expectFmt = std.testing.expectFmt; | |
| 6 | ||
| 7 | const 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. | |
| 11 | pub const min_buffer_size = 53; | |
| 12 | ||
| 13 | /// Returns the minimum buffer size needed to print every float of a specific type and format. | |
| 14 | pub 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 | ||
| 30 | pub const FormatError = error{ | |
| 31 | BufferTooSmall, | |
| 32 | }; | |
| 33 | ||
| 34 | pub const Format = enum { | |
| 35 | scientific, | |
| 36 | decimal, | |
| 37 | }; | |
| 38 | ||
| 39 | pub 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. | |
| 55 | pub 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 | ||
| 82 | pub 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 | ||
| 91 | fn 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 | ||
| 104 | fn 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 | ||
| 122 | fn 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 | ||
| 130 | const RoundMode = enum { | |
| 131 | /// 1234.56 = precision 2 | |
| 132 | decimal, | |
| 133 | /// 1.23456e3 = precision 5 | |
| 134 | scientific, | |
| 135 | }; | |
| 136 | ||
| 137 | fn 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. | |
| 195 | pub 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. | |
| 266 | pub 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 | ||
| 356 | fn cast_i32(v: anytype) i32 { | |
| 357 | return @intCast(v); | |
| 358 | } | |
| 359 | ||
| 360 | /// Convert a binary float representation to decimal. | |
| 361 | pub 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 | ||
| 498 | fn 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)) | |
| 535 | fn 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)) | |
| 541 | fn 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)) | |
| 547 | fn pow5Bits(e: u32) u32 { | |
| 548 | std.debug.assert(e <= 1 << 15); | |
| 549 | return @intCast(((@as(u64, @intCast(e)) * 163391164108059) >> 46) + 1); | |
| 550 | } | |
| 551 | ||
| 552 | fn 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 | ||
| 564 | fn 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 | ||
| 570 | fn 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 | ||
| 576 | fn 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 | ||
| 583 | fn 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 | ||
| 632 | pub 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 | ||
| 677 | fn 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 | ||
| 690 | pub 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 | ||
| 709 | pub 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 | ||
| 756 | const FLOAT64_POW5_INV_BITCOUNT = 125; | |
| 757 | const FLOAT64_POW5_BITCOUNT = 125; | |
| 758 | ||
| 759 | // zig fmt: off | |
| 760 | // | |
| 761 | // f64 small tables: 816 bytes | |
| 762 | ||
| 763 | const FLOAT64_POW5_TABLE_SIZE: comptime_int = FLOAT64_POW5_TABLE.len; | |
| 764 | ||
| 765 | const 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 | ||
| 781 | const 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 | ||
| 797 | const 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 | ||
| 806 | const 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 | ||
| 824 | const 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 | ||
| 837 | const 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 | ||
| 1003 | const 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 | ||
| 1181 | const FLOAT128_POW5_INV_BITCOUNT = 249; | |
| 1182 | const FLOAT128_POW5_BITCOUNT = 249; | |
| 1183 | const FLOAT128_POW5_TABLE_SIZE: comptime_int = FLOAT128_POW5_TABLE.len; | |
| 1184 | ||
| 1185 | const 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 | ||
| 1244 | const 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. | |
| 1338 | const 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 | ||
| 1380 | const 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 | ||
| 1472 | const 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 | ||
| 1516 | const builtin = @import("builtin"); | |
| 1517 | ||
| 1518 | fn 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 | ||
| 1538 | test "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 | ||
| 1599 | test "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 | ||
| 1648 | test "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 | ||
| 1669 | test "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 | ||
| 1690 | test "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 | const builtin = @import("builtin"); | |
| 2 | const Os = std.builtin.Os; | |
| 3 | const native_os = builtin.os.tag; | |
| 4 | const is_windows = native_os == .windows; | |
| 5 | ||
| 6 | const File = @This(); | |
| 7 | const std = @import("../std.zig"); | |
| 8 | const Allocator = std.mem.Allocator; | |
| 9 | const posix = std.posix; | |
| 10 | const io = std.io; | |
| 11 | const math = std.math; | |
| 12 | const assert = std.debug.assert; | |
| 13 | const linux = std.os.linux; | |
| 14 | const windows = std.os.windows; | |
| 15 | const maxInt = std.math.maxInt; | |
| 16 | const Alignment = std.mem.Alignment; | |
| 17 | ||
| 1 | 18 | /// The OS-specific file descriptor or file handle. |
| 2 | 19 | handle: Handle, |
| 3 | 20 | |
| ... | ... | @@ -168,6 +185,18 @@ pub const CreateFlags = struct { |
| 168 | 185 | mode: Mode = default_mode, |
| 169 | 186 | }; |
| 170 | 187 | |
| 188 | pub fn stdout() File { | |
| 189 | return .{ .handle = if (is_windows) windows.peb().ProcessParameters.hStdOutput else posix.STDOUT_FILENO }; | |
| 190 | } | |
| 191 | ||
| 192 | pub fn stderr() File { | |
| 193 | return .{ .handle = if (is_windows) windows.peb().ProcessParameters.hStdError else posix.STDERR_FILENO }; | |
| 194 | } | |
| 195 | ||
| 196 | pub fn stdin() File { | |
| 197 | return .{ .handle = if (is_windows) windows.peb().ProcessParameters.hStdInput else posix.STDIN_FILENO }; | |
| 198 | } | |
| 199 | ||
| 171 | 200 | /// Upon success, the stream is in an uninitialized state. To continue using it, |
| 172 | 201 | /// you must use the open() function. |
| 173 | 202 | pub fn close(self: File) void { |
| ... | ... | @@ -351,8 +380,10 @@ pub fn getPos(self: File) GetSeekPosError!u64 { |
| 351 | 380 | return posix.lseek_CUR_get(self.handle); |
| 352 | 381 | } |
| 353 | 382 | |
| 383 | pub const GetEndPosError = std.os.windows.GetFileSizeError || StatError; | |
| 384 | ||
| 354 | 385 | /// TODO: integrate with async I/O |
| 355 | pub fn getEndPos(self: File) GetSeekPosError!u64 { | |
| 386 | pub fn getEndPos(self: File) GetEndPosError!u64 { | |
| 356 | 387 | if (builtin.os.tag == .windows) { |
| 357 | 388 | return windows.GetFileSizeEx(self.handle); |
| 358 | 389 | } |
| ... | ... | @@ -477,7 +508,6 @@ pub const Stat = struct { |
| 477 | 508 | pub const StatError = posix.FStatError; |
| 478 | 509 | |
| 479 | 510 | /// Returns `Stat` containing basic information about the `File`. |
| 480 | /// Use `metadata` to retrieve more detailed information (e.g. creation time, permissions). | |
| 481 | 511 | /// TODO: integrate with async I/O |
| 482 | 512 | pub fn stat(self: File) StatError!Stat { |
| 483 | 513 | if (builtin.os.tag == .windows) { |
| ... | ... | @@ -743,361 +773,6 @@ pub fn setPermissions(self: File, permissions: Permissions) SetPermissionsError! |
| 743 | 773 | } |
| 744 | 774 | } |
| 745 | 775 | |
| 746 | /// Cross-platform representation of file metadata. | |
| 747 | /// Platform-specific functionality is available through the `inner` field. | |
| 748 | pub 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 | ||
| 795 | pub 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. | |
| 878 | pub 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 | ||
| 929 | pub 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 | ||
| 965 | pub 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 | ||
| 1017 | pub const MetadataError = posix.FStatError; | |
| 1018 | ||
| 1019 | pub 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 | ||
| 1101 | 776 | pub const UpdateTimesError = posix.FutimensError || windows.SetFileTimeError; |
| 1102 | 777 | |
| 1103 | 778 | /// The underlying file system may have a different granularity than nanoseconds, |
| ... | ... | @@ -1130,19 +805,12 @@ pub fn updateTimes( |
| 1130 | 805 | try posix.futimens(self.handle, &times); |
| 1131 | 806 | } |
| 1132 | 807 | |
| 1133 | /// Reads all the bytes from the current position to the end of the file. | |
| 1134 | /// On success, caller owns returned buffer. | |
| 1135 | /// If the file is larger than `max_bytes`, returns `error.FileTooBig`. | |
| 808 | /// Deprecated in favor of `Reader`. | |
| 1136 | 809 | pub fn readToEndAlloc(self: File, allocator: Allocator, max_bytes: usize) ![]u8 { |
| 1137 | 810 | return self.readToEndAllocOptions(allocator, max_bytes, null, .of(u8), null); |
| 1138 | 811 | } |
| 1139 | 812 | |
| 1140 | /// Reads all the bytes from the current position to the end of the file. | |
| 1141 | /// On success, caller owns returned buffer. | |
| 1142 | /// If the file is larger than `max_bytes`, returns `error.FileTooBig`. | |
| 1143 | /// If `size_hint` is specified the initial buffer size is calculated using | |
| 1144 | /// that value, otherwise an arbitrary value is used instead. | |
| 1145 | /// Allows specifying alignment and a sentinel value. | |
| 813 | /// Deprecated in favor of `Reader`. | |
| 1146 | 814 | pub fn readToEndAllocOptions( |
| 1147 | 815 | self: File, |
| 1148 | 816 | allocator: Allocator, |
| ... | ... | @@ -1161,7 +829,7 @@ pub fn readToEndAllocOptions( |
| 1161 | 829 | var array_list = try std.ArrayListAligned(u8, alignment).initCapacity(allocator, initial_cap); |
| 1162 | 830 | defer array_list.deinit(); |
| 1163 | 831 | |
| 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 | 833 | error.StreamTooLong => return error.FileTooBig, |
| 1166 | 834 | else => |e| return e, |
| 1167 | 835 | }; |
| ... | ... | @@ -1184,8 +852,7 @@ pub fn read(self: File, buffer: []u8) ReadError!usize { |
| 1184 | 852 | return posix.read(self.handle, buffer); |
| 1185 | 853 | } |
| 1186 | 854 | |
| 1187 | /// Returns the number of bytes read. If the number read is smaller than `buffer.len`, it | |
| 1188 | /// means the file reached the end. Reaching the end of a file is not an error condition. | |
| 855 | /// Deprecated in favor of `Reader`. | |
| 1189 | 856 | pub fn readAll(self: File, buffer: []u8) ReadError!usize { |
| 1190 | 857 | var index: usize = 0; |
| 1191 | 858 | while (index != buffer.len) { |
| ... | ... | @@ -1206,10 +873,7 @@ pub fn pread(self: File, buffer: []u8, offset: u64) PReadError!usize { |
| 1206 | 873 | return posix.pread(self.handle, buffer, offset); |
| 1207 | 874 | } |
| 1208 | 875 | |
| 1209 | /// Returns the number of bytes read. If the number read is smaller than `buffer.len`, it | |
| 1210 | /// means the file reached the end. Reaching the end of a file is not an error condition. | |
| 1211 | /// On Windows, this function currently does alter the file pointer. | |
| 1212 | /// https://github.com/ziglang/zig/issues/12783 | |
| 876 | /// Deprecated in favor of `Reader`. | |
| 1213 | 877 | pub fn preadAll(self: File, buffer: []u8, offset: u64) PReadError!usize { |
| 1214 | 878 | var index: usize = 0; |
| 1215 | 879 | while (index != buffer.len) { |
| ... | ... | @@ -1223,8 +887,7 @@ pub fn preadAll(self: File, buffer: []u8, offset: u64) PReadError!usize { |
| 1223 | 887 | /// See https://github.com/ziglang/zig/issues/7699 |
| 1224 | 888 | pub fn readv(self: File, iovecs: []const posix.iovec) ReadError!usize { |
| 1225 | 889 | if (is_windows) { |
| 1226 | // TODO improve this to use ReadFileScatter | |
| 1227 | if (iovecs.len == 0) return @as(usize, 0); | |
| 890 | if (iovecs.len == 0) return 0; | |
| 1228 | 891 | const first = iovecs[0]; |
| 1229 | 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 | 895 | return posix.readv(self.handle, iovecs); |
| 1233 | 896 | } |
| 1234 | 897 | |
| 1235 | /// Returns the number of bytes read. If the number read is smaller than the total bytes | |
| 1236 | /// from all the buffers, it means the file reached the end. Reaching the end of a file | |
| 1237 | /// is not an error condition. | |
| 1238 | /// | |
| 1239 | /// The `iovecs` parameter is mutable because: | |
| 1240 | /// * This function needs to mutate the fields in order to handle partial | |
| 1241 | /// reads from the underlying OS layer. | |
| 1242 | /// * The OS layer expects pointer addresses to be inside the application's address space | |
| 1243 | /// even if the length is zero. Meanwhile, in Zig, slices may have undefined pointer | |
| 1244 | /// addresses when the length is zero. So this function modifies the base fields | |
| 1245 | /// when the length is zero. | |
| 1246 | /// | |
| 1247 | /// Related open issue: https://github.com/ziglang/zig/issues/7699 | |
| 898 | /// Deprecated in favor of `Reader`. | |
| 1248 | 899 | pub fn readvAll(self: File, iovecs: []posix.iovec) ReadError!usize { |
| 1249 | 900 | if (iovecs.len == 0) return 0; |
| 1250 | 901 | |
| ... | ... | @@ -1279,8 +930,7 @@ pub fn readvAll(self: File, iovecs: []posix.iovec) ReadError!usize { |
| 1279 | 930 | /// https://github.com/ziglang/zig/issues/12783 |
| 1280 | 931 | pub fn preadv(self: File, iovecs: []const posix.iovec, offset: u64) PReadError!usize { |
| 1281 | 932 | if (is_windows) { |
| 1282 | // TODO improve this to use ReadFileScatter | |
| 1283 | if (iovecs.len == 0) return @as(usize, 0); | |
| 933 | if (iovecs.len == 0) return 0; | |
| 1284 | 934 | const first = iovecs[0]; |
| 1285 | 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 | 938 | return posix.preadv(self.handle, iovecs, offset); |
| 1289 | 939 | } |
| 1290 | 940 | |
| 1291 | /// Returns the number of bytes read. If the number read is smaller than the total bytes | |
| 1292 | /// from all the buffers, it means the file reached the end. Reaching the end of a file | |
| 1293 | /// is not an error condition. | |
| 1294 | /// The `iovecs` parameter is mutable because this function needs to mutate the fields in | |
| 1295 | /// order to handle partial reads from the underlying OS layer. | |
| 1296 | /// See https://github.com/ziglang/zig/issues/7699 | |
| 1297 | /// On Windows, this function currently does alter the file pointer. | |
| 1298 | /// https://github.com/ziglang/zig/issues/12783 | |
| 941 | /// Deprecated in favor of `Reader`. | |
| 1299 | 942 | pub fn preadvAll(self: File, iovecs: []posix.iovec, offset: u64) PReadError!usize { |
| 1300 | 943 | if (iovecs.len == 0) return 0; |
| 1301 | 944 | |
| ... | ... | @@ -1328,6 +971,7 @@ pub fn write(self: File, bytes: []const u8) WriteError!usize { |
| 1328 | 971 | return posix.write(self.handle, bytes); |
| 1329 | 972 | } |
| 1330 | 973 | |
| 974 | /// Deprecated in favor of `Writer`. | |
| 1331 | 975 | pub fn writeAll(self: File, bytes: []const u8) WriteError!void { |
| 1332 | 976 | var index: usize = 0; |
| 1333 | 977 | while (index < bytes.len) { |
| ... | ... | @@ -1345,8 +989,7 @@ pub fn pwrite(self: File, bytes: []const u8, offset: u64) PWriteError!usize { |
| 1345 | 989 | return posix.pwrite(self.handle, bytes, offset); |
| 1346 | 990 | } |
| 1347 | 991 | |
| 1348 | /// On Windows, this function currently does alter the file pointer. | |
| 1349 | /// https://github.com/ziglang/zig/issues/12783 | |
| 992 | /// Deprecated in favor of `Writer`. | |
| 1350 | 993 | pub fn pwriteAll(self: File, bytes: []const u8, offset: u64) PWriteError!void { |
| 1351 | 994 | var index: usize = 0; |
| 1352 | 995 | while (index < bytes.len) { |
| ... | ... | @@ -1355,11 +998,10 @@ pub fn pwriteAll(self: File, bytes: []const u8, offset: u64) PWriteError!void { |
| 1355 | 998 | } |
| 1356 | 999 | |
| 1357 | 1000 | /// See https://github.com/ziglang/zig/issues/7699 |
| 1358 | /// See equivalent function: `std.net.Stream.writev`. | |
| 1359 | 1001 | pub fn writev(self: File, iovecs: []const posix.iovec_const) WriteError!usize { |
| 1360 | 1002 | if (is_windows) { |
| 1361 | 1003 | // TODO improve this to use WriteFileScatter |
| 1362 | if (iovecs.len == 0) return @as(usize, 0); | |
| 1004 | if (iovecs.len == 0) return 0; | |
| 1363 | 1005 | const first = iovecs[0]; |
| 1364 | 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 | 1009 | return posix.writev(self.handle, iovecs); |
| 1368 | 1010 | } |
| 1369 | 1011 | |
| 1370 | /// The `iovecs` parameter is mutable because: | |
| 1371 | /// * This function needs to mutate the fields in order to handle partial | |
| 1372 | /// writes from the underlying OS layer. | |
| 1373 | /// * The OS layer expects pointer addresses to be inside the application's address space | |
| 1374 | /// even if the length is zero. Meanwhile, in Zig, slices may have undefined pointer | |
| 1375 | /// addresses when the length is zero. So this function modifies the base fields | |
| 1376 | /// when the length is zero. | |
| 1377 | /// See https://github.com/ziglang/zig/issues/7699 | |
| 1378 | /// See equivalent function: `std.net.Stream.writevAll`. | |
| 1012 | /// Deprecated in favor of `Writer`. | |
| 1379 | 1013 | pub fn writevAll(self: File, iovecs: []posix.iovec_const) WriteError!void { |
| 1380 | 1014 | if (iovecs.len == 0) return; |
| 1381 | 1015 | |
| ... | ... | @@ -1405,8 +1039,7 @@ pub fn writevAll(self: File, iovecs: []posix.iovec_const) WriteError!void { |
| 1405 | 1039 | /// https://github.com/ziglang/zig/issues/12783 |
| 1406 | 1040 | pub fn pwritev(self: File, iovecs: []posix.iovec_const, offset: u64) PWriteError!usize { |
| 1407 | 1041 | if (is_windows) { |
| 1408 | // TODO improve this to use WriteFileScatter | |
| 1409 | if (iovecs.len == 0) return @as(usize, 0); | |
| 1042 | if (iovecs.len == 0) return 0; | |
| 1410 | 1043 | const first = iovecs[0]; |
| 1411 | 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 | 1047 | return posix.pwritev(self.handle, iovecs, offset); |
| 1415 | 1048 | } |
| 1416 | 1049 | |
| 1417 | /// The `iovecs` parameter is mutable because this function needs to mutate the fields in | |
| 1418 | /// order to handle partial writes from the underlying OS layer. | |
| 1419 | /// See https://github.com/ziglang/zig/issues/7699 | |
| 1420 | /// On Windows, this function currently does alter the file pointer. | |
| 1421 | /// https://github.com/ziglang/zig/issues/12783 | |
| 1050 | /// Deprecated in favor of `Writer`. | |
| 1422 | 1051 | pub fn pwritevAll(self: File, iovecs: []posix.iovec_const, offset: u64) PWriteError!void { |
| 1423 | 1052 | if (iovecs.len == 0) return; |
| 1424 | ||
| 1425 | 1053 | var i: usize = 0; |
| 1426 | 1054 | var off: u64 = 0; |
| 1427 | 1055 | while (true) { |
| ... | ... | @@ -1439,14 +1067,14 @@ pub fn pwritevAll(self: File, iovecs: []posix.iovec_const, offset: u64) PWriteEr |
| 1439 | 1067 | |
| 1440 | 1068 | pub const CopyRangeError = posix.CopyFileRangeError; |
| 1441 | 1069 | |
| 1070 | /// Deprecated in favor of `Writer`. | |
| 1442 | 1071 | pub fn copyRange(in: File, in_offset: u64, out: File, out_offset: u64, len: u64) CopyRangeError!u64 { |
| 1443 | 1072 | const adjusted_len = math.cast(usize, len) orelse maxInt(usize); |
| 1444 | 1073 | const result = try posix.copy_file_range(in.handle, in_offset, out.handle, out_offset, adjusted_len, 0); |
| 1445 | 1074 | return result; |
| 1446 | 1075 | } |
| 1447 | 1076 | |
| 1448 | /// Returns the number of bytes copied. If the number read is smaller than `buffer.len`, it | |
| 1449 | /// means the in file reached the end. Reaching the end of a file is not an error condition. | |
| 1077 | /// Deprecated in favor of `Writer`. | |
| 1450 | 1078 | pub fn copyRangeAll(in: File, in_offset: u64, out: File, out_offset: u64, len: u64) CopyRangeError!u64 { |
| 1451 | 1079 | var total_bytes_copied: u64 = 0; |
| 1452 | 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 | 1089 | return total_bytes_copied; |
| 1462 | 1090 | } |
| 1463 | 1091 | |
| 1092 | /// Deprecated in favor of `Writer`. | |
| 1464 | 1093 | pub const WriteFileOptions = struct { |
| 1465 | 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 | 1095 | in_len: ?u64 = null, |
| 1473 | ||
| 1474 | 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 | 1097 | header_count: usize = 0, |
| 1478 | 1098 | }; |
| 1479 | 1099 | |
| 1100 | /// Deprecated in favor of `Writer`. | |
| 1480 | 1101 | pub const WriteFileError = ReadError || error{EndOfStream} || WriteError; |
| 1481 | 1102 | |
| 1103 | /// Deprecated in favor of `Writer`. | |
| 1482 | 1104 | pub fn writeFileAll(self: File, in_file: File, args: WriteFileOptions) WriteFileError!void { |
| 1483 | 1105 | return self.writeFileAllSendfile(in_file, args) catch |err| switch (err) { |
| 1484 | 1106 | error.Unseekable, |
| ... | ... | @@ -1488,35 +1110,27 @@ pub fn writeFileAll(self: File, in_file: File, args: WriteFileOptions) WriteFile |
| 1488 | 1110 | error.NetworkUnreachable, |
| 1489 | 1111 | error.NetworkSubsystemFailed, |
| 1490 | 1112 | => return self.writeFileAllUnseekable(in_file, args), |
| 1491 | ||
| 1492 | 1113 | else => |e| return e, |
| 1493 | 1114 | }; |
| 1494 | 1115 | } |
| 1495 | 1116 | |
| 1496 | /// Does not try seeking in either of the File parameters. | |
| 1497 | /// See `writeFileAll` as an alternative to calling this. | |
| 1117 | /// Deprecated in favor of `Writer`. | |
| 1498 | 1118 | pub fn writeFileAllUnseekable(self: File, in_file: File, args: WriteFileOptions) WriteFileError!void { |
| 1499 | 1119 | const headers = args.headers_and_trailers[0..args.header_count]; |
| 1500 | 1120 | const trailers = args.headers_and_trailers[args.header_count..]; |
| 1501 | ||
| 1502 | 1121 | try self.writevAll(headers); |
| 1503 | ||
| 1504 | try in_file.reader().skipBytes(args.in_offset, .{ .buf_size = 4096 }); | |
| 1505 | ||
| 1122 | try in_file.deprecatedReader().skipBytes(args.in_offset, .{ .buf_size = 4096 }); | |
| 1506 | 1123 | var fifo = std.fifo.LinearFifo(u8, .{ .Static = 4096 }).init(); |
| 1507 | 1124 | if (args.in_len) |len| { |
| 1508 | var stream = std.io.limitedReader(in_file.reader(), len); | |
| 1509 | try fifo.pump(stream.reader(), self.writer()); | |
| 1125 | var stream = std.io.limitedReader(in_file.deprecatedReader(), len); | |
| 1126 | try fifo.pump(stream.reader(), self.deprecatedWriter()); | |
| 1510 | 1127 | } else { |
| 1511 | try fifo.pump(in_file.reader(), self.writer()); | |
| 1128 | try fifo.pump(in_file.deprecatedReader(), self.deprecatedWriter()); | |
| 1512 | 1129 | } |
| 1513 | ||
| 1514 | 1130 | try self.writevAll(trailers); |
| 1515 | 1131 | } |
| 1516 | 1132 | |
| 1517 | /// Low level function which can fail for OS-specific reasons. | |
| 1518 | /// See `writeFileAll` as an alternative to calling this. | |
| 1519 | /// TODO integrate with async I/O | |
| 1133 | /// Deprecated in favor of `Writer`. | |
| 1520 | 1134 | fn writeFileAllSendfile(self: File, in_file: File, args: WriteFileOptions) posix.SendFileError!void { |
| 1521 | 1135 | const count = blk: { |
| 1522 | 1136 | if (args.in_len) |l| { |
| ... | ... | @@ -1581,18 +1195,23 @@ fn writeFileAllSendfile(self: File, in_file: File, args: WriteFileOptions) posix |
| 1581 | 1195 | } |
| 1582 | 1196 | } |
| 1583 | 1197 | |
| 1584 | pub const Reader = io.Reader(File, ReadError, read); | |
| 1198 | /// Deprecated in favor of `Reader`. | |
| 1199 | pub const DeprecatedReader = io.GenericReader(File, ReadError, read); | |
| 1585 | 1200 | |
| 1586 | pub fn reader(file: File) Reader { | |
| 1201 | /// Deprecated in favor of `Reader`. | |
| 1202 | pub fn deprecatedReader(file: File) DeprecatedReader { | |
| 1587 | 1203 | return .{ .context = file }; |
| 1588 | 1204 | } |
| 1589 | 1205 | |
| 1590 | pub const Writer = io.Writer(File, WriteError, write); | |
| 1206 | /// Deprecated in favor of `Writer`. | |
| 1207 | pub const DeprecatedWriter = io.GenericWriter(File, WriteError, write); | |
| 1591 | 1208 | |
| 1592 | pub fn writer(file: File) Writer { | |
| 1209 | /// Deprecated in favor of `Writer`. | |
| 1210 | pub fn deprecatedWriter(file: File) DeprecatedWriter { | |
| 1593 | 1211 | return .{ .context = file }; |
| 1594 | 1212 | } |
| 1595 | 1213 | |
| 1214 | /// Deprecated in favor of `Reader` and `Writer`. | |
| 1596 | 1215 | pub const SeekableStream = io.SeekableStream( |
| 1597 | 1216 | File, |
| 1598 | 1217 | SeekError, |
| ... | ... | @@ -1603,10 +1222,800 @@ pub const SeekableStream = io.SeekableStream( |
| 1603 | 1222 | getEndPos, |
| 1604 | 1223 | ); |
| 1605 | 1224 | |
| 1225 | /// Deprecated in favor of `Reader` and `Writer`. | |
| 1606 | 1226 | pub fn seekableStream(file: File) SeekableStream { |
| 1607 | 1227 | return .{ .context = file }; |
| 1608 | 1228 | } |
| 1609 | 1229 | |
| 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. | |
| 1239 | pub 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 | ||
| 1595 | pub 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. | |
| 1988 | pub 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. | |
| 1995 | pub 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. | |
| 2008 | pub 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. | |
| 2015 | pub fn writerStreaming(file: File, buffer: []u8) Writer { | |
| 2016 | return .initMode(file, buffer, .streaming); | |
| 2017 | } | |
| 2018 | ||
| 1610 | 2019 | const range_off: windows.LARGE_INTEGER = 0; |
| 1611 | 2020 | const range_len: windows.LARGE_INTEGER = 1; |
| 1612 | 2021 | |
| ... | ... | @@ -1769,18 +2178,3 @@ pub fn downgradeLock(file: File) LockError!void { |
| 1769 | 2178 | }; |
| 1770 | 2179 | } |
| 1771 | 2180 | } |
| 1772 | ||
| 1773 | const File = @This(); | |
| 1774 | const std = @import("../std.zig"); | |
| 1775 | const builtin = @import("builtin"); | |
| 1776 | const Allocator = std.mem.Allocator; | |
| 1777 | const posix = std.posix; | |
| 1778 | const io = std.io; | |
| 1779 | const math = std.math; | |
| 1780 | const assert = std.debug.assert; | |
| 1781 | const linux = std.os.linux; | |
| 1782 | const windows = std.os.windows; | |
| 1783 | const Os = std.builtin.Os; | |
| 1784 | const maxInt = std.math.maxInt; | |
| 1785 | const is_windows = builtin.os.tag == .windows; | |
| 1786 | const 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 | 146 | return out[0 .. out.len - 1 :0]; |
| 147 | 147 | } |
| 148 | 148 | |
| 149 | pub fn fmtJoin(paths: []const []const u8) std.fmt.Formatter(formatJoin) { | |
| 149 | pub fn fmtJoin(paths: []const []const u8) std.fmt.Formatter([]const []const u8, formatJoin) { | |
| 150 | 150 | return .{ .data = paths }; |
| 151 | 151 | } |
| 152 | 152 | |
| 153 | fn formatJoin(paths: []const []const u8, comptime fmt: []const u8, options: std.fmt.FormatOptions, w: anytype) !void { | |
| 154 | _ = fmt; | |
| 155 | _ = options; | |
| 156 | ||
| 153 | fn formatJoin(paths: []const []const u8, w: *std.io.Writer) std.io.Writer.Error!void { | |
| 157 | 154 | const first_path_idx = for (paths, 0..) |p, idx| { |
| 158 | 155 | if (p.len != 0) break idx; |
| 159 | 156 | } else return; |
lib/std/fs/test.zig+2-109| ... | ... | @@ -1798,11 +1798,11 @@ test "walker" { |
| 1798 | 1798 | var num_walked: usize = 0; |
| 1799 | 1799 | while (try walker.next()) |entry| { |
| 1800 | 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 | 1802 | return err; |
| 1803 | 1803 | }; |
| 1804 | 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 | 1806 | return err; |
| 1807 | 1807 | }; |
| 1808 | 1808 | // make sure that the entry.dir is the containing dir |
| ... | ... | @@ -1953,113 +1953,6 @@ test "chown" { |
| 1953 | 1953 | try dir.chown(null, null); |
| 1954 | 1954 | } |
| 1955 | 1955 | |
| 1956 | test "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 | ||
| 1971 | test "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 | ||
| 1997 | test "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 | ||
| 2032 | test "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 | ||
| 2063 | 1956 | test "delete a setAsCwd directory on Windows" { |
| 2064 | 1957 | if (native_os != .windows) return error.SkipZigTest; |
| 2065 | 1958 |
lib/std/hash/benchmark.zig+1-1| ... | ... | @@ -346,7 +346,7 @@ fn mode(comptime x: comptime_int) comptime_int { |
| 346 | 346 | } |
| 347 | 347 | |
| 348 | 348 | pub fn main() !void { |
| 349 | const stdout = std.io.getStdOut().writer(); | |
| 349 | const stdout = std.fs.File.stdout().deprecatedWriter(); | |
| 350 | 350 | |
| 351 | 351 | var buffer: [1024]u8 = undefined; |
| 352 | 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 | 436 | const stack_trace = bucketStackTrace(bucket, slot_count, slot_index, .alloc); |
| 437 | 437 | const page_addr = @intFromPtr(bucket) & ~(page_size - 1); |
| 438 | 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 | 440 | leaks = true; |
| 441 | 441 | } |
| 442 | 442 | } |
| ... | ... | @@ -463,7 +463,7 @@ pub fn DebugAllocator(comptime config: Config) type { |
| 463 | 463 | while (it.next()) |large_alloc| { |
| 464 | 464 | if (config.retain_metadata and large_alloc.freed) continue; |
| 465 | 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 | 467 | @intFromPtr(large_alloc.bytes.ptr), stack_trace, |
| 468 | 468 | }); |
| 469 | 469 | leaks = true; |
| ... | ... | @@ -522,7 +522,7 @@ pub fn DebugAllocator(comptime config: Config) type { |
| 522 | 522 | .index = 0, |
| 523 | 523 | }; |
| 524 | 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 | 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 | 568 | .index = 0, |
| 569 | 569 | }; |
| 570 | 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 | 572 | entry.value_ptr.bytes.len, |
| 573 | 573 | old_mem.len, |
| 574 | 574 | entry.value_ptr.getStackTrace(.alloc), |
| ... | ... | @@ -678,7 +678,7 @@ pub fn DebugAllocator(comptime config: Config) type { |
| 678 | 678 | .index = 0, |
| 679 | 679 | }; |
| 680 | 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 | 682 | entry.value_ptr.bytes.len, |
| 683 | 683 | old_mem.len, |
| 684 | 684 | entry.value_ptr.getStackTrace(.alloc), |
| ... | ... | @@ -907,7 +907,7 @@ pub fn DebugAllocator(comptime config: Config) type { |
| 907 | 907 | }; |
| 908 | 908 | std.debug.captureStackTrace(return_address, &free_stack_trace); |
| 909 | 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 | 911 | requested_size, |
| 912 | 912 | old_memory.len, |
| 913 | 913 | bucketStackTrace(bucket, slot_count, slot_index, .alloc), |
| ... | ... | @@ -915,7 +915,7 @@ pub fn DebugAllocator(comptime config: Config) type { |
| 915 | 915 | }); |
| 916 | 916 | } |
| 917 | 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 | 919 | slot_alignment.toByteUnits(), |
| 920 | 920 | alignment.toByteUnits(), |
| 921 | 921 | bucketStackTrace(bucket, slot_count, slot_index, .alloc), |
| ... | ... | @@ -1006,7 +1006,7 @@ pub fn DebugAllocator(comptime config: Config) type { |
| 1006 | 1006 | }; |
| 1007 | 1007 | std.debug.captureStackTrace(return_address, &free_stack_trace); |
| 1008 | 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 | 1010 | requested_size, |
| 1011 | 1011 | memory.len, |
| 1012 | 1012 | bucketStackTrace(bucket, slot_count, slot_index, .alloc), |
| ... | ... | @@ -1014,7 +1014,7 @@ pub fn DebugAllocator(comptime config: Config) type { |
| 1014 | 1014 | }); |
| 1015 | 1015 | } |
| 1016 | 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 | 1018 | slot_alignment.toByteUnits(), |
| 1019 | 1019 | alignment.toByteUnits(), |
| 1020 | 1020 | bucketStackTrace(bucket, slot_count, slot_index, .alloc), |
| ... | ... | @@ -1054,7 +1054,7 @@ const TraceKind = enum { |
| 1054 | 1054 | free, |
| 1055 | 1055 | }; |
| 1056 | 1056 | |
| 1057 | const test_config = Config{}; | |
| 1057 | const test_config: Config = .{}; | |
| 1058 | 1058 | |
| 1059 | 1059 | test "small allocations - free in same order" { |
| 1060 | 1060 | var gpa = DebugAllocator(test_config){}; |
lib/std/http.zig+12-8| ... | ... | @@ -1,3 +1,7 @@ |
| 1 | const builtin = @import("builtin"); | |
| 2 | const std = @import("std.zig"); | |
| 3 | const assert = std.debug.assert; | |
| 4 | ||
| 1 | 5 | pub const Client = @import("http/Client.zig"); |
| 2 | 6 | pub const Server = @import("http/Server.zig"); |
| 3 | 7 | pub const protocol = @import("http/protocol.zig"); |
| ... | ... | @@ -38,8 +42,8 @@ pub const Method = enum(u64) { |
| 38 | 42 | return x; |
| 39 | 43 | } |
| 40 | 44 | |
| 41 | pub fn write(self: Method, w: anytype) !void { | |
| 42 | const bytes = std.mem.asBytes(&@intFromEnum(self)); | |
| 45 | pub fn format(self: Method, w: *std.io.Writer) std.io.Writer.Error!void { | |
| 46 | const bytes: []const u8 = @ptrCast(&@intFromEnum(self)); | |
| 43 | 47 | const str = std.mem.sliceTo(bytes, 0); |
| 44 | 48 | try w.writeAll(str); |
| 45 | 49 | } |
| ... | ... | @@ -77,7 +81,9 @@ pub const Method = enum(u64) { |
| 77 | 81 | }; |
| 78 | 82 | } |
| 79 | 83 | |
| 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 | 88 | /// https://developer.mozilla.org/en-US/docs/Glossary/Idempotent |
| 83 | 89 | /// |
| ... | ... | @@ -90,7 +96,8 @@ pub const Method = enum(u64) { |
| 90 | 96 | }; |
| 91 | 97 | } |
| 92 | 98 | |
| 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 | 102 | /// https://developer.mozilla.org/en-US/docs/Glossary/cacheable |
| 96 | 103 | /// |
| ... | ... | @@ -282,10 +289,10 @@ pub const Status = enum(u10) { |
| 282 | 289 | } |
| 283 | 290 | }; |
| 284 | 291 | |
| 292 | /// compression is intentionally omitted here since it is handled in `ContentEncoding`. | |
| 285 | 293 | pub const TransferEncoding = enum { |
| 286 | 294 | chunked, |
| 287 | 295 | none, |
| 288 | // compression is intentionally omitted here, as std.http.Client stores it as content-encoding | |
| 289 | 296 | }; |
| 290 | 297 | |
| 291 | 298 | pub const ContentEncoding = enum { |
| ... | ... | @@ -308,9 +315,6 @@ pub const Header = struct { |
| 308 | 315 | value: []const u8, |
| 309 | 316 | }; |
| 310 | 317 | |
| 311 | const builtin = @import("builtin"); | |
| 312 | const std = @import("std.zig"); | |
| 313 | ||
| 314 | 318 | test { |
| 315 | 319 | if (builtin.os.tag != .wasi) { |
| 316 | 320 | _ = Client; |
lib/std/http/Client.zig+37-24| ... | ... | @@ -311,7 +311,7 @@ pub const Connection = struct { |
| 311 | 311 | EndOfStream, |
| 312 | 312 | }; |
| 313 | 313 | |
| 314 | pub const Reader = std.io.Reader(*Connection, ReadError, read); | |
| 314 | pub const Reader = std.io.GenericReader(*Connection, ReadError, read); | |
| 315 | 315 | |
| 316 | 316 | pub fn reader(conn: *Connection) Reader { |
| 317 | 317 | return Reader{ .context = conn }; |
| ... | ... | @@ -374,7 +374,7 @@ pub const Connection = struct { |
| 374 | 374 | UnexpectedWriteFailure, |
| 375 | 375 | }; |
| 376 | 376 | |
| 377 | pub const Writer = std.io.Writer(*Connection, WriteError, write); | |
| 377 | pub const Writer = std.io.GenericWriter(*Connection, WriteError, write); | |
| 378 | 378 | |
| 379 | 379 | pub fn writer(conn: *Connection) Writer { |
| 380 | 380 | return Writer{ .context = conn }; |
| ... | ... | @@ -823,21 +823,28 @@ pub const Request = struct { |
| 823 | 823 | return error.UnsupportedTransferEncoding; |
| 824 | 824 | |
| 825 | 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 | } | |
| 827 | 833 | |
| 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 | 836 | try w.writeByte(' '); |
| 830 | 837 | |
| 831 | 838 | if (req.method == .CONNECT) { |
| 832 | try req.uri.writeToStream(.{ .authority = true }, w); | |
| 839 | try req.uri.writeToStream(w, .{ .authority = true }); | |
| 833 | 840 | } else { |
| 834 | try req.uri.writeToStream(.{ | |
| 841 | try req.uri.writeToStream(w, .{ | |
| 835 | 842 | .scheme = connection.proxied, |
| 836 | 843 | .authentication = connection.proxied, |
| 837 | 844 | .authority = connection.proxied, |
| 838 | 845 | .path = true, |
| 839 | 846 | .query = true, |
| 840 | }, w); | |
| 847 | }); | |
| 841 | 848 | } |
| 842 | 849 | try w.writeByte(' '); |
| 843 | 850 | try w.writeAll(@tagName(req.version)); |
| ... | ... | @@ -845,7 +852,7 @@ pub const Request = struct { |
| 845 | 852 | |
| 846 | 853 | if (try emitOverridableHeader("host: ", req.headers.host, w)) { |
| 847 | 854 | try w.writeAll("host: "); |
| 848 | try req.uri.writeToStream(.{ .authority = true }, w); | |
| 855 | try req.uri.writeToStream(w, .{ .authority = true }); | |
| 849 | 856 | try w.writeAll("\r\n"); |
| 850 | 857 | } |
| 851 | 858 | |
| ... | ... | @@ -934,7 +941,7 @@ pub const Request = struct { |
| 934 | 941 | |
| 935 | 942 | const TransferReadError = Connection.ReadError || proto.HeadersParser.ReadError; |
| 936 | 943 | |
| 937 | const TransferReader = std.io.Reader(*Request, TransferReadError, transferRead); | |
| 944 | const TransferReader = std.io.GenericReader(*Request, TransferReadError, transferRead); | |
| 938 | 945 | |
| 939 | 946 | fn transferReader(req: *Request) TransferReader { |
| 940 | 947 | return .{ .context = req }; |
| ... | ... | @@ -1094,7 +1101,7 @@ pub const Request = struct { |
| 1094 | 1101 | pub const ReadError = TransferReadError || proto.HeadersParser.CheckCompleteHeadError || |
| 1095 | 1102 | error{ DecompressionFailure, InvalidTrailers }; |
| 1096 | 1103 | |
| 1097 | pub const Reader = std.io.Reader(*Request, ReadError, read); | |
| 1104 | pub const Reader = std.io.GenericReader(*Request, ReadError, read); | |
| 1098 | 1105 | |
| 1099 | 1106 | pub fn reader(req: *Request) Reader { |
| 1100 | 1107 | return .{ .context = req }; |
| ... | ... | @@ -1134,7 +1141,7 @@ pub const Request = struct { |
| 1134 | 1141 | |
| 1135 | 1142 | pub const WriteError = Connection.WriteError || error{ NotWriteable, MessageTooLong }; |
| 1136 | 1143 | |
| 1137 | pub const Writer = std.io.Writer(*Request, WriteError, write); | |
| 1144 | pub const Writer = std.io.GenericWriter(*Request, WriteError, write); | |
| 1138 | 1145 | |
| 1139 | 1146 | pub fn writer(req: *Request) Writer { |
| 1140 | 1147 | return .{ .context = req }; |
| ... | ... | @@ -1283,26 +1290,32 @@ pub const basic_authorization = struct { |
| 1283 | 1290 | } |
| 1284 | 1291 | |
| 1285 | 1292 | pub fn valueLengthFromUri(uri: Uri) usize { |
| 1286 | var stream = std.io.countingWriter(std.io.null_writer); | |
| 1287 | try stream.writer().print("{user}", .{uri.user orelse Uri.Component.empty}); | |
| 1288 | const user_len = stream.bytes_written; | |
| 1289 | stream.bytes_written = 0; | |
| 1290 | try stream.writer().print("{password}", .{uri.password orelse Uri.Component.empty}); | |
| 1291 | const password_len = stream.bytes_written; | |
| 1293 | const user: Uri.Component = uri.user orelse .empty; | |
| 1294 | const password: Uri.Component = uri.password orelse .empty; | |
| 1295 | ||
| 1296 | var dw: std.io.Writer.Discarding = .init(&.{}); | |
| 1297 | user.formatUser(&dw.writer) catch unreachable; // discarding | |
| 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 | 1305 | return valueLength(@intCast(user_len), @intCast(password_len)); |
| 1293 | 1306 | } |
| 1294 | 1307 | |
| 1295 | 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 | 1312 | var buf: [max_user_len + ":".len + max_password_len]u8 = undefined; |
| 1297 | var stream = std.io.fixedBufferStream(&buf); | |
| 1298 | stream.writer().print("{user}", .{uri.user orelse Uri.Component.empty}) catch | |
| 1299 | unreachable; | |
| 1300 | assert(stream.pos <= max_user_len); | |
| 1301 | stream.writer().print(":{password}", .{uri.password orelse Uri.Component.empty}) catch | |
| 1302 | unreachable; | |
| 1313 | var w: std.io.Writer = .fixed(&buf); | |
| 1314 | user.formatUser(&w) catch unreachable; // fixed | |
| 1315 | password.formatPassword(&w) catch unreachable; // fixed | |
| 1303 | 1316 | |
| 1304 | 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 | 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 | 344 | } |
| 345 | 345 | |
| 346 | 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); | |
| 348 | 348 | |
| 349 | 349 | pub fn reader(conn: *MockBufferedConnection) Reader { |
| 350 | 350 | return Reader{ .context = conn }; |
| ... | ... | @@ -359,7 +359,7 @@ const MockBufferedConnection = struct { |
| 359 | 359 | } |
| 360 | 360 | |
| 361 | 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); | |
| 363 | 363 | |
| 364 | 364 | pub fn writer(conn: *MockBufferedConnection) Writer { |
| 365 | 365 | return Writer{ .context = conn }; |
lib/std/http/test.zig+2-4| ... | ... | @@ -385,10 +385,8 @@ test "general client/server API coverage" { |
| 385 | 385 | fn handleRequest(request: *http.Server.Request, listen_port: u16) !void { |
| 386 | 386 | const log = std.log.scoped(.server); |
| 387 | 387 | |
| 388 | log.info("{} {s} {s}", .{ | |
| 389 | request.head.method, | |
| 390 | @tagName(request.head.version), | |
| 391 | request.head.target, | |
| 388 | log.info("{f} {s} {s}", .{ | |
| 389 | request.head.method, @tagName(request.head.version), request.head.target, | |
| 392 | 390 | }); |
| 393 | 391 | |
| 394 | 392 | const gpa = std.testing.allocator; |
lib/std/io.zig+90-42| ... | ... | @@ -14,54 +14,80 @@ const File = std.fs.File; |
| 14 | 14 | const Allocator = std.mem.Allocator; |
| 15 | 15 | const Alignment = std.mem.Alignment; |
| 16 | 16 | |
| 17 | fn getStdOutHandle() posix.fd_t { | |
| 18 | if (is_windows) { | |
| 19 | return windows.peb().ProcessParameters.hStdOutput; | |
| 17 | pub const Limit = enum(usize) { | |
| 18 | nothing = 0, | |
| 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 | } |
| 21 | 26 | |
| 22 | if (@hasDecl(root, "os") and @hasDecl(root.os, "io") and @hasDecl(root.os.io, "getStdOutHandle")) { | |
| 23 | return root.os.io.getStdOutHandle(); | |
| 27 | /// Any value grater than `std.math.maxInt(usize)` is interpreted to mean | |
| 28 | /// `.unlimited`. | |
| 29 | pub fn limited64(n: u64) Limit { | |
| 30 | return @enumFromInt(@min(n, std.math.maxInt(usize))); | |
| 24 | 31 | } |
| 25 | 32 | |
| 26 | return posix.STDOUT_FILENO; | |
| 27 | } | |
| 33 | pub fn countVec(data: []const []const u8) Limit { | |
| 34 | var total: usize = 0; | |
| 35 | for (data) |d| total += d.len; | |
| 36 | return .limited(total); | |
| 37 | } | |
| 28 | 38 | |
| 29 | pub fn getStdOut() File { | |
| 30 | return .{ .handle = getStdOutHandle() }; | |
| 31 | } | |
| 39 | pub fn min(a: Limit, b: Limit) Limit { | |
| 40 | return @enumFromInt(@min(@intFromEnum(a), @intFromEnum(b))); | |
| 41 | } | |
| 32 | 42 | |
| 33 | fn getStdErrHandle() posix.fd_t { | |
| 34 | if (is_windows) { | |
| 35 | return windows.peb().ProcessParameters.hStdError; | |
| 43 | pub fn minInt(l: Limit, n: usize) usize { | |
| 44 | return @min(n, @intFromEnum(l)); | |
| 36 | 45 | } |
| 37 | 46 | |
| 38 | if (@hasDecl(root, "os") and @hasDecl(root.os, "io") and @hasDecl(root.os.io, "getStdErrHandle")) { | |
| 39 | return root.os.io.getStdErrHandle(); | |
| 47 | pub fn minInt64(l: Limit, n: u64) usize { | |
| 48 | return @min(n, @intFromEnum(l)); | |
| 40 | 49 | } |
| 41 | 50 | |
| 42 | return posix.STDERR_FILENO; | |
| 43 | } | |
| 51 | pub fn slice(l: Limit, s: []u8) []u8 { | |
| 52 | return s[0..l.minInt(s.len)]; | |
| 53 | } | |
| 44 | 54 | |
| 45 | pub fn getStdErr() File { | |
| 46 | return .{ .handle = getStdErrHandle() }; | |
| 47 | } | |
| 55 | pub fn sliceConst(l: Limit, s: []const u8) []const u8 { | |
| 56 | return s[0..l.minInt(s.len)]; | |
| 57 | } | |
| 48 | 58 | |
| 49 | fn getStdInHandle() posix.fd_t { | |
| 50 | if (is_windows) { | |
| 51 | return windows.peb().ProcessParameters.hStdInput; | |
| 59 | pub fn toInt(l: Limit) ?usize { | |
| 60 | return switch (l) { | |
| 61 | else => @intFromEnum(l), | |
| 62 | .unlimited => null, | |
| 63 | }; | |
| 52 | 64 | } |
| 53 | 65 | |
| 54 | if (@hasDecl(root, "os") and @hasDecl(root.os, "io") and @hasDecl(root.os.io, "getStdInHandle")) { | |
| 55 | return root.os.io.getStdInHandle(); | |
| 66 | /// Reduces a slice to account for the limit, leaving room for one extra | |
| 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 | } |
| 57 | 73 | |
| 58 | return posix.STDIN_FILENO; | |
| 59 | } | |
| 74 | pub fn nonzero(l: Limit) bool { | |
| 75 | return @intFromEnum(l) > 0; | |
| 76 | } | |
| 60 | 77 | |
| 61 | pub fn getStdIn() File { | |
| 62 | return .{ .handle = getStdInHandle() }; | |
| 63 | } | |
| 78 | /// Return a new limit reduced by `amount` or return `null` indicating | |
| 79 | /// limit would be exceeded. | |
| 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 | ||
| 87 | pub const Reader = @import("io/Reader.zig"); | |
| 88 | pub const Writer = @import("io/Writer.zig"); | |
| 64 | 89 | |
| 90 | /// Deprecated in favor of `Reader`. | |
| 65 | 91 | pub fn GenericReader( |
| 66 | 92 | comptime Context: type, |
| 67 | 93 | comptime ReadError: type, |
| ... | ... | @@ -289,6 +315,7 @@ pub fn GenericReader( |
| 289 | 315 | }; |
| 290 | 316 | } |
| 291 | 317 | |
| 318 | /// Deprecated in favor of `Writer`. | |
| 292 | 319 | pub fn GenericWriter( |
| 293 | 320 | comptime Context: type, |
| 294 | 321 | comptime WriteError: type, |
| ... | ... | @@ -347,18 +374,39 @@ pub fn GenericWriter( |
| 347 | 374 | const ptr: *const Context = @alignCast(@ptrCast(context)); |
| 348 | 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 | } |
| 352 | 405 | |
| 353 | /// Deprecated; consider switching to `AnyReader` or use `GenericReader` | |
| 354 | /// to use previous API. | |
| 355 | pub const Reader = GenericReader; | |
| 356 | /// Deprecated; consider switching to `AnyWriter` or use `GenericWriter` | |
| 357 | /// to use previous API. | |
| 358 | pub const Writer = GenericWriter; | |
| 359 | ||
| 360 | pub const AnyReader = @import("io/Reader.zig"); | |
| 361 | pub const AnyWriter = @import("io/Writer.zig"); | |
| 406 | /// Deprecated in favor of `Reader`. | |
| 407 | pub const AnyReader = @import("io/DeprecatedReader.zig"); | |
| 408 | /// Deprecated in favor of `Writer`. | |
| 409 | pub const AnyWriter = @import("io/DeprecatedWriter.zig"); | |
| 362 | 410 | |
| 363 | 411 | pub const SeekableStream = @import("io/seekable_stream.zig").SeekableStream; |
| 364 | 412 | |
| ... | ... | @@ -407,7 +455,7 @@ pub const tty = @import("io/tty.zig"); |
| 407 | 455 | /// A Writer that doesn't write to anything. |
| 408 | 456 | pub const null_writer: NullWriter = .{ .context = {} }; |
| 409 | 457 | |
| 410 | pub const NullWriter = Writer(void, error{}, dummyWrite); | |
| 458 | pub const NullWriter = GenericWriter(void, error{}, dummyWrite); | |
| 411 | 459 | fn dummyWrite(context: void, data: []const u8) error{}!usize { |
| 412 | 460 | _ = context; |
| 413 | 461 | return data.len; |
| ... | ... | @@ -819,8 +867,8 @@ pub fn PollFiles(comptime StreamEnum: type) type { |
| 819 | 867 | } |
| 820 | 868 | |
| 821 | 869 | test { |
| 822 | _ = AnyReader; | |
| 823 | _ = AnyWriter; | |
| 870 | _ = Reader; | |
| 871 | _ = Writer; | |
| 824 | 872 | _ = @import("io/bit_reader.zig"); |
| 825 | 873 | _ = @import("io/bit_writer.zig"); |
| 826 | 874 | _ = @import("io/buffered_atomic_file.zig"); |
lib/std/io/DeprecatedReader.zig created+386| ... | ... | @@ -0,0 +1,386 @@ |
| 1 | context: *const anyopaque, | |
| 2 | readFn: *const fn (context: *const anyopaque, buffer: []u8) anyerror!usize, | |
| 3 | ||
| 4 | pub 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. | |
| 9 | pub 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. | |
| 16 | pub 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. | |
| 25 | pub 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. | |
| 37 | pub 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. | |
| 47 | pub 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 | ||
| 55 | pub 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. | |
| 89 | pub 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. | |
| 101 | pub 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. | |
| 116 | pub 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. | |
| 135 | pub 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. | |
| 151 | pub 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. | |
| 176 | pub 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. | |
| 195 | pub 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. | |
| 221 | pub 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`. | |
| 232 | pub 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. | |
| 240 | pub 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 | |
| 246 | pub 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()` | |
| 256 | pub 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. | |
| 273 | pub 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 | ||
| 279 | pub 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 | ||
| 284 | pub 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` | |
| 298 | pub 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 | |
| 304 | pub 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 | |
| 316 | pub 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 | ||
| 327 | pub 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 | ||
| 335 | pub 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 | |
| 346 | pub 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. | |
| 365 | pub 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 | ||
| 375 | const std = @import("../std.zig"); | |
| 376 | const Self = @This(); | |
| 377 | const math = std.math; | |
| 378 | const assert = std.debug.assert; | |
| 379 | const mem = std.mem; | |
| 380 | const testing = std.testing; | |
| 381 | const native_endian = @import("builtin").target.cpu.arch.endian(); | |
| 382 | const Alignment = std.mem.Alignment; | |
| 383 | ||
| 384 | test { | |
| 385 | _ = @import("Reader/test.zig"); | |
| 386 | } |
lib/std/io/DeprecatedWriter.zig created+109| ... | ... | @@ -0,0 +1,109 @@ |
| 1 | const std = @import("../std.zig"); | |
| 2 | const assert = std.debug.assert; | |
| 3 | const mem = std.mem; | |
| 4 | const native_endian = @import("builtin").target.cpu.arch.endian(); | |
| 5 | ||
| 6 | context: *const anyopaque, | |
| 7 | writeFn: *const fn (context: *const anyopaque, bytes: []const u8) anyerror!usize, | |
| 8 | ||
| 9 | const Self = @This(); | |
| 10 | pub const Error = anyerror; | |
| 11 | ||
| 12 | pub fn write(self: Self, bytes: []const u8) anyerror!usize { | |
| 13 | return self.writeFn(self.context, bytes); | |
| 14 | } | |
| 15 | ||
| 16 | pub 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 | ||
| 23 | pub fn print(self: Self, comptime format: []const u8, args: anytype) anyerror!void { | |
| 24 | return std.fmt.format(self, format, args); | |
| 25 | } | |
| 26 | ||
| 27 | pub fn writeByte(self: Self, byte: u8) anyerror!void { | |
| 28 | const array = [1]u8{byte}; | |
| 29 | return self.writeAll(&array); | |
| 30 | } | |
| 31 | ||
| 32 | pub 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 | ||
| 44 | pub 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 | ||
| 51 | pub 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 | ||
| 57 | pub 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 | ||
| 63 | pub 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 | ||
| 74 | pub 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. | |
| 86 | pub 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 | ||
| 96 | pub 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 | context: *const anyopaque, | |
| 2 | readFn: *const fn (context: *const anyopaque, buffer: []u8) anyerror!usize, | |
| 1 | const Reader = @This(); | |
| 3 | 2 | |
| 4 | pub const Error = anyerror; | |
| 3 | const builtin = @import("builtin"); | |
| 4 | const native_endian = builtin.target.cpu.arch.endian(); | |
| 5 | 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. | |
| 9 | pub fn read(self: Self, buffer: []u8) anyerror!usize { | |
| 10 | return self.readFn(self.context, buffer); | |
| 6 | const std = @import("../std.zig"); | |
| 7 | const Writer = std.io.Writer; | |
| 8 | const assert = std.debug.assert; | |
| 9 | const testing = std.testing; | |
| 10 | const Allocator = std.mem.Allocator; | |
| 11 | const ArrayList = std.ArrayListUnmanaged; | |
| 12 | const Limit = std.io.Limit; | |
| 13 | ||
| 14 | pub const Limited = @import("Reader/Limited.zig"); | |
| 15 | ||
| 16 | vtable: *const VTable, | |
| 17 | buffer: []u8, | |
| 18 | /// Number of bytes which have been consumed from `buffer`. | |
| 19 | seek: usize, | |
| 20 | /// In `buffer` before this are buffered bytes, after this is `undefined`. | |
| 21 | end: usize, | |
| 22 | ||
| 23 | pub 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 | ||
| 72 | pub 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 | ||
| 82 | pub const Error = error{ | |
| 83 | /// See the `Reader` implementation for detailed diagnostics. | |
| 84 | ReadFailed, | |
| 85 | EndOfStream, | |
| 86 | }; | |
| 87 | ||
| 88 | pub 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 | ||
| 95 | pub const ShortError = error{ | |
| 96 | /// See the `Reader` implementation for detailed diagnostics. | |
| 97 | ReadFailed, | |
| 98 | }; | |
| 99 | ||
| 100 | pub 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. | |
| 112 | const ending_state: Reader = .fixed(&.{}); | |
| 113 | pub const ending: *Reader = @constCast(&ending_state); | |
| 114 | ||
| 115 | pub fn limited(r: *Reader, limit: Limit, buffer: []u8) Limited { | |
| 116 | return .init(r, limit, buffer); | |
| 11 | 117 | } |
| 12 | 118 | |
| 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. | |
| 16 | pub fn readAll(self: Self, buffer: []u8) anyerror!usize { | |
| 17 | return readAtLeast(self, buffer, buffer.len); | |
| 119 | /// Constructs a `Reader` such that it will read from `buffer` and then end. | |
| 120 | pub fn fixed(buffer: []const u8) Reader { | |
| 121 | return .{ | |
| 122 | .vtable = &.{ | |
| 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 | } |
| 19 | 133 | |
| 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. | |
| 25 | pub 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; | |
| 134 | pub fn stream(r: *Reader, w: *Writer, limit: Limit) StreamError!usize { | |
| 135 | const buffer = limit.slice(r.buffer[r.seek..r.end]); | |
| 136 | if (buffer.len > 0) { | |
| 137 | @branchHint(.likely); | |
| 138 | const n = try w.write(buffer); | |
| 139 | r.seek += n; | |
| 140 | return n; | |
| 141 | } | |
| 142 | const n = try r.vtable.stream(r, w, limit); | |
| 143 | assert(n <= @intFromEnum(limit)); | |
| 144 | return n; | |
| 145 | } | |
| 146 | ||
| 147 | pub 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 | ||
| 163 | pub 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. | |
| 177 | pub 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`. | |
| 186 | pub 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; | |
| 34 | } | |
| 35 | ||
| 36 | /// If the number read would be smaller than `buf.len`, `error.EndOfStream` is returned instead. | |
| 37 | pub 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. | |
| 47 | pub 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 | ||
| 55 | pub 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; | |
| 194 | } | |
| 195 | ||
| 196 | /// Consumes the stream until the end, ignoring all the data, returning the | |
| 197 | /// number of bytes discarded. | |
| 198 | pub fn discardRemaining(r: *Reader) ShortError!usize { | |
| 199 | var offset: usize = r.end - r.seek; | |
| 200 | r.seek = 0; | |
| 201 | r.end = 0; | |
| 64 | 202 | 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; | |
| 203 | offset += r.vtable.discard(r, .unlimited) catch |err| switch (err) { | |
| 204 | error.EndOfStream => return offset, | |
| 205 | else => |e| return e, | |
| 206 | }; | |
| 207 | } | |
| 208 | } | |
| 209 | ||
| 210 | pub const LimitedAllocError = Allocator.Error || ShortError || error{StreamTooLong}; | |
| 69 | 211 | |
| 70 | if (start_index - original_len > max_append_size) { | |
| 71 | array_list.shrinkAndFree(original_len + max_append_size); | |
| 212 | /// Transfers all bytes from the current position to the end of the stream, up | |
| 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` | |
| 223 | pub 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` | |
| 241 | pub 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 | 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. | |
| 286 | pub 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. | |
| 297 | pub 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; | |
| 74 | 308 | |
| 75 | if (bytes_read != dest_slice.len) { | |
| 76 | array_list.shrinkAndFree(start_index); | |
| 77 | return; | |
| 309 | // All of `buffer` has been copied to `data`. We now set up a structure | |
| 310 | // that enables the `Writer.writableVector` API, while also ensuring | |
| 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 | ||
| 371 | pub fn buffered(r: *Reader) []u8 { | |
| 372 | return r.buffer[r.seek..r.end]; | |
| 373 | } | |
| 374 | ||
| 375 | pub fn bufferedLen(r: *const Reader) usize { | |
| 376 | return r.end - r.seek; | |
| 377 | } | |
| 79 | 378 | |
| 80 | // This will trigger ArrayList to expand superlinearly at whatever its growth rate is. | |
| 81 | try array_list.ensureTotalCapacity(start_index + 1); | |
| 379 | pub fn hashed(r: *Reader, hasher: anytype) Hashed(@TypeOf(hasher)) { | |
| 380 | return .{ .in = r, .hasher = hasher }; | |
| 381 | } | |
| 382 | ||
| 383 | pub 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 | } |
| 84 | 399 | |
| 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. | |
| 89 | pub 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. | |
| 101 | pub 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. | |
| 116 | pub 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. | |
| 135 | pub 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. | |
| 151 | pub 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; | |
| 400 | /// Returns the next `len` bytes from the stream, filling the buffer as | |
| 401 | /// necessary. | |
| 402 | /// | |
| 403 | /// Invalidates previously returned values from `peek`. | |
| 404 | /// | |
| 405 | /// Asserts that the `Reader` was initialized with a buffer capacity at | |
| 406 | /// least as big as `len`. | |
| 407 | /// | |
| 408 | /// If there are fewer than `len` bytes left in the stream, `error.EndOfStream` | |
| 409 | /// is returned instead. | |
| 410 | /// | |
| 411 | /// See also: | |
| 412 | /// * `peek` | |
| 413 | /// * `toss` | |
| 414 | pub fn peek(r: *Reader, n: usize) Error![]u8 { | |
| 415 | try r.fill(n); | |
| 416 | return r.buffer[r.seek..][0..n]; | |
| 417 | } | |
| 418 | ||
| 419 | /// Returns all the next buffered bytes, after filling the buffer to ensure it | |
| 420 | /// contains at least `n` bytes. | |
| 421 | /// | |
| 422 | /// Invalidates previously returned values from `peek` and `peekGreedy`. | |
| 423 | /// | |
| 424 | /// Asserts that the `Reader` was initialized with a buffer capacity at | |
| 425 | /// least as big as `n`. | |
| 426 | /// | |
| 427 | /// If there are fewer than `n` bytes left in the stream, `error.EndOfStream` | |
| 428 | /// is returned instead. | |
| 429 | /// | |
| 430 | /// See also: | |
| 431 | /// * `peek` | |
| 432 | /// * `toss` | |
| 433 | pub fn peekGreedy(r: *Reader, n: usize) Error![]u8 { | |
| 434 | try r.fill(n); | |
| 435 | return r.buffer[r.seek..r.end]; | |
| 436 | } | |
| 437 | ||
| 438 | /// Skips the next `n` bytes from the stream, advancing the seek position. This | |
| 439 | /// is typically and safely used after `peek`. | |
| 440 | /// | |
| 441 | /// Asserts that the number of bytes buffered is at least as many as `n`. | |
| 442 | /// | |
| 443 | /// The "tossed" memory remains alive until a "peek" operation occurs. | |
| 444 | /// | |
| 445 | /// See also: | |
| 446 | /// * `peek`. | |
| 447 | /// * `discard`. | |
| 448 | pub fn toss(r: *Reader, n: usize) void { | |
| 449 | r.seek += n; | |
| 450 | assert(r.seek <= r.end); | |
| 451 | } | |
| 452 | ||
| 453 | /// Equivalent to `toss(r.bufferedLen())`. | |
| 454 | pub fn tossBuffered(r: *Reader) void { | |
| 455 | r.seek = 0; | |
| 456 | r.end = 0; | |
| 457 | } | |
| 458 | ||
| 459 | /// Equivalent to `peek` followed by `toss`. | |
| 460 | /// | |
| 461 | /// The data returned is invalidated by the next call to `take`, `peek`, | |
| 462 | /// `fill`, and functions with those prefixes. | |
| 463 | pub fn take(r: *Reader, n: usize) Error![]u8 { | |
| 464 | const result = try r.peek(n); | |
| 465 | r.toss(n); | |
| 466 | return result; | |
| 467 | } | |
| 468 | ||
| 469 | /// Returns the next `n` bytes from the stream as an array, filling the buffer | |
| 470 | /// as necessary and advancing the seek position `n` bytes. | |
| 471 | /// | |
| 472 | /// Asserts that the `Reader` was initialized with a buffer capacity at | |
| 473 | /// least as big as `n`. | |
| 474 | /// | |
| 475 | /// If there are fewer than `n` bytes left in the stream, `error.EndOfStream` | |
| 476 | /// is returned instead. | |
| 477 | /// | |
| 478 | /// See also: | |
| 479 | /// * `take` | |
| 480 | pub 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` | |
| 496 | pub 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` | |
| 511 | pub fn discardAll(r: *Reader, n: usize) Error!void { | |
| 512 | if ((try r.discardShort(n)) != n) return error.EndOfStream; | |
| 513 | } | |
| 514 | ||
| 515 | pub 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` | |
| 535 | pub 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` | |
| 566 | pub 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` | |
| 581 | pub 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` | |
| 640 | pub 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 | ||
| 650 | pub 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. | |
| 654 | pub 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`. | |
| 669 | pub 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 | ||
| 676 | pub 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` | |
| 699 | pub 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` | |
| 716 | pub 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` | |
| 732 | pub 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` | |
| 749 | pub 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` | |
| 793 | pub 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 | 801 | else => |e| return e, |
| 164 | 802 | }; |
| 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. | |
| 176 | pub 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; | |
| 803 | r.toss(result.len); | |
| 804 | return result[0 .. result.len - 1]; | |
| 805 | } | |
| 806 | ||
| 807 | /// Returns a slice of the next bytes of buffered data from the stream until | |
| 808 | /// `delimiter` is found, without advancing the seek position. | |
| 809 | /// | |
| 810 | /// Returned slice excludes the delimiter. End-of-stream is treated equivalent | |
| 811 | /// to a delimiter, unless it would result in a length 0 return value, in which | |
| 812 | /// case `error.EndOfStream` is returned instead. | |
| 813 | /// | |
| 814 | /// If the delimiter is not found within a number of bytes matching the | |
| 815 | /// capacity of this `Reader`, `error.StreamTooLong` is returned. In | |
| 816 | /// such case, the stream state is unmodified as if this function was never | |
| 817 | /// called. | |
| 818 | /// | |
| 819 | /// Invalidates previously returned values from `peek`. | |
| 820 | /// | |
| 821 | /// See also: | |
| 822 | /// * `peekDelimiterInclusive` | |
| 823 | /// * `takeDelimiterExclusive` | |
| 824 | pub 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 | } | |
| 182 | 836 | |
| 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` | |
| 846 | pub 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 | 849 | else => |e| return e, |
| 184 | 850 | }; |
| 185 | const output = fbs.getWritten(); | |
| 186 | buf[output.len] = delimiter; // emulating old behaviour | |
| 187 | return output; | |
| 851 | if (r.seek == r.end) return error.EndOfStream; | |
| 852 | return n; | |
| 188 | 853 | } |
| 189 | 854 | |
| 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 | 856 | /// 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. | |
| 195 | pub fn streamUntilDelimiter( | |
| 196 | self: Self, | |
| 197 | writer: anytype, | |
| 857 | /// | |
| 858 | /// Returns number of bytes streamed, which may be zero. End of stream can be | |
| 859 | /// detected by checking if the next byte in the stream is the delimiter. | |
| 860 | /// | |
| 861 | /// See also: | |
| 862 | /// * `streamDelimiter` | |
| 863 | /// * `streamDelimiterLimit` | |
| 864 | pub fn streamDelimiterEnding( | |
| 865 | r: *Reader, | |
| 866 | w: *Writer, | |
| 198 | 867 | 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); | |
| 868 | ) StreamRemainingError!usize { | |
| 869 | return streamDelimiterLimit(r, w, delimiter, .unlimited) catch |err| switch (err) { | |
| 870 | error.StreamTooLong => unreachable, // unlimited is passed | |
| 871 | else => |e| return e, | |
| 872 | }; | |
| 873 | } | |
| 874 | ||
| 875 | pub const StreamDelimiterLimitError = error{ | |
| 876 | ReadFailed, | |
| 877 | WriteFailed, | |
| 878 | /// The delimiter was not found within the limit. | |
| 879 | StreamTooLong, | |
| 880 | }; | |
| 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. | |
| 887 | pub 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 | } |
| 217 | 911 | |
| 218 | 912 | /// Reads from the stream until specified byte is found, discarding all data, |
| 219 | 913 | /// including the delimiter. |
| 220 | /// If end-of-stream is found, this function succeeds. | |
| 221 | pub fn skipUntilDelimiterOrEof(self: Self, delimiter: u8) anyerror!void { | |
| 222 | while (true) { | |
| 223 | const byte = self.readByte() catch |err| switch (err) { | |
| 224 | error.EndOfStream => return, | |
| 914 | /// | |
| 915 | /// Returns number of bytes discarded, or `error.EndOfStream` if the delimiter | |
| 916 | /// is not found. | |
| 917 | /// | |
| 918 | /// See also: | |
| 919 | /// * `discardDelimiterExclusive` | |
| 920 | /// * `discardDelimiterLimit` | |
| 921 | pub 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` | |
| 943 | pub 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 | ||
| 950 | pub 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. | |
| 963 | pub 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`. | |
| 988 | pub 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 | 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 | } |
| 230 | 1020 | |
| 231 | /// Reads 1 byte from the stream or returns `error.EndOfStream`. | |
| 232 | pub 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. | |
| 240 | pub 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 | |
| 246 | pub 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()` | |
| 256 | pub 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)); | |
| 1021 | /// Without advancing the seek position, does exactly one underlying read, filling the buffer as | |
| 1022 | /// much as possible. This may result in zero bytes added to the buffer, which is not an end of | |
| 1023 | /// stream condition. End of stream is communicated via returning `error.EndOfStream`. | |
| 1024 | /// | |
| 1025 | /// Asserts buffer capacity is at least 1. | |
| 1026 | pub fn fillMore(r: *Reader) Error!void { | |
| 1027 | rebaseCapacity(r, 1); | |
| 1028 | var writer: Writer = .{ | |
| 1029 | .buffer = r.buffer, | |
| 1030 | .end = r.end, | |
| 1031 | .vtable = &.{ .drain = Writer.fixedDrain }, | |
| 1032 | }; | |
| 1033 | r.end += r.vtable.stream(r, &writer, .limited(r.buffer.len - r.end)) catch |err| switch (err) { | |
| 1034 | error.WriteFailed => unreachable, | |
| 1035 | else => |e| return e, | |
| 1036 | }; | |
| 1037 | } | |
| 1038 | ||
| 1039 | /// Returns the next byte from the stream or returns `error.EndOfStream`. | |
| 1040 | /// | |
| 1041 | /// Does not advance the seek position. | |
| 1042 | /// | |
| 1043 | /// Asserts the buffer capacity is nonzero. | |
| 1044 | pub fn peekByte(r: *Reader) Error!u8 { | |
| 1045 | const buffer = r.buffer[0..r.end]; | |
| 1046 | const seek = r.seek; | |
| 1047 | if (seek < buffer.len) { | |
| 1048 | @branchHint(.likely); | |
| 1049 | return buffer[seek]; | |
| 269 | 1050 | } |
| 1051 | try fill(r, 1); | |
| 1052 | return r.buffer[r.seek]; | |
| 270 | 1053 | } |
| 271 | 1054 | |
| 272 | /// Reads at most `num_bytes` and returns as a bounded array. | |
| 273 | pub 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); | |
| 1055 | /// Reads 1 byte from the stream or returns `error.EndOfStream`. | |
| 1056 | /// | |
| 1057 | /// Asserts the buffer capacity is nonzero. | |
| 1058 | pub fn takeByte(r: *Reader) Error!u8 { | |
| 1059 | const result = try peekByte(r); | |
| 1060 | r.seek += 1; | |
| 276 | 1061 | return result; |
| 277 | 1062 | } |
| 278 | 1063 | |
| 279 | pub 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); | |
| 1064 | /// Same as `takeByte` except the returned byte is signed. | |
| 1065 | pub fn takeByteSigned(r: *Reader) Error!i8 { | |
| 1066 | return @bitCast(try r.takeByte()); | |
| 282 | 1067 | } |
| 283 | 1068 | |
| 284 | pub 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` | |
| 298 | pub 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 | |
| 304 | pub 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; | |
| 1069 | /// Asserts the buffer was initialized with a capacity at least `@bitSizeOf(T) / 8`. | |
| 1070 | pub inline fn takeInt(r: *Reader, comptime T: type, endian: std.builtin.Endian) Error!T { | |
| 1071 | const n = @divExact(@typeInfo(T).int.bits, 8); | |
| 1072 | return std.mem.readInt(T, try r.takeArray(n), endian); | |
| 1073 | } | |
| 307 | 1074 | |
| 308 | while (remaining > 0) { | |
| 309 | const amt = @min(remaining, options.buf_size); | |
| 310 | try self.readNoEof(buf[0..amt]); | |
| 311 | remaining -= amt; | |
| 312 | } | |
| 1075 | /// Asserts the buffer was initialized with a capacity at least `n`. | |
| 1076 | pub fn takeVarInt(r: *Reader, comptime Int: type, endian: std.builtin.Endian, n: usize) Error!Int { | |
| 1077 | assert(n <= @sizeOf(Int)); | |
| 1078 | return std.mem.readVarInt(Int, try r.take(n), endian); | |
| 313 | 1079 | } |
| 314 | 1080 | |
| 315 | /// Reads `slice.len` bytes from the stream and returns if they are the same as the passed slice | |
| 316 | pub 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; | |
| 1081 | /// Asserts the buffer was initialized with a capacity at least `@sizeOf(T)`. | |
| 1082 | /// | |
| 1083 | /// Advances the seek position. | |
| 1084 | /// | |
| 1085 | /// See also: | |
| 1086 | /// * `peekStruct` | |
| 1087 | /// * `takeStructEndian` | |
| 1088 | pub fn takeStruct(r: *Reader, comptime T: type) Error!*align(1) T { | |
| 1089 | // Only extern and packed structs have defined in-memory layout. | |
| 1090 | comptime assert(@typeInfo(T).@"struct".layout != .auto); | |
| 1091 | return @ptrCast(try r.takeArray(@sizeOf(T))); | |
| 325 | 1092 | } |
| 326 | 1093 | |
| 327 | pub 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` | |
| 1101 | pub fn peekStruct(r: *Reader, comptime T: type) Error!*align(1) T { | |
| 328 | 1102 | // Only extern and packed structs have defined in-memory layout. |
| 329 | 1103 | 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]; | |
| 1104 | return @ptrCast(try r.peekArray(@sizeOf(T))); | |
| 333 | 1105 | } |
| 334 | 1106 | |
| 335 | pub 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 | } | |
| 1107 | /// Asserts the buffer was initialized with a capacity at least `@sizeOf(T)`. | |
| 1108 | /// | |
| 1109 | /// This function is inline to avoid referencing `std.mem.byteSwapAllFields` | |
| 1110 | /// when `endian` is comptime-known and matches the host endianness. | |
| 1111 | /// | |
| 1112 | /// See also: | |
| 1113 | /// * `takeStruct` | |
| 1114 | /// * `peekStructEndian` | |
| 1115 | pub 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 | 1118 | return res; |
| 341 | 1119 | } |
| 342 | 1120 | |
| 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 | |
| 346 | pub 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, | |
| 1121 | /// Asserts the buffer was initialized with a capacity at least `@sizeOf(T)`. | |
| 1122 | /// | |
| 1123 | /// This function is inline to avoid referencing `std.mem.byteSwapAllFields` | |
| 1124 | /// when `endian` is comptime-known and matches the host endianness. | |
| 1125 | /// | |
| 1126 | /// See also: | |
| 1127 | /// * `takeStructEndian` | |
| 1128 | /// * `peekStruct` | |
| 1129 | pub 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 | ||
| 1135 | pub 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)`. | |
| 1142 | pub 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)`. | |
| 1151 | pub 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"; | |
| 352 | const tag = try self.readInt(type_info.tag_type, endian); | |
| 1159 | } | |
| 353 | 1160 | |
| 354 | inline for (std.meta.fields(Enum)) |field| { | |
| 355 | if (tag == field.value) { | |
| 356 | return @field(Enum, field.name); | |
| 357 | } | |
| 1161 | pub const TakeLeb128Error = Error || error{Overflow}; | |
| 1162 | ||
| 1163 | /// Read a single LEB128 value as type T, or `error.Overflow` if the value cannot fit. | |
| 1164 | pub 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 | ||
| 1172 | pub 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 | ||
| 1183 | pub const FillAllocError = Error || Allocator.Error; | |
| 1184 | ||
| 1185 | pub 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. | |
| 1195 | pub 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 | } | |
| 359 | 1213 | |
| 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. | |
| 1216 | pub fn advanceBufferEnd(r: *Reader, n: usize) void { | |
| 1217 | assert(n <= r.buffer.len - r.end); | |
| 1218 | r.end += n; | |
| 361 | 1219 | } |
| 362 | 1220 | |
| 363 | /// Reads the stream until the end, ignoring all the data. | |
| 364 | /// Returns the number of bytes discarded. | |
| 365 | pub fn discard(self: Self) anyerror!u64 { | |
| 366 | var trash: [4096]u8 = undefined; | |
| 367 | var index: u64 = 0; | |
| 1221 | fn takeMultipleOf7Leb128(r: *Reader, comptime Result: type) TakeLeb128Error!Result { | |
| 1222 | const result_info = @typeInfo(Result).int; | |
| 1223 | comptime assert(result_info.bits % 7 == 0); | |
| 1224 | var remaining_bits: std.math.Log2IntCeil(Result) = result_info.bits; | |
| 1225 | const UnsignedResult = @Type(.{ .int = .{ | |
| 1226 | .signedness = .unsigned, | |
| 1227 | .bits = result_info.bits, | |
| 1228 | } }); | |
| 1229 | var result: UnsignedResult = 0; | |
| 1230 | var fits = true; | |
| 368 | 1231 | while (true) { |
| 369 | const n = try self.read(&trash); | |
| 370 | if (n == 0) return index; | |
| 371 | index += n; | |
| 1232 | const buffer: []const packed struct(u8) { bits: u7, more: bool } = @ptrCast(try r.peekGreedy(1)); | |
| 1233 | for (buffer, 1..) |byte, len| { | |
| 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 | } |
| 374 | 1250 | |
| 375 | const std = @import("../std.zig"); | |
| 376 | const Self = @This(); | |
| 377 | const math = std.math; | |
| 378 | const assert = std.debug.assert; | |
| 379 | const mem = std.mem; | |
| 380 | const testing = std.testing; | |
| 381 | const native_endian = @import("builtin").target.cpu.arch.endian(); | |
| 382 | const Alignment = std.mem.Alignment; | |
| 1251 | /// Left-aligns data such that `r.seek` becomes zero. | |
| 1252 | pub fn rebase(r: *Reader) void { | |
| 1253 | if (r.seek == 0) return; | |
| 1254 | const data = r.buffer[r.seek..r.end]; | |
| 1255 | @memmove(r.buffer[0..data.len], data); | |
| 1256 | r.seek = 0; | |
| 1257 | r.end = data.len; | |
| 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. | |
| 1264 | pub 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. | |
| 1276 | pub 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. | |
| 1287 | pub 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 | } | |
| 383 | 1292 | |
| 384 | test { | |
| 385 | _ = @import("Reader/test.zig"); | |
| 1293 | test fixed { | |
| 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 | ||
| 1305 | test 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 | ||
| 1311 | test peekGreedy { | |
| 1312 | var r: Reader = .fixed("abc"); | |
| 1313 | try testing.expectEqualStrings("abc", try r.peekGreedy(1)); | |
| 1314 | } | |
| 1315 | ||
| 1316 | test toss { | |
| 1317 | var r: Reader = .fixed("abc"); | |
| 1318 | r.toss(1); | |
| 1319 | try testing.expectEqualStrings("bc", r.buffered()); | |
| 1320 | } | |
| 1321 | ||
| 1322 | test 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 | ||
| 1328 | test 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 | ||
| 1334 | test 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 | ||
| 1340 | test 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 | ||
| 1348 | test 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 | ||
| 1355 | test 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 | ||
| 1366 | test 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 | ||
| 1373 | test 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 | ||
| 1379 | test 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 | ||
| 1385 | test 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 | ||
| 1393 | test 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 | ||
| 1400 | test 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 | ||
| 1408 | test 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 | ||
| 1419 | test 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 | ||
| 1432 | test 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 | ||
| 1443 | test 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 | ||
| 1451 | test 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 | ||
| 1457 | test 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 | ||
| 1466 | test fill { | |
| 1467 | var r: Reader = .fixed("abc"); | |
| 1468 | try r.fill(1); | |
| 1469 | try r.fill(3); | |
| 1470 | } | |
| 1471 | ||
| 1472 | test 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 | ||
| 1479 | test 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 | ||
| 1486 | test 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 | ||
| 1492 | test 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 | ||
| 1498 | test 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 | ||
| 1508 | test 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 | ||
| 1523 | test 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 | ||
| 1530 | test 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 | ||
| 1537 | test 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 | ||
| 1545 | test 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 | ||
| 1552 | test 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 | ||
| 1562 | test 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 | ||
| 1575 | test 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 | ||
| 1588 | test "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 | ||
| 1597 | fn endingStream(r: *Reader, w: *Writer, limit: Limit) StreamError!usize { | |
| 1598 | _ = r; | |
| 1599 | _ = w; | |
| 1600 | _ = limit; | |
| 1601 | return error.EndOfStream; | |
| 1602 | } | |
| 1603 | ||
| 1604 | fn endingDiscard(r: *Reader, limit: Limit) Error!usize { | |
| 1605 | _ = r; | |
| 1606 | _ = limit; | |
| 1607 | return error.EndOfStream; | |
| 1608 | } | |
| 1609 | ||
| 1610 | fn failingStream(r: *Reader, w: *Writer, limit: Limit) StreamError!usize { | |
| 1611 | _ = r; | |
| 1612 | _ = w; | |
| 1613 | _ = limit; | |
| 1614 | return error.ReadFailed; | |
| 1615 | } | |
| 1616 | ||
| 1617 | fn failingDiscard(r: *Reader, limit: Limit) Error!usize { | |
| 1618 | _ = r; | |
| 1619 | _ = limit; | |
| 1620 | return error.ReadFailed; | |
| 1621 | } | |
| 1622 | ||
| 1623 | test "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 | ||
| 1654 | test "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. | |
| 1680 | pub 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 @@ |
| 1 | const Limited = @This(); | |
| 2 | ||
| 3 | const std = @import("../../std.zig"); | |
| 4 | const Reader = std.io.Reader; | |
| 5 | const Writer = std.io.Writer; | |
| 6 | const Limit = std.io.Limit; | |
| 7 | ||
| 8 | unlimited: *Reader, | |
| 9 | remaining: Limit, | |
| 10 | interface: Reader, | |
| 11 | ||
| 12 | pub 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 | ||
| 28 | fn 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 | ||
| 36 | fn 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 | const builtin = @import("builtin"); | |
| 2 | const native_endian = builtin.target.cpu.arch.endian(); | |
| 3 | ||
| 4 | const Writer = @This(); | |
| 1 | 5 | const std = @import("../std.zig"); |
| 2 | 6 | const assert = std.debug.assert; |
| 3 | const mem = std.mem; | |
| 4 | const native_endian = @import("builtin").target.cpu.arch.endian(); | |
| 7 | const Limit = std.io.Limit; | |
| 8 | const File = std.fs.File; | |
| 9 | const testing = std.testing; | |
| 10 | const Allocator = std.mem.Allocator; | |
| 11 | ||
| 12 | vtable: *const VTable, | |
| 13 | /// If this has length zero, the writer is unbuffered, and `flush` is a no-op. | |
| 14 | buffer: []u8, | |
| 15 | /// In `buffer` before this are buffered bytes, after this is `undefined`. | |
| 16 | end: usize = 0, | |
| 17 | ||
| 18 | pub 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 | ||
| 81 | pub const Error = error{ | |
| 82 | /// See the `Writer` implementation for detailed diagnostics. | |
| 83 | WriteFailed, | |
| 84 | }; | |
| 5 | 85 | |
| 6 | context: *const anyopaque, | |
| 7 | writeFn: *const fn (context: *const anyopaque, bytes: []const u8) anyerror!usize, | |
| 86 | pub const FileAllError = error{ | |
| 87 | /// Detailed diagnostics are found on the `File.Reader` struct. | |
| 88 | ReadFailed, | |
| 89 | /// See the `Writer` implementation for detailed diagnostics. | |
| 90 | WriteFailed, | |
| 91 | }; | |
| 8 | 92 | |
| 9 | const Self = @This(); | |
| 10 | pub const Error = anyerror; | |
| 93 | pub const FileReadingError = error{ | |
| 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 | }; | |
| 11 | 101 | |
| 12 | pub fn write(self: Self, bytes: []const u8) anyerror!usize { | |
| 13 | return self.writeFn(self.context, bytes); | |
| 102 | pub const FileError = error{ | |
| 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. | |
| 115 | pub fn fixed(buffer: []u8) Writer { | |
| 116 | return .{ | |
| 117 | .vtable = &.{ .drain = fixedDrain }, | |
| 118 | .buffer = buffer, | |
| 119 | }; | |
| 14 | 120 | } |
| 15 | 121 | |
| 16 | pub 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..]); | |
| 122 | pub fn hashed(w: *Writer, hasher: anytype, buffer: []u8) Hashed(@TypeOf(hasher)) { | |
| 123 | return .initHasher(w, hasher, buffer); | |
| 124 | } | |
| 125 | ||
| 126 | pub const failing: Writer = .{ | |
| 127 | .vtable = &.{ | |
| 128 | .drain = failingDrain, | |
| 129 | .sendFile = failingSendFile, | |
| 130 | }, | |
| 131 | }; | |
| 132 | ||
| 133 | /// Returns the contents not yet drained. | |
| 134 | pub fn buffered(w: *const Writer) []u8 { | |
| 135 | return w.buffer[0..w.end]; | |
| 136 | } | |
| 137 | ||
| 138 | pub 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 | ||
| 145 | pub 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`. | |
| 153 | pub 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. | |
| 160 | pub 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`. | |
| 185 | pub 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 | } |
| 22 | 215 | |
| 23 | pub fn print(self: Self, comptime format: []const u8, args: anytype) anyerror!void { | |
| 24 | return std.fmt.format(self, format, args); | |
| 216 | test "writeSplatHeader splatting avoids buffer aliasing temptation" { | |
| 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 | } |
| 26 | 230 | |
| 27 | pub fn writeByte(self: Self, byte: u8) anyerror!void { | |
| 28 | const array = [1]u8{byte}; | |
| 29 | return self.writeAll(&array); | |
| 231 | /// Drains all remaining buffered data. | |
| 232 | pub fn flush(w: *Writer) Error!void { | |
| 233 | return w.vtable.flush(w); | |
| 30 | 234 | } |
| 31 | 235 | |
| 32 | pub fn writeByteNTimes(self: Self, byte: u8, n: usize) anyerror!void { | |
| 33 | var bytes: [256]u8 = undefined; | |
| 34 | @memset(bytes[0..], byte); | |
| 236 | /// Repeatedly calls `VTable.drain` until `end` is zero. | |
| 237 | pub fn defaultFlush(w: *Writer) Error!void { | |
| 238 | const drainFn = w.vtable.drain; | |
| 239 | while (w.end != 0) _ = try drainFn(w, &.{""}, 1); | |
| 240 | } | |
| 35 | 241 | |
| 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; | |
| 242 | /// Does nothing. | |
| 243 | pub fn noopFlush(w: *Writer) Error!void { | |
| 244 | _ = w; | |
| 245 | } | |
| 246 | ||
| 247 | /// Calls `VTable.drain` but hides the last `preserve_length` bytes from the | |
| 248 | /// implementation, keeping them buffered. | |
| 249 | pub 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 | ||
| 259 | pub fn unusedCapacitySlice(w: *const Writer) []u8 { | |
| 260 | return w.buffer[w.end..]; | |
| 261 | } | |
| 262 | ||
| 263 | pub 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`. | |
| 270 | pub 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`. | |
| 279 | pub 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`. | |
| 290 | pub 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 | } |
| 43 | 299 | |
| 44 | pub 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`. | |
| 309 | pub 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 | ||
| 319 | pub 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 | ||
| 348 | pub 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 | ||
| 359 | pub 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 | ||
| 368 | pub fn writableVectorPosix(w: *Writer, buffer: []std.posix.iovec, limit: Limit) Error![]std.posix.iovec { | |
| 369 | var it = try writableVectorIterator(w); | |
| 45 | 370 | var i: usize = 0; |
| 46 | while (i < n) : (i += 1) { | |
| 47 | try self.writeAll(bytes); | |
| 371 | var remaining = limit; | |
| 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 | ||
| 384 | pub fn ensureUnusedCapacity(w: *Writer, n: usize) Error!void { | |
| 385 | _ = try writableSliceGreedy(w, n); | |
| 386 | } | |
| 387 | ||
| 388 | pub 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`. | |
| 396 | pub 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. | |
| 404 | pub 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`. | |
| 410 | pub 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`. | |
| 429 | pub 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 | ||
| 457 | pub 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`. | |
| 468 | pub 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. | |
| 488 | pub 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`. | |
| 500 | pub 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 `}}`. | |
| 563 | pub 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. | |
| 694 | pub 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. | |
| 707 | pub 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. | |
| 719 | pub 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`. | |
| 727 | pub 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. | |
| 733 | pub 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 | } |
| 50 | 742 | |
| 51 | pub 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`. | |
| 746 | pub 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. | |
| 751 | pub inline fn writeInt(w: *Writer, comptime T: type, value: T, endian: std.builtin.Endian) Error!void { | |
| 52 | 752 | 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); | |
| 753 | std.mem.writeInt(std.math.ByteAlignedInt(@TypeOf(value)), &bytes, value, endian); | |
| 754 | return w.writeAll(&bytes); | |
| 55 | 755 | } |
| 56 | 756 | |
| 57 | pub fn writeStruct(self: Self, value: anytype) anyerror!void { | |
| 757 | pub fn writeStruct(w: *Writer, value: anytype) Error!void { | |
| 58 | 758 | // Only extern and packed structs have defined in-memory layout. |
| 59 | 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 | |
| 766 | pub 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 | } |
| 62 | 786 | |
| 63 | pub fn writeStructEndian(self: Self, value: anytype, endian: std.builtin.Endian) anyerror!void { | |
| 64 | // TODO: make sure this value is not a reference type | |
| 787 | pub inline fn writeSliceEndian( | |
| 788 | w: *Writer, | |
| 789 | Elem: type, | |
| 790 | slice: []const Elem, | |
| 791 | endian: std.builtin.Endian, | |
| 792 | ) Error!void { | |
| 65 | 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. | |
| 810 | pub 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. | |
| 815 | pub 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. | |
| 834 | pub 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. | |
| 843 | pub 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. | |
| 866 | pub 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 | ||
| 877 | pub 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 | ||
| 908 | pub 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 | ||
| 912 | pub 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 | ||
| 933 | pub 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 | ||
| 1304 | fn optionsForbidden(options: std.fmt.Options) void { | |
| 1305 | assert(options.precision == null); | |
| 1306 | assert(options.width == null); | |
| 1307 | } | |
| 1308 | ||
| 1309 | fn 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 | ||
| 1314 | fn printEnumExhaustive(w: *Writer, value: anytype) Error!void { | |
| 1315 | var vecs: [2][]const u8 = .{ ".", @tagName(value) }; | |
| 1316 | try w.writeVecAll(&vecs); | |
| 1317 | } | |
| 1318 | ||
| 1319 | fn 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 | ||
| 1330 | pub 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`. | |
| 1349 | pub 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. | |
| 1375 | pub 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 | ||
| 1437 | pub fn printAsciiChar(w: *Writer, c: u8, options: std.fmt.Options) Error!void { | |
| 1438 | return w.alignBufferOptions(@as(*const [1]u8, &c), options); | |
| 1439 | } | |
| 1440 | ||
| 1441 | pub fn printAscii(w: *Writer, bytes: []const u8, options: std.fmt.Options) Error!void { | |
| 1442 | return w.alignBufferOptions(bytes, options); | |
| 1443 | } | |
| 1444 | ||
| 1445 | pub 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. | |
| 1457 | pub 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. | |
| 1474 | pub 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 | ||
| 1490 | pub 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 | 1536 | } else { |
| 68 | var copy = value; | |
| 69 | mem.byteSwapAllFields(@TypeOf(value), &copy); | |
| 70 | return self.writeStruct(copy); | |
| 1537 | if (fractional_bits == mantissa_bits) | |
| 1538 | mantissa |= 1 << fractional_bits; // Add the implicit integer bit. | |
| 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 | ||
| 1595 | pub 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 | |
| 1605 | pub 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 | |
| 1659 | const ANY = "any"; | |
| 1660 | ||
| 1661 | fn 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 | } |
| 73 | 1667 | |
| 74 | pub 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; | |
| 1668 | pub fn invalidFmtError(comptime fmt: []const u8, value: anytype) noreturn { | |
| 1669 | @compileError("invalid format string '" ++ fmt ++ "' for type '" ++ @typeName(@TypeOf(value)) ++ "'"); | |
| 1670 | } | |
| 1671 | ||
| 1672 | pub fn printDurationSigned(w: *Writer, ns: i64) Error!void { | |
| 1673 | if (ns < 0) try w.writeByte('-'); | |
| 1674 | return w.printDurationUnsigned(@abs(ns)); | |
| 1675 | } | |
| 1676 | ||
| 1677 | pub 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`. | |
| 1726 | pub 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 | ||
| 1743 | pub 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 | ||
| 1754 | pub 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. | |
| 1763 | pub 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. | |
| 1775 | pub 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. | |
| 1787 | pub 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 | ||
| 1795 | fn 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 | 1799 | while (true) { |
| 79 | const n = try file.readAll(&buf); | |
| 80 | try self.writeAll(buf[0..n]); | |
| 81 | if (n < buf.len) return; | |
| 1800 | const buffer: []packed struct(u8) { bits: u7, more: bool } = @ptrCast(try w.writableSliceGreedy(1)); | |
| 1801 | for (buffer, 1..) |*byte, len| { | |
| 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 | ||
| 1826 | test "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 | ||
| 1891 | test 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 | ||
| 1928 | test 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 | ||
| 1996 | fn 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 | ||
| 2003 | fn 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 | ||
| 2010 | test 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 | ||
| 2030 | test "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 | ||
| 2038 | fn 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 | ||
| 2045 | test 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 | ||
| 2060 | test "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 | ||
| 2070 | test 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 | ||
| 2086 | test "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 | ||
| 2107 | test "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 | ||
| 2114 | pub fn failingDrain(w: *Writer, data: []const []const u8, splat: usize) Error!usize { | |
| 2115 | _ = w; | |
| 2116 | _ = data; | |
| 2117 | _ = splat; | |
| 2118 | return error.WriteFailed; | |
| 2119 | } | |
| 2120 | ||
| 2121 | pub 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 | ||
| 2128 | pub 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. | |
| 2181 | pub 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`. | |
| 2194 | pub 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. | |
| 2201 | pub 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. | |
| 2212 | pub 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. | |
| 2254 | pub 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`. | |
| 2333 | pub 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 | 11 | |
| 12 | 12 | pub const buffer_size = 4096; |
| 13 | 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); | |
| 15 | 15 | |
| 16 | 16 | /// TODO when https://github.com/ziglang/zig/issues/2761 is solved |
| 17 | 17 | /// this API will not need an allocator |
| ... | ... | @@ -33,7 +33,7 @@ pub const BufferedAtomicFile = struct { |
| 33 | 33 | self.atomic_file = try dir.atomicFile(dest_path, atomic_file_options); |
| 34 | 34 | errdefer self.atomic_file.deinit(); |
| 35 | 35 | |
| 36 | self.file_writer = self.atomic_file.file.writer(); | |
| 36 | self.file_writer = self.atomic_file.file.deprecatedWriter(); | |
| 37 | 37 | self.buffered_writer = .{ .unbuffered_writer = self.file_writer }; |
| 38 | 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 | 12 | end: usize = 0, |
| 13 | 13 | |
| 14 | 14 | pub const Error = ReaderType.Error; |
| 15 | pub const Reader = io.Reader(*Self, Error, read); | |
| 15 | pub const Reader = io.GenericReader(*Self, Error, read); | |
| 16 | 16 | |
| 17 | 17 | const Self = @This(); |
| 18 | 18 | |
| ... | ... | @@ -61,7 +61,7 @@ test "OneByte" { |
| 61 | 61 | |
| 62 | 62 | const Error = error{NoError}; |
| 63 | 63 | const Self = @This(); |
| 64 | const Reader = io.Reader(*Self, Error, read); | |
| 64 | const Reader = io.GenericReader(*Self, Error, read); | |
| 65 | 65 | |
| 66 | 66 | fn init(str: []const u8) Self { |
| 67 | 67 | return Self{ |
| ... | ... | @@ -105,7 +105,7 @@ test "Block" { |
| 105 | 105 | |
| 106 | 106 | const Error = error{NoError}; |
| 107 | 107 | const Self = @This(); |
| 108 | const Reader = io.Reader(*Self, Error, read); | |
| 108 | const Reader = io.GenericReader(*Self, Error, read); | |
| 109 | 109 | |
| 110 | 110 | fn init(block: []const u8, reads_allowed: usize) Self { |
| 111 | 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 | 10 | end: usize = 0, |
| 11 | 11 | |
| 12 | 12 | pub const Error = WriterType.Error; |
| 13 | pub const Writer = io.Writer(*Self, Error, write); | |
| 13 | pub const Writer = io.GenericWriter(*Self, Error, write); | |
| 14 | 14 | |
| 15 | 15 | const Self = @This(); |
| 16 | 16 |
lib/std/io/c_writer.zig+1-1| ... | ... | @@ -3,7 +3,7 @@ const builtin = @import("builtin"); |
| 3 | 3 | const io = std.io; |
| 4 | 4 | const testing = std.testing; |
| 5 | 5 | |
| 6 | pub const CWriter = io.Writer(*std.c.FILE, std.fs.File.WriteError, cWriterWrite); | |
| 6 | pub const CWriter = io.GenericWriter(*std.c.FILE, std.fs.File.WriteError, cWriterWrite); | |
| 7 | 7 | |
| 8 | 8 | pub fn cWriter(c_file: *std.c.FILE) CWriter { |
| 9 | 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 | 8 | return struct { |
| 9 | 9 | const Self = @This(); |
| 10 | 10 | pub const Error = WriterType.Error; |
| 11 | pub const Writer = io.Writer(*Self, Error, write); | |
| 11 | pub const Writer = io.GenericWriter(*Self, Error, write); | |
| 12 | 12 | |
| 13 | 13 | anything_changed: bool, |
| 14 | 14 | underlying_writer: WriterType, |
lib/std/io/counting_reader.zig+1-1| ... | ... | @@ -9,7 +9,7 @@ pub fn CountingReader(comptime ReaderType: anytype) type { |
| 9 | 9 | bytes_read: u64 = 0, |
| 10 | 10 | |
| 11 | 11 | pub const Error = ReaderType.Error; |
| 12 | pub const Reader = io.Reader(*@This(), Error, read); | |
| 12 | pub const Reader = io.GenericReader(*@This(), Error, read); | |
| 13 | 13 | |
| 14 | 14 | pub fn read(self: *@This(), buf: []u8) Error!usize { |
| 15 | 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 | 9 | child_stream: WriterType, |
| 10 | 10 | |
| 11 | 11 | pub const Error = WriterType.Error; |
| 12 | pub const Writer = io.Writer(*Self, Error, write); | |
| 12 | pub const Writer = io.GenericWriter(*Self, Error, write); | |
| 13 | 13 | |
| 14 | 14 | const Self = @This(); |
| 15 | 15 |
lib/std/io/find_byte_writer.zig+1-1| ... | ... | @@ -8,7 +8,7 @@ pub fn FindByteWriter(comptime UnderlyingWriter: type) type { |
| 8 | 8 | return struct { |
| 9 | 9 | const Self = @This(); |
| 10 | 10 | pub const Error = UnderlyingWriter.Error; |
| 11 | pub const Writer = io.Writer(*Self, Error, write); | |
| 11 | pub const Writer = io.GenericWriter(*Self, Error, write); | |
| 12 | 12 | |
| 13 | 13 | underlying_writer: UnderlyingWriter, |
| 14 | 14 | byte_found: bool, |
lib/std/io/fixed_buffer_stream.zig+4-4| ... | ... | @@ -4,8 +4,8 @@ const testing = std.testing; |
| 4 | 4 | const mem = std.mem; |
| 5 | 5 | const assert = std.debug.assert; |
| 6 | 6 | |
| 7 | /// This turns a byte buffer into an `io.Writer`, `io.Reader`, or `io.SeekableStream`. | |
| 8 | /// If the supplied byte buffer is const, then `io.Writer` is not available. | |
| 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.GenericWriter` is not available. | |
| 9 | 9 | pub fn FixedBufferStream(comptime Buffer: type) type { |
| 10 | 10 | return struct { |
| 11 | 11 | /// `Buffer` is either a `[]u8` or `[]const u8`. |
| ... | ... | @@ -17,8 +17,8 @@ pub fn FixedBufferStream(comptime Buffer: type) type { |
| 17 | 17 | pub const SeekError = error{}; |
| 18 | 18 | pub const GetSeekPosError = error{}; |
| 19 | 19 | |
| 20 | pub const Reader = io.Reader(*Self, ReadError, read); | |
| 21 | pub const Writer = io.Writer(*Self, WriteError, write); | |
| 20 | pub const Reader = io.GenericReader(*Self, ReadError, read); | |
| 21 | pub const Writer = io.GenericWriter(*Self, WriteError, write); | |
| 22 | 22 | |
| 23 | 23 | pub const SeekableStream = io.SeekableStream( |
| 24 | 24 | *Self, |
lib/std/io/limited_reader.zig+1-1| ... | ... | @@ -9,7 +9,7 @@ pub fn LimitedReader(comptime ReaderType: type) type { |
| 9 | 9 | bytes_left: u64, |
| 10 | 10 | |
| 11 | 11 | pub const Error = ReaderType.Error; |
| 12 | pub const Reader = io.Reader(*Self, Error, read); | |
| 12 | pub const Reader = io.GenericReader(*Self, Error, read); | |
| 13 | 13 | |
| 14 | 14 | const Self = @This(); |
| 15 | 15 |
lib/std/io/multi_writer.zig+1-1| ... | ... | @@ -15,7 +15,7 @@ pub fn MultiWriter(comptime Writers: type) type { |
| 15 | 15 | streams: Writers, |
| 16 | 16 | |
| 17 | 17 | pub const Error = ErrSet; |
| 18 | pub const Writer = io.Writer(*Self, Error, write); | |
| 18 | pub const Writer = io.GenericWriter(*Self, Error, write); | |
| 19 | 19 | |
| 20 | 20 | pub fn writer(self: *Self) Writer { |
| 21 | 21 | return .{ .context = self }; |
lib/std/io/stream_source.zig+4-4| ... | ... | @@ -2,9 +2,9 @@ const std = @import("../std.zig"); |
| 2 | 2 | const builtin = @import("builtin"); |
| 3 | 3 | const io = std.io; |
| 4 | 4 | |
| 5 | /// Provides `io.Reader`, `io.Writer`, and `io.SeekableStream` for in-memory buffers as | |
| 5 | /// Provides `io.GenericReader`, `io.GenericWriter`, and `io.SeekableStream` for in-memory buffers as | |
| 6 | 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 | 8 | /// The error set of the stream functions is the error set of the corresponding file functions. |
| 9 | 9 | pub const StreamSource = union(enum) { |
| 10 | 10 | // 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 | 26 | pub const SeekError = io.FixedBufferStream([]u8).SeekError || (if (has_file) std.fs.File.SeekError else error{}); |
| 27 | 27 | pub const GetSeekPosError = io.FixedBufferStream([]u8).GetSeekPosError || (if (has_file) std.fs.File.GetSeekPosError else error{}); |
| 28 | 28 | |
| 29 | pub const Reader = io.Reader(*StreamSource, ReadError, read); | |
| 30 | pub const Writer = io.Writer(*StreamSource, WriteError, write); | |
| 29 | pub const Reader = io.GenericReader(*StreamSource, ReadError, read); | |
| 30 | pub const Writer = io.GenericWriter(*StreamSource, WriteError, write); | |
| 31 | 31 | pub const SeekableStream = io.SeekableStream( |
| 32 | 32 | *StreamSource, |
| 33 | 33 | SeekError, |
lib/std/io/test.zig+4-4| ... | ... | @@ -24,7 +24,7 @@ test "write a file, read it, then delete it" { |
| 24 | 24 | var file = try tmp.dir.createFile(tmp_file_name, .{}); |
| 25 | 25 | defer file.close(); |
| 26 | 26 | |
| 27 | var buf_stream = io.bufferedWriter(file.writer()); | |
| 27 | var buf_stream = io.bufferedWriter(file.deprecatedWriter()); | |
| 28 | 28 | const st = buf_stream.writer(); |
| 29 | 29 | try st.print("begin", .{}); |
| 30 | 30 | try st.writeAll(data[0..]); |
| ... | ... | @@ -45,7 +45,7 @@ test "write a file, read it, then delete it" { |
| 45 | 45 | const expected_file_size: u64 = "begin".len + data.len + "end".len; |
| 46 | 46 | try expectEqual(expected_file_size, file_size); |
| 47 | 47 | |
| 48 | var buf_stream = io.bufferedReader(file.reader()); | |
| 48 | var buf_stream = io.bufferedReader(file.deprecatedReader()); | |
| 49 | 49 | const st = buf_stream.reader(); |
| 50 | 50 | const contents = try st.readAllAlloc(std.testing.allocator, 2 * 1024); |
| 51 | 51 | defer std.testing.allocator.free(contents); |
| ... | ... | @@ -66,7 +66,7 @@ test "BitStreams with File Stream" { |
| 66 | 66 | var file = try tmp.dir.createFile(tmp_file_name, .{}); |
| 67 | 67 | defer file.close(); |
| 68 | 68 | |
| 69 | var bit_stream = io.bitWriter(native_endian, file.writer()); | |
| 69 | var bit_stream = io.bitWriter(native_endian, file.deprecatedWriter()); | |
| 70 | 70 | |
| 71 | 71 | try bit_stream.writeBits(@as(u2, 1), 1); |
| 72 | 72 | try bit_stream.writeBits(@as(u5, 2), 2); |
| ... | ... | @@ -80,7 +80,7 @@ test "BitStreams with File Stream" { |
| 80 | 80 | var file = try tmp.dir.openFile(tmp_file_name, .{}); |
| 81 | 81 | defer file.close(); |
| 82 | 82 | |
| 83 | var bit_stream = io.bitReader(native_endian, file.reader()); | |
| 83 | var bit_stream = io.bitReader(native_endian, file.deprecatedReader()); | |
| 84 | 84 | |
| 85 | 85 | var out_bits: u16 = undefined; |
| 86 | 86 |
lib/std/io/tty.zig+39-36| ... | ... | @@ -5,36 +5,9 @@ const process = std.process; |
| 5 | 5 | const windows = std.os.windows; |
| 6 | 6 | const native_os = builtin.os.tag; |
| 7 | 7 | |
| 8 | /// Detect suitable TTY configuration options for the given file (commonly stdout/stderr). | |
| 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. | |
| 8 | /// Deprecated in favor of `Config.detect`. | |
| 12 | 9 | pub fn detectConfig(file: File) Config { |
| 13 | const force_color: ?bool = if (builtin.os.tag == .wasi) | |
| 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; | |
| 10 | return .detect(file); | |
| 38 | 11 | } |
| 39 | 12 | |
| 40 | 13 | pub const Color = enum { |
| ... | ... | @@ -66,17 +39,46 @@ pub const Config = union(enum) { |
| 66 | 39 | escape_codes, |
| 67 | 40 | windows_api: if (native_os == .windows) WindowsContext else void, |
| 68 | 41 | |
| 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 | 74 | pub const WindowsContext = struct { |
| 70 | 75 | handle: File.Handle, |
| 71 | 76 | reset_attributes: u16, |
| 72 | 77 | }; |
| 73 | 78 | |
| 74 | pub fn setColor( | |
| 75 | conf: Config, | |
| 76 | writer: anytype, | |
| 77 | color: Color, | |
| 78 | ) (@typeInfo(@TypeOf(writer.writeAll(""))).error_union.error_set || | |
| 79 | windows.SetConsoleTextAttributeError)!void { | |
| 79 | pub const SetColorError = std.os.windows.SetConsoleTextAttributeError || std.io.Writer.Error; | |
| 80 | ||
| 81 | pub fn setColor(conf: Config, w: *std.io.Writer, color: Color) SetColorError!void { | |
| 80 | 82 | nosuspend switch (conf) { |
| 81 | 83 | .no_color => return, |
| 82 | 84 | .escape_codes => { |
| ... | ... | @@ -101,7 +103,7 @@ pub const Config = union(enum) { |
| 101 | 103 | .dim => "\x1b[2m", |
| 102 | 104 | .reset => "\x1b[0m", |
| 103 | 105 | }; |
| 104 | try writer.writeAll(color_string); | |
| 106 | try w.writeAll(color_string); | |
| 105 | 107 | }, |
| 106 | 108 | .windows_api => |ctx| if (native_os == .windows) { |
| 107 | 109 | const attributes = switch (color) { |
| ... | ... | @@ -126,6 +128,7 @@ pub const Config = union(enum) { |
| 126 | 128 | .dim => windows.FOREGROUND_INTENSITY, |
| 127 | 129 | .reset => ctx.reset_attributes, |
| 128 | 130 | }; |
| 131 | try w.flush(); | |
| 129 | 132 | try windows.SetConsoleTextAttribute(ctx.handle, attributes); |
| 130 | 133 | } else { |
| 131 | 134 | unreachable; |
lib/std/json.zig+2-2| ... | ... | @@ -1,12 +1,12 @@ |
| 1 | 1 | //! JSON parsing and stringification conforming to RFC 8259. https://datatracker.ietf.org/doc/html/rfc8259 |
| 2 | 2 | //! |
| 3 | 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 | 6 | //! The high-level `parseFromSlice` and `parseFromTokenSource` deserialize a JSON document into a Zig type. |
| 7 | 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 | 10 | //! The high-level `stringify` serializes a Zig or `Value` type into JSON. |
| 11 | 11 | |
| 12 | 12 | const builtin = @import("builtin"); |
lib/std/json/dynamic.zig+1-1| ... | ... | @@ -56,7 +56,7 @@ pub const Value = union(enum) { |
| 56 | 56 | std.debug.lockStdErr(); |
| 57 | 57 | defer std.debug.unlockStdErr(); |
| 58 | 58 | |
| 59 | const stderr = std.io.getStdErr().writer(); | |
| 59 | const stderr = std.fs.File.stderr().deprecatedWriter(); | |
| 60 | 60 | stringify(self, .{}, stderr) catch return; |
| 61 | 61 | } |
| 62 | 62 |
lib/std/json/dynamic_test.zig+2-2| ... | ... | @@ -254,7 +254,7 @@ test "Value.jsonStringify" { |
| 254 | 254 | \\ true, |
| 255 | 255 | \\ 42, |
| 256 | 256 | \\ 43, |
| 257 | \\ 4.2e1, | |
| 257 | \\ 42, | |
| 258 | 258 | \\ "weeee", |
| 259 | 259 | \\ [ |
| 260 | 260 | \\ 1, |
| ... | ... | @@ -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 | } |
| 271 | 271 | |
| 272 | 272 | test "parseFromValue(std.json.Value,...)" { |
lib/std/json/fmt.zig+3-9| ... | ... | @@ -1,4 +1,5 @@ |
| 1 | const std = @import("std"); | |
| 1 | const std = @import("../std.zig"); | |
| 2 | const assert = std.debug.assert; | |
| 2 | 3 | |
| 3 | 4 | const stringify = @import("stringify.zig").stringify; |
| 4 | 5 | const StringifyOptions = @import("stringify.zig").StringifyOptions; |
| ... | ... | @@ -14,14 +15,7 @@ pub fn Formatter(comptime T: type) type { |
| 14 | 15 | value: T, |
| 15 | 16 | options: StringifyOptions, |
| 16 | 17 | |
| 17 | pub fn format( | |
| 18 | self: @This(), | |
| 19 | comptime fmt_spec: []const u8, | |
| 20 | options: std.fmt.FormatOptions, | |
| 21 | writer: anytype, | |
| 22 | ) !void { | |
| 23 | _ = fmt_spec; | |
| 24 | _ = options; | |
| 18 | pub fn format(self: @This(), writer: *std.io.Writer) std.io.Writer.Error!void { | |
| 25 | 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 | 219 | /// This limit can be specified by calling `nextAllocMax()` instead of `nextAlloc()`. |
| 220 | 220 | pub const default_max_value_len = 4 * 1024 * 1024; |
| 221 | 221 | |
| 222 | /// Connects a `std.io.Reader` to a `std.json.Scanner`. | |
| 222 | /// Connects a `std.io.GenericReader` to a `std.json.Scanner`. | |
| 223 | 223 | /// All `next*()` methods here handle `error.BufferUnderrun` from `std.json.Scanner`, and then read from the reader. |
| 224 | 224 | pub fn Reader(comptime buffer_size: usize, comptime ReaderType: type) type { |
| 225 | 225 | return struct { |
lib/std/json/stringify.zig+8-6| ... | ... | @@ -38,7 +38,7 @@ pub const StringifyOptions = struct { |
| 38 | 38 | emit_nonportable_numbers_as_strings: bool = false, |
| 39 | 39 | }; |
| 40 | 40 | |
| 41 | /// Writes the given value to the `std.io.Writer` stream. | |
| 41 | /// Writes the given value to the `std.io.GenericWriter` stream. | |
| 42 | 42 | /// See `WriteStream` for how the given value is serialized into JSON. |
| 43 | 43 | /// The maximum nesting depth of the output JSON document is 256. |
| 44 | 44 | /// See also `stringifyMaxDepth` and `stringifyArbitraryDepth`. |
| ... | ... | @@ -81,7 +81,7 @@ pub fn stringifyArbitraryDepth( |
| 81 | 81 | } |
| 82 | 82 | |
| 83 | 83 | /// 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 | 86 | /// Caller owns returned memory. |
| 87 | 87 | pub fn stringifyAlloc( |
| ... | ... | @@ -469,7 +469,6 @@ pub fn WriteStream( |
| 469 | 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 | 470 | /// * Zig floats -> JSON number or string. |
| 471 | 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 | 472 | /// * Zig `[]const u8`, `[]u8`, `*[N]u8`, `@Vector(N, u8)`, and similar -> JSON string. |
| 474 | 473 | /// * See `StringifyOptions.emit_strings_as_arrays`. |
| 475 | 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 | 688 | // then it may be represented as a six-character sequence: a reverse solidus, followed |
| 690 | 689 | // by the lowercase letter u, followed by four hexadecimal digits that encode the character's code point. |
| 691 | 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 | 693 | } else { |
| 694 | 694 | assert(codepoint <= 0x10FFFF); |
| 695 | 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 | 697 | const high = @as(u16, @intCast((codepoint - 0x10000) >> 10)) + 0xD800; |
| 698 | 698 | const low = @as(u16, @intCast(codepoint & 0x3FF)) + 0xDC00; |
| 699 | 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 | 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 | } |
| 705 | 707 |
lib/std/json/stringify_test.zig+7-7| ... | ... | @@ -74,16 +74,16 @@ fn testBasicWriteStream(w: anytype, slice_stream: anytype) !void { |
| 74 | 74 | \\{ |
| 75 | 75 | \\ "object": { |
| 76 | 76 | \\ "one": 1, |
| 77 | \\ "two": 2e0 | |
| 77 | \\ "two": 2 | |
| 78 | 78 | \\ }, |
| 79 | 79 | \\ "string": "This is a string", |
| 80 | 80 | \\ "array": [ |
| 81 | 81 | \\ "Another string", |
| 82 | 82 | \\ 1, |
| 83 | \\ 3.5e0 | |
| 83 | \\ 3.5 | |
| 84 | 84 | \\ ], |
| 85 | 85 | \\ "int": 10, |
| 86 | \\ "float": 3.5e0 | |
| 86 | \\ "float": 3.5 | |
| 87 | 87 | \\} |
| 88 | 88 | ; |
| 89 | 89 | try std.testing.expectEqualStrings(expected, result); |
| ... | ... | @@ -123,12 +123,12 @@ test "stringify basic types" { |
| 123 | 123 | try testStringify("null", @as(?u8, null), .{}); |
| 124 | 124 | try testStringify("null", @as(?*u32, null), .{}); |
| 125 | 125 | try testStringify("42", 42, .{}); |
| 126 | try testStringify("4.2e1", 42.0, .{}); | |
| 126 | try testStringify("42", 42.0, .{}); | |
| 127 | 127 | try testStringify("42", @as(u8, 42), .{}); |
| 128 | 128 | try testStringify("42", @as(u128, 42), .{}); |
| 129 | 129 | try testStringify("9999999999999999", 9999999999999999, .{}); |
| 130 | try testStringify("4.2e1", @as(f32, 42), .{}); | |
| 131 | try testStringify("4.2e1", @as(f64, 42), .{}); | |
| 130 | try testStringify("42", @as(f32, 42), .{}); | |
| 131 | try testStringify("42", @as(f64, 42), .{}); | |
| 132 | 132 | try testStringify("\"ItBroke\"", @as(anyerror, error.ItBroke), .{}); |
| 133 | 133 | try testStringify("\"ItBroke\"", error.ItBroke, .{}); |
| 134 | 134 | } |
| ... | ... | @@ -307,7 +307,7 @@ test "stringify tuple" { |
| 307 | 307 | fn testStringify(expected: []const u8, value: anytype, options: StringifyOptions) !void { |
| 308 | 308 | const ValidationWriter = struct { |
| 309 | 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 | 311 | pub const Error = error{ |
| 312 | 312 | TooMuchData, |
| 313 | 313 | DifferentData, |
lib/std/log.zig+2-2| ... | ... | @@ -47,7 +47,7 @@ |
| 47 | 47 | //! // Print the message to stderr, silently ignoring any errors |
| 48 | 48 | //! std.debug.lockStdErr(); |
| 49 | 49 | //! defer std.debug.unlockStdErr(); |
| 50 | //! const stderr = std.io.getStdErr().writer(); | |
| 50 | //! const stderr = std.fs.File.stderr().deprecatedWriter(); | |
| 51 | 51 | //! nosuspend stderr.print(prefix ++ format ++ "\n", args) catch return; |
| 52 | 52 | //! } |
| 53 | 53 | //! |
| ... | ... | @@ -148,7 +148,7 @@ pub fn defaultLog( |
| 148 | 148 | ) void { |
| 149 | 149 | const level_txt = comptime message_level.asText(); |
| 150 | 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 | 152 | var bw = std.io.bufferedWriter(stderr); |
| 153 | 153 | const writer = bw.writer(); |
| 154 | 154 |
lib/std/math/big/int.zig+21-39| ... | ... | @@ -2028,6 +2028,14 @@ pub const Mutable = struct { |
| 2028 | 2028 | pub fn normalize(r: *Mutable, length: usize) void { |
| 2029 | 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 | }; |
| 2032 | 2040 | |
| 2033 | 2041 | /// A arbitrary-precision big integer, with a fixed set of immutable limbs. |
| ... | ... | @@ -2317,50 +2325,25 @@ pub const Const = struct { |
| 2317 | 2325 | return .{ normalized_res.reconstruct(if (self.positive) .positive else .negative), exactness }; |
| 2318 | 2326 | } |
| 2319 | 2327 | |
| 2320 | /// To allow `std.fmt.format` to work with this type. | |
| 2321 | 2328 | /// If the absolute value of integer is greater than or equal to `pow(2, 64 * @sizeOf(usize) * 8)`, |
| 2322 | 2329 | /// this function will fail to print the string, printing "(BigInt)" instead of a number. |
| 2323 | 2330 | /// This is because the rendering algorithm requires reversing a string, which requires O(N) memory. |
| 2324 | 2331 | /// See `toString` and `toStringAlloc` for a way to print big integers without failure. |
| 2325 | pub fn format( | |
| 2326 | self: Const, | |
| 2327 | comptime fmt: []const u8, | |
| 2328 | options: std.fmt.FormatOptions, | |
| 2329 | out_stream: anytype, | |
| 2330 | ) !void { | |
| 2331 | _ = options; | |
| 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 | ||
| 2332 | pub fn formatNumber(self: Const, w: *std.io.Writer, number: std.fmt.Number) std.io.Writer.Error!void { | |
| 2351 | 2333 | const available_len = 64; |
| 2352 | 2334 | if (self.limbs.len > available_len) |
| 2353 | return out_stream.writeAll("(BigInt)"); | |
| 2335 | return w.writeAll("(BigInt)"); | |
| 2354 | 2336 | |
| 2355 | var limbs: [calcToStringLimbsBufferLen(available_len, base)]Limb = undefined; | |
| 2337 | var limbs: [calcToStringLimbsBufferLen(available_len, 10)]Limb = undefined; | |
| 2356 | 2338 | |
| 2357 | 2339 | const biggest: Const = .{ |
| 2358 | 2340 | .limbs = &([1]Limb{comptime math.maxInt(Limb)} ** available_len), |
| 2359 | 2341 | .positive = false, |
| 2360 | 2342 | }; |
| 2361 | var buf: [biggest.sizeInBaseUpperBound(base)]u8 = undefined; | |
| 2362 | const len = self.toString(&buf, base, case, &limbs); | |
| 2363 | return out_stream.writeAll(buf[0..len]); | |
| 2343 | var buf: [biggest.sizeInBaseUpperBound(2)]u8 = undefined; | |
| 2344 | const base: u8 = number.mode.base() orelse @panic("TODO print big int in scientific form"); | |
| 2345 | const len = self.toString(&buf, base, number.case, &limbs); | |
| 2346 | return w.writeAll(buf[0..len]); | |
| 2364 | 2347 | } |
| 2365 | 2348 | |
| 2366 | 2349 | /// Converts self to a string in the requested base. |
| ... | ... | @@ -2930,17 +2913,16 @@ pub const Managed = struct { |
| 2930 | 2913 | } |
| 2931 | 2914 | |
| 2932 | 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 | 2920 | /// If the absolute value of integer is greater than or equal to `pow(2, 64 * @sizeOf(usize) * 8)`, |
| 2934 | 2921 | /// this function will fail to print the string, printing "(BigInt)" instead of a number. |
| 2935 | 2922 | /// This is because the rendering algorithm requires reversing a string, which requires O(N) memory. |
| 2936 | 2923 | /// See `toString` and `toStringAlloc` for a way to print big integers without failure. |
| 2937 | pub fn format( | |
| 2938 | self: Managed, | |
| 2939 | comptime fmt: []const u8, | |
| 2940 | options: std.fmt.FormatOptions, | |
| 2941 | out_stream: anytype, | |
| 2942 | ) !void { | |
| 2943 | return self.toConst().format(fmt, options, out_stream); | |
| 2924 | pub fn formatNumber(self: Managed, w: *std.io.Writer, n: std.fmt.Number) std.io.Writer.Error!void { | |
| 2925 | return self.toConst().formatNumber(w, n); | |
| 2944 | 2926 | } |
| 2945 | 2927 | |
| 2946 | 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 | 3813 | try a.pow(&a, 64 * @sizeOf(Limb) * 8); |
| 3814 | 3814 | try b.sub(&a, &c); |
| 3815 | 3815 | |
| 3816 | const a_fmt = try std.fmt.allocPrintZ(testing.allocator, "{d}", .{a}); | |
| 3817 | defer testing.allocator.free(a_fmt); | |
| 3816 | try testing.expectFmt("(BigInt)", "{d}", .{a}); | |
| 3818 | 3817 | |
| 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 | 3819 | defer testing.allocator.free(b_fmt); |
| 3821 | ||
| 3822 | try testing.expect(mem.eql(u8, a_fmt, "(BigInt)")); | |
| 3823 | 3820 | try testing.expect(!mem.eql(u8, b_fmt, "(BigInt)")); |
| 3824 | 3821 | } |
| 3825 | 3822 | |
| ... | ... | @@ -3838,10 +3835,10 @@ test "(BigInt) negative" { |
| 3838 | 3835 | a.negate(); |
| 3839 | 3836 | try b.add(&a, &c); |
| 3840 | 3837 | |
| 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 | 3839 | defer testing.allocator.free(a_fmt); |
| 3843 | 3840 | |
| 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 | 3842 | defer testing.allocator.free(b_fmt); |
| 3846 | 3843 | |
| 3847 | 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 | 1714 | } |
| 1715 | 1715 | }, |
| 1716 | 1716 | } |
| 1717 | return @as(ReturnType, @truncate(result)); | |
| 1717 | return @truncate(result); | |
| 1718 | 1718 | } |
| 1719 | 1719 | |
| 1720 | 1720 | test readVarInt { |
| ... | ... | @@ -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 | } |
| 2202 | 2204 |
lib/std/multi_array_list.zig+1| ... | ... | @@ -991,6 +991,7 @@ test "0 sized struct" { |
| 991 | 991 | test "struct with many fields" { |
| 992 | 992 | const ManyFields = struct { |
| 993 | 993 | fn Type(count: comptime_int) type { |
| 994 | @setEvalBranchQuota(50000); | |
| 994 | 995 | var fields: [count]std.builtin.Type.StructField = undefined; |
| 995 | 996 | for (0..count) |i| { |
| 996 | 997 | fields[i] = .{ |
lib/std/net.zig+21-50| ... | ... | @@ -161,22 +161,13 @@ pub const Address = extern union { |
| 161 | 161 | } |
| 162 | 162 | } |
| 163 | 163 | |
| 164 | pub fn format( | |
| 165 | self: Address, | |
| 166 | comptime fmt: []const u8, | |
| 167 | options: std.fmt.FormatOptions, | |
| 168 | out_stream: anytype, | |
| 169 | ) !void { | |
| 170 | if (fmt.len != 0) std.fmt.invalidFmtError(fmt, self); | |
| 164 | pub fn format(self: Address, w: *std.io.Writer) std.io.Writer.Error!void { | |
| 171 | 165 | switch (self.any.family) { |
| 172 | posix.AF.INET => try self.in.format(fmt, options, out_stream), | |
| 173 | posix.AF.INET6 => try self.in6.format(fmt, options, out_stream), | |
| 166 | posix.AF.INET => try self.in.format(w), | |
| 167 | posix.AF.INET6 => try self.in6.format(w), | |
| 174 | 168 | posix.AF.UNIX => { |
| 175 | if (!has_unix_sockets) { | |
| 176 | unreachable; | |
| 177 | } | |
| 178 | ||
| 179 | try std.fmt.format(out_stream, "{s}", .{std.mem.sliceTo(&self.un.path, 0)}); | |
| 169 | if (!has_unix_sockets) unreachable; | |
| 170 | try w.writeAll(std.mem.sliceTo(&self.un.path, 0)); | |
| 180 | 171 | }, |
| 181 | 172 | else => unreachable, |
| 182 | 173 | } |
| ... | ... | @@ -349,22 +340,9 @@ pub const Ip4Address = extern struct { |
| 349 | 340 | self.sa.port = mem.nativeToBig(u16, port); |
| 350 | 341 | } |
| 351 | 342 | |
| 352 | pub fn format( | |
| 353 | self: Ip4Address, | |
| 354 | comptime fmt: []const u8, | |
| 355 | options: std.fmt.FormatOptions, | |
| 356 | out_stream: anytype, | |
| 357 | ) !void { | |
| 358 | if (fmt.len != 0) std.fmt.invalidFmtError(fmt, self); | |
| 359 | _ = options; | |
| 360 | const bytes = @as(*const [4]u8, @ptrCast(&self.sa.addr)); | |
| 361 | try std.fmt.format(out_stream, "{}.{}.{}.{}:{}", .{ | |
| 362 | bytes[0], | |
| 363 | bytes[1], | |
| 364 | bytes[2], | |
| 365 | bytes[3], | |
| 366 | self.getPort(), | |
| 367 | }); | |
| 343 | pub fn format(self: Ip4Address, w: *std.io.Writer) std.io.Writer.Error!void { | |
| 344 | const bytes: *const [4]u8 = @ptrCast(&self.sa.addr); | |
| 345 | try w.print("{d}.{d}.{d}.{d}:{d}", .{ bytes[0], bytes[1], bytes[2], bytes[3], self.getPort() }); | |
| 368 | 346 | } |
| 369 | 347 | |
| 370 | 348 | pub fn getOsSockLen(self: Ip4Address) posix.socklen_t { |
| ... | ... | @@ -653,17 +631,10 @@ pub const Ip6Address = extern struct { |
| 653 | 631 | self.sa.port = mem.nativeToBig(u16, port); |
| 654 | 632 | } |
| 655 | 633 | |
| 656 | pub fn format( | |
| 657 | self: Ip6Address, | |
| 658 | comptime fmt: []const u8, | |
| 659 | options: std.fmt.FormatOptions, | |
| 660 | out_stream: anytype, | |
| 661 | ) !void { | |
| 662 | if (fmt.len != 0) std.fmt.invalidFmtError(fmt, self); | |
| 663 | _ = options; | |
| 634 | pub fn format(self: Ip6Address, w: *std.io.Writer) std.io.Writer.Error!void { | |
| 664 | 635 | const port = mem.bigToNative(u16, self.sa.port); |
| 665 | 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 | 638 | self.sa.addr[12], |
| 668 | 639 | self.sa.addr[13], |
| 669 | 640 | self.sa.addr[14], |
| ... | ... | @@ -711,14 +682,14 @@ pub const Ip6Address = extern struct { |
| 711 | 682 | longest_len = 0; |
| 712 | 683 | } |
| 713 | 684 | |
| 714 | try out_stream.writeAll("["); | |
| 685 | try w.writeAll("["); | |
| 715 | 686 | var i: usize = 0; |
| 716 | 687 | var abbrv = false; |
| 717 | 688 | while (i < native_endian_parts.len) : (i += 1) { |
| 718 | 689 | if (i == longest_start) { |
| 719 | 690 | // Emit "::" for the longest zero run |
| 720 | 691 | if (!abbrv) { |
| 721 | try out_stream.writeAll(if (i == 0) "::" else ":"); | |
| 692 | try w.writeAll(if (i == 0) "::" else ":"); | |
| 722 | 693 | abbrv = true; |
| 723 | 694 | } |
| 724 | 695 | i += longest_len - 1; // Skip the compressed range |
| ... | ... | @@ -727,12 +698,12 @@ pub const Ip6Address = extern struct { |
| 727 | 698 | if (abbrv) { |
| 728 | 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 | 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 | } |
| 737 | 708 | |
| 738 | 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 | 865 | const name_c = try allocator.dupeZ(u8, name); |
| 895 | 866 | defer allocator.free(name_c); |
| 896 | 867 | |
| 897 | const port_c = try std.fmt.allocPrintZ(allocator, "{}", .{port}); | |
| 868 | const port_c = try std.fmt.allocPrintSentinel(allocator, "{}", .{port}, 0); | |
| 898 | 869 | defer allocator.free(port_c); |
| 899 | 870 | |
| 900 | 871 | const ws2_32 = windows.ws2_32; |
| ... | ... | @@ -966,7 +937,7 @@ pub fn getAddressList(allocator: mem.Allocator, name: []const u8, port: u16) Get |
| 966 | 937 | const name_c = try allocator.dupeZ(u8, name); |
| 967 | 938 | defer allocator.free(name_c); |
| 968 | 939 | |
| 969 | const port_c = try std.fmt.allocPrintZ(allocator, "{}", .{port}); | |
| 940 | const port_c = try std.fmt.allocPrintSentinel(allocator, "{}", .{port}, 0); | |
| 970 | 941 | defer allocator.free(port_c); |
| 971 | 942 | |
| 972 | 943 | const hints: posix.addrinfo = .{ |
| ... | ... | @@ -1356,7 +1327,7 @@ fn linuxLookupNameFromHosts( |
| 1356 | 1327 | }; |
| 1357 | 1328 | defer file.close(); |
| 1358 | 1329 | |
| 1359 | var buffered_reader = std.io.bufferedReader(file.reader()); | |
| 1330 | var buffered_reader = std.io.bufferedReader(file.deprecatedReader()); | |
| 1360 | 1331 | const reader = buffered_reader.reader(); |
| 1361 | 1332 | var line_buf: [512]u8 = undefined; |
| 1362 | 1333 | while (reader.readUntilDelimiterOrEof(&line_buf, '\n') catch |err| switch (err) { |
| ... | ... | @@ -1557,7 +1528,7 @@ fn getResolvConf(allocator: mem.Allocator, rc: *ResolvConf) !void { |
| 1557 | 1528 | }; |
| 1558 | 1529 | defer file.close(); |
| 1559 | 1530 | |
| 1560 | var buf_reader = std.io.bufferedReader(file.reader()); | |
| 1531 | var buf_reader = std.io.bufferedReader(file.deprecatedReader()); | |
| 1561 | 1532 | const stream = buf_reader.reader(); |
| 1562 | 1533 | var line_buf: [512]u8 = undefined; |
| 1563 | 1534 | while (stream.readUntilDelimiterOrEof(&line_buf, '\n') catch |err| switch (err) { |
| ... | ... | @@ -1845,8 +1816,8 @@ pub const Stream = struct { |
| 1845 | 1816 | pub const ReadError = posix.ReadError; |
| 1846 | 1817 | pub const WriteError = posix.WriteError; |
| 1847 | 1818 | |
| 1848 | pub const Reader = io.Reader(Stream, ReadError, read); | |
| 1849 | pub const Writer = io.Writer(Stream, WriteError, write); | |
| 1819 | pub const Reader = io.GenericReader(Stream, ReadError, read); | |
| 1820 | pub const Writer = io.GenericWriter(Stream, WriteError, write); | |
| 1850 | 1821 | |
| 1851 | 1822 | pub fn reader(self: Stream) Reader { |
| 1852 | 1823 | return .{ .context = self }; |
lib/std/net/test.zig+16-53| ... | ... | @@ -5,20 +5,13 @@ const mem = std.mem; |
| 5 | 5 | const testing = std.testing; |
| 6 | 6 | |
| 7 | 7 | test "parse and render IP addresses at comptime" { |
| 8 | if (builtin.os.tag == .wasi) return error.SkipZigTest; | |
| 9 | 8 | comptime { |
| 10 | var ipAddrBuffer: [16]u8 = undefined; | |
| 11 | // Parses IPv6 at comptime | |
| 12 | 9 | const ipv6addr = net.Address.parseIp("::1", 0) catch unreachable; |
| 13 | var ipv6 = std.fmt.bufPrint(ipAddrBuffer[0..], "{}", .{ipv6addr}) catch unreachable; | |
| 14 | try std.testing.expect(std.mem.eql(u8, "::1", ipv6[1 .. ipv6.len - 3])); | |
| 10 | try std.testing.expectFmt("[::1]:0", "{f}", .{ipv6addr}); | |
| 15 | 11 | |
| 16 | // Parses IPv4 at comptime | |
| 17 | 12 | const ipv4addr = net.Address.parseIp("127.0.0.1", 0) catch unreachable; |
| 18 | var ipv4 = std.fmt.bufPrint(ipAddrBuffer[0..], "{}", .{ipv4addr}) catch unreachable; | |
| 19 | try std.testing.expect(std.mem.eql(u8, "127.0.0.1", ipv4[0 .. ipv4.len - 2])); | |
| 13 | try std.testing.expectFmt("127.0.0.1:0", "{f}", .{ipv4addr}); | |
| 20 | 14 | |
| 21 | // Returns error for invalid IP addresses at comptime | |
| 22 | 15 | try testing.expectError(error.InvalidIPAddressFormat, net.Address.parseIp("::123.123.123.123", 0)); |
| 23 | 16 | try testing.expectError(error.InvalidIPAddressFormat, net.Address.parseIp("127.01.0.1", 0)); |
| 24 | 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 | 20 | } |
| 28 | 21 | |
| 29 | 22 | test "format IPv6 address with no zero runs" { |
| 30 | if (builtin.os.tag == .wasi) return error.SkipZigTest; | |
| 31 | ||
| 32 | 23 | const addr = try std.net.Address.parseIp6("2001:db8:1:2:3:4:5:6", 0); |
| 33 | ||
| 34 | var buffer: [50]u8 = undefined; | |
| 35 | const result = std.fmt.bufPrint(buffer[0..], "{}", .{addr}) catch unreachable; | |
| 36 | ||
| 37 | try std.testing.expectEqualStrings("[2001:db8:1:2:3:4:5:6]:0", result); | |
| 24 | try std.testing.expectFmt("[2001:db8:1:2:3:4:5:6]:0", "{f}", .{addr}); | |
| 38 | 25 | } |
| 39 | 26 | |
| 40 | 27 | test "parse IPv6 addresses and check compressed form" { |
| 41 | if (builtin.os.tag == .wasi) return error.SkipZigTest; | |
| 42 | ||
| 43 | const alloc = testing.allocator; | |
| 44 | ||
| 45 | // 1) Parse an IPv6 address that should compress to [2001:db8::1:0:0:2]:0 | |
| 46 | const addr1 = try std.net.Address.parseIp6("2001:0db8:0000:0000:0001:0000:0000:0002", 0); | |
| 47 | ||
| 48 | // 2) Parse an IPv6 address that should compress to [2001:db8::1:2]:0 | |
| 49 | const addr2 = try std.net.Address.parseIp6("2001:0db8:0000:0000:0000:0000:0001:0002", 0); | |
| 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); | |
| 28 | try std.testing.expectFmt("[2001:db8::1:0:0:2]:0", "{f}", .{ | |
| 29 | try std.net.Address.parseIp6("2001:0db8:0000:0000:0001:0000:0000:0002", 0), | |
| 30 | }); | |
| 31 | try std.testing.expectFmt("[2001:db8::1:2]:0", "{f}", .{ | |
| 32 | try std.net.Address.parseIp6("2001:0db8:0000:0000:0000:0000:0001:0002", 0), | |
| 33 | }); | |
| 34 | try std.testing.expectFmt("[2001:db8:1:0:1::2]:0", "{f}", .{ | |
| 35 | try std.net.Address.parseIp6("2001:0db8:0001:0000:0001:0000:0000:0002", 0), | |
| 36 | }); | |
| 66 | 37 | } |
| 67 | 38 | |
| 68 | 39 | test "parse IPv6 address, check raw bytes" { |
| 69 | if (builtin.os.tag == .wasi) return error.SkipZigTest; | |
| 70 | ||
| 71 | 40 | const expected_raw: [16]u8 = .{ |
| 72 | 41 | 0x20, 0x01, 0x0d, 0xb8, // 2001:db8 |
| 73 | 42 | 0x00, 0x00, 0x00, 0x00, // :0000:0000 |
| ... | ... | @@ -82,8 +51,6 @@ test "parse IPv6 address, check raw bytes" { |
| 82 | 51 | } |
| 83 | 52 | |
| 84 | 53 | test "parse and render IPv6 addresses" { |
| 85 | if (builtin.os.tag == .wasi) return error.SkipZigTest; | |
| 86 | ||
| 87 | 54 | var buffer: [100]u8 = undefined; |
| 88 | 55 | const ips = [_][]const u8{ |
| 89 | 56 | "FF01:0:0:0:0:0:0:FB", |
| ... | ... | @@ -111,12 +78,12 @@ test "parse and render IPv6 addresses" { |
| 111 | 78 | }; |
| 112 | 79 | for (ips, 0..) |ip, i| { |
| 113 | 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 | 82 | try std.testing.expect(std.mem.eql(u8, printed[i], newIp[1 .. newIp.len - 3])); |
| 116 | 83 | |
| 117 | 84 | if (builtin.os.tag == .linux) { |
| 118 | 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 | 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 | 115 | } |
| 149 | 116 | |
| 150 | 117 | test "parse and render IPv4 addresses" { |
| 151 | if (builtin.os.tag == .wasi) return error.SkipZigTest; | |
| 152 | ||
| 153 | 118 | var buffer: [18]u8 = undefined; |
| 154 | 119 | for ([_][]const u8{ |
| 155 | 120 | "0.0.0.0", |
| ... | ... | @@ -159,7 +124,7 @@ test "parse and render IPv4 addresses" { |
| 159 | 124 | "127.0.0.1", |
| 160 | 125 | }) |ip| { |
| 161 | 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 | 128 | try std.testing.expect(std.mem.eql(u8, ip, newIp[0 .. newIp.len - 2])); |
| 164 | 129 | } |
| 165 | 130 | |
| ... | ... | @@ -175,10 +140,8 @@ test "parse and render UNIX addresses" { |
| 175 | 140 | if (builtin.os.tag == .wasi) return error.SkipZigTest; |
| 176 | 141 | if (!net.has_unix_sockets) return error.SkipZigTest; |
| 177 | 142 | |
| 178 | var buffer: [14]u8 = undefined; | |
| 179 | 143 | const addr = net.Address.initUnix("/tmp/testpath") catch unreachable; |
| 180 | const fmt_addr = std.fmt.bufPrint(buffer[0..], "{}", .{addr}) catch unreachable; | |
| 181 | try std.testing.expectEqualSlices(u8, "/tmp/testpath", fmt_addr); | |
| 144 | try std.testing.expectFmt("/tmp/testpath", "{f}", .{addr}); | |
| 182 | 145 | |
| 183 | 146 | const too_long = [_]u8{'a'} ** 200; |
| 184 | 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 | 31 | pub const wasi = @import("os/wasi.zig"); |
| 32 | 32 | pub const emscripten = @import("os/emscripten.zig"); |
| 33 | 33 | pub const windows = @import("os/windows.zig"); |
| 34 | pub const freebsd = @import("os/freebsd.zig"); | |
| 34 | 35 | |
| 35 | 36 | test { |
| 36 | 37 | _ = linux; |
lib/std/os/freebsd.zig created+49| ... | ... | @@ -0,0 +1,49 @@ |
| 1 | const std = @import("../std.zig"); | |
| 2 | const fd_t = std.c.fd_t; | |
| 3 | const off_t = std.c.off_t; | |
| 4 | const unexpectedErrno = std.posix.unexpectedErrno; | |
| 5 | const errno = std.posix.errno; | |
| 6 | ||
| 7 | pub 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 | ||
| 35 | 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 { | |
| 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 | 103 | pub const ino_t = arch_bits.ino_t; |
| 104 | 104 | pub const mcontext_t = arch_bits.mcontext_t; |
| 105 | 105 | pub const mode_t = arch_bits.mode_t; |
| 106 | pub const msghdr = arch_bits.msghdr; | |
| 107 | pub const msghdr_const = arch_bits.msghdr_const; | |
| 108 | 106 | pub const nlink_t = arch_bits.nlink_t; |
| 109 | 107 | pub const off_t = arch_bits.off_t; |
| 110 | 108 | pub const time_t = arch_bits.time_t; |
| ... | ... | @@ -9403,3 +9401,151 @@ pub const SHADOW_STACK = struct { |
| 9403 | 9401 | /// Set up a restore token in the shadow stack. |
| 9404 | 9402 | pub const SET_TOKEN: u64 = 1 << 0; |
| 9405 | 9403 | }; |
| 9404 | ||
| 9405 | pub 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 | ||
| 9415 | pub 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. | |
| 9427 | pub 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 | 199 | __unused: [4]u8, |
| 200 | 200 | }; |
| 201 | 201 | |
| 202 | pub 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 | ||
| 214 | pub 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 | ||
| 226 | 202 | pub const blksize_t = i32; |
| 227 | 203 | pub const nlink_t = u32; |
| 228 | 204 | pub const time_t = isize; |
lib/std/os/linux/arm.zig-20| ... | ... | @@ -237,26 +237,6 @@ pub const Flock = extern struct { |
| 237 | 237 | __unused: [4]u8, |
| 238 | 238 | }; |
| 239 | 239 | |
| 240 | pub 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 | ||
| 250 | pub 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 | ||
| 260 | 240 | pub const blksize_t = i32; |
| 261 | 241 | pub const nlink_t = u32; |
| 262 | 242 | pub const time_t = isize; |
lib/std/os/linux/mips.zig-20| ... | ... | @@ -309,26 +309,6 @@ pub const Flock = extern struct { |
| 309 | 309 | __unused: [4]u8, |
| 310 | 310 | }; |
| 311 | 311 | |
| 312 | pub 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 | ||
| 322 | pub 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 | ||
| 332 | 312 | pub const blksize_t = u32; |
| 333 | 313 | pub const nlink_t = u32; |
| 334 | 314 | pub const time_t = i32; |
lib/std/os/linux/mips64.zig-20| ... | ... | @@ -288,26 +288,6 @@ pub const Flock = extern struct { |
| 288 | 288 | __unused: [4]u8, |
| 289 | 289 | }; |
| 290 | 290 | |
| 291 | pub 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 | ||
| 301 | pub 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 | ||
| 311 | 291 | pub const blksize_t = u32; |
| 312 | 292 | pub const nlink_t = u32; |
| 313 | 293 | pub const time_t = i32; |
lib/std/os/linux/powerpc.zig-20| ... | ... | @@ -247,26 +247,6 @@ pub const Flock = extern struct { |
| 247 | 247 | pid: pid_t, |
| 248 | 248 | }; |
| 249 | 249 | |
| 250 | pub 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 | ||
| 260 | pub 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 | ||
| 270 | 250 | pub const blksize_t = i32; |
| 271 | 251 | pub const nlink_t = u32; |
| 272 | 252 | pub const time_t = isize; |
lib/std/os/linux/powerpc64.zig-20| ... | ... | @@ -233,26 +233,6 @@ pub const Flock = extern struct { |
| 233 | 233 | __unused: [4]u8, |
| 234 | 234 | }; |
| 235 | 235 | |
| 236 | pub 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 | ||
| 246 | pub 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 | ||
| 256 | 236 | pub const blksize_t = i64; |
| 257 | 237 | pub const nlink_t = u64; |
| 258 | 238 | pub const time_t = i64; |
lib/std/os/linux/riscv32.zig-24| ... | ... | @@ -200,30 +200,6 @@ pub const Flock = extern struct { |
| 200 | 200 | __unused: [4]u8, |
| 201 | 201 | }; |
| 202 | 202 | |
| 203 | pub 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 | ||
| 215 | pub 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 | 203 | // The `stat` definition used by the Linux kernel. |
| 228 | 204 | pub const Stat = extern struct { |
| 229 | 205 | dev: dev_t, |
lib/std/os/linux/riscv64.zig-24| ... | ... | @@ -200,30 +200,6 @@ pub const Flock = extern struct { |
| 200 | 200 | __unused: [4]u8, |
| 201 | 201 | }; |
| 202 | 202 | |
| 203 | pub 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 | ||
| 215 | pub 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 | 203 | // The `stat` definition used by the Linux kernel. |
| 228 | 204 | pub const Stat = extern struct { |
| 229 | 205 | dev: dev_t, |
lib/std/os/linux/sparc64.zig-20| ... | ... | @@ -282,26 +282,6 @@ pub const Flock = extern struct { |
| 282 | 282 | pid: pid_t, |
| 283 | 283 | }; |
| 284 | 284 | |
| 285 | pub 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 | ||
| 295 | pub 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 | ||
| 305 | 285 | pub const off_t = i64; |
| 306 | 286 | pub const ino_t = u64; |
| 307 | 287 | pub const time_t = isize; |
lib/std/os/linux/x86.zig-20| ... | ... | @@ -245,26 +245,6 @@ pub const Flock = extern struct { |
| 245 | 245 | pid: pid_t, |
| 246 | 246 | }; |
| 247 | 247 | |
| 248 | pub 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 | ||
| 258 | pub 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 | ||
| 268 | 248 | pub const blksize_t = i32; |
| 269 | 249 | pub const nlink_t = u32; |
| 270 | 250 | pub const time_t = isize; |
lib/std/os/linux/x86_64.zig-24| ... | ... | @@ -233,30 +233,6 @@ pub const Flock = extern struct { |
| 233 | 233 | pid: pid_t, |
| 234 | 234 | }; |
| 235 | 235 | |
| 236 | pub 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 | ||
| 248 | pub 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 | ||
| 260 | 236 | pub const off_t = i64; |
| 261 | 237 | pub const ino_t = u64; |
| 262 | 238 | pub const dev_t = u64; |
lib/std/os/uefi.zig+14-25| ... | ... | @@ -1,4 +1,5 @@ |
| 1 | 1 | const std = @import("../std.zig"); |
| 2 | const assert = std.debug.assert; | |
| 2 | 3 | |
| 3 | 4 | /// A protocol is an interface identified by a GUID. |
| 4 | 5 | pub const protocol = @import("uefi/protocol.zig"); |
| ... | ... | @@ -59,31 +60,19 @@ pub const Guid = extern struct { |
| 59 | 60 | node: [6]u8, |
| 60 | 61 | |
| 61 | 62 | /// Format GUID into hexadecimal lowercase xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx format |
| 62 | pub fn format( | |
| 63 | self: @This(), | |
| 64 | comptime f: []const u8, | |
| 65 | options: std.fmt.FormatOptions, | |
| 66 | writer: anytype, | |
| 67 | ) !void { | |
| 68 | _ = options; | |
| 69 | if (f.len == 0) { | |
| 70 | const fmt = std.fmt.fmtSliceHexLower; | |
| 71 | ||
| 72 | const time_low = @byteSwap(self.time_low); | |
| 73 | const time_mid = @byteSwap(self.time_mid); | |
| 74 | const time_high_and_version = @byteSwap(self.time_high_and_version); | |
| 75 | ||
| 76 | return std.fmt.format(writer, "{:0>8}-{:0>4}-{:0>4}-{:0>2}{:0>2}-{:0>12}", .{ | |
| 77 | fmt(std.mem.asBytes(&time_low)), | |
| 78 | fmt(std.mem.asBytes(&time_mid)), | |
| 79 | fmt(std.mem.asBytes(&time_high_and_version)), | |
| 80 | fmt(std.mem.asBytes(&self.clock_seq_high_and_reserved)), | |
| 81 | fmt(std.mem.asBytes(&self.clock_seq_low)), | |
| 82 | fmt(std.mem.asBytes(&self.node)), | |
| 83 | }); | |
| 84 | } else { | |
| 85 | std.fmt.invalidFmtError(f, self); | |
| 86 | } | |
| 63 | pub fn format(self: @This(), writer: *std.io.Writer) std.io.Writer.Error!void { | |
| 64 | const time_low = @byteSwap(self.time_low); | |
| 65 | const time_mid = @byteSwap(self.time_mid); | |
| 66 | const time_high_and_version = @byteSwap(self.time_high_and_version); | |
| 67 | ||
| 68 | return writer.print("{x:0>8}-{x:0>4}-{x:0>4}-{x:0>2}{x:0>2}-{x:0>12}", .{ | |
| 69 | std.mem.asBytes(&time_low), | |
| 70 | std.mem.asBytes(&time_mid), | |
| 71 | std.mem.asBytes(&time_high_and_version), | |
| 72 | std.mem.asBytes(&self.clock_seq_high_and_reserved), | |
| 73 | std.mem.asBytes(&self.clock_seq_low), | |
| 74 | std.mem.asBytes(&self.node), | |
| 75 | }); | |
| 87 | 76 | } |
| 88 | 77 | |
| 89 | 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 | 79 | VolumeFull, |
| 80 | 80 | }; |
| 81 | 81 | |
| 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 | 82 | pub fn open( |
| 107 | 83 | self: *const File, |
| 108 | 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 | 1690 | return ws2_32.getpeername(s, name, @as(*i32, @ptrCast(namelen))); |
| 1691 | 1691 | } |
| 1692 | 1692 | |
| 1693 | pub 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 | ||
| 1706 | pub 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 | ||
| 1716 | pub 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 | ||
| 1727 | 1693 | pub fn poll(fds: [*]ws2_32.pollfd, n: c_ulong, timeout: i32) i32 { |
| 1728 | 1694 | return ws2_32.WSAPoll(fds, n, timeout); |
| 1729 | 1695 | } |
| ... | ... | @@ -2846,9 +2812,8 @@ pub fn unexpectedError(err: Win32Error) UnexpectedError { |
| 2846 | 2812 | buf_wstr.len, |
| 2847 | 2813 | null, |
| 2848 | 2814 | ); |
| 2849 | std.debug.print("error.Unexpected: GetLastError({}): {}\n", .{ | |
| 2850 | @intFromEnum(err), | |
| 2851 | std.unicode.fmtUtf16Le(buf_wstr[0..len]), | |
| 2815 | std.debug.print("error.Unexpected: GetLastError({d}): {f}\n", .{ | |
| 2816 | err, std.unicode.fmtUtf16Le(buf_wstr[0..len]), | |
| 2852 | 2817 | }); |
| 2853 | 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 | 30 | const expected_path_utf16 = std.unicode.utf8ToUtf16LeStringLiteral(expected_path); |
| 31 | 31 | const actual_path = try windows.wToPrefixedFileW(null, path_utf16); |
| 32 | 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 | 34 | return e; |
| 35 | 35 | }; |
| 36 | 36 | } |
| ... | ... | @@ -48,7 +48,7 @@ fn testToPrefixedFileOnlyOracle(comptime path: []const u8) !void { |
| 48 | 48 | const zig_result = try windows.wToPrefixedFileW(null, path_utf16); |
| 49 | 49 | const win32_api_result = try RtlDosPathNameToNtPathName_U(path_utf16); |
| 50 | 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 | 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 | 1829 | buf: [*]const u8, |
| 1830 | 1830 | len: i32, |
| 1831 | 1831 | flags: i32, |
| 1832 | to: *const sockaddr, | |
| 1832 | to: ?*const sockaddr, | |
| 1833 | 1833 | tolen: i32, |
| 1834 | 1834 | ) callconv(.winapi) i32; |
| 1835 | 1835 | |
| ... | ... | @@ -2116,14 +2116,6 @@ pub extern "ws2_32" fn WSASendMsg( |
| 2116 | 2116 | lpCompletionRoutine: ?LPWSAOVERLAPPED_COMPLETION_ROUTINE, |
| 2117 | 2117 | ) callconv(.winapi) i32; |
| 2118 | 2118 | |
| 2119 | pub 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 | ||
| 2127 | 2119 | pub extern "ws2_32" fn WSASendDisconnect( |
| 2128 | 2120 | s: SOCKET, |
| 2129 | 2121 | lpOutboundDisconnectData: ?*WSABUF, |
lib/std/posix.zig+1-1| ... | ... | @@ -651,7 +651,7 @@ fn getRandomBytesDevURandom(buf: []u8) !void { |
| 651 | 651 | } |
| 652 | 652 | |
| 653 | 653 | const file: fs.File = .{ .handle = fd }; |
| 654 | const stream = file.reader(); | |
| 654 | const stream = file.deprecatedReader(); | |
| 655 | 655 | stream.readNoEof(buf) catch return error.Unexpected; |
| 656 | 656 | } |
| 657 | 657 |
lib/std/posix/test.zig+1-1| ... | ... | @@ -667,7 +667,7 @@ test "mmap" { |
| 667 | 667 | const file = try tmp.dir.createFile(test_out_file, .{}); |
| 668 | 668 | defer file.close(); |
| 669 | 669 | |
| 670 | const stream = file.writer(); | |
| 670 | const stream = file.deprecatedWriter(); | |
| 671 | 671 | |
| 672 | 672 | var i: u32 = 0; |
| 673 | 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 | 1553 | const file = try std.fs.openFileAbsolute("/etc/passwd", .{}); |
| 1554 | 1554 | defer file.close(); |
| 1555 | 1555 | |
| 1556 | const reader = file.reader(); | |
| 1556 | const reader = file.deprecatedReader(); | |
| 1557 | 1557 | |
| 1558 | 1558 | const State = enum { |
| 1559 | 1559 | Start, |
| ... | ... | @@ -1895,7 +1895,7 @@ pub fn createEnvironFromMap( |
| 1895 | 1895 | var i: usize = 0; |
| 1896 | 1896 | |
| 1897 | 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 | 1899 | i += 1; |
| 1900 | 1900 | } |
| 1901 | 1901 | |
| ... | ... | @@ -1906,16 +1906,16 @@ pub fn createEnvironFromMap( |
| 1906 | 1906 | .add => unreachable, |
| 1907 | 1907 | .delete => continue, |
| 1908 | 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 | 1910 | pair.key_ptr.*, options.zig_progress_fd.?, |
| 1911 | }); | |
| 1911 | }, 0); | |
| 1912 | 1912 | i += 1; |
| 1913 | 1913 | continue; |
| 1914 | 1914 | }, |
| 1915 | 1915 | .nothing => {}, |
| 1916 | 1916 | }; |
| 1917 | 1917 | |
| 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 | 1919 | i += 1; |
| 1920 | 1920 | } |
| 1921 | 1921 | } |
| ... | ... | @@ -1965,7 +1965,7 @@ pub fn createEnvironFromExisting( |
| 1965 | 1965 | var existing_index: usize = 0; |
| 1966 | 1966 | |
| 1967 | 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 | 1969 | i += 1; |
| 1970 | 1970 | } |
| 1971 | 1971 | |
| ... | ... | @@ -1974,7 +1974,7 @@ pub fn createEnvironFromExisting( |
| 1974 | 1974 | .add => unreachable, |
| 1975 | 1975 | .delete => continue, |
| 1976 | 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 | 1978 | i += 1; |
| 1979 | 1979 | continue; |
| 1980 | 1980 | }, |
lib/std/process/Child.zig+2-2| ... | ... | @@ -1004,12 +1004,12 @@ fn forkChildErrReport(fd: i32, err: ChildProcess.SpawnError) noreturn { |
| 1004 | 1004 | |
| 1005 | 1005 | fn writeIntFd(fd: i32, value: ErrInt) !void { |
| 1006 | 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 | } |
| 1009 | 1009 | |
| 1010 | 1010 | fn readIntFd(fd: i32) !ErrInt { |
| 1011 | 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 | } |
| 1014 | 1014 | |
| 1015 | 1015 | const 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 | 348 | unread_bytes: *u64, |
| 349 | 349 | parent_reader: ReaderType, |
| 350 | 350 | |
| 351 | pub const Reader = std.io.Reader(File, ReaderType.Error, File.read); | |
| 351 | pub const Reader = std.io.GenericReader(File, ReaderType.Error, File.read); | |
| 352 | 352 | |
| 353 | 353 | pub fn reader(self: File) Reader { |
| 354 | 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 | 105 | .error_set, |
| 106 | 106 | => { |
| 107 | 107 | if (actual != expected) { |
| 108 | print("expected {}, found {}\n", .{ expected, actual }); | |
| 108 | print("expected {any}, found {any}\n", .{ expected, actual }); | |
| 109 | 109 | return error.TestExpectedEqual; |
| 110 | 110 | } |
| 111 | 111 | }, |
| ... | ... | @@ -267,9 +267,13 @@ test "expectEqual null" { |
| 267 | 267 | |
| 268 | 268 | /// This function is intended to be used only in tests. When the formatted result of the template |
| 269 | 269 | /// and its arguments does not equal the expected text, it prints diagnostics to stderr to show how |
| 270 | /// they are not equal, then returns an error. It depends on `expectEqualStrings()` for printing | |
| 270 | /// they are not equal, then returns an error. It depends on `expectEqualStrings` for printing | |
| 271 | 271 | /// diagnostics. |
| 272 | 272 | pub 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 | 277 | const actual = try std.fmt.allocPrint(allocator, template, args); |
| 274 | 278 | defer allocator.free(actual); |
| 275 | 279 | return expectEqualStrings(expected, actual); |
| ... | ... | @@ -356,9 +360,6 @@ test expectApproxEqRel { |
| 356 | 360 | /// The colorized output is optional and controlled by the return of `std.io.tty.detectConfig()`. |
| 357 | 361 | /// If your inputs are UTF-8 encoded strings, consider calling `expectEqualStrings` instead. |
| 358 | 362 | pub 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 | 363 | const diff_index: usize = diff_index: { |
| 363 | 364 | const shortest = @min(expected.len, actual.len); |
| 364 | 365 | var index: usize = 0; |
| ... | ... | @@ -367,12 +368,21 @@ pub fn expectEqualSlices(comptime T: type, expected: []const T, actual: []const |
| 367 | 368 | } |
| 368 | 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 | } | |
| 370 | 377 | |
| 371 | if (!backend_can_print) { | |
| 372 | return error.TestExpectedEqual; | |
| 373 | } | |
| 374 | ||
| 375 | print("slices differ. first difference occurs at index {d} (0x{X})\n", .{ diff_index, diff_index }); | |
| 378 | fn failEqualSlices( | |
| 379 | comptime T: type, | |
| 380 | expected: []const T, | |
| 381 | actual: []const T, | |
| 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 }); | |
| 376 | 386 | |
| 377 | 387 | // TODO: Should this be configurable by the caller? |
| 378 | 388 | const max_lines: usize = 16; |
| ... | ... | @@ -390,8 +400,7 @@ pub fn expectEqualSlices(comptime T: type, expected: []const T, actual: []const |
| 390 | 400 | const actual_window = actual[window_start..@min(actual.len, window_start + max_window_size)]; |
| 391 | 401 | const actual_truncated = window_start + actual_window.len < actual.len; |
| 392 | 402 | |
| 393 | const stderr = std.io.getStdErr(); | |
| 394 | const ttyconf = std.io.tty.detectConfig(stderr); | |
| 403 | const ttyconf = std.io.tty.detectConfig(.stderr()); | |
| 395 | 404 | var differ = if (T == u8) BytesDiffer{ |
| 396 | 405 | .expected = expected_window, |
| 397 | 406 | .actual = actual_window, |
| ... | ... | @@ -407,47 +416,47 @@ pub fn expectEqualSlices(comptime T: type, expected: []const T, actual: []const |
| 407 | 416 | // that is usually useful. |
| 408 | 417 | const index_fmt = if (T == u8) "0x{X}" else "{}"; |
| 409 | 418 | |
| 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 | 420 | if (window_start > 0) { |
| 412 | 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 | 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 | 428 | if (expected_truncated) { |
| 420 | 429 | const end_offset = window_start + expected_window.len; |
| 421 | 430 | const num_missing_items = expected.len - (window_start + expected_window.len); |
| 422 | 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 | 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 | } |
| 428 | 437 | |
| 429 | 438 | // now reverse expected/actual and print again |
| 430 | 439 | differ.expected = actual_window; |
| 431 | 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 | 442 | if (window_start > 0) { |
| 434 | 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 | 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 | 450 | if (actual_truncated) { |
| 442 | 451 | const end_offset = window_start + actual_window.len; |
| 443 | 452 | const num_missing_items = actual.len - (window_start + actual_window.len); |
| 444 | 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 | 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", .{}); | |
| 451 | 460 | |
| 452 | 461 | return error.TestExpectedEqual; |
| 453 | 462 | } |
| ... | ... | @@ -461,7 +470,7 @@ fn SliceDiffer(comptime T: type) type { |
| 461 | 470 | |
| 462 | 471 | const Self = @This(); |
| 463 | 472 | |
| 464 | pub fn write(self: Self, writer: anytype) !void { | |
| 473 | pub fn write(self: Self, writer: *std.io.Writer) !void { | |
| 465 | 474 | for (self.expected, 0..) |value, i| { |
| 466 | 475 | const full_index = self.start_index + i; |
| 467 | 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 | 491 | actual: []const u8, |
| 483 | 492 | ttyconf: std.io.tty.Config, |
| 484 | 493 | |
| 485 | pub fn write(self: BytesDiffer, writer: anytype) !void { | |
| 494 | pub fn write(self: BytesDiffer, writer: *std.io.Writer) !void { | |
| 486 | 495 | var expected_iterator = std.mem.window(u8, self.expected, 16, 16); |
| 487 | 496 | var row: usize = 0; |
| 488 | 497 | while (expected_iterator.next()) |chunk| { |
| ... | ... | @@ -499,7 +508,7 @@ const BytesDiffer = struct { |
| 499 | 508 | if (chunk.len < 16) { |
| 500 | 509 | var missing_columns = (16 - chunk.len) * 3; |
| 501 | 510 | if (chunk.len < 8) missing_columns += 1; |
| 502 | try writer.writeByteNTimes(' ', missing_columns); | |
| 511 | try writer.splatByteAll(' ', missing_columns); | |
| 503 | 512 | } |
| 504 | 513 | for (chunk, 0..) |byte, col| { |
| 505 | 514 | const diff = diffs.isSet(col); |
| ... | ... | @@ -528,7 +537,7 @@ const BytesDiffer = struct { |
| 528 | 537 | } |
| 529 | 538 | } |
| 530 | 539 | |
| 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 | 541 | if (diff) try self.ttyconf.setColor(writer, .red); |
| 533 | 542 | try writer.print(fmt, args); |
| 534 | 543 | if (diff) try self.ttyconf.setColor(writer, .reset); |
| ... | ... | @@ -637,6 +646,11 @@ pub fn tmpDir(opts: std.fs.Dir.OpenOptions) TmpDir { |
| 637 | 646 | |
| 638 | 647 | pub fn expectEqualStrings(expected: []const u8, actual: []const u8) !void { |
| 639 | 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 | 654 | print("\n====== expected this output: =========\n", .{}); |
| 641 | 655 | printWithVisibleNewlines(expected); |
| 642 | 656 | print("\n======== instead found this: =========\n", .{}); |
| ... | ... | @@ -1108,7 +1122,7 @@ pub fn checkAllAllocationFailures(backing_allocator: std.mem.Allocator, comptime |
| 1108 | 1122 | const arg_i_str = comptime str: { |
| 1109 | 1123 | var str_buf: [100]u8 = undefined; |
| 1110 | 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 | 1126 | break :str str_buf[0..str_len]; |
| 1113 | 1127 | }; |
| 1114 | 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 | 1152 | error.OutOfMemory => { |
| 1139 | 1153 | if (failing_allocator_inst.allocated_bytes != failing_allocator_inst.freed_bytes) { |
| 1140 | 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 | 1157 | fail_index, |
| 1144 | 1158 | needed_alloc_count, |
| ... | ... | @@ -1192,3 +1206,43 @@ pub inline fn fuzz( |
| 1192 | 1206 | ) anyerror!void { |
| 1193 | 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`. | |
| 1211 | pub 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 | 9 | /// |
| 10 | 10 | /// See also: https://en.wikipedia.org/wiki/Specials_(Unicode_block)#Replacement_character |
| 11 | 11 | pub const replacement_character: u21 = 0xFFFD; |
| 12 | pub const replacement_character_utf8: [3]u8 = utf8EncodeComptime(replacement_character); | |
| 12 | 13 | |
| 13 | 14 | /// Returns how many bytes the UTF-8 representation would require |
| 14 | 15 | /// for the given codepoint. |
| ... | ... | @@ -802,14 +803,7 @@ fn testDecode(bytes: []const u8) !u21 { |
| 802 | 803 | /// Ill-formed UTF-8 byte sequences are replaced by the replacement character (U+FFFD) |
| 803 | 804 | /// according to "U+FFFD Substitution of Maximal Subparts" from Chapter 3 of |
| 804 | 805 | /// the Unicode standard, and as specified by https://encoding.spec.whatwg.org/#utf-8-decoder |
| 805 | fn formatUtf8( | |
| 806 | utf8: []const u8, | |
| 807 | comptime fmt: []const u8, | |
| 808 | options: std.fmt.FormatOptions, | |
| 809 | writer: anytype, | |
| 810 | ) !void { | |
| 811 | _ = fmt; | |
| 812 | _ = options; | |
| 806 | fn formatUtf8(utf8: []const u8, writer: *std.io.Writer) std.io.Writer.Error!void { | |
| 813 | 807 | var buf: [300]u8 = undefined; // just an arbitrary size |
| 814 | 808 | var u8len: usize = 0; |
| 815 | 809 | |
| ... | ... | @@ -898,27 +892,27 @@ fn formatUtf8( |
| 898 | 892 | /// Ill-formed UTF-8 byte sequences are replaced by the replacement character (U+FFFD) |
| 899 | 893 | /// according to "U+FFFD Substitution of Maximal Subparts" from Chapter 3 of |
| 900 | 894 | /// the Unicode standard, and as specified by https://encoding.spec.whatwg.org/#utf-8-decoder |
| 901 | pub fn fmtUtf8(utf8: []const u8) std.fmt.Formatter(formatUtf8) { | |
| 895 | pub fn fmtUtf8(utf8: []const u8) std.fmt.Formatter([]const u8, formatUtf8) { | |
| 902 | 896 | return .{ .data = utf8 }; |
| 903 | 897 | } |
| 904 | 898 | |
| 905 | 899 | test fmtUtf8 { |
| 906 | 900 | const expectFmt = testing.expectFmt; |
| 907 | try expectFmt("", "{}", .{fmtUtf8("")}); | |
| 908 | try expectFmt("foo", "{}", .{fmtUtf8("foo")}); | |
| 909 | try expectFmt("𐐷", "{}", .{fmtUtf8("𐐷")}); | |
| 901 | try expectFmt("", "{f}", .{fmtUtf8("")}); | |
| 902 | try expectFmt("foo", "{f}", .{fmtUtf8("foo")}); | |
| 903 | try expectFmt("𐐷", "{f}", .{fmtUtf8("𐐷")}); | |
| 910 | 904 | |
| 911 | 905 | // 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")}); | |
| 913 | 907 | |
| 914 | 908 | // 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")}); | |
| 916 | 910 | |
| 917 | 911 | // 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")}); | |
| 919 | 913 | |
| 920 | 914 | // 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 | } |
| 923 | 917 | |
| 924 | 918 | fn utf16LeToUtf8ArrayListImpl( |
| ... | ... | @@ -1477,14 +1471,7 @@ test calcWtf16LeLen { |
| 1477 | 1471 | |
| 1478 | 1472 | /// Print the given `utf16le` string, encoded as UTF-8 bytes. |
| 1479 | 1473 | /// Unpaired surrogates are replaced by the replacement character (U+FFFD). |
| 1480 | fn formatUtf16Le( | |
| 1481 | utf16le: []const u16, | |
| 1482 | comptime fmt: []const u8, | |
| 1483 | options: std.fmt.FormatOptions, | |
| 1484 | writer: anytype, | |
| 1485 | ) !void { | |
| 1486 | _ = fmt; | |
| 1487 | _ = options; | |
| 1474 | fn formatUtf16Le(utf16le: []const u16, writer: *std.io.Writer) std.io.Writer.Error!void { | |
| 1488 | 1475 | var buf: [300]u8 = undefined; // just an arbitrary size |
| 1489 | 1476 | var it = Utf16LeIterator.init(utf16le); |
| 1490 | 1477 | var u8len: usize = 0; |
| ... | ... | @@ -1505,23 +1492,23 @@ pub const fmtUtf16le = @compileError("deprecated; renamed to fmtUtf16Le"); |
| 1505 | 1492 | /// Return a Formatter for a (potentially ill-formed) UTF-16 LE string, |
| 1506 | 1493 | /// which will be converted to UTF-8 during formatting. |
| 1507 | 1494 | /// Unpaired surrogates are replaced by the replacement character (U+FFFD). |
| 1508 | pub fn fmtUtf16Le(utf16le: []const u16) std.fmt.Formatter(formatUtf16Le) { | |
| 1495 | pub fn fmtUtf16Le(utf16le: []const u16) std.fmt.Formatter([]const u16, formatUtf16Le) { | |
| 1509 | 1496 | return .{ .data = utf16le }; |
| 1510 | 1497 | } |
| 1511 | 1498 | |
| 1512 | 1499 | test fmtUtf16Le { |
| 1513 | 1500 | const expectFmt = testing.expectFmt; |
| 1514 | try expectFmt("", "{}", .{fmtUtf16Le(utf8ToUtf16LeStringLiteral(""))}); | |
| 1515 | try expectFmt("", "{}", .{fmtUtf16Le(wtf8ToWtf16LeStringLiteral(""))}); | |
| 1516 | try expectFmt("foo", "{}", .{fmtUtf16Le(utf8ToUtf16LeStringLiteral("foo"))}); | |
| 1517 | try expectFmt("foo", "{}", .{fmtUtf16Le(wtf8ToWtf16LeStringLiteral("foo"))}); | |
| 1518 | try expectFmt("𐐷", "{}", .{fmtUtf16Le(wtf8ToWtf16LeStringLiteral("𐐷"))}); | |
| 1519 | try expectFmt("", "{}", .{fmtUtf16Le(&[_]u16{mem.readInt(u16, "\xff\xd7", native_endian)})}); | |
| 1520 | try expectFmt("�", "{}", .{fmtUtf16Le(&[_]u16{mem.readInt(u16, "\x00\xd8", native_endian)})}); | |
| 1521 | try expectFmt("�", "{}", .{fmtUtf16Le(&[_]u16{mem.readInt(u16, "\xff\xdb", native_endian)})}); | |
| 1522 | try expectFmt("�", "{}", .{fmtUtf16Le(&[_]u16{mem.readInt(u16, "\x00\xdc", native_endian)})}); | |
| 1523 | try expectFmt("�", "{}", .{fmtUtf16Le(&[_]u16{mem.readInt(u16, "\xff\xdf", native_endian)})}); | |
| 1524 | try expectFmt("", "{}", .{fmtUtf16Le(&[_]u16{mem.readInt(u16, "\x00\xe0", native_endian)})}); | |
| 1501 | try expectFmt("", "{f}", .{fmtUtf16Le(utf8ToUtf16LeStringLiteral(""))}); | |
| 1502 | try expectFmt("", "{f}", .{fmtUtf16Le(wtf8ToWtf16LeStringLiteral(""))}); | |
| 1503 | try expectFmt("foo", "{f}", .{fmtUtf16Le(utf8ToUtf16LeStringLiteral("foo"))}); | |
| 1504 | try expectFmt("foo", "{f}", .{fmtUtf16Le(wtf8ToWtf16LeStringLiteral("foo"))}); | |
| 1505 | try expectFmt("𐐷", "{f}", .{fmtUtf16Le(wtf8ToWtf16LeStringLiteral("𐐷"))}); | |
| 1506 | try expectFmt("", "{f}", .{fmtUtf16Le(&[_]u16{mem.readInt(u16, "\xff\xd7", native_endian)})}); | |
| 1507 | try expectFmt("�", "{f}", .{fmtUtf16Le(&[_]u16{mem.readInt(u16, "\x00\xd8", native_endian)})}); | |
| 1508 | try expectFmt("�", "{f}", .{fmtUtf16Le(&[_]u16{mem.readInt(u16, "\xff\xdb", native_endian)})}); | |
| 1509 | try expectFmt("�", "{f}", .{fmtUtf16Le(&[_]u16{mem.readInt(u16, "\x00\xdc", native_endian)})}); | |
| 1510 | try expectFmt("�", "{f}", .{fmtUtf16Le(&[_]u16{mem.readInt(u16, "\xff\xdf", native_endian)})}); | |
| 1511 | try expectFmt("", "{f}", .{fmtUtf16Le(&[_]u16{mem.readInt(u16, "\x00\xe0", native_endian)})}); | |
| 1525 | 1512 | } |
| 1526 | 1513 | |
| 1527 | 1514 | fn testUtf8ToUtf16LeStringLiteral(utf8ToUtf16LeStringLiteral_: anytype) !void { |
lib/std/unicode/throughput_test.zig+1-1| ... | ... | @@ -39,7 +39,7 @@ fn benchmarkCodepointCount(buf: []const u8) !ResultCount { |
| 39 | 39 | } |
| 40 | 40 | |
| 41 | 41 | pub fn main() !void { |
| 42 | const stdout = std.io.getStdOut().writer(); | |
| 42 | const stdout = std.fs.File.stdout().deprecatedWriter(); | |
| 43 | 43 | |
| 44 | 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 | 48 | |
| 49 | 49 | pub fn get_tty_conf(color: Color) std.io.tty.Config { |
| 50 | 50 | return switch (color) { |
| 51 | .auto => std.io.tty.detectConfig(std.io.getStdErr()), | |
| 51 | .auto => std.io.tty.detectConfig(std.fs.File.stderr()), | |
| 52 | 52 | .on => .escape_codes, |
| 53 | 53 | .off => .no_color, |
| 54 | 54 | }; |
| ... | ... | @@ -363,149 +363,136 @@ const Allocator = std.mem.Allocator; |
| 363 | 363 | |
| 364 | 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 primitives | |
| 367 | /// and the reserved `_` identifier. | |
| 368 | /// - Add `p` to the specifier to render identifiers that shadow primitives unescaped. | |
| 369 | /// - Add `_` to the specifier to render the reserved `_` identifier unescaped. | |
| 370 | /// - `p` and `_` can be combined, e.g. `{p_}`. | |
| 366 | /// See also `fmtIdFlags`. | |
| 367 | pub fn fmtId(bytes: []const u8) std.fmt.Formatter(FormatId, FormatId.render) { | |
| 368 | return .{ .data = .{ .bytes = bytes, .flags = .{} } }; | |
| 369 | } | |
| 370 | ||
| 371 | /// Return a Formatter for a Zig identifier, escaping it with `@""` syntax if needed. | |
| 371 | 372 | /// |
| 372 | pub fn fmtId(bytes: []const u8) std.fmt.Formatter(formatId) { | |
| 373 | return .{ .data = bytes }; | |
| 373 | /// See also `fmtId`. | |
| 374 | pub fn fmtIdFlags(bytes: []const u8, flags: FormatId.Flags) std.fmt.Formatter(FormatId, FormatId.render) { | |
| 375 | return .{ .data = .{ .bytes = bytes, .flags = flags } }; | |
| 376 | } | |
| 377 | ||
| 378 | pub 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 | ||
| 382 | pub fn fmtIdP(bytes: []const u8) std.fmt.Formatter(FormatId, FormatId.render) { | |
| 383 | return .{ .data = .{ .bytes = bytes, .flags = .{ .allow_primitive = true } } }; | |
| 374 | 384 | } |
| 375 | 385 | |
| 376 | 386 | test fmtId { |
| 377 | 387 | const expectFmt = std.testing.expectFmt; |
| 378 | try expectFmt("@\"while\"", "{}", .{fmtId("while")}); | |
| 379 | try expectFmt("@\"while\"", "{p}", .{fmtId("while")}); | |
| 380 | try expectFmt("@\"while\"", "{_}", .{fmtId("while")}); | |
| 381 | try expectFmt("@\"while\"", "{p_}", .{fmtId("while")}); | |
| 382 | try expectFmt("@\"while\"", "{_p}", .{fmtId("while")}); | |
| 383 | ||
| 384 | try expectFmt("hello", "{}", .{fmtId("hello")}); | |
| 385 | try expectFmt("hello", "{p}", .{fmtId("hello")}); | |
| 386 | try expectFmt("hello", "{_}", .{fmtId("hello")}); | |
| 387 | try expectFmt("hello", "{p_}", .{fmtId("hello")}); | |
| 388 | try expectFmt("hello", "{_p}", .{fmtId("hello")}); | |
| 389 | ||
| 390 | try expectFmt("@\"type\"", "{}", .{fmtId("type")}); | |
| 391 | try expectFmt("type", "{p}", .{fmtId("type")}); | |
| 392 | try expectFmt("@\"type\"", "{_}", .{fmtId("type")}); | |
| 393 | try expectFmt("type", "{p_}", .{fmtId("type")}); | |
| 394 | try expectFmt("type", "{_p}", .{fmtId("type")}); | |
| 395 | ||
| 396 | try expectFmt("@\"_\"", "{}", .{fmtId("_")}); | |
| 397 | try expectFmt("@\"_\"", "{p}", .{fmtId("_")}); | |
| 398 | try expectFmt("_", "{_}", .{fmtId("_")}); | |
| 399 | try expectFmt("_", "{p_}", .{fmtId("_")}); | |
| 400 | try expectFmt("_", "{_p}", .{fmtId("_")}); | |
| 401 | ||
| 402 | try expectFmt("@\"i123\"", "{}", .{fmtId("i123")}); | |
| 403 | try expectFmt("i123", "{p}", .{fmtId("i123")}); | |
| 404 | try expectFmt("@\"4four\"", "{}", .{fmtId("4four")}); | |
| 405 | try expectFmt("_underscore", "{}", .{fmtId("_underscore")}); | |
| 406 | try expectFmt("@\"11\\\"23\"", "{}", .{fmtId("11\"23")}); | |
| 407 | try expectFmt("@\"11\\x0f23\"", "{}", .{fmtId("11\x0F23")}); | |
| 388 | try expectFmt("@\"while\"", "{f}", .{fmtId("while")}); | |
| 389 | try expectFmt("@\"while\"", "{f}", .{fmtIdFlags("while", .{ .allow_primitive = true })}); | |
| 390 | try expectFmt("@\"while\"", "{f}", .{fmtIdFlags("while", .{ .allow_underscore = true })}); | |
| 391 | try expectFmt("@\"while\"", "{f}", .{fmtIdFlags("while", .{ .allow_primitive = true, .allow_underscore = true })}); | |
| 392 | ||
| 393 | try expectFmt("hello", "{f}", .{fmtId("hello")}); | |
| 394 | try expectFmt("hello", "{f}", .{fmtIdFlags("hello", .{ .allow_primitive = true })}); | |
| 395 | try expectFmt("hello", "{f}", .{fmtIdFlags("hello", .{ .allow_underscore = true })}); | |
| 396 | try expectFmt("hello", "{f}", .{fmtIdFlags("hello", .{ .allow_primitive = true, .allow_underscore = true })}); | |
| 397 | ||
| 398 | try expectFmt("@\"type\"", "{f}", .{fmtId("type")}); | |
| 399 | try expectFmt("type", "{f}", .{fmtIdFlags("type", .{ .allow_primitive = true })}); | |
| 400 | try expectFmt("@\"type\"", "{f}", .{fmtIdFlags("type", .{ .allow_underscore = true })}); | |
| 401 | try expectFmt("type", "{f}", .{fmtIdFlags("type", .{ .allow_primitive = true, .allow_underscore = true })}); | |
| 402 | ||
| 403 | try expectFmt("@\"_\"", "{f}", .{fmtId("_")}); | |
| 404 | try expectFmt("@\"_\"", "{f}", .{fmtIdFlags("_", .{ .allow_primitive = true })}); | |
| 405 | try expectFmt("_", "{f}", .{fmtIdFlags("_", .{ .allow_underscore = true })}); | |
| 406 | try expectFmt("_", "{f}", .{fmtIdFlags("_", .{ .allow_primitive = true, .allow_underscore = true })}); | |
| 407 | ||
| 408 | try expectFmt("@\"i123\"", "{f}", .{fmtId("i123")}); | |
| 409 | try expectFmt("i123", "{f}", .{fmtIdFlags("i123", .{ .allow_primitive = true })}); | |
| 410 | try expectFmt("@\"4four\"", "{f}", .{fmtId("4four")}); | |
| 411 | try expectFmt("_underscore", "{f}", .{fmtId("_underscore")}); | |
| 412 | try expectFmt("@\"11\\\"23\"", "{f}", .{fmtId("11\"23")}); | |
| 413 | try expectFmt("@\"11\\x0f23\"", "{f}", .{fmtId("11\x0F23")}); | |
| 408 | 414 | |
| 409 | 415 | // These are technically not currently legal in Zig. |
| 410 | try expectFmt("@\"\"", "{}", .{fmtId("")}); | |
| 411 | try expectFmt("@\"\\x00\"", "{}", .{fmtId("\x00")}); | |
| 416 | try expectFmt("@\"\"", "{f}", .{fmtId("")}); | |
| 417 | try expectFmt("@\"\\x00\"", "{f}", .{fmtId("\x00")}); | |
| 412 | 418 | } |
| 413 | 419 | |
| 414 | /// Print the string as a Zig identifier, escaping it with `@""` syntax if needed. | |
| 415 | fn formatId( | |
| 420 | pub const FormatId = struct { | |
| 416 | 421 | bytes: []const u8, |
| 417 | comptime fmt: []const u8, | |
| 418 | options: std.fmt.FormatOptions, | |
| 419 | writer: anytype, | |
| 420 | ) !void { | |
| 421 | const allow_primitive, const allow_underscore = comptime parse_fmt: { | |
| 422 | var allow_primitive = false; | |
| 423 | var allow_underscore = false; | |
| 424 | for (fmt) |char| { | |
| 425 | switch (char) { | |
| 426 | 'p' => if (!allow_primitive) { | |
| 427 | allow_primitive = true; | |
| 428 | continue; | |
| 429 | }, | |
| 430 | '_' => if (!allow_underscore) { | |
| 431 | allow_underscore = true; | |
| 432 | continue; | |
| 433 | }, | |
| 434 | else => {}, | |
| 435 | } | |
| 436 | @compileError("expected {}, {p}, {_}, {p_} or {_p}, found {" ++ fmt ++ "}"); | |
| 437 | } | |
| 438 | break :parse_fmt .{ allow_primitive, allow_underscore }; | |
| 422 | flags: Flags, | |
| 423 | pub const Flags = struct { | |
| 424 | allow_primitive: bool = false, | |
| 425 | allow_underscore: bool = false, | |
| 439 | 426 | }; |
| 440 | 427 | |
| 441 | if (isValidId(bytes) and | |
| 442 | (allow_primitive or !std.zig.isPrimitive(bytes)) and | |
| 443 | (allow_underscore or !isUnderscore(bytes))) | |
| 444 | { | |
| 445 | return writer.writeAll(bytes); | |
| 428 | /// Print the string as a Zig identifier, escaping it with `@""` syntax if needed. | |
| 429 | fn render(ctx: FormatId, writer: *std.io.Writer) std.io.Writer.Error!void { | |
| 430 | const bytes = ctx.bytes; | |
| 431 | if (isValidId(bytes) and | |
| 432 | (ctx.flags.allow_primitive or !std.zig.isPrimitive(bytes)) and | |
| 433 | (ctx.flags.allow_underscore or !isUnderscore(bytes))) | |
| 434 | { | |
| 435 | return writer.writeAll(bytes); | |
| 436 | } | |
| 437 | try writer.writeAll("@\""); | |
| 438 | try stringEscape(bytes, writer); | |
| 439 | try writer.writeByte('"'); | |
| 446 | 440 | } |
| 447 | try writer.writeAll("@\""); | |
| 448 | try stringEscape(bytes, "", options, writer); | |
| 449 | try writer.writeByte('"'); | |
| 441 | }; | |
| 442 | ||
| 443 | /// Return a formatter for escaping a double quoted Zig string. | |
| 444 | pub fn fmtString(bytes: []const u8) std.fmt.Formatter([]const u8, stringEscape) { | |
| 445 | return .{ .data = bytes }; | |
| 450 | 446 | } |
| 451 | 447 | |
| 452 | /// Return a Formatter for Zig Escapes of a double quoted string. | |
| 453 | /// The format specifier must be one of: | |
| 454 | /// * `{}` treats contents as a double-quoted string. | |
| 455 | /// * `{'}` treats contents as a single-quoted string. | |
| 456 | pub fn fmtEscapes(bytes: []const u8) std.fmt.Formatter(stringEscape) { | |
| 448 | /// Return a formatter for escaping a single quoted Zig string. | |
| 449 | pub fn fmtChar(bytes: []const u8) std.fmt.Formatter([]const u8, charEscape) { | |
| 457 | 450 | return .{ .data = bytes }; |
| 458 | 451 | } |
| 459 | 452 | |
| 460 | test fmtEscapes { | |
| 461 | const expectFmt = std.testing.expectFmt; | |
| 462 | try expectFmt("\\x0f", "{}", .{fmtEscapes("\x0f")}); | |
| 463 | try expectFmt( | |
| 464 | \\" \\ hi \x07 \x11 " derp \'" | |
| 465 | , "\"{'}\"", .{fmtEscapes(" \\ hi \x07 \x11 \" derp '")}); | |
| 466 | try expectFmt( | |
| 453 | test fmtString { | |
| 454 | try std.testing.expectFmt("\\x0f", "{f}", .{fmtString("\x0f")}); | |
| 455 | try std.testing.expectFmt( | |
| 467 | 456 | \\" \\ hi \x07 \x11 \" derp '" |
| 468 | , "\"{}\"", .{fmtEscapes(" \\ hi \x07 \x11 \" derp '")}); | |
| 457 | , "\"{f}\"", .{fmtString(" \\ hi \x07 \x11 \" derp '")}); | |
| 469 | 458 | } |
| 470 | 459 | |
| 471 | /// Print the string as escaped contents of a double quoted or single-quoted string. | |
| 472 | /// Format `{}` treats contents as a double-quoted string. | |
| 473 | /// Format `{'}` treats contents as a single-quoted string. | |
| 474 | pub fn stringEscape( | |
| 475 | bytes: []const u8, | |
| 476 | comptime f: []const u8, | |
| 477 | options: std.fmt.FormatOptions, | |
| 478 | writer: anytype, | |
| 479 | ) !void { | |
| 480 | _ = options; | |
| 460 | test fmtChar { | |
| 461 | try std.testing.expectFmt( | |
| 462 | \\" \\ hi \x07 \x11 " derp \'" | |
| 463 | , "\"{f}\"", .{fmtChar(" \\ hi \x07 \x11 \" derp '")}); | |
| 464 | } | |
| 465 | ||
| 466 | /// Print the string as escaped contents of a double quoted string. | |
| 467 | pub fn stringEscape(bytes: []const u8, w: *std.io.Writer) std.io.Writer.Error!void { | |
| 481 | 468 | for (bytes) |byte| switch (byte) { |
| 482 | '\n' => try writer.writeAll("\\n"), | |
| 483 | '\r' => try writer.writeAll("\\r"), | |
| 484 | '\t' => try writer.writeAll("\\t"), | |
| 485 | '\\' => try writer.writeAll("\\\\"), | |
| 486 | '"' => { | |
| 487 | if (f.len == 1 and f[0] == '\'') { | |
| 488 | try writer.writeByte('"'); | |
| 489 | } else if (f.len == 0) { | |
| 490 | try writer.writeAll("\\\""); | |
| 491 | } else { | |
| 492 | @compileError("expected {} or {'}, found {" ++ f ++ "}"); | |
| 493 | } | |
| 494 | }, | |
| 495 | '\'' => { | |
| 496 | if (f.len == 1 and f[0] == '\'') { | |
| 497 | try writer.writeAll("\\'"); | |
| 498 | } else if (f.len == 0) { | |
| 499 | try writer.writeByte('\''); | |
| 500 | } else { | |
| 501 | @compileError("expected {} or {'}, found {" ++ f ++ "}"); | |
| 502 | } | |
| 469 | '\n' => try w.writeAll("\\n"), | |
| 470 | '\r' => try w.writeAll("\\r"), | |
| 471 | '\t' => try w.writeAll("\\t"), | |
| 472 | '\\' => try w.writeAll("\\\\"), | |
| 473 | '"' => try w.writeAll("\\\""), | |
| 474 | '\'' => try w.writeByte('\''), | |
| 475 | ' ', '!', '#'...'&', '('...'[', ']'...'~' => try w.writeByte(byte), | |
| 476 | else => { | |
| 477 | try w.writeAll("\\x"); | |
| 478 | try w.printInt(byte, 16, .lower, .{ .width = 2, .fill = '0' }); | |
| 503 | 479 | }, |
| 504 | ' ', '!', '#'...'&', '('...'[', ']'...'~' => try writer.writeByte(byte), | |
| 505 | // Use hex escapes for rest any unprintable characters. | |
| 480 | }; | |
| 481 | } | |
| 482 | ||
| 483 | /// Print the string as escaped contents of a single-quoted string. | |
| 484 | pub 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 | 493 | else => { |
| 507 | try writer.writeAll("\\x"); | |
| 508 | try std.fmt.formatInt(byte, 16, .lower, .{ .width = 2, .fill = '0' }, writer); | |
| 494 | try w.writeAll("\\x"); | |
| 495 | try w.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 | 565 | |
| 566 | 566 | .invalid_byte => { |
| 567 | 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 | 569 | switch (tok_slice[0]) { |
| 570 | 570 | '\'' => "character literal", |
| 571 | 571 | '"', '\\' => "string literal", |
| 572 | 572 | '/' => "comment", |
| 573 | 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 | }, |
| 578 | 578 |
lib/std/zig/AstGen.zig+1-7| ... | ... | @@ -11305,13 +11305,7 @@ fn failWithStrLitError( |
| 11305 | 11305 | offset: u32, |
| 11306 | 11306 | ) InnerError { |
| 11307 | 11307 | const raw_string = bytes[offset..]; |
| 11308 | return failOff( | |
| 11309 | astgen, | |
| 11310 | token, | |
| 11311 | @intCast(offset + err.offset()), | |
| 11312 | "{}", | |
| 11313 | .{err.fmt(raw_string)}, | |
| 11314 | ); | |
| 11308 | return failOff(astgen, token, @intCast(offset + err.offset()), "{f}", .{err.fmt(raw_string)}); | |
| 11315 | 11309 | } |
| 11316 | 11310 | |
| 11317 | 11311 | fn failNode( |
lib/std/zig/ErrorBundle.zig+81-71| ... | ... | @@ -7,6 +7,12 @@ |
| 7 | 7 | //! empty, it means there are no errors. This special encoding exists so that |
| 8 | 8 | //! heap allocation is not needed in the common case of no errors. |
| 9 | 9 | |
| 10 | const std = @import("std"); | |
| 11 | const ErrorBundle = @This(); | |
| 12 | const Allocator = std.mem.Allocator; | |
| 13 | const assert = std.debug.assert; | |
| 14 | const Writer = std.io.Writer; | |
| 15 | ||
| 10 | 16 | string_bytes: []const u8, |
| 11 | 17 | /// The first thing in this array is an `ErrorMessageList`. |
| 12 | 18 | extra: []const u32, |
| ... | ... | @@ -157,23 +163,23 @@ pub const RenderOptions = struct { |
| 157 | 163 | }; |
| 158 | 164 | |
| 159 | 165 | pub fn renderToStdErr(eb: ErrorBundle, options: RenderOptions) void { |
| 160 | std.debug.lockStdErr(); | |
| 161 | defer std.debug.unlockStdErr(); | |
| 162 | const stderr = std.io.getStdErr(); | |
| 163 | return renderToWriter(eb, options, stderr.writer()) catch return; | |
| 166 | var buffer: [256]u8 = undefined; | |
| 167 | const w = std.debug.lockStderrWriter(&buffer); | |
| 168 | defer std.debug.unlockStderrWriter(); | |
| 169 | renderToWriter(eb, options, w) catch return; | |
| 164 | 170 | } |
| 165 | 171 | |
| 166 | pub fn renderToWriter(eb: ErrorBundle, options: RenderOptions, writer: anytype) anyerror!void { | |
| 172 | pub fn renderToWriter(eb: ErrorBundle, options: RenderOptions, w: *Writer) (Writer.Error || std.posix.UnexpectedError)!void { | |
| 167 | 173 | if (eb.extra.len == 0) return; |
| 168 | 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 | } |
| 171 | 177 | |
| 172 | 178 | if (options.include_log_text) { |
| 173 | 179 | const log_text = eb.getCompileLogOutput(); |
| 174 | 180 | if (log_text.len != 0) { |
| 175 | try writer.writeAll("\nCompile Log Output:\n"); | |
| 176 | try writer.writeAll(log_text); | |
| 181 | try w.writeAll("\nCompile Log Output:\n"); | |
| 182 | try w.writeAll(log_text); | |
| 177 | 183 | } |
| 178 | 184 | } |
| 179 | 185 | } |
| ... | ... | @@ -182,74 +188,81 @@ fn renderErrorMessageToWriter( |
| 182 | 188 | eb: ErrorBundle, |
| 183 | 189 | options: RenderOptions, |
| 184 | 190 | err_msg_index: MessageIndex, |
| 185 | stderr: anytype, | |
| 191 | w: *Writer, | |
| 186 | 192 | kind: []const u8, |
| 187 | 193 | color: std.io.tty.Color, |
| 188 | 194 | indent: usize, |
| 189 | ) anyerror!void { | |
| 195 | ) (Writer.Error || std.posix.UnexpectedError)!void { | |
| 190 | 196 | const ttyconf = options.ttyconf; |
| 191 | var counting_writer = std.io.countingWriter(stderr); | |
| 192 | const counting_stderr = counting_writer.writer(); | |
| 193 | 197 | const err_msg = eb.getErrorMessage(err_msg_index); |
| 194 | 198 | if (err_msg.src_loc != .none) { |
| 195 | 199 | const src = eb.extraData(SourceLocation, @intFromEnum(err_msg.src_loc)); |
| 196 | try counting_stderr.writeByteNTimes(' ', indent); | |
| 197 | try ttyconf.setColor(stderr, .bold); | |
| 198 | try counting_stderr.print("{s}:{d}:{d}: ", .{ | |
| 200 | var prefix: std.io.Writer.Discarding = .init(&.{}); | |
| 201 | try w.splatByteAll(' ', indent); | |
| 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 | 210 | eb.nullTerminatedString(src.data.src_path), |
| 200 | 211 | src.data.line + 1, |
| 201 | 212 | src.data.column + 1, |
| 202 | 213 | }); |
| 203 | try ttyconf.setColor(stderr, color); | |
| 204 | try counting_stderr.writeAll(kind); | |
| 205 | try counting_stderr.writeAll(": "); | |
| 214 | try ttyconf.setColor(w, color); | |
| 215 | try w.writeAll(kind); | |
| 216 | prefix.count += kind.len; | |
| 217 | try w.writeAll(": "); | |
| 218 | prefix.count += 2; | |
| 206 | 219 | // This is the length of the part before the error message: |
| 207 | 220 | // e.g. "file.zig:4:5: error: " |
| 208 | const prefix_len: usize = @intCast(counting_stderr.context.bytes_written); | |
| 209 | try ttyconf.setColor(stderr, .reset); | |
| 210 | try ttyconf.setColor(stderr, .bold); | |
| 221 | const prefix_len: usize = @intCast(prefix.count); | |
| 222 | try ttyconf.setColor(w, .reset); | |
| 223 | try ttyconf.setColor(w, .bold); | |
| 211 | 224 | if (err_msg.count == 1) { |
| 212 | try writeMsg(eb, err_msg, stderr, prefix_len); | |
| 213 | try stderr.writeByte('\n'); | |
| 225 | try writeMsg(eb, err_msg, w, prefix_len); | |
| 226 | try w.writeByte('\n'); | |
| 214 | 227 | } else { |
| 215 | try writeMsg(eb, err_msg, stderr, prefix_len); | |
| 216 | try ttyconf.setColor(stderr, .dim); | |
| 217 | try stderr.print(" ({d} times)\n", .{err_msg.count}); | |
| 228 | try writeMsg(eb, err_msg, w, prefix_len); | |
| 229 | try ttyconf.setColor(w, .dim); | |
| 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 | 233 | if (src.data.source_line != 0 and options.include_source_line) { |
| 221 | 234 | const line = eb.nullTerminatedString(src.data.source_line); |
| 222 | 235 | for (line) |b| switch (b) { |
| 223 | '\t' => try stderr.writeByte(' '), | |
| 224 | else => try stderr.writeByte(b), | |
| 236 | '\t' => try w.writeByte(' '), | |
| 237 | else => try w.writeByte(b), | |
| 225 | 238 | }; |
| 226 | try stderr.writeByte('\n'); | |
| 239 | try w.writeByte('\n'); | |
| 227 | 240 | // TODO basic unicode code point monospace width |
| 228 | 241 | const before_caret = src.data.span_main - src.data.span_start; |
| 229 | 242 | // -1 since span.main includes the caret |
| 230 | 243 | const after_caret = src.data.span_end -| src.data.span_main -| 1; |
| 231 | try stderr.writeByteNTimes(' ', src.data.column - before_caret); | |
| 232 | try ttyconf.setColor(stderr, .green); | |
| 233 | try stderr.writeByteNTimes('~', before_caret); | |
| 234 | try stderr.writeByte('^'); | |
| 235 | try stderr.writeByteNTimes('~', after_caret); | |
| 236 | try stderr.writeByte('\n'); | |
| 237 | try ttyconf.setColor(stderr, .reset); | |
| 244 | try w.splatByteAll(' ', src.data.column - before_caret); | |
| 245 | try ttyconf.setColor(w, .green); | |
| 246 | try w.splatByteAll('~', before_caret); | |
| 247 | try w.writeByte('^'); | |
| 248 | try w.splatByteAll('~', after_caret); | |
| 249 | try w.writeByte('\n'); | |
| 250 | try ttyconf.setColor(w, .reset); | |
| 238 | 251 | } |
| 239 | 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 | 255 | if (src.data.reference_trace_len > 0 and options.include_reference_trace) { |
| 243 | try ttyconf.setColor(stderr, .reset); | |
| 244 | try ttyconf.setColor(stderr, .dim); | |
| 245 | try stderr.print("referenced by:\n", .{}); | |
| 256 | try ttyconf.setColor(w, .reset); | |
| 257 | try ttyconf.setColor(w, .dim); | |
| 258 | try w.print("referenced by:\n", .{}); | |
| 246 | 259 | var ref_index = src.end; |
| 247 | 260 | for (0..src.data.reference_trace_len) |_| { |
| 248 | 261 | const ref_trace = eb.extraData(ReferenceTrace, ref_index); |
| 249 | 262 | ref_index = ref_trace.end; |
| 250 | 263 | if (ref_trace.data.src_loc != .none) { |
| 251 | 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 | 266 | eb.nullTerminatedString(ref_trace.data.decl_name), |
| 254 | 267 | eb.nullTerminatedString(ref_src.src_path), |
| 255 | 268 | ref_src.line + 1, |
| ... | ... | @@ -257,36 +270,36 @@ fn renderErrorMessageToWriter( |
| 257 | 270 | }); |
| 258 | 271 | } else if (ref_trace.data.decl_name != 0) { |
| 259 | 272 | const count = ref_trace.data.decl_name; |
| 260 | try stderr.print( | |
| 273 | try w.print( | |
| 261 | 274 | " {d} reference(s) hidden; use '-freference-trace={d}' to see all references\n", |
| 262 | 275 | .{ count, count + src.data.reference_trace_len - 1 }, |
| 263 | 276 | ); |
| 264 | 277 | } else { |
| 265 | try stderr.print( | |
| 278 | try w.print( | |
| 266 | 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 | 286 | } else { |
| 274 | try ttyconf.setColor(stderr, color); | |
| 275 | try stderr.writeByteNTimes(' ', indent); | |
| 276 | try stderr.writeAll(kind); | |
| 277 | try stderr.writeAll(": "); | |
| 278 | try ttyconf.setColor(stderr, .reset); | |
| 287 | try ttyconf.setColor(w, color); | |
| 288 | try w.splatByteAll(' ', indent); | |
| 289 | try w.writeAll(kind); | |
| 290 | try w.writeAll(": "); | |
| 291 | try ttyconf.setColor(w, .reset); | |
| 279 | 292 | const msg = eb.nullTerminatedString(err_msg.msg); |
| 280 | 293 | if (err_msg.count == 1) { |
| 281 | try stderr.print("{s}\n", .{msg}); | |
| 294 | try w.print("{s}\n", .{msg}); | |
| 282 | 295 | } else { |
| 283 | try stderr.print("{s}", .{msg}); | |
| 284 | try ttyconf.setColor(stderr, .dim); | |
| 285 | try stderr.print(" ({d} times)\n", .{err_msg.count}); | |
| 296 | try w.print("{s}", .{msg}); | |
| 297 | try ttyconf.setColor(w, .dim); | |
| 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 | 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 | 308 | /// to allow for long, good-looking error messages. |
| 296 | 309 | /// |
| 297 | 310 | /// This is used to split the message in `@compileError("hello\nworld")` for example. |
| 298 | fn writeMsg(eb: ErrorBundle, err_msg: ErrorMessage, stderr: anytype, indent: usize) !void { | |
| 311 | fn writeMsg(eb: ErrorBundle, err_msg: ErrorMessage, w: *Writer, indent: usize) !void { | |
| 299 | 312 | var lines = std.mem.splitScalar(u8, eb.nullTerminatedString(err_msg.msg), '\n'); |
| 300 | 313 | while (lines.next()) |line| { |
| 301 | try stderr.writeAll(line); | |
| 314 | try w.writeAll(line); | |
| 302 | 315 | if (lines.index == null) break; |
| 303 | try stderr.writeByte('\n'); | |
| 304 | try stderr.writeByteNTimes(' ', indent); | |
| 316 | try w.writeByte('\n'); | |
| 317 | try w.splatByteAll(' ', indent); | |
| 305 | 318 | } |
| 306 | 319 | } |
| 307 | 320 | |
| 308 | const std = @import("std"); | |
| 309 | const ErrorBundle = @This(); | |
| 310 | const Allocator = std.mem.Allocator; | |
| 311 | const assert = std.debug.assert; | |
| 312 | ||
| 313 | 321 | pub const Wip = struct { |
| 314 | 322 | gpa: Allocator, |
| 315 | 323 | string_bytes: std.ArrayListUnmanaged(u8), |
| ... | ... | @@ -398,7 +406,7 @@ pub const Wip = struct { |
| 398 | 406 | pub fn printString(wip: *Wip, comptime fmt: []const u8, args: anytype) Allocator.Error!String { |
| 399 | 407 | const gpa = wip.gpa; |
| 400 | 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 | 410 | try wip.string_bytes.append(gpa, 0); |
| 403 | 411 | return index; |
| 404 | 412 | } |
| ... | ... | @@ -788,9 +796,10 @@ pub const Wip = struct { |
| 788 | 796 | |
| 789 | 797 | const ttyconf: std.io.tty.Config = .no_color; |
| 790 | 798 | |
| 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 | 801 | defer bundle_buf.deinit(); |
| 793 | try bundle.renderToWriter(.{ .ttyconf = ttyconf }, bundle_buf.writer()); | |
| 802 | try bundle.renderToWriter(.{ .ttyconf = ttyconf }, bundle_bw); | |
| 794 | 803 | |
| 795 | 804 | var copy = copy: { |
| 796 | 805 | var wip: ErrorBundle.Wip = undefined; |
| ... | ... | @@ -803,10 +812,11 @@ pub const Wip = struct { |
| 803 | 812 | }; |
| 804 | 813 | defer copy.deinit(std.testing.allocator); |
| 805 | 814 | |
| 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 | 817 | defer copy_buf.deinit(); |
| 808 | try copy.renderToWriter(.{ .ttyconf = ttyconf }, copy_buf.writer()); | |
| 818 | try copy.renderToWriter(.{ .ttyconf = ttyconf }, copy_bw); | |
| 809 | 819 | |
| 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 | 756 | raw_string: []const u8, |
| 757 | 757 | offset: u32, |
| 758 | 758 | ) Allocator.Error!void { |
| 759 | return ZonGen.addErrorTokOff( | |
| 760 | zg, | |
| 761 | token, | |
| 762 | @intCast(offset + err.offset()), | |
| 763 | "{}", | |
| 764 | .{err.fmt(raw_string)}, | |
| 765 | ); | |
| 759 | return ZonGen.addErrorTokOff(zg, token, @intCast(offset + err.offset()), "{f}", .{err.fmt(raw_string)}); | |
| 766 | 760 | } |
| 767 | 761 | |
| 768 | 762 | fn 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 | const std = @import("../../std.zig"); | |
| 2 | const Allocator = std.mem.Allocator; | |
| 3 | const assert = std.debug.assert; | |
| 4 | const bitcode_writer = @import("bitcode_writer.zig"); | |
| 5 | const Builder = @This(); | |
| 6 | const builtin = @import("builtin"); | |
| 7 | const DW = std.dwarf; | |
| 8 | const ir = @import("ir.zig"); | |
| 9 | const log = std.log.scoped(.llvm); | |
| 10 | const Writer = std.io.Writer; | |
| 11 | ||
| 1 | 12 | gpa: Allocator, |
| 2 | 13 | strip: bool, |
| 3 | 14 | |
| ... | ... | @@ -90,31 +101,38 @@ pub const String = enum(u32) { |
| 90 | 101 | const FormatData = struct { |
| 91 | 102 | string: String, |
| 92 | 103 | builder: *const Builder, |
| 104 | quote_behavior: ?QuoteBehavior, | |
| 93 | 105 | }; |
| 94 | fn format( | |
| 95 | data: FormatData, | |
| 96 | comptime fmt_str: []const u8, | |
| 97 | _: std.fmt.FormatOptions, | |
| 98 | writer: anytype, | |
| 99 | ) @TypeOf(writer).Error!void { | |
| 100 | if (comptime std.mem.indexOfNone(u8, fmt_str, "\"r")) |_| | |
| 101 | @compileError("invalid format string: '" ++ fmt_str ++ "'"); | |
| 106 | fn format(data: FormatData, w: *Writer) Writer.Error!void { | |
| 102 | 107 | assert(data.string != .none); |
| 103 | 108 | const string_slice = data.string.slice(data.builder) orelse |
| 104 | return writer.print("{d}", .{@intFromEnum(data.string)}); | |
| 105 | if (comptime std.mem.indexOfScalar(u8, fmt_str, 'r')) |_| | |
| 106 | return writer.writeAll(string_slice); | |
| 107 | try printEscapedString( | |
| 108 | string_slice, | |
| 109 | if (comptime std.mem.indexOfScalar(u8, fmt_str, '"')) |_| | |
| 110 | .always_quote | |
| 111 | else | |
| 112 | .quote_unless_valid_identifier, | |
| 113 | writer, | |
| 114 | ); | |
| 109 | return w.print("{d}", .{@intFromEnum(data.string)}); | |
| 110 | const quote_behavior = data.quote_behavior orelse return w.writeAll(string_slice); | |
| 111 | return printEscapedString(string_slice, quote_behavior, w); | |
| 112 | } | |
| 113 | ||
| 114 | pub fn fmt(self: String, builder: *const Builder) std.fmt.Formatter(FormatData, format) { | |
| 115 | return .{ .data = .{ | |
| 116 | .string = self, | |
| 117 | .builder = builder, | |
| 118 | .quote_behavior = .quote_unless_valid_identifier, | |
| 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) { | |
| 117 | return .{ .data = .{ .string = self, .builder = builder } }; | |
| 129 | ||
| 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 | } |
| 119 | 137 | |
| 120 | 138 | fn fromIndex(index: ?usize) String { |
| ... | ... | @@ -228,7 +246,7 @@ pub const Type = enum(u32) { |
| 228 | 246 | _, |
| 229 | 247 | |
| 230 | 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(" ")})); | |
| 232 | 250 | |
| 233 | 251 | pub const Tag = enum(u4) { |
| 234 | 252 | simple, |
| ... | ... | @@ -653,18 +671,16 @@ pub const Type = enum(u32) { |
| 653 | 671 | const FormatData = struct { |
| 654 | 672 | type: Type, |
| 655 | 673 | builder: *const Builder, |
| 674 | mode: Mode, | |
| 675 | ||
| 676 | const Mode = enum { default, m, lt, gt, percent }; | |
| 656 | 677 | }; |
| 657 | fn format( | |
| 658 | data: FormatData, | |
| 659 | comptime fmt_str: []const u8, | |
| 660 | fmt_opts: std.fmt.FormatOptions, | |
| 661 | writer: anytype, | |
| 662 | ) @TypeOf(writer).Error!void { | |
| 678 | fn format(data: FormatData, w: *Writer) Writer.Error!void { | |
| 663 | 679 | assert(data.type != .none); |
| 664 | if (comptime std.mem.eql(u8, fmt_str, "m")) { | |
| 680 | if (data.mode == .m) { | |
| 665 | 681 | const item = data.builder.type_items.items[@intFromEnum(data.type)]; |
| 666 | 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 | 684 | .void => "isVoid", |
| 669 | 685 | .half => "f16", |
| 670 | 686 | .bfloat => "bf16", |
| ... | ... | @@ -681,36 +697,36 @@ pub const Type = enum(u32) { |
| 681 | 697 | .function, .vararg_function => |kind| { |
| 682 | 698 | var extra = data.builder.typeExtraDataTrail(Type.Function, item.data); |
| 683 | 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)}); | |
| 685 | for (params) |param| try writer.print("{m}", .{param.fmt(data.builder)}); | |
| 700 | try w.print("f_{f}", .{extra.data.ret.fmt(data.builder, .m)}); | |
| 701 | for (params) |param| try w.print("{f}", .{param.fmt(data.builder, .m)}); | |
| 686 | 702 | switch (kind) { |
| 687 | 703 | .function => {}, |
| 688 | .vararg_function => try writer.writeAll("vararg"), | |
| 704 | .vararg_function => try w.writeAll("vararg"), | |
| 689 | 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}), | |
| 694 | .pointer => try writer.print("p{d}", .{item.data}), | |
| 709 | .integer => try w.print("i{d}", .{item.data}), | |
| 710 | .pointer => try w.print("p{d}", .{item.data}), | |
| 695 | 711 | .target => { |
| 696 | 712 | var extra = data.builder.typeExtraDataTrail(Type.Target, item.data); |
| 697 | 713 | const types = extra.trail.next(extra.data.types_len, Type, data.builder); |
| 698 | 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).?}); | |
| 700 | for (types) |ty| try writer.print("_{m}", .{ty.fmt(data.builder)}); | |
| 701 | for (ints) |int| try writer.print("_{d}", .{int}); | |
| 702 | try writer.writeByte('t'); | |
| 715 | try w.print("t{s}", .{extra.data.name.slice(data.builder).?}); | |
| 716 | for (types) |ty| try w.print("_{f}", .{ty.fmt(data.builder, .m)}); | |
| 717 | for (ints) |int| try w.print("_{d}", .{int}); | |
| 718 | try w.writeByte('t'); | |
| 703 | 719 | }, |
| 704 | 720 | .vector, .scalable_vector => |kind| { |
| 705 | 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 | 723 | switch (kind) { |
| 708 | 724 | .vector => "", |
| 709 | 725 | .scalable_vector => "nx", |
| 710 | 726 | else => unreachable, |
| 711 | 727 | }, |
| 712 | 728 | extra.len, |
| 713 | extra.child.fmt(data.builder), | |
| 729 | extra.child.fmt(data.builder, .m), | |
| 714 | 730 | }); |
| 715 | 731 | }, |
| 716 | 732 | inline .small_array, .array => |kind| { |
| ... | ... | @@ -719,72 +735,72 @@ pub const Type = enum(u32) { |
| 719 | 735 | .array => Type.Array, |
| 720 | 736 | else => unreachable, |
| 721 | 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 | 740 | .structure, .packed_structure => { |
| 725 | 741 | var extra = data.builder.typeExtraDataTrail(Type.Structure, item.data); |
| 726 | 742 | const fields = extra.trail.next(extra.data.fields_len, Type, data.builder); |
| 727 | try writer.writeAll("sl_"); | |
| 728 | for (fields) |field| try writer.print("{m}", .{field.fmt(data.builder)}); | |
| 729 | try writer.writeByte('s'); | |
| 743 | try w.writeAll("sl_"); | |
| 744 | for (fields) |field| try w.print("{f}", .{field.fmt(data.builder, .m)}); | |
| 745 | try w.writeByte('s'); | |
| 730 | 746 | }, |
| 731 | 747 | .named_structure => { |
| 732 | 748 | const extra = data.builder.typeExtraData(Type.NamedStructure, item.data); |
| 733 | try writer.writeAll("s_"); | |
| 734 | if (extra.id.slice(data.builder)) |id| try writer.writeAll(id); | |
| 749 | try w.writeAll("s_"); | |
| 750 | if (extra.id.slice(data.builder)) |id| try w.writeAll(id); | |
| 735 | 751 | }, |
| 736 | 752 | } |
| 737 | 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 | 756 | const item = data.builder.type_items.items[@intFromEnum(data.type)]; |
| 741 | 757 | switch (item.tag) { |
| 742 | 758 | .simple => unreachable, |
| 743 | 759 | .function, .vararg_function => |kind| { |
| 744 | 760 | var extra = data.builder.typeExtraDataTrail(Type.Function, item.data); |
| 745 | 761 | const params = extra.trail.next(extra.data.params_len, Type, data.builder); |
| 746 | if (!comptime std.mem.eql(u8, fmt_str, ">")) | |
| 747 | try writer.print("{%} ", .{extra.data.ret.fmt(data.builder)}); | |
| 748 | if (!comptime std.mem.eql(u8, fmt_str, "<")) { | |
| 749 | try writer.writeByte('('); | |
| 762 | if (data.mode != .gt) | |
| 763 | try w.print("{f} ", .{extra.data.ret.fmt(data.builder, .percent)}); | |
| 764 | if (data.mode != .lt) { | |
| 765 | try w.writeByte('('); | |
| 750 | 766 | for (params, 0..) |param, index| { |
| 751 | if (index > 0) try writer.writeAll(", "); | |
| 752 | try writer.print("{%}", .{param.fmt(data.builder)}); | |
| 767 | if (index > 0) try w.writeAll(", "); | |
| 768 | try w.print("{f}", .{param.fmt(data.builder, .percent)}); | |
| 753 | 769 | } |
| 754 | 770 | switch (kind) { |
| 755 | 771 | .function => {}, |
| 756 | 772 | .vararg_function => { |
| 757 | if (params.len > 0) try writer.writeAll(", "); | |
| 758 | try writer.writeAll("..."); | |
| 773 | if (params.len > 0) try w.writeAll(", "); | |
| 774 | try w.writeAll("..."); | |
| 759 | 775 | }, |
| 760 | 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}), | |
| 766 | .pointer => try writer.print("ptr{ }", .{@as(AddrSpace, @enumFromInt(item.data))}), | |
| 781 | .integer => try w.print("i{d}", .{item.data}), | |
| 782 | .pointer => try w.print("ptr{f}", .{@as(AddrSpace, @enumFromInt(item.data)).fmt(" ")}), | |
| 767 | 783 | .target => { |
| 768 | 784 | var extra = data.builder.typeExtraDataTrail(Type.Target, item.data); |
| 769 | 785 | const types = extra.trail.next(extra.data.types_len, Type, data.builder); |
| 770 | 786 | const ints = extra.trail.next(extra.data.ints_len, u32, data.builder); |
| 771 | try writer.print( | |
| 772 | \\target({"} | |
| 773 | , .{extra.data.name.fmt(data.builder)}); | |
| 774 | for (types) |ty| try writer.print(", {%}", .{ty.fmt(data.builder)}); | |
| 775 | for (ints) |int| try writer.print(", {d}", .{int}); | |
| 776 | try writer.writeByte(')'); | |
| 787 | try w.print( | |
| 788 | \\target({f} | |
| 789 | , .{extra.data.name.fmtQ(data.builder)}); | |
| 790 | for (types) |ty| try w.print(", {f}", .{ty.fmt(data.builder, .percent)}); | |
| 791 | for (ints) |int| try w.print(", {d}", .{int}); | |
| 792 | try w.writeByte(')'); | |
| 777 | 793 | }, |
| 778 | 794 | .vector, .scalable_vector => |kind| { |
| 779 | 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 | 797 | switch (kind) { |
| 782 | 798 | .vector => "", |
| 783 | 799 | .scalable_vector => "vscale x ", |
| 784 | 800 | else => unreachable, |
| 785 | 801 | }, |
| 786 | 802 | extra.len, |
| 787 | extra.child.fmt(data.builder), | |
| 803 | extra.child.fmt(data.builder, .percent), | |
| 788 | 804 | }); |
| 789 | 805 | }, |
| 790 | 806 | inline .small_array, .array => |kind| { |
| ... | ... | @@ -793,44 +809,45 @@ pub const Type = enum(u32) { |
| 793 | 809 | .array => Type.Array, |
| 794 | 810 | else => unreachable, |
| 795 | 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 | 814 | .structure, .packed_structure => |kind| { |
| 799 | 815 | var extra = data.builder.typeExtraDataTrail(Type.Structure, item.data); |
| 800 | 816 | const fields = extra.trail.next(extra.data.fields_len, Type, data.builder); |
| 801 | 817 | switch (kind) { |
| 802 | 818 | .structure => {}, |
| 803 | .packed_structure => try writer.writeByte('<'), | |
| 819 | .packed_structure => try w.writeByte('<'), | |
| 804 | 820 | else => unreachable, |
| 805 | 821 | } |
| 806 | try writer.writeAll("{ "); | |
| 822 | try w.writeAll("{ "); | |
| 807 | 823 | for (fields, 0..) |field, index| { |
| 808 | if (index > 0) try writer.writeAll(", "); | |
| 809 | try writer.print("{%}", .{field.fmt(data.builder)}); | |
| 824 | if (index > 0) try w.writeAll(", "); | |
| 825 | try w.print("{f}", .{field.fmt(data.builder, .percent)}); | |
| 810 | 826 | } |
| 811 | try writer.writeAll(" }"); | |
| 827 | try w.writeAll(" }"); | |
| 812 | 828 | switch (kind) { |
| 813 | 829 | .structure => {}, |
| 814 | .packed_structure => try writer.writeByte('>'), | |
| 830 | .packed_structure => try w.writeByte('>'), | |
| 815 | 831 | else => unreachable, |
| 816 | 832 | } |
| 817 | 833 | }, |
| 818 | 834 | .named_structure => { |
| 819 | 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 | 837 | extra.id.fmt(data.builder), |
| 822 | 838 | }) else switch (extra.body) { |
| 823 | .none => try writer.writeAll("opaque"), | |
| 839 | .none => try w.writeAll("opaque"), | |
| 824 | 840 | else => try format(.{ |
| 825 | 841 | .type = extra.body, |
| 826 | 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) { | |
| 833 | return .{ .data = .{ .type = self, .builder = builder } }; | |
| 849 | pub fn fmt(self: Type, builder: *const Builder, mode: FormatData.Mode) std.fmt.Formatter(FormatData, format) { | |
| 850 | return .{ .data = .{ .type = self, .builder = builder, .mode = mode } }; | |
| 834 | 851 | } |
| 835 | 852 | |
| 836 | 853 | const IsSizedVisited = std.AutoHashMapUnmanaged(Type, void); |
| ... | ... | @@ -1138,15 +1155,13 @@ pub const Attribute = union(Kind) { |
| 1138 | 1155 | const FormatData = struct { |
| 1139 | 1156 | attribute_index: Index, |
| 1140 | 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( | |
| 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 ++ "'"); | |
| 1164 | fn format(data: FormatData, w: *Writer) Writer.Error!void { | |
| 1150 | 1165 | const attribute = data.attribute_index.toAttribute(data.builder); |
| 1151 | 1166 | switch (attribute) { |
| 1152 | 1167 | .zeroext, |
| ... | ... | @@ -1219,97 +1234,99 @@ pub const Attribute = union(Kind) { |
| 1219 | 1234 | .no_sanitize_address, |
| 1220 | 1235 | .no_sanitize_hwaddress, |
| 1221 | 1236 | .sanitize_address_dyninit, |
| 1222 | => try writer.print(" {s}", .{@tagName(attribute)}), | |
| 1237 | => try w.print(" {s}", .{@tagName(attribute)}), | |
| 1223 | 1238 | .byval, |
| 1224 | 1239 | .byref, |
| 1225 | 1240 | .preallocated, |
| 1226 | 1241 | .inalloca, |
| 1227 | 1242 | .sret, |
| 1228 | 1243 | .elementtype, |
| 1229 | => |ty| try writer.print(" {s}({%})", .{ @tagName(attribute), ty.fmt(data.builder) }), | |
| 1230 | .@"align" => |alignment| try writer.print("{ }", .{alignment}), | |
| 1244 | => |ty| try w.print(" {s}({f})", .{ @tagName(attribute), ty.fmt(data.builder, .percent) }), | |
| 1245 | .@"align" => |alignment| try w.print("{f}", .{alignment.fmt(" ")}), | |
| 1231 | 1246 | .dereferenceable, |
| 1232 | 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 | 1249 | .nofpclass => |fpclass| { |
| 1235 | 1250 | const Int = @typeInfo(FpClass).@"struct".backing_integer.?; |
| 1236 | try writer.print(" {s}(", .{@tagName(attribute)}); | |
| 1251 | try w.print(" {s}(", .{@tagName(attribute)}); | |
| 1237 | 1252 | var any = false; |
| 1238 | 1253 | var remaining: Int = @bitCast(fpclass); |
| 1239 | 1254 | inline for (@typeInfo(FpClass).@"struct".decls) |decl| { |
| 1240 | 1255 | const pattern: Int = @bitCast(@field(FpClass, decl.name)); |
| 1241 | 1256 | if (remaining & pattern == pattern) { |
| 1242 | 1257 | if (!any) { |
| 1243 | try writer.writeByte(' '); | |
| 1258 | try w.writeByte(' '); | |
| 1244 | 1259 | any = true; |
| 1245 | 1260 | } |
| 1246 | try writer.writeAll(decl.name); | |
| 1261 | try w.writeAll(decl.name); | |
| 1247 | 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 | 1276 | .allockind => |allockind| { |
| 1260 | try writer.print(" {s}(\"", .{@tagName(attribute)}); | |
| 1277 | try w.print(" {t}(\"", .{attribute}); | |
| 1261 | 1278 | var any = false; |
| 1262 | 1279 | inline for (@typeInfo(AllocKind).@"struct".fields) |field| { |
| 1263 | 1280 | if (comptime std.mem.eql(u8, field.name, "_")) continue; |
| 1264 | 1281 | if (@field(allockind, field.name)) { |
| 1265 | 1282 | if (!any) { |
| 1266 | try writer.writeByte(','); | |
| 1283 | try w.writeByte(','); | |
| 1267 | 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 | 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 | 1293 | if (allocsize.num_elems != AllocSize.none) |
| 1277 | try writer.print(",{d}", .{allocsize.num_elems}); | |
| 1278 | try writer.writeByte(')'); | |
| 1294 | try w.print(",{d}", .{allocsize.num_elems}); | |
| 1295 | try w.writeByte(')'); | |
| 1279 | 1296 | }, |
| 1280 | 1297 | .memory => |memory| { |
| 1281 | try writer.print(" {s}(", .{@tagName(attribute)}); | |
| 1298 | try w.print(" {t}(", .{attribute}); | |
| 1282 | 1299 | var any = memory.other != .none or |
| 1283 | 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 | 1302 | inline for (.{ "argmem", "inaccessiblemem" }) |kind| { |
| 1286 | 1303 | if (@field(memory, kind) != memory.other) { |
| 1287 | if (any) try writer.writeAll(", "); | |
| 1288 | try writer.print("{s}: {s}", .{ kind, @tagName(@field(memory, kind)) }); | |
| 1304 | if (any) try w.writeAll(", "); | |
| 1305 | try w.print("{s}: {s}", .{ kind, @tagName(@field(memory, kind)) }); | |
| 1289 | 1306 | any = true; |
| 1290 | 1307 | } |
| 1291 | 1308 | } |
| 1292 | try writer.writeByte(')'); | |
| 1309 | try w.writeByte(')'); | |
| 1293 | 1310 | }, |
| 1294 | 1311 | .uwtable => |uwtable| if (uwtable != .none) { |
| 1295 | try writer.print(" {s}", .{@tagName(attribute)}); | |
| 1296 | if (uwtable != UwTable.default) try writer.print("({s})", .{@tagName(uwtable)}); | |
| 1312 | try w.print(" {s}", .{@tagName(attribute)}); | |
| 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 | 1316 | @tagName(attribute), |
| 1300 | 1317 | vscale_range.min.toByteUnits().?, |
| 1301 | 1318 | vscale_range.max.toByteUnits() orelse 0, |
| 1302 | 1319 | }), |
| 1303 | .string => |string_attr| if (comptime std.mem.indexOfScalar(u8, fmt_str, '"') != null) { | |
| 1304 | try writer.print(" {\"}", .{string_attr.kind.fmt(data.builder)}); | |
| 1320 | .string => |string_attr| if (data.flags.quote) { | |
| 1321 | try w.print(" {f}", .{string_attr.kind.fmtQ(data.builder)}); | |
| 1305 | 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 | 1325 | .none => unreachable, |
| 1309 | 1326 | } |
| 1310 | 1327 | } |
| 1311 | pub fn fmt(self: Index, builder: *const Builder) std.fmt.Formatter(format) { | |
| 1312 | return .{ .data = .{ .attribute_index = self, .builder = builder } }; | |
| 1328 | pub fn fmt(self: Index, builder: *const Builder, mode: FormatData.mode) std.fmt.Formatter(FormatData, format) { | |
| 1329 | return .{ .data = .{ .attribute_index = self, .builder = builder, .mode = mode } }; | |
| 1313 | 1330 | } |
| 1314 | 1331 | |
| 1315 | 1332 | fn toStorage(self: Index, builder: *const Builder) Storage { |
| ... | ... | @@ -1582,20 +1599,18 @@ pub const Attributes = enum(u32) { |
| 1582 | 1599 | const FormatData = struct { |
| 1583 | 1600 | attributes: Attributes, |
| 1584 | 1601 | builder: *const Builder, |
| 1602 | flags: Flags = .{}, | |
| 1603 | const Flags = Attribute.Index.FormatData.Flags; | |
| 1585 | 1604 | }; |
| 1586 | fn format( | |
| 1587 | data: FormatData, | |
| 1588 | comptime fmt_str: []const u8, | |
| 1589 | fmt_opts: std.fmt.FormatOptions, | |
| 1590 | writer: anytype, | |
| 1591 | ) @TypeOf(writer).Error!void { | |
| 1605 | fn format(data: FormatData, w: *Writer) Writer.Error!void { | |
| 1592 | 1606 | for (data.attributes.slice(data.builder)) |attribute_index| try Attribute.Index.format(.{ |
| 1593 | 1607 | .attribute_index = attribute_index, |
| 1594 | 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) { | |
| 1598 | return .{ .data = .{ .attributes = self, .builder = builder } }; | |
| 1612 | pub fn fmt(self: Attributes, builder: *const Builder, flags: FormatData.Flags) std.fmt.Formatter(FormatData, format) { | |
| 1613 | return .{ .data = .{ .attributes = self, .builder = builder, .flags = flags } }; | |
| 1599 | 1614 | } |
| 1600 | 1615 | }; |
| 1601 | 1616 | |
| ... | ... | @@ -1781,24 +1796,14 @@ pub const Linkage = enum(u4) { |
| 1781 | 1796 | extern_weak = 7, |
| 1782 | 1797 | external = 0, |
| 1783 | 1798 | |
| 1784 | pub fn format( | |
| 1785 | self: Linkage, | |
| 1786 | comptime _: []const u8, | |
| 1787 | _: std.fmt.FormatOptions, | |
| 1788 | writer: anytype, | |
| 1789 | ) @TypeOf(writer).Error!void { | |
| 1790 | if (self != .external) try writer.print(" {s}", .{@tagName(self)}); | |
| 1799 | pub fn format(self: Linkage, w: *Writer) Writer.Error!void { | |
| 1800 | if (self != .external) try w.print(" {s}", .{@tagName(self)}); | |
| 1791 | 1801 | } |
| 1792 | 1802 | |
| 1793 | fn formatOptional( | |
| 1794 | data: ?Linkage, | |
| 1795 | comptime _: []const u8, | |
| 1796 | _: std.fmt.FormatOptions, | |
| 1797 | writer: anytype, | |
| 1798 | ) @TypeOf(writer).Error!void { | |
| 1799 | if (data) |linkage| try writer.print(" {s}", .{@tagName(linkage)}); | |
| 1803 | fn formatOptional(data: ?Linkage, w: *Writer) Writer.Error!void { | |
| 1804 | if (data) |linkage| try w.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 | 1807 | return .{ .data = self }; |
| 1803 | 1808 | } |
| 1804 | 1809 | }; |
| ... | ... | @@ -1808,13 +1813,8 @@ pub const Preemption = enum { |
| 1808 | 1813 | dso_local, |
| 1809 | 1814 | implicit_dso_local, |
| 1810 | 1815 | |
| 1811 | pub fn format( | |
| 1812 | self: Preemption, | |
| 1813 | comptime _: []const u8, | |
| 1814 | _: std.fmt.FormatOptions, | |
| 1815 | writer: anytype, | |
| 1816 | ) @TypeOf(writer).Error!void { | |
| 1817 | if (self == .dso_local) try writer.print(" {s}", .{@tagName(self)}); | |
| 1816 | pub fn format(self: Preemption, w: *Writer) Writer.Error!void { | |
| 1817 | if (self == .dso_local) try w.print(" {s}", .{@tagName(self)}); | |
| 1818 | 1818 | } |
| 1819 | 1819 | }; |
| 1820 | 1820 | |
| ... | ... | @@ -1831,12 +1831,7 @@ pub const Visibility = enum(u2) { |
| 1831 | 1831 | }; |
| 1832 | 1832 | } |
| 1833 | 1833 | |
| 1834 | pub fn format( | |
| 1835 | self: Visibility, | |
| 1836 | comptime _: []const u8, | |
| 1837 | _: std.fmt.FormatOptions, | |
| 1838 | writer: anytype, | |
| 1839 | ) @TypeOf(writer).Error!void { | |
| 1834 | pub fn format(self: Visibility, writer: *Writer) Writer.Error!void { | |
| 1840 | 1835 | if (self != .default) try writer.print(" {s}", .{@tagName(self)}); |
| 1841 | 1836 | } |
| 1842 | 1837 | }; |
| ... | ... | @@ -1846,13 +1841,8 @@ pub const DllStorageClass = enum(u2) { |
| 1846 | 1841 | dllimport = 1, |
| 1847 | 1842 | dllexport = 2, |
| 1848 | 1843 | |
| 1849 | pub fn format( | |
| 1850 | self: DllStorageClass, | |
| 1851 | comptime _: []const u8, | |
| 1852 | _: std.fmt.FormatOptions, | |
| 1853 | writer: anytype, | |
| 1854 | ) @TypeOf(writer).Error!void { | |
| 1855 | if (self != .default) try writer.print(" {s}", .{@tagName(self)}); | |
| 1844 | pub fn format(self: DllStorageClass, w: *Writer) Writer.Error!void { | |
| 1845 | if (self != .default) try w.print(" {s}", .{@tagName(self)}); | |
| 1856 | 1846 | } |
| 1857 | 1847 | }; |
| 1858 | 1848 | |
| ... | ... | @@ -1863,15 +1853,31 @@ pub const ThreadLocal = enum(u3) { |
| 1863 | 1853 | initialexec = 3, |
| 1864 | 1854 | localexec = 4, |
| 1865 | 1855 | |
| 1866 | pub fn format( | |
| 1867 | self: ThreadLocal, | |
| 1868 | comptime prefix: []const u8, | |
| 1869 | _: std.fmt.FormatOptions, | |
| 1870 | writer: anytype, | |
| 1871 | ) @TypeOf(writer).Error!void { | |
| 1872 | if (self == .default) return; | |
| 1873 | try writer.print("{s}thread_local", .{prefix}); | |
| 1874 | if (self != .generaldynamic) try writer.print("({s})", .{@tagName(self)}); | |
| 1856 | pub fn format(tl: ThreadLocal, w: *Writer) Writer.Error!void { | |
| 1857 | return Prefixed.format(.{ .thread_local = tl, .prefix = "" }, w); | |
| 1858 | } | |
| 1859 | ||
| 1860 | pub const Prefixed = struct { | |
| 1861 | thread_local: ThreadLocal, | |
| 1862 | prefix: []const u8, | |
| 1863 | ||
| 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 | }; |
| 1877 | 1883 | |
| ... | ... | @@ -1882,13 +1888,8 @@ pub const UnnamedAddr = enum(u2) { |
| 1882 | 1888 | unnamed_addr = 1, |
| 1883 | 1889 | local_unnamed_addr = 2, |
| 1884 | 1890 | |
| 1885 | pub fn format( | |
| 1886 | self: UnnamedAddr, | |
| 1887 | comptime _: []const u8, | |
| 1888 | _: std.fmt.FormatOptions, | |
| 1889 | writer: anytype, | |
| 1890 | ) @TypeOf(writer).Error!void { | |
| 1891 | if (self != .default) try writer.print(" {s}", .{@tagName(self)}); | |
| 1891 | pub fn format(self: UnnamedAddr, w: *Writer) Writer.Error!void { | |
| 1892 | if (self != .default) try w.print(" {s}", .{@tagName(self)}); | |
| 1892 | 1893 | } |
| 1893 | 1894 | }; |
| 1894 | 1895 | |
| ... | ... | @@ -1981,13 +1982,24 @@ pub const AddrSpace = enum(u24) { |
| 1981 | 1982 | pub const funcref: AddrSpace = @enumFromInt(20); |
| 1982 | 1983 | }; |
| 1983 | 1984 | |
| 1984 | pub fn format( | |
| 1985 | self: AddrSpace, | |
| 1986 | comptime prefix: []const u8, | |
| 1987 | _: std.fmt.FormatOptions, | |
| 1988 | writer: anytype, | |
| 1989 | ) @TypeOf(writer).Error!void { | |
| 1990 | if (self != .default) try writer.print("{s}addrspace({d})", .{ prefix, @intFromEnum(self) }); | |
| 1985 | pub fn format(addr_space: AddrSpace, w: *Writer) Writer.Error!void { | |
| 1986 | return Prefixed.format(.{ .addr_space = addr_space, .prefix = "" }, w); | |
| 1987 | } | |
| 1988 | ||
| 1989 | pub const Prefixed = struct { | |
| 1990 | addr_space: AddrSpace, | |
| 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 | }; |
| 1993 | 2005 | |
| ... | ... | @@ -1995,15 +2007,8 @@ pub const ExternallyInitialized = enum { |
| 1995 | 2007 | default, |
| 1996 | 2008 | externally_initialized, |
| 1997 | 2009 | |
| 1998 | pub fn format( | |
| 1999 | self: ExternallyInitialized, | |
| 2000 | comptime _: []const u8, | |
| 2001 | _: std.fmt.FormatOptions, | |
| 2002 | writer: anytype, | |
| 2003 | ) @TypeOf(writer).Error!void { | |
| 2004 | if (self == .default) return; | |
| 2005 | try writer.writeByte(' '); | |
| 2006 | try writer.writeAll(@tagName(self)); | |
| 2010 | pub fn format(self: ExternallyInitialized, w: *Writer) Writer.Error!void { | |
| 2011 | if (self != .default) try w.print(" {s}", .{@tagName(self)}); | |
| 2007 | 2012 | } |
| 2008 | 2013 | }; |
| 2009 | 2014 | |
| ... | ... | @@ -2026,13 +2031,18 @@ pub const Alignment = enum(u6) { |
| 2026 | 2031 | return if (self == .default) 0 else (@intFromEnum(self) + 1); |
| 2027 | 2032 | } |
| 2028 | 2033 | |
| 2029 | pub fn format( | |
| 2030 | self: Alignment, | |
| 2031 | comptime prefix: []const u8, | |
| 2032 | _: std.fmt.FormatOptions, | |
| 2033 | writer: anytype, | |
| 2034 | ) @TypeOf(writer).Error!void { | |
| 2035 | try writer.print("{s}align {d}", .{ prefix, self.toByteUnits() orelse return }); | |
| 2034 | pub const Prefixed = struct { | |
| 2035 | alignment: Alignment, | |
| 2036 | prefix: []const u8, | |
| 2037 | ||
| 2038 | pub fn format(p: Prefixed, w: *Writer) Writer.Error!void { | |
| 2039 | const byte_units = p.alignment.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 | }; |
| 2038 | 2048 | |
| ... | ... | @@ -2105,12 +2115,7 @@ pub const CallConv = enum(u10) { |
| 2105 | 2115 | |
| 2106 | 2116 | pub const default = CallConv.ccc; |
| 2107 | 2117 | |
| 2108 | pub fn format( | |
| 2109 | self: CallConv, | |
| 2110 | comptime _: []const u8, | |
| 2111 | _: std.fmt.FormatOptions, | |
| 2112 | writer: anytype, | |
| 2113 | ) @TypeOf(writer).Error!void { | |
| 2118 | pub fn format(self: CallConv, w: *Writer) Writer.Error!void { | |
| 2114 | 2119 | switch (self) { |
| 2115 | 2120 | default => {}, |
| 2116 | 2121 | .fastcc, |
| ... | ... | @@ -2164,8 +2169,8 @@ pub const CallConv = enum(u10) { |
| 2164 | 2169 | .aarch64_sme_preservemost_from_x2, |
| 2165 | 2170 | .m68k_rtdcc, |
| 2166 | 2171 | .riscv_vectorcallcc, |
| 2167 | => try writer.print(" {s}", .{@tagName(self)}), | |
| 2168 | _ => try writer.print(" cc{d}", .{@intFromEnum(self)}), | |
| 2172 | => try w.print(" {s}", .{@tagName(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 | 2195 | const FormatData = struct { |
| 2191 | 2196 | string: StrtabString, |
| 2192 | 2197 | builder: *const Builder, |
| 2198 | quote_behavior: ?QuoteBehavior, | |
| 2193 | 2199 | }; |
| 2194 | fn format( | |
| 2195 | data: FormatData, | |
| 2196 | comptime fmt_str: []const u8, | |
| 2197 | _: std.fmt.FormatOptions, | |
| 2198 | writer: anytype, | |
| 2199 | ) @TypeOf(writer).Error!void { | |
| 2200 | if (comptime std.mem.indexOfNone(u8, fmt_str, "\"r")) |_| | |
| 2201 | @compileError("invalid format string: '" ++ fmt_str ++ "'"); | |
| 2200 | fn format(data: FormatData, w: *Writer) Writer.Error!void { | |
| 2202 | 2201 | assert(data.string != .none); |
| 2203 | 2202 | const string_slice = data.string.slice(data.builder) orelse |
| 2204 | return writer.print("{d}", .{@intFromEnum(data.string)}); | |
| 2205 | if (comptime std.mem.indexOfScalar(u8, fmt_str, 'r')) |_| | |
| 2206 | return writer.writeAll(string_slice); | |
| 2207 | try printEscapedString( | |
| 2208 | string_slice, | |
| 2209 | if (comptime std.mem.indexOfScalar(u8, fmt_str, '"')) |_| | |
| 2210 | .always_quote | |
| 2211 | else | |
| 2212 | .quote_unless_valid_identifier, | |
| 2213 | writer, | |
| 2214 | ); | |
| 2203 | return w.print("{d}", .{@intFromEnum(data.string)}); | |
| 2204 | const quote_behavior = data.quote_behavior orelse return w.writeAll(string_slice); | |
| 2205 | return printEscapedString(string_slice, quote_behavior, w); | |
| 2215 | 2206 | } |
| 2216 | pub fn fmt(self: StrtabString, builder: *const Builder) std.fmt.Formatter(format) { | |
| 2217 | return .{ .data = .{ .string = self, .builder = builder } }; | |
| 2207 | pub fn fmt( | |
| 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 | } |
| 2219 | 2218 | |
| 2220 | 2219 | fn fromIndex(index: ?usize) StrtabString { |
| ... | ... | @@ -2264,7 +2263,7 @@ pub fn strtabStringFmt(self: *Builder, comptime fmt_str: []const u8, fmt_args: a |
| 2264 | 2263 | } |
| 2265 | 2264 | |
| 2266 | 2265 | pub 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 | 2267 | return self.trailingStrtabStringAssumeCapacity(); |
| 2269 | 2268 | } |
| 2270 | 2269 | |
| ... | ... | @@ -2383,17 +2382,12 @@ pub const Global = struct { |
| 2383 | 2382 | global: Index, |
| 2384 | 2383 | builder: *const Builder, |
| 2385 | 2384 | }; |
| 2386 | fn format( | |
| 2387 | data: FormatData, | |
| 2388 | comptime _: []const u8, | |
| 2389 | _: std.fmt.FormatOptions, | |
| 2390 | writer: anytype, | |
| 2391 | ) @TypeOf(writer).Error!void { | |
| 2392 | try writer.print("@{}", .{ | |
| 2393 | data.global.unwrap(data.builder).name(data.builder).fmt(data.builder), | |
| 2385 | fn format(data: FormatData, w: *Writer) Writer.Error!void { | |
| 2386 | try w.print("@{f}", .{ | |
| 2387 | data.global.unwrap(data.builder).name(data.builder).fmt(data.builder, null), | |
| 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 | 2391 | return .{ .data = .{ .global = self, .builder = builder } }; |
| 2398 | 2392 | } |
| 2399 | 2393 | |
| ... | ... | @@ -4833,29 +4827,23 @@ pub const Function = struct { |
| 4833 | 4827 | instruction: Instruction.Index, |
| 4834 | 4828 | function: Function.Index, |
| 4835 | 4829 | builder: *Builder, |
| 4830 | flags: FormatFlags, | |
| 4836 | 4831 | }; |
| 4837 | fn format( | |
| 4838 | data: FormatData, | |
| 4839 | comptime fmt_str: []const u8, | |
| 4840 | _: std.fmt.FormatOptions, | |
| 4841 | writer: anytype, | |
| 4842 | ) @TypeOf(writer).Error!void { | |
| 4843 | if (comptime std.mem.indexOfNone(u8, fmt_str, ", %")) |_| | |
| 4844 | @compileError("invalid format string: '" ++ fmt_str ++ "'"); | |
| 4845 | if (comptime std.mem.indexOfScalar(u8, fmt_str, ',') != null) { | |
| 4832 | fn format(data: FormatData, w: *Writer) Writer.Error!void { | |
| 4833 | if (data.flags.comma) { | |
| 4846 | 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 | 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( | |
| 4854 | "{%} ", | |
| 4855 | .{data.instruction.typeOf(data.function, data.builder).fmt(data.builder)}, | |
| 4841 | if (data.flags.percent) try w.print( | |
| 4842 | "{f} ", | |
| 4843 | .{data.instruction.typeOf(data.function, data.builder).fmt(data.builder, .percent)}, | |
| 4856 | 4844 | ); |
| 4857 | 4845 | assert(data.instruction != .none); |
| 4858 | try writer.print("%{}", .{ | |
| 4846 | try w.print("%{f}", .{ | |
| 4859 | 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 | 4851 | self: Instruction.Index, |
| 4864 | 4852 | function: Function.Index, |
| 4865 | 4853 | builder: *Builder, |
| 4866 | ) std.fmt.Formatter(format) { | |
| 4867 | return .{ .data = .{ .instruction = self, .function = function, .builder = builder } }; | |
| 4854 | flags: FormatFlags, | |
| 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 | }; |
| 4870 | 4864 | |
| ... | ... | @@ -6361,10 +6355,10 @@ pub const WipFunction = struct { |
| 6361 | 6355 | |
| 6362 | 6356 | while (true) { |
| 6363 | 6357 | gop.value_ptr.* = @enumFromInt(@intFromEnum(gop.value_ptr.*) + 1); |
| 6364 | const unique_name = try wip_name.builder.fmt("{r}{s}{r}", .{ | |
| 6365 | name.fmt(wip_name.builder), | |
| 6358 | const unique_name = try wip_name.builder.fmt("{f}{s}{f}", .{ | |
| 6359 | name.fmtRaw(wip_name.builder), | |
| 6366 | 6360 | sep, |
| 6367 | gop.value_ptr.fmt(wip_name.builder), | |
| 6361 | gop.value_ptr.fmtRaw(wip_name.builder), | |
| 6368 | 6362 | }); |
| 6369 | 6363 | const unique_gop = try wip_name.next_unique_name.getOrPut(unique_name); |
| 6370 | 6364 | if (!unique_gop.found_existing) { |
| ... | ... | @@ -7031,13 +7025,27 @@ pub const MemoryAccessKind = enum(u1) { |
| 7031 | 7025 | normal, |
| 7032 | 7026 | @"volatile", |
| 7033 | 7027 | |
| 7034 | pub fn format( | |
| 7035 | self: MemoryAccessKind, | |
| 7036 | comptime prefix: []const u8, | |
| 7037 | _: std.fmt.FormatOptions, | |
| 7038 | writer: anytype, | |
| 7039 | ) @TypeOf(writer).Error!void { | |
| 7040 | if (self != .normal) try writer.print("{s}{s}", .{ prefix, @tagName(self) }); | |
| 7028 | pub fn format(memory_access_kind: MemoryAccessKind, w: *Writer) Writer.Error!void { | |
| 7029 | return Prefixed.format(.{ .memory_access_kind = memory_access_kind, .prefix = "" }, w); | |
| 7030 | } | |
| 7031 | ||
| 7032 | pub const Prefixed = struct { | |
| 7033 | memory_access_kind: MemoryAccessKind, | |
| 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 | }; |
| 7043 | 7051 | |
| ... | ... | @@ -7045,15 +7053,27 @@ pub const SyncScope = enum(u1) { |
| 7045 | 7053 | singlethread, |
| 7046 | 7054 | system, |
| 7047 | 7055 | |
| 7048 | pub fn format( | |
| 7049 | self: SyncScope, | |
| 7050 | comptime prefix: []const u8, | |
| 7051 | _: std.fmt.FormatOptions, | |
| 7052 | writer: anytype, | |
| 7053 | ) @TypeOf(writer).Error!void { | |
| 7054 | if (self != .system) try writer.print( | |
| 7055 | \\{s}syncscope("{s}") | |
| 7056 | , .{ prefix, @tagName(self) }); | |
| 7056 | pub fn format(sync_scope: SyncScope, w: *Writer) Writer.Error!void { | |
| 7057 | return Prefixed.format(.{ .sync_scope = sync_scope, .prefix = "" }, w); | |
| 7058 | } | |
| 7059 | ||
| 7060 | pub const Prefixed = struct { | |
| 7061 | sync_scope: SyncScope, | |
| 7062 | prefix: []const u8, | |
| 7063 | ||
| 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 | }; |
| 7059 | 7079 | |
| ... | ... | @@ -7066,13 +7086,27 @@ pub const AtomicOrdering = enum(u3) { |
| 7066 | 7086 | acq_rel = 5, |
| 7067 | 7087 | seq_cst = 6, |
| 7068 | 7088 | |
| 7069 | pub fn format( | |
| 7070 | self: AtomicOrdering, | |
| 7071 | comptime prefix: []const u8, | |
| 7072 | _: std.fmt.FormatOptions, | |
| 7073 | writer: anytype, | |
| 7074 | ) @TypeOf(writer).Error!void { | |
| 7075 | if (self != .none) try writer.print("{s}{s}", .{ prefix, @tagName(self) }); | |
| 7089 | pub fn format(atomic_ordering: AtomicOrdering, w: *Writer) Writer.Error!void { | |
| 7090 | return Prefixed.format(.{ .atomic_ordering = atomic_ordering, .prefix = "" }, w); | |
| 7091 | } | |
| 7092 | ||
| 7093 | pub const Prefixed = struct { | |
| 7094 | atomic_ordering: AtomicOrdering, | |
| 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 | }; |
| 7078 | 7112 | |
| ... | ... | @@ -7486,27 +7520,21 @@ pub const Constant = enum(u32) { |
| 7486 | 7520 | const FormatData = struct { |
| 7487 | 7521 | constant: Constant, |
| 7488 | 7522 | builder: *Builder, |
| 7523 | flags: FormatFlags, | |
| 7489 | 7524 | }; |
| 7490 | fn format( | |
| 7491 | data: FormatData, | |
| 7492 | comptime fmt_str: []const u8, | |
| 7493 | _: std.fmt.FormatOptions, | |
| 7494 | writer: anytype, | |
| 7495 | ) @TypeOf(writer).Error!void { | |
| 7496 | if (comptime std.mem.indexOfNone(u8, fmt_str, ", %")) |_| | |
| 7497 | @compileError("invalid format string: '" ++ fmt_str ++ "'"); | |
| 7498 | if (comptime std.mem.indexOfScalar(u8, fmt_str, ',') != null) { | |
| 7525 | fn format(data: FormatData, w: *Writer) Writer.Error!void { | |
| 7526 | if (data.flags.comma) { | |
| 7499 | 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 | 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) | |
| 7507 | try writer.print("{%} ", .{data.constant.typeOf(data.builder).fmt(data.builder)}); | |
| 7534 | if (data.flags.percent) | |
| 7535 | try w.print("{f} ", .{data.constant.typeOf(data.builder).fmt(data.builder, .percent)}); | |
| 7508 | 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 | 7538 | switch (data.constant.unwrap()) { |
| 7511 | 7539 | .constant => |constant| { |
| 7512 | 7540 | const item = data.builder.constant_items.get(constant); |
| ... | ... | @@ -7543,13 +7571,13 @@ pub const Constant = enum(u32) { |
| 7543 | 7571 | var stack align(@alignOf(ExpectedContents)) = |
| 7544 | 7572 | std.heap.stackFallback(@sizeOf(ExpectedContents), data.builder.gpa); |
| 7545 | 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 | 7575 | defer allocator.free(str); |
| 7548 | try writer.writeAll(str); | |
| 7576 | try w.writeAll(str); | |
| 7549 | 7577 | }, |
| 7550 | 7578 | .half, |
| 7551 | 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 | 7581 | .half => 'H', |
| 7554 | 7582 | .bfloat => 'R', |
| 7555 | 7583 | else => unreachable, |
| ... | ... | @@ -7580,7 +7608,7 @@ pub const Constant = enum(u32) { |
| 7580 | 7608 | ) + 1, |
| 7581 | 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 | 7612 | .mantissa = std.math.shl( |
| 7585 | 7613 | Mantissa64, |
| 7586 | 7614 | repr.mantissa, |
| ... | ... | @@ -7602,13 +7630,13 @@ pub const Constant = enum(u32) { |
| 7602 | 7630 | }, |
| 7603 | 7631 | .double => { |
| 7604 | 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 | 7635 | .fp128, |
| 7608 | 7636 | .ppc_fp128, |
| 7609 | 7637 | => |tag| { |
| 7610 | 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 | 7640 | @as(u8, switch (tag) { |
| 7613 | 7641 | .fp128 => 'L', |
| 7614 | 7642 | .ppc_fp128 => 'M', |
| ... | ... | @@ -7622,7 +7650,7 @@ pub const Constant = enum(u32) { |
| 7622 | 7650 | }, |
| 7623 | 7651 | .x86_fp80 => { |
| 7624 | 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 | 7654 | extra.hi, extra.lo_hi, extra.lo_lo, |
| 7627 | 7655 | }); |
| 7628 | 7656 | }, |
| ... | ... | @@ -7631,7 +7659,7 @@ pub const Constant = enum(u32) { |
| 7631 | 7659 | .zeroinitializer, |
| 7632 | 7660 | .undef, |
| 7633 | 7661 | .poison, |
| 7634 | => |tag| try writer.writeAll(@tagName(tag)), | |
| 7662 | => |tag| try w.writeAll(@tagName(tag)), | |
| 7635 | 7663 | .structure, |
| 7636 | 7664 | .packed_structure, |
| 7637 | 7665 | .array, |
| ... | ... | @@ -7640,7 +7668,7 @@ pub const Constant = enum(u32) { |
| 7640 | 7668 | var extra = data.builder.constantExtraDataTrail(Aggregate, item.data); |
| 7641 | 7669 | const len: u32 = @intCast(extra.data.type.aggregateLen(data.builder)); |
| 7642 | 7670 | const vals = extra.trail.next(len, Constant, data.builder); |
| 7643 | try writer.writeAll(switch (tag) { | |
| 7671 | try w.writeAll(switch (tag) { | |
| 7644 | 7672 | .structure => "{ ", |
| 7645 | 7673 | .packed_structure => "<{ ", |
| 7646 | 7674 | .array => "[", |
| ... | ... | @@ -7648,10 +7676,10 @@ pub const Constant = enum(u32) { |
| 7648 | 7676 | else => unreachable, |
| 7649 | 7677 | }); |
| 7650 | 7678 | for (vals, 0..) |val, index| { |
| 7651 | if (index > 0) try writer.writeAll(", "); | |
| 7652 | try writer.print("{%}", .{val.fmt(data.builder)}); | |
| 7679 | if (index > 0) try w.writeAll(", "); | |
| 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 | 7683 | .structure => " }", |
| 7656 | 7684 | .packed_structure => " }>", |
| 7657 | 7685 | .array => "]", |
| ... | ... | @@ -7662,30 +7690,30 @@ pub const Constant = enum(u32) { |
| 7662 | 7690 | .splat => { |
| 7663 | 7691 | const extra = data.builder.constantExtraData(Splat, item.data); |
| 7664 | 7692 | const len = extra.type.vectorLen(data.builder); |
| 7665 | try writer.writeByte('<'); | |
| 7693 | try w.writeByte('<'); | |
| 7666 | 7694 | for (0..len) |index| { |
| 7667 | if (index > 0) try writer.writeAll(", "); | |
| 7668 | try writer.print("{%}", .{extra.value.fmt(data.builder)}); | |
| 7695 | if (index > 0) try w.writeAll(", "); | |
| 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{\"}", .{ | |
| 7673 | @as(String, @enumFromInt(item.data)).fmt(data.builder), | |
| 7700 | .string => try w.print("c{f}", .{ | |
| 7701 | @as(String, @enumFromInt(item.data)).fmtQ(data.builder), | |
| 7674 | 7702 | }), |
| 7675 | 7703 | .blockaddress => |tag| { |
| 7676 | 7704 | const extra = data.builder.constantExtraData(BlockAddress, item.data); |
| 7677 | 7705 | const function = extra.function.ptrConst(data.builder); |
| 7678 | try writer.print("{s}({}, {})", .{ | |
| 7706 | try w.print("{s}({f}, {f})", .{ | |
| 7679 | 7707 | @tagName(tag), |
| 7680 | 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 | 7712 | .dso_local_equivalent, |
| 7685 | 7713 | .no_cfi, |
| 7686 | 7714 | => |tag| { |
| 7687 | 7715 | const function: Function.Index = @enumFromInt(item.data); |
| 7688 | try writer.print("{s} {}", .{ | |
| 7716 | try w.print("{s} {f}", .{ | |
| 7689 | 7717 | @tagName(tag), |
| 7690 | 7718 | function.ptrConst(data.builder).global.fmt(data.builder), |
| 7691 | 7719 | }); |
| ... | ... | @@ -7697,10 +7725,10 @@ pub const Constant = enum(u32) { |
| 7697 | 7725 | .addrspacecast, |
| 7698 | 7726 | => |tag| { |
| 7699 | 7727 | const extra = data.builder.constantExtraData(Cast, item.data); |
| 7700 | try writer.print("{s} ({%} to {%})", .{ | |
| 7728 | try w.print("{s} ({f} to {f})", .{ | |
| 7701 | 7729 | @tagName(tag), |
| 7702 | extra.val.fmt(data.builder), | |
| 7703 | extra.type.fmt(data.builder), | |
| 7730 | extra.val.fmt(data.builder, .{ .percent = true }), | |
| 7731 | extra.type.fmt(data.builder, .percent), | |
| 7704 | 7732 | }); |
| 7705 | 7733 | }, |
| 7706 | 7734 | .getelementptr, |
| ... | ... | @@ -7709,13 +7737,13 @@ pub const Constant = enum(u32) { |
| 7709 | 7737 | var extra = data.builder.constantExtraDataTrail(GetElementPtr, item.data); |
| 7710 | 7738 | const indices = |
| 7711 | 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 | 7741 | @tagName(tag), |
| 7714 | extra.data.type.fmt(data.builder), | |
| 7715 | extra.data.base.fmt(data.builder), | |
| 7742 | extra.data.type.fmt(data.builder, .percent), | |
| 7743 | extra.data.base.fmt(data.builder, .{ .percent = true }), | |
| 7716 | 7744 | }); |
| 7717 | for (indices) |index| try writer.print(", {%}", .{index.fmt(data.builder)}); | |
| 7718 | try writer.writeByte(')'); | |
| 7745 | for (indices) |index| try w.print(", {f}", .{index.fmt(data.builder, .{ .percent = true })}); | |
| 7746 | try w.writeByte(')'); | |
| 7719 | 7747 | }, |
| 7720 | 7748 | .add, |
| 7721 | 7749 | .@"add nsw", |
| ... | ... | @@ -7727,10 +7755,10 @@ pub const Constant = enum(u32) { |
| 7727 | 7755 | .xor, |
| 7728 | 7756 | => |tag| { |
| 7729 | 7757 | const extra = data.builder.constantExtraData(Binary, item.data); |
| 7730 | try writer.print("{s} ({%}, {%})", .{ | |
| 7758 | try w.print("{s} ({f}, {f})", .{ | |
| 7731 | 7759 | @tagName(tag), |
| 7732 | extra.lhs.fmt(data.builder), | |
| 7733 | extra.rhs.fmt(data.builder), | |
| 7760 | extra.lhs.fmt(data.builder, .{ .percent = true }), | |
| 7761 | extra.rhs.fmt(data.builder, .{ .percent = true }), | |
| 7734 | 7762 | }); |
| 7735 | 7763 | }, |
| 7736 | 7764 | .@"asm", |
| ... | ... | @@ -7751,19 +7779,23 @@ pub const Constant = enum(u32) { |
| 7751 | 7779 | .@"asm sideeffect alignstack inteldialect unwind", |
| 7752 | 7780 | => |tag| { |
| 7753 | 7781 | const extra = data.builder.constantExtraData(Assembly, item.data); |
| 7754 | try writer.print("{s} {\"}, {\"}", .{ | |
| 7782 | try w.print("{s} {f}, {f}", .{ | |
| 7755 | 7783 | @tagName(tag), |
| 7756 | extra.assembly.fmt(data.builder), | |
| 7757 | extra.constraints.fmt(data.builder), | |
| 7784 | extra.assembly.fmtQ(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) { | |
| 7766 | return .{ .data = .{ .constant = self, .builder = builder } }; | |
| 7793 | pub fn fmt(self: Constant, builder: *Builder, flags: FormatFlags) std.fmt.Formatter(FormatData, format) { | |
| 7794 | return .{ .data = .{ | |
| 7795 | .constant = self, | |
| 7796 | .builder = builder, | |
| 7797 | .flags = flags, | |
| 7798 | } }; | |
| 7767 | 7799 | } |
| 7768 | 7800 | }; |
| 7769 | 7801 | |
| ... | ... | @@ -7818,28 +7850,26 @@ pub const Value = enum(u32) { |
| 7818 | 7850 | value: Value, |
| 7819 | 7851 | function: Function.Index, |
| 7820 | 7852 | builder: *Builder, |
| 7853 | flags: FormatFlags, | |
| 7821 | 7854 | }; |
| 7822 | fn format( | |
| 7823 | data: FormatData, | |
| 7824 | comptime fmt_str: []const u8, | |
| 7825 | fmt_opts: std.fmt.FormatOptions, | |
| 7826 | writer: anytype, | |
| 7827 | ) @TypeOf(writer).Error!void { | |
| 7855 | fn format(data: FormatData, w: *Writer) Writer.Error!void { | |
| 7828 | 7856 | switch (data.value.unwrap()) { |
| 7829 | 7857 | .instruction => |instruction| try Function.Instruction.Index.format(.{ |
| 7830 | 7858 | .instruction = instruction, |
| 7831 | 7859 | .function = data.function, |
| 7832 | 7860 | .builder = data.builder, |
| 7833 | }, fmt_str, fmt_opts, writer), | |
| 7861 | .flags = data.flags, | |
| 7862 | }, w), | |
| 7834 | 7863 | .constant => |constant| try Constant.format(.{ |
| 7835 | 7864 | .constant = constant, |
| 7836 | 7865 | .builder = data.builder, |
| 7837 | }, fmt_str, fmt_opts, writer), | |
| 7866 | .flags = data.flags, | |
| 7867 | }, w), | |
| 7838 | 7868 | .metadata => unreachable, |
| 7839 | 7869 | } |
| 7840 | 7870 | } |
| 7841 | pub fn fmt(self: Value, function: Function.Index, builder: *Builder) std.fmt.Formatter(format) { | |
| 7842 | return .{ .data = .{ .value = self, .function = function, .builder = builder } }; | |
| 7871 | pub fn fmt(self: Value, function: Function.Index, builder: *Builder, flags: FormatFlags) std.fmt.Formatter(FormatData, format) { | |
| 7872 | return .{ .data = .{ .value = self, .function = function, .builder = builder, .flags = flags } }; | |
| 7843 | 7873 | } |
| 7844 | 7874 | }; |
| 7845 | 7875 | |
| ... | ... | @@ -7869,15 +7899,10 @@ pub const MetadataString = enum(u32) { |
| 7869 | 7899 | metadata_string: MetadataString, |
| 7870 | 7900 | builder: *const Builder, |
| 7871 | 7901 | }; |
| 7872 | fn format( | |
| 7873 | data: FormatData, | |
| 7874 | comptime _: []const u8, | |
| 7875 | _: std.fmt.FormatOptions, | |
| 7876 | writer: anytype, | |
| 7877 | ) @TypeOf(writer).Error!void { | |
| 7878 | try printEscapedString(data.metadata_string.slice(data.builder), .always_quote, writer); | |
| 7902 | fn format(data: FormatData, w: *Writer) Writer.Error!void { | |
| 7903 | try printEscapedString(data.metadata_string.slice(data.builder), .always_quote, w); | |
| 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 | 7906 | return .{ .data = .{ .metadata_string = self, .builder = builder } }; |
| 7882 | 7907 | } |
| 7883 | 7908 | }; |
| ... | ... | @@ -8039,29 +8064,24 @@ pub const Metadata = enum(u32) { |
| 8039 | 8064 | AllCallsDescribed: bool = false, |
| 8040 | 8065 | Unused: u2 = 0, |
| 8041 | 8066 | |
| 8042 | pub fn format( | |
| 8043 | self: DIFlags, | |
| 8044 | comptime _: []const u8, | |
| 8045 | _: std.fmt.FormatOptions, | |
| 8046 | writer: anytype, | |
| 8047 | ) @TypeOf(writer).Error!void { | |
| 8067 | pub fn format(self: DIFlags, w: *Writer) Writer.Error!void { | |
| 8048 | 8068 | var need_pipe = false; |
| 8049 | 8069 | inline for (@typeInfo(DIFlags).@"struct".fields) |field| { |
| 8050 | 8070 | switch (@typeInfo(field.type)) { |
| 8051 | 8071 | .bool => if (@field(self, field.name)) { |
| 8052 | if (need_pipe) try writer.writeAll(" | ") else need_pipe = true; | |
| 8053 | try writer.print("DIFlag{s}", .{field.name}); | |
| 8072 | if (need_pipe) try w.writeAll(" | ") else need_pipe = true; | |
| 8073 | try w.print("DIFlag{s}", .{field.name}); | |
| 8054 | 8074 | }, |
| 8055 | 8075 | .@"enum" => if (@field(self, field.name) != .Zero) { |
| 8056 | if (need_pipe) try writer.writeAll(" | ") else need_pipe = true; | |
| 8057 | try writer.print("DIFlag{s}", .{@tagName(@field(self, field.name))}); | |
| 8076 | if (need_pipe) try w.writeAll(" | ") else need_pipe = true; | |
| 8077 | try w.print("DIFlag{s}", .{@tagName(@field(self, field.name))}); | |
| 8058 | 8078 | }, |
| 8059 | 8079 | .int => assert(@field(self, field.name) == 0), |
| 8060 | 8080 | else => @compileError("bad field type: " ++ field.name ++ ": " ++ |
| 8061 | 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 | }; |
| 8067 | 8087 | |
| ... | ... | @@ -8101,29 +8121,24 @@ pub const Metadata = enum(u32) { |
| 8101 | 8121 | ObjCDirect: bool = false, |
| 8102 | 8122 | Unused: u20 = 0, |
| 8103 | 8123 | |
| 8104 | pub fn format( | |
| 8105 | self: DISPFlags, | |
| 8106 | comptime _: []const u8, | |
| 8107 | _: std.fmt.FormatOptions, | |
| 8108 | writer: anytype, | |
| 8109 | ) @TypeOf(writer).Error!void { | |
| 8124 | pub fn format(self: DISPFlags, w: *Writer) Writer.Error!void { | |
| 8110 | 8125 | var need_pipe = false; |
| 8111 | 8126 | inline for (@typeInfo(DISPFlags).@"struct".fields) |field| { |
| 8112 | 8127 | switch (@typeInfo(field.type)) { |
| 8113 | 8128 | .bool => if (@field(self, field.name)) { |
| 8114 | if (need_pipe) try writer.writeAll(" | ") else need_pipe = true; | |
| 8115 | try writer.print("DISPFlag{s}", .{field.name}); | |
| 8129 | if (need_pipe) try w.writeAll(" | ") else need_pipe = true; | |
| 8130 | try w.print("DISPFlag{s}", .{field.name}); | |
| 8116 | 8131 | }, |
| 8117 | 8132 | .@"enum" => if (@field(self, field.name) != .Zero) { |
| 8118 | if (need_pipe) try writer.writeAll(" | ") else need_pipe = true; | |
| 8119 | try writer.print("DISPFlag{s}", .{@tagName(@field(self, field.name))}); | |
| 8133 | if (need_pipe) try w.writeAll(" | ") else need_pipe = true; | |
| 8134 | try w.print("DISPFlag{s}", .{@tagName(@field(self, field.name))}); | |
| 8120 | 8135 | }, |
| 8121 | 8136 | .int => assert(@field(self, field.name) == 0), |
| 8122 | 8137 | else => @compileError("bad field type: " ++ field.name ++ ": " ++ |
| 8123 | 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 | }; |
| 8129 | 8144 | |
| ... | ... | @@ -8298,6 +8313,7 @@ pub const Metadata = enum(u32) { |
| 8298 | 8313 | formatter: *Formatter, |
| 8299 | 8314 | prefix: []const u8 = "", |
| 8300 | 8315 | node: Node, |
| 8316 | specialized: ?FormatFlags, | |
| 8301 | 8317 | |
| 8302 | 8318 | const Node = union(enum) { |
| 8303 | 8319 | none, |
| ... | ... | @@ -8323,20 +8339,14 @@ pub const Metadata = enum(u32) { |
| 8323 | 8339 | }; |
| 8324 | 8340 | }; |
| 8325 | 8341 | }; |
| 8326 | fn format( | |
| 8327 | data: FormatData, | |
| 8328 | comptime fmt_str: []const u8, | |
| 8329 | fmt_opts: std.fmt.FormatOptions, | |
| 8330 | writer: anytype, | |
| 8331 | ) @TypeOf(writer).Error!void { | |
| 8342 | fn format(data: FormatData, w: *Writer) Writer.Error!void { | |
| 8332 | 8343 | if (data.node == .none) return; |
| 8333 | 8344 | |
| 8334 | const is_specialized = fmt_str.len > 0 and fmt_str[0] == 'S'; | |
| 8335 | const recurse_fmt_str = if (is_specialized) fmt_str[1..] else fmt_str; | |
| 8345 | const is_specialized = data.specialized != null; | |
| 8336 | 8346 | |
| 8337 | if (data.formatter.need_comma) try writer.writeAll(", "); | |
| 8347 | if (data.formatter.need_comma) try w.writeAll(", "); | |
| 8338 | 8348 | defer data.formatter.need_comma = true; |
| 8339 | try writer.writeAll(data.prefix); | |
| 8349 | try w.writeAll(data.prefix); | |
| 8340 | 8350 | |
| 8341 | 8351 | const builder = data.formatter.builder; |
| 8342 | 8352 | switch (data.node) { |
| ... | ... | @@ -8351,54 +8361,57 @@ pub const Metadata = enum(u32) { |
| 8351 | 8361 | .expression => { |
| 8352 | 8362 | var extra = builder.metadataExtraDataTrail(Expression, item.data); |
| 8353 | 8363 | const elements = extra.trail.next(extra.data.elements_len, u32, builder); |
| 8354 | try writer.writeAll("!DIExpression("); | |
| 8364 | try w.writeAll("!DIExpression("); | |
| 8355 | 8365 | for (elements) |element| try format(.{ |
| 8356 | 8366 | .formatter = data.formatter, |
| 8357 | 8367 | .node = .{ .u64 = element }, |
| 8358 | }, "%", fmt_opts, writer); | |
| 8359 | try writer.writeByte(')'); | |
| 8368 | .specialized = .{ .percent = true }, | |
| 8369 | }, w); | |
| 8370 | try w.writeByte(')'); | |
| 8360 | 8371 | }, |
| 8361 | 8372 | .constant => try Constant.format(.{ |
| 8362 | 8373 | .constant = @enumFromInt(item.data), |
| 8363 | 8374 | .builder = builder, |
| 8364 | }, recurse_fmt_str, fmt_opts, writer), | |
| 8375 | .flags = data.specialized orelse .{}, | |
| 8376 | }, w), | |
| 8365 | 8377 | else => unreachable, |
| 8366 | 8378 | } |
| 8367 | 8379 | }, |
| 8368 | .index => |node| try writer.print("!{d}", .{node}), | |
| 8380 | .index => |node| try w.print("!{d}", .{node}), | |
| 8369 | 8381 | inline .local_value, .local_metadata => |node, tag| try Value.format(.{ |
| 8370 | 8382 | .value = node.value, |
| 8371 | 8383 | .function = node.function, |
| 8372 | 8384 | .builder = builder, |
| 8373 | }, switch (tag) { | |
| 8374 | .local_value => recurse_fmt_str, | |
| 8375 | .local_metadata => "%", | |
| 8376 | else => unreachable, | |
| 8377 | }, fmt_opts, writer), | |
| 8385 | .flags = switch (tag) { | |
| 8386 | .local_value => data.specialized orelse .{}, | |
| 8387 | .local_metadata => .{ .percent = true }, | |
| 8388 | else => unreachable, | |
| 8389 | }, | |
| 8390 | }, w), | |
| 8378 | 8391 | inline .local_inline, .local_index => |node, tag| { |
| 8379 | if (comptime std.mem.eql(u8, recurse_fmt_str, "%")) | |
| 8380 | try writer.print("{%} ", .{Type.metadata.fmt(builder)}); | |
| 8392 | if (data.specialized) |flags| { | |
| 8393 | if (flags.onlyPercent()) { | |
| 8394 | try w.print("{f} ", .{Type.metadata.fmt(builder, .percent)}); | |
| 8395 | } | |
| 8396 | } | |
| 8381 | 8397 | try format(.{ |
| 8382 | 8398 | .formatter = data.formatter, |
| 8383 | 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 "!") ++ "{}", .{ | |
| 8387 | node.fmt(builder), | |
| 8403 | .string => |node| try w.print("{s}{f}", .{ | |
| 8404 | @as([]const u8, if (is_specialized) "" else "!"), node.fmt(builder), | |
| 8388 | 8405 | }), |
| 8389 | inline .bool, | |
| 8390 | .u32, | |
| 8391 | .u64, | |
| 8392 | .di_flags, | |
| 8393 | .sp_flags, | |
| 8394 | => |node| try writer.print("{}", .{node}), | |
| 8395 | .raw => |node| try writer.writeAll(node), | |
| 8406 | inline .bool, .u32, .u64 => |node| try w.print("{}", .{node}), | |
| 8407 | inline .di_flags, .sp_flags => |node| try w.print("{f}", .{node}), | |
| 8408 | .raw => |node| try w.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 | 8412 | Metadata => Allocator.Error, |
| 8400 | 8413 | else => error{}, |
| 8401 | }!std.fmt.Formatter(format) { | |
| 8414 | }!std.fmt.Formatter(FormatData, format) { | |
| 8402 | 8415 | const Node = @TypeOf(node); |
| 8403 | 8416 | const MaybeNode = switch (@typeInfo(Node)) { |
| 8404 | 8417 | .optional => Node, |
| ... | ... | @@ -8435,6 +8448,7 @@ pub const Metadata = enum(u32) { |
| 8435 | 8448 | .optional, .null => .none, |
| 8436 | 8449 | else => unreachable, |
| 8437 | 8450 | }, |
| 8451 | .specialized = special, | |
| 8438 | 8452 | } }; |
| 8439 | 8453 | } |
| 8440 | 8454 | inline fn fmtLocal( |
| ... | ... | @@ -8442,7 +8456,7 @@ pub const Metadata = enum(u32) { |
| 8442 | 8456 | prefix: []const u8, |
| 8443 | 8457 | value: Value, |
| 8444 | 8458 | function: Function.Index, |
| 8445 | ) Allocator.Error!std.fmt.Formatter(format) { | |
| 8459 | ) Allocator.Error!std.fmt.Formatter(FormatData, format) { | |
| 8446 | 8460 | return .{ .data = .{ |
| 8447 | 8461 | .formatter = formatter, |
| 8448 | 8462 | .prefix = prefix, |
| ... | ... | @@ -8467,6 +8481,7 @@ pub const Metadata = enum(u32) { |
| 8467 | 8481 | }; |
| 8468 | 8482 | }, |
| 8469 | 8483 | }, |
| 8484 | .specialized = null, | |
| 8470 | 8485 | } }; |
| 8471 | 8486 | } |
| 8472 | 8487 | fn refUnwrapped(formatter: *Formatter, node: Metadata) Allocator.Error!FormatData.Node { |
| ... | ... | @@ -8506,7 +8521,7 @@ pub const Metadata = enum(u32) { |
| 8506 | 8521 | DIGlobalVariableExpression, |
| 8507 | 8522 | }, |
| 8508 | 8523 | nodes: anytype, |
| 8509 | writer: anytype, | |
| 8524 | w: *Writer, | |
| 8510 | 8525 | ) !void { |
| 8511 | 8526 | comptime var fmt_str: []const u8 = ""; |
| 8512 | 8527 | const names = comptime std.meta.fieldNames(@TypeOf(nodes)); |
| ... | ... | @@ -8523,10 +8538,10 @@ pub const Metadata = enum(u32) { |
| 8523 | 8538 | } |
| 8524 | 8539 | fmt_str = fmt_str ++ "("; |
| 8525 | 8540 | inline for (fields[2..], names) |*field, name| { |
| 8526 | fmt_str = fmt_str ++ "{[" ++ name ++ "]S}"; | |
| 8541 | fmt_str = fmt_str ++ "{[" ++ name ++ "]f}"; | |
| 8527 | 8542 | field.* = .{ |
| 8528 | 8543 | .name = name, |
| 8529 | .type = std.fmt.Formatter(format), | |
| 8544 | .type = std.fmt.Formatter(FormatData, format), | |
| 8530 | 8545 | .default_value_ptr = null, |
| 8531 | 8546 | .is_comptime = false, |
| 8532 | 8547 | .alignment = 0, |
| ... | ... | @@ -8545,8 +8560,9 @@ pub const Metadata = enum(u32) { |
| 8545 | 8560 | inline for (names) |name| @field(fmt_args, name) = try formatter.fmt( |
| 8546 | 8561 | name ++ ": ", |
| 8547 | 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 | 8652 | inline for (.{ 0, 4 }) |addr_space_index| { |
| 8637 | 8653 | const addr_space: AddrSpace = @enumFromInt(addr_space_index); |
| 8638 | 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 | } |
| 8642 | 8658 | |
| ... | ... | @@ -8759,16 +8775,8 @@ pub fn deinit(self: *Builder) void { |
| 8759 | 8775 | self.* = undefined; |
| 8760 | 8776 | } |
| 8761 | 8777 | |
| 8762 | pub fn setModuleAsm(self: *Builder) std.ArrayListUnmanaged(u8).Writer { | |
| 8763 | self.module_asm.clearRetainingCapacity(); | |
| 8764 | return self.appendModuleAsm(); | |
| 8765 | } | |
| 8766 | ||
| 8767 | pub fn appendModuleAsm(self: *Builder) std.ArrayListUnmanaged(u8).Writer { | |
| 8768 | return self.module_asm.writer(self.gpa); | |
| 8769 | } | |
| 8770 | ||
| 8771 | pub fn finishModuleAsm(self: *Builder) Allocator.Error!void { | |
| 8778 | pub fn finishModuleAsm(self: *Builder, aw: *Writer.Allocating) Allocator.Error!void { | |
| 8779 | self.module_asm = aw.toArrayList(); | |
| 8772 | 8780 | if (self.module_asm.getLastOrNull()) |last| if (last != '\n') |
| 8773 | 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 | 8812 | } |
| 8805 | 8813 | |
| 8806 | 8814 | pub 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 | 8816 | return self.trailingStringAssumeCapacity(); |
| 8809 | 8817 | } |
| 8810 | 8818 | |
| ... | ... | @@ -9076,9 +9084,13 @@ pub fn getIntrinsic( |
| 9076 | 9084 | const allocator = stack.get(); |
| 9077 | 9085 | |
| 9078 | 9086 | const name = name: { |
| 9079 | const writer = self.strtab_string_bytes.writer(self.gpa); | |
| 9080 | try writer.print("llvm.{s}", .{@tagName(id)}); | |
| 9081 | for (overload) |ty| try writer.print(".{m}", .{ty.fmt(self)}); | |
| 9087 | { | |
| 9088 | var aw: Writer.Allocating = .fromArrayList(self.gpa, &self.strtab_string_bytes); | |
| 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 | 9094 | break :name try self.trailingStrtabString(); |
| 9083 | 9095 | }; |
| 9084 | 9096 | if (self.getGlobal(name)) |global| return global.ptrConst(self).kind.function; |
| ... | ... | @@ -9492,139 +9504,105 @@ pub fn asmValue( |
| 9492 | 9504 | return (try self.asmConst(ty, info, assembly, constraints)).toValue(); |
| 9493 | 9505 | } |
| 9494 | 9506 | |
| 9495 | pub fn dump(self: *Builder) void { | |
| 9496 | self.print(std.io.getStdErr().writer()) catch {}; | |
| 9507 | pub fn dump(b: *Builder) void { | |
| 9508 | var buffer: [4000]u8 = undefined; | |
| 9509 | const stderr: std.fs.File = .stderr(); | |
| 9510 | b.printToFile(stderr, &buffer) catch {}; | |
| 9497 | 9511 | } |
| 9498 | 9512 | |
| 9499 | pub fn printToFile(self: *Builder, path: []const u8) Allocator.Error!bool { | |
| 9500 | var file = std.fs.cwd().createFile(path, .{}) catch |err| { | |
| 9501 | log.err("failed printing LLVM module to \"{s}\": {s}", .{ path, @errorName(err) }); | |
| 9502 | return false; | |
| 9503 | }; | |
| 9513 | pub fn printToFilePath(b: *Builder, dir: std.fs.Dir, path: []const u8) !void { | |
| 9514 | var buffer: [4000]u8 = undefined; | |
| 9515 | const file = try dir.createFile(path, .{}); | |
| 9504 | 9516 | defer file.close(); |
| 9505 | self.print(file.writer()) catch |err| { | |
| 9506 | log.err("failed printing LLVM module to \"{s}\": {s}", .{ path, @errorName(err) }); | |
| 9507 | return false; | |
| 9508 | }; | |
| 9509 | return true; | |
| 9517 | try b.printToFile(file, &buffer); | |
| 9510 | 9518 | } |
| 9511 | 9519 | |
| 9512 | pub fn print(self: *Builder, writer: anytype) (@TypeOf(writer).Error || Allocator.Error)!void { | |
| 9513 | var bw = std.io.bufferedWriter(writer); | |
| 9514 | try self.printUnbuffered(bw.writer()); | |
| 9515 | try bw.flush(); | |
| 9520 | pub fn printToFile(b: *Builder, file: std.fs.File, buffer: []u8) !void { | |
| 9521 | var fw = file.writer(buffer); | |
| 9522 | try print(b, &fw.interface); | |
| 9523 | try fw.interface.flush(); | |
| 9516 | 9524 | } |
| 9517 | 9525 | |
| 9518 | fn WriterWithErrors(comptime BackingWriter: type, comptime ExtraErrors: type) type { | |
| 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 | } | |
| 9536 | fn writerWithErrors( | |
| 9537 | backing_writer: anytype, | |
| 9538 | comptime ExtraErrors: type, | |
| 9539 | ) WriterWithErrors(@TypeOf(backing_writer), ExtraErrors) { | |
| 9540 | return .{ .backing_writer = backing_writer }; | |
| 9541 | } | |
| 9542 | ||
| 9543 | pub 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 | ||
| 9526 | pub fn print(self: *Builder, w: *Writer) (Writer.Error || Allocator.Error)!void { | |
| 9550 | 9527 | var need_newline = false; |
| 9551 | 9528 | var metadata_formatter: Metadata.Formatter = .{ .builder = self, .need_comma = undefined }; |
| 9552 | 9529 | defer metadata_formatter.map.deinit(self.gpa); |
| 9553 | 9530 | |
| 9554 | 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; | |
| 9556 | if (self.source_filename != .none) try writer.print( | |
| 9532 | if (need_newline) try w.writeByte('\n') else need_newline = true; | |
| 9533 | if (self.source_filename != .none) try w.print( | |
| 9557 | 9534 | \\; ModuleID = '{s}' |
| 9558 | \\source_filename = {"} | |
| 9535 | \\source_filename = {f} | |
| 9559 | 9536 | \\ |
| 9560 | , .{ self.source_filename.slice(self).?, self.source_filename.fmt(self) }); | |
| 9561 | if (self.data_layout != .none) try writer.print( | |
| 9562 | \\target datalayout = {"} | |
| 9537 | , .{ self.source_filename.slice(self).?, self.source_filename.fmtQ(self) }); | |
| 9538 | if (self.data_layout != .none) try w.print( | |
| 9539 | \\target datalayout = {f} | |
| 9563 | 9540 | \\ |
| 9564 | , .{self.data_layout.fmt(self)}); | |
| 9565 | if (self.target_triple != .none) try writer.print( | |
| 9566 | \\target triple = {"} | |
| 9541 | , .{self.data_layout.fmtQ(self)}); | |
| 9542 | if (self.target_triple != .none) try w.print( | |
| 9543 | \\target triple = {f} | |
| 9567 | 9544 | \\ |
| 9568 | , .{self.target_triple.fmt(self)}); | |
| 9545 | , .{self.target_triple.fmtQ(self)}); | |
| 9569 | 9546 | } |
| 9570 | 9547 | |
| 9571 | 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 | 9550 | var line_it = std.mem.tokenizeScalar(u8, self.module_asm.items, '\n'); |
| 9574 | 9551 | while (line_it.next()) |line| { |
| 9575 | try writer.writeAll("module asm "); | |
| 9576 | try printEscapedString(line, .always_quote, writer); | |
| 9577 | try writer.writeByte('\n'); | |
| 9552 | try w.writeAll("module asm "); | |
| 9553 | try printEscapedString(line, .always_quote, w); | |
| 9554 | try w.writeByte('\n'); | |
| 9578 | 9555 | } |
| 9579 | 9556 | } |
| 9580 | 9557 | |
| 9581 | 9558 | if (self.types.count() > 0) { |
| 9582 | if (need_newline) try writer.writeByte('\n') else need_newline = true; | |
| 9583 | for (self.types.keys(), self.types.values()) |id, ty| try writer.print( | |
| 9584 | \\%{} = type {} | |
| 9559 | if (need_newline) try w.writeByte('\n') else need_newline = true; | |
| 9560 | for (self.types.keys(), self.types.values()) |id, ty| try w.print( | |
| 9561 | \\%{f} = type {f} | |
| 9585 | 9562 | \\ |
| 9586 | , .{ id.fmt(self), ty.fmt(self) }); | |
| 9563 | , .{ id.fmt(self), ty.fmt(self, .default) }); | |
| 9587 | 9564 | } |
| 9588 | 9565 | |
| 9589 | 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 | 9568 | for (self.variables.items) |variable| { |
| 9592 | 9569 | if (variable.global.getReplacement(self) != .none) continue; |
| 9593 | 9570 | const global = variable.global.ptrConst(self); |
| 9594 | 9571 | metadata_formatter.need_comma = true; |
| 9595 | 9572 | defer metadata_formatter.need_comma = undefined; |
| 9596 | try writer.print( | |
| 9597 | \\{} ={}{}{}{}{ }{}{ }{} {s} {%}{ }{, }{} | |
| 9573 | try w.print( | |
| 9574 | \\{f} ={f}{f}{f}{f}{f}{f}{f}{f} {s} {f}{f}{f}{f} | |
| 9598 | 9575 | \\ |
| 9599 | 9576 | , .{ |
| 9600 | 9577 | variable.global.fmt(self), |
| 9601 | Linkage.fmtOptional(if (global.linkage == .external and | |
| 9602 | variable.init != .no_init) null else global.linkage), | |
| 9578 | Linkage.fmtOptional( | |
| 9579 | if (global.linkage == .external and variable.init != .no_init) null else global.linkage, | |
| 9580 | ), | |
| 9603 | 9581 | global.preemption, |
| 9604 | 9582 | global.visibility, |
| 9605 | 9583 | global.dll_storage_class, |
| 9606 | variable.thread_local, | |
| 9584 | variable.thread_local.fmt(" "), | |
| 9607 | 9585 | global.unnamed_addr, |
| 9608 | global.addr_space, | |
| 9586 | global.addr_space.fmt(" "), | |
| 9609 | 9587 | global.externally_initialized, |
| 9610 | 9588 | @tagName(variable.mutability), |
| 9611 | global.type.fmt(self), | |
| 9612 | variable.init.fmt(self), | |
| 9613 | variable.alignment, | |
| 9614 | try metadata_formatter.fmt("!dbg ", global.dbg), | |
| 9589 | global.type.fmt(self, .percent), | |
| 9590 | variable.init.fmt(self, .{ .space = true }), | |
| 9591 | variable.alignment.fmt(", "), | |
| 9592 | try metadata_formatter.fmt("!dbg ", global.dbg, null), | |
| 9615 | 9593 | }); |
| 9616 | 9594 | } |
| 9617 | 9595 | } |
| 9618 | 9596 | |
| 9619 | 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 | 9599 | for (self.aliases.items) |alias| { |
| 9622 | 9600 | if (alias.global.getReplacement(self) != .none) continue; |
| 9623 | 9601 | const global = alias.global.ptrConst(self); |
| 9624 | 9602 | metadata_formatter.need_comma = true; |
| 9625 | 9603 | defer metadata_formatter.need_comma = undefined; |
| 9626 | try writer.print( | |
| 9627 | \\{} ={}{}{}{}{ }{} alias {%}, {%}{} | |
| 9604 | try w.print( | |
| 9605 | \\{f} ={f}{f}{f}{f}{f}{f} alias {f}, {f}{f} | |
| 9628 | 9606 | \\ |
| 9629 | 9607 | , .{ |
| 9630 | 9608 | alias.global.fmt(self), |
| ... | ... | @@ -9632,11 +9610,11 @@ pub fn printUnbuffered( |
| 9632 | 9610 | global.preemption, |
| 9633 | 9611 | global.visibility, |
| 9634 | 9612 | global.dll_storage_class, |
| 9635 | alias.thread_local, | |
| 9613 | alias.thread_local.fmt(" "), | |
| 9636 | 9614 | global.unnamed_addr, |
| 9637 | global.type.fmt(self), | |
| 9638 | alias.aliasee.fmt(self), | |
| 9639 | try metadata_formatter.fmt("!dbg ", global.dbg), | |
| 9615 | global.type.fmt(self, .percent), | |
| 9616 | alias.aliasee.fmt(self, .{ .percent = true }), | |
| 9617 | try metadata_formatter.fmt("!dbg ", global.dbg, null), | |
| 9640 | 9618 | }); |
| 9641 | 9619 | } |
| 9642 | 9620 | } |
| ... | ... | @@ -9646,17 +9624,17 @@ pub fn printUnbuffered( |
| 9646 | 9624 | |
| 9647 | 9625 | for (0.., self.functions.items) |function_i, function| { |
| 9648 | 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 | 9628 | const function_index: Function.Index = @enumFromInt(function_i); |
| 9651 | 9629 | const global = function.global.ptrConst(self); |
| 9652 | 9630 | const params_len = global.type.functionParameters(self).len; |
| 9653 | 9631 | const function_attributes = function.attributes.func(self); |
| 9654 | if (function_attributes != .none) try writer.print( | |
| 9655 | \\; Function Attrs:{} | |
| 9632 | if (function_attributes != .none) try w.print( | |
| 9633 | \\; Function Attrs:{f} | |
| 9656 | 9634 | \\ |
| 9657 | , .{function_attributes.fmt(self)}); | |
| 9658 | try writer.print( | |
| 9659 | \\{s}{}{}{}{}{}{"} {%} {}( | |
| 9635 | , .{function_attributes.fmt(self, .{})}); | |
| 9636 | try w.print( | |
| 9637 | \\{s}{f}{f}{f}{f}{f}{f} {f} {f}( | |
| 9660 | 9638 | , .{ |
| 9661 | 9639 | if (function.instructions.len > 0) "define" else "declare", |
| 9662 | 9640 | global.linkage, |
| ... | ... | @@ -9664,45 +9642,45 @@ pub fn printUnbuffered( |
| 9664 | 9642 | global.visibility, |
| 9665 | 9643 | global.dll_storage_class, |
| 9666 | 9644 | function.call_conv, |
| 9667 | function.attributes.ret(self).fmt(self), | |
| 9668 | global.type.functionReturn(self).fmt(self), | |
| 9645 | function.attributes.ret(self).fmt(self, .{}), | |
| 9646 | global.type.functionReturn(self).fmt(self, .percent), | |
| 9669 | 9647 | function.global.fmt(self), |
| 9670 | 9648 | }); |
| 9671 | 9649 | for (0..params_len) |arg| { |
| 9672 | if (arg > 0) try writer.writeAll(", "); | |
| 9673 | try writer.print( | |
| 9674 | \\{%}{"} | |
| 9650 | if (arg > 0) try w.writeAll(", "); | |
| 9651 | try w.print( | |
| 9652 | \\{f}{f} | |
| 9675 | 9653 | , .{ |
| 9676 | global.type.functionParameters(self)[arg].fmt(self), | |
| 9677 | function.attributes.param(arg, self).fmt(self), | |
| 9654 | global.type.functionParameters(self)[arg].fmt(self, .percent), | |
| 9655 | function.attributes.param(arg, self).fmt(self, .{}), | |
| 9678 | 9656 | }); |
| 9679 | 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 | 9659 | else |
| 9682 | try writer.print(" %{d}", .{arg}); | |
| 9660 | try w.print(" %{d}", .{arg}); | |
| 9683 | 9661 | } |
| 9684 | 9662 | switch (global.type.functionKind(self)) { |
| 9685 | 9663 | .normal => {}, |
| 9686 | 9664 | .vararg => { |
| 9687 | if (params_len > 0) try writer.writeAll(", "); | |
| 9688 | try writer.writeAll("..."); | |
| 9665 | if (params_len > 0) try w.writeAll(", "); | |
| 9666 | try w.writeAll("..."); | |
| 9689 | 9667 | }, |
| 9690 | 9668 | } |
| 9691 | try writer.print("){}{ }", .{ global.unnamed_addr, global.addr_space }); | |
| 9692 | if (function_attributes != .none) try writer.print(" #{d}", .{ | |
| 9669 | try w.print("){f}{f}", .{ global.unnamed_addr, global.addr_space.fmt(" ") }); | |
| 9670 | if (function_attributes != .none) try w.print(" #{d}", .{ | |
| 9693 | 9671 | (try attribute_groups.getOrPutValue(self.gpa, function_attributes, {})).index, |
| 9694 | 9672 | }); |
| 9695 | 9673 | { |
| 9696 | 9674 | metadata_formatter.need_comma = false; |
| 9697 | 9675 | defer metadata_formatter.need_comma = undefined; |
| 9698 | try writer.print("{ }{}", .{ | |
| 9699 | function.alignment, | |
| 9700 | try metadata_formatter.fmt(" !dbg ", global.dbg), | |
| 9676 | try w.print("{f}{f}", .{ | |
| 9677 | function.alignment.fmt(" "), | |
| 9678 | try metadata_formatter.fmt(" !dbg ", global.dbg, null), | |
| 9701 | 9679 | }); |
| 9702 | 9680 | } |
| 9703 | 9681 | if (function.instructions.len > 0) { |
| 9704 | 9682 | var block_incoming_len: u32 = undefined; |
| 9705 | try writer.writeAll(" {\n"); | |
| 9683 | try w.writeAll(" {\n"); | |
| 9706 | 9684 | var maybe_dbg_index: ?u32 = null; |
| 9707 | 9685 | for (params_len..function.instructions.len) |instruction_i| { |
| 9708 | 9686 | const instruction_index: Function.Instruction.Index = @enumFromInt(instruction_i); |
| ... | ... | @@ -9800,11 +9778,11 @@ pub fn printUnbuffered( |
| 9800 | 9778 | .xor, |
| 9801 | 9779 | => |tag| { |
| 9802 | 9780 | const extra = function.extraData(Function.Instruction.Binary, instruction.data); |
| 9803 | try writer.print(" %{} = {s} {%}, {}", .{ | |
| 9781 | try w.print(" %{f} = {s} {f}, {f}", .{ | |
| 9804 | 9782 | instruction_index.name(&function).fmt(self), |
| 9805 | 9783 | @tagName(tag), |
| 9806 | extra.lhs.fmt(function_index, self), | |
| 9807 | extra.rhs.fmt(function_index, self), | |
| 9784 | extra.lhs.fmt(function_index, self, .{ .percent = true }), | |
| 9785 | extra.rhs.fmt(function_index, self, .{ .percent = true }), | |
| 9808 | 9786 | }); |
| 9809 | 9787 | }, |
| 9810 | 9788 | .addrspacecast, |
| ... | ... | @@ -9822,73 +9800,76 @@ pub fn printUnbuffered( |
| 9822 | 9800 | .zext, |
| 9823 | 9801 | => |tag| { |
| 9824 | 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 | 9804 | instruction_index.name(&function).fmt(self), |
| 9827 | 9805 | @tagName(tag), |
| 9828 | extra.val.fmt(function_index, self), | |
| 9829 | extra.type.fmt(self), | |
| 9806 | extra.val.fmt(function_index, self, .{ .percent = true }), | |
| 9807 | extra.type.fmt(self, .percent), | |
| 9830 | 9808 | }); |
| 9831 | 9809 | }, |
| 9832 | 9810 | .alloca, |
| 9833 | 9811 | .@"alloca inalloca", |
| 9834 | 9812 | => |tag| { |
| 9835 | 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 | 9815 | instruction_index.name(&function).fmt(self), |
| 9838 | 9816 | @tagName(tag), |
| 9839 | extra.type.fmt(self), | |
| 9817 | extra.type.fmt(self, .percent), | |
| 9840 | 9818 | Value.fmt(switch (extra.len) { |
| 9841 | 9819 | .@"1" => .none, |
| 9842 | 9820 | else => extra.len, |
| 9843 | }, function_index, self), | |
| 9844 | extra.info.alignment, | |
| 9845 | extra.info.addr_space, | |
| 9821 | }, function_index, self, .{ | |
| 9822 | .comma = true, | |
| 9823 | .percent = true, | |
| 9824 | }), | |
| 9825 | extra.info.alignment.fmt(", "), | |
| 9826 | extra.info.addr_space.fmt(", "), | |
| 9846 | 9827 | }); |
| 9847 | 9828 | }, |
| 9848 | 9829 | .arg => unreachable, |
| 9849 | 9830 | .atomicrmw => |tag| { |
| 9850 | 9831 | const extra = |
| 9851 | 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 | 9834 | instruction_index.name(&function).fmt(self), |
| 9854 | @tagName(tag), | |
| 9855 | extra.info.access_kind, | |
| 9856 | @tagName(extra.info.atomic_rmw_operation), | |
| 9857 | extra.ptr.fmt(function_index, self), | |
| 9858 | extra.val.fmt(function_index, self), | |
| 9859 | extra.info.sync_scope, | |
| 9860 | extra.info.success_ordering, | |
| 9861 | extra.info.alignment, | |
| 9835 | tag, | |
| 9836 | extra.info.access_kind.fmt(" "), | |
| 9837 | extra.info.atomic_rmw_operation, | |
| 9838 | extra.ptr.fmt(function_index, self, .{ .percent = true }), | |
| 9839 | extra.val.fmt(function_index, self, .{ .percent = true }), | |
| 9840 | extra.info.sync_scope.fmt(" "), | |
| 9841 | extra.info.success_ordering.fmt(" "), | |
| 9842 | extra.info.alignment.fmt(", "), | |
| 9862 | 9843 | }); |
| 9863 | 9844 | }, |
| 9864 | 9845 | .block => { |
| 9865 | 9846 | block_incoming_len = instruction.data; |
| 9866 | 9847 | const name = instruction_index.name(&function); |
| 9867 | 9848 | if (@intFromEnum(instruction_index) > params_len) |
| 9868 | try writer.writeByte('\n'); | |
| 9869 | try writer.print("{}:\n", .{name.fmt(self)}); | |
| 9849 | try w.writeByte('\n'); | |
| 9850 | try w.print("{f}:\n", .{name.fmt(self)}); | |
| 9870 | 9851 | continue; |
| 9871 | 9852 | }, |
| 9872 | 9853 | .br => |tag| { |
| 9873 | 9854 | const target: Function.Block.Index = @enumFromInt(instruction.data); |
| 9874 | try writer.print(" {s} {%}", .{ | |
| 9875 | @tagName(tag), target.toInst(&function).fmt(function_index, self), | |
| 9855 | try w.print(" {s} {f}", .{ | |
| 9856 | @tagName(tag), target.toInst(&function).fmt(function_index, self, .{ .percent = true }), | |
| 9876 | 9857 | }); |
| 9877 | 9858 | }, |
| 9878 | 9859 | .br_cond => { |
| 9879 | 9860 | const extra = function.extraData(Function.Instruction.BrCond, instruction.data); |
| 9880 | try writer.print(" br {%}, {%}, {%}", .{ | |
| 9881 | extra.cond.fmt(function_index, self), | |
| 9882 | extra.then.toInst(&function).fmt(function_index, self), | |
| 9883 | extra.@"else".toInst(&function).fmt(function_index, self), | |
| 9861 | try w.print(" br {f}, {f}, {f}", .{ | |
| 9862 | extra.cond.fmt(function_index, self, .{ .percent = true }), | |
| 9863 | extra.then.toInst(&function).fmt(function_index, self, .{ .percent = true }), | |
| 9864 | extra.@"else".toInst(&function).fmt(function_index, self, .{ .percent = true }), | |
| 9884 | 9865 | }); |
| 9885 | 9866 | metadata_formatter.need_comma = true; |
| 9886 | 9867 | defer metadata_formatter.need_comma = undefined; |
| 9887 | 9868 | switch (extra.weights) { |
| 9888 | 9869 | .none => {}, |
| 9889 | .unpredictable => try writer.writeAll("!unpredictable !{}"), | |
| 9890 | _ => try writer.print("{}", .{ | |
| 9891 | try metadata_formatter.fmt("!prof ", @as(Metadata, @enumFromInt(@intFromEnum(extra.weights)))), | |
| 9870 | .unpredictable => try w.writeAll("!unpredictable !{}"), | |
| 9871 | _ => try w.print("{f}", .{ | |
| 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 | 9885 | var extra = |
| 9905 | 9886 | function.extraDataTrail(Function.Instruction.Call, instruction.data); |
| 9906 | 9887 | const args = extra.trail.next(extra.data.args_len, Value, &function); |
| 9907 | try writer.writeAll(" "); | |
| 9888 | try w.writeAll(" "); | |
| 9908 | 9889 | const ret_ty = extra.data.ty.functionReturn(self); |
| 9909 | 9890 | switch (ret_ty) { |
| 9910 | 9891 | .void => {}, |
| 9911 | else => try writer.print("%{} = ", .{ | |
| 9892 | else => try w.print("%{f} = ", .{ | |
| 9912 | 9893 | instruction_index.name(&function).fmt(self), |
| 9913 | 9894 | }), |
| 9914 | 9895 | .none => unreachable, |
| 9915 | 9896 | } |
| 9916 | try writer.print("{s}{}{}{} {%} {}(", .{ | |
| 9917 | @tagName(tag), | |
| 9897 | try w.print("{t}{f}{f}{f} {f} {f}(", .{ | |
| 9898 | tag, | |
| 9918 | 9899 | extra.data.info.call_conv, |
| 9919 | extra.data.attributes.ret(self).fmt(self), | |
| 9900 | extra.data.attributes.ret(self).fmt(self, .{}), | |
| 9920 | 9901 | extra.data.callee.typeOf(function_index, self).pointerAddrSpace(self), |
| 9921 | 9902 | switch (extra.data.ty.functionKind(self)) { |
| 9922 | 9903 | .normal => ret_ty, |
| 9923 | 9904 | .vararg => extra.data.ty, |
| 9924 | }.fmt(self), | |
| 9925 | extra.data.callee.fmt(function_index, self), | |
| 9905 | }.fmt(self, .percent), | |
| 9906 | extra.data.callee.fmt(function_index, self, .{}), | |
| 9926 | 9907 | }); |
| 9927 | 9908 | for (0.., args) |arg_index, arg| { |
| 9928 | if (arg_index > 0) try writer.writeAll(", "); | |
| 9909 | if (arg_index > 0) try w.writeAll(", "); | |
| 9929 | 9910 | metadata_formatter.need_comma = false; |
| 9930 | 9911 | defer metadata_formatter.need_comma = undefined; |
| 9931 | try writer.print("{%}{}{}", .{ | |
| 9932 | arg.typeOf(function_index, self).fmt(self), | |
| 9933 | extra.data.attributes.param(arg_index, self).fmt(self), | |
| 9912 | try w.print("{f}{f}{f}", .{ | |
| 9913 | arg.typeOf(function_index, self).fmt(self, .percent), | |
| 9914 | extra.data.attributes.param(arg_index, self).fmt(self, .{}), | |
| 9934 | 9915 | try metadata_formatter.fmtLocal(" ", arg, function_index), |
| 9935 | 9916 | }); |
| 9936 | 9917 | } |
| 9937 | try writer.writeByte(')'); | |
| 9918 | try w.writeByte(')'); | |
| 9938 | 9919 | if (extra.data.info.has_op_bundle_cold) { |
| 9939 | try writer.writeAll(" [ \"cold\"() ]"); | |
| 9920 | try w.writeAll(" [ \"cold\"() ]"); | |
| 9940 | 9921 | } |
| 9941 | 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 | 9924 | (try attribute_groups.getOrPutValue( |
| 9944 | 9925 | self.gpa, |
| 9945 | 9926 | call_function_attributes, |
| ... | ... | @@ -9952,27 +9933,27 @@ pub fn printUnbuffered( |
| 9952 | 9933 | => |tag| { |
| 9953 | 9934 | const extra = |
| 9954 | 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 | 9937 | instruction_index.name(&function).fmt(self), |
| 9957 | @tagName(tag), | |
| 9958 | extra.info.access_kind, | |
| 9959 | extra.ptr.fmt(function_index, self), | |
| 9960 | extra.cmp.fmt(function_index, self), | |
| 9961 | extra.new.fmt(function_index, self), | |
| 9962 | extra.info.sync_scope, | |
| 9963 | extra.info.success_ordering, | |
| 9964 | extra.info.failure_ordering, | |
| 9965 | extra.info.alignment, | |
| 9938 | tag, | |
| 9939 | extra.info.access_kind.fmt(" "), | |
| 9940 | extra.ptr.fmt(function_index, self, .{ .percent = true }), | |
| 9941 | extra.cmp.fmt(function_index, self, .{ .percent = true }), | |
| 9942 | extra.new.fmt(function_index, self, .{ .percent = true }), | |
| 9943 | extra.info.sync_scope.fmt(" "), | |
| 9944 | extra.info.success_ordering.fmt(" "), | |
| 9945 | extra.info.failure_ordering.fmt(" "), | |
| 9946 | extra.info.alignment.fmt(", "), | |
| 9966 | 9947 | }); |
| 9967 | 9948 | }, |
| 9968 | 9949 | .extractelement => |tag| { |
| 9969 | 9950 | const extra = |
| 9970 | 9951 | function.extraData(Function.Instruction.ExtractElement, instruction.data); |
| 9971 | try writer.print(" %{} = {s} {%}, {%}", .{ | |
| 9952 | try w.print(" %{f} = {s} {f}, {f}", .{ | |
| 9972 | 9953 | instruction_index.name(&function).fmt(self), |
| 9973 | 9954 | @tagName(tag), |
| 9974 | extra.val.fmt(function_index, self), | |
| 9975 | extra.index.fmt(function_index, self), | |
| 9955 | extra.val.fmt(function_index, self, .{ .percent = true }), | |
| 9956 | extra.index.fmt(function_index, self, .{ .percent = true }), | |
| 9976 | 9957 | }); |
| 9977 | 9958 | }, |
| 9978 | 9959 | .extractvalue => |tag| { |
| ... | ... | @@ -9981,29 +9962,29 @@ pub fn printUnbuffered( |
| 9981 | 9962 | instruction.data, |
| 9982 | 9963 | ); |
| 9983 | 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 | 9966 | instruction_index.name(&function).fmt(self), |
| 9986 | 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 | 9972 | .fence => |tag| { |
| 9992 | 9973 | const info: MemoryAccessInfo = @bitCast(instruction.data); |
| 9993 | try writer.print(" {s}{ }{ }", .{ | |
| 9994 | @tagName(tag), | |
| 9995 | info.sync_scope, | |
| 9996 | info.success_ordering, | |
| 9974 | try w.print(" {t}{f}{f}", .{ | |
| 9975 | tag, | |
| 9976 | info.sync_scope.fmt(" "), | |
| 9977 | info.success_ordering.fmt(" "), | |
| 9997 | 9978 | }); |
| 9998 | 9979 | }, |
| 9999 | 9980 | .fneg, |
| 10000 | 9981 | .@"fneg fast", |
| 10001 | 9982 | => |tag| { |
| 10002 | 9983 | const val: Value = @enumFromInt(instruction.data); |
| 10003 | try writer.print(" %{} = {s} {%}", .{ | |
| 9984 | try w.print(" %{f} = {s} {f}", .{ | |
| 10004 | 9985 | instruction_index.name(&function).fmt(self), |
| 10005 | 9986 | @tagName(tag), |
| 10006 | val.fmt(function_index, self), | |
| 9987 | val.fmt(function_index, self, .{ .percent = true }), | |
| 10007 | 9988 | }); |
| 10008 | 9989 | }, |
| 10009 | 9990 | .getelementptr, |
| ... | ... | @@ -10014,14 +9995,14 @@ pub fn printUnbuffered( |
| 10014 | 9995 | instruction.data, |
| 10015 | 9996 | ); |
| 10016 | 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 | 9999 | instruction_index.name(&function).fmt(self), |
| 10019 | 10000 | @tagName(tag), |
| 10020 | extra.data.type.fmt(self), | |
| 10021 | extra.data.base.fmt(function_index, self), | |
| 10001 | extra.data.type.fmt(self, .percent), | |
| 10002 | extra.data.base.fmt(function_index, self, .{ .percent = true }), | |
| 10022 | 10003 | }); |
| 10023 | for (indices) |index| try writer.print(", {%}", .{ | |
| 10024 | index.fmt(function_index, self), | |
| 10004 | for (indices) |index| try w.print(", {f}", .{ | |
| 10005 | index.fmt(function_index, self, .{ .percent = true }), | |
| 10025 | 10006 | }); |
| 10026 | 10007 | }, |
| 10027 | 10008 | .indirectbr => |tag| { |
| ... | ... | @@ -10029,54 +10010,54 @@ pub fn printUnbuffered( |
| 10029 | 10010 | function.extraDataTrail(Function.Instruction.IndirectBr, instruction.data); |
| 10030 | 10011 | const targets = |
| 10031 | 10012 | extra.trail.next(extra.data.targets_len, Function.Block.Index, &function); |
| 10032 | try writer.print(" {s} {%}, [", .{ | |
| 10013 | try w.print(" {s} {f}, [", .{ | |
| 10033 | 10014 | @tagName(tag), |
| 10034 | extra.data.addr.fmt(function_index, self), | |
| 10015 | extra.data.addr.fmt(function_index, self, .{ .percent = true }), | |
| 10035 | 10016 | }); |
| 10036 | 10017 | for (0.., targets) |target_index, target| { |
| 10037 | if (target_index > 0) try writer.writeAll(", "); | |
| 10038 | try writer.print("{%}", .{ | |
| 10039 | target.toInst(&function).fmt(function_index, self), | |
| 10018 | if (target_index > 0) try w.writeAll(", "); | |
| 10019 | try w.print("{f}", .{ | |
| 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 | 10025 | .insertelement => |tag| { |
| 10045 | 10026 | const extra = |
| 10046 | 10027 | function.extraData(Function.Instruction.InsertElement, instruction.data); |
| 10047 | try writer.print(" %{} = {s} {%}, {%}, {%}", .{ | |
| 10028 | try w.print(" %{f} = {s} {f}, {f}, {f}", .{ | |
| 10048 | 10029 | instruction_index.name(&function).fmt(self), |
| 10049 | 10030 | @tagName(tag), |
| 10050 | extra.val.fmt(function_index, self), | |
| 10051 | extra.elem.fmt(function_index, self), | |
| 10052 | extra.index.fmt(function_index, self), | |
| 10031 | extra.val.fmt(function_index, self, .{ .percent = true }), | |
| 10032 | extra.elem.fmt(function_index, self, .{ .percent = true }), | |
| 10033 | extra.index.fmt(function_index, self, .{ .percent = true }), | |
| 10053 | 10034 | }); |
| 10054 | 10035 | }, |
| 10055 | 10036 | .insertvalue => |tag| { |
| 10056 | 10037 | var extra = |
| 10057 | 10038 | function.extraDataTrail(Function.Instruction.InsertValue, instruction.data); |
| 10058 | 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 | 10041 | instruction_index.name(&function).fmt(self), |
| 10061 | 10042 | @tagName(tag), |
| 10062 | extra.data.val.fmt(function_index, self), | |
| 10063 | extra.data.elem.fmt(function_index, self), | |
| 10043 | extra.data.val.fmt(function_index, self, .{ .percent = true }), | |
| 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 | 10048 | .load, |
| 10068 | 10049 | .@"load atomic", |
| 10069 | 10050 | => |tag| { |
| 10070 | 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 | 10053 | instruction_index.name(&function).fmt(self), |
| 10073 | @tagName(tag), | |
| 10074 | extra.info.access_kind, | |
| 10075 | extra.type.fmt(self), | |
| 10076 | extra.ptr.fmt(function_index, self), | |
| 10077 | extra.info.sync_scope, | |
| 10078 | extra.info.success_ordering, | |
| 10079 | extra.info.alignment, | |
| 10054 | tag, | |
| 10055 | extra.info.access_kind.fmt(" "), | |
| 10056 | extra.type.fmt(self, .percent), | |
| 10057 | extra.ptr.fmt(function_index, self, .{ .percent = true }), | |
| 10058 | extra.info.sync_scope.fmt(" "), | |
| 10059 | extra.info.success_ordering.fmt(" "), | |
| 10060 | extra.info.alignment.fmt(", "), | |
| 10080 | 10061 | }); |
| 10081 | 10062 | }, |
| 10082 | 10063 | .phi, |
| ... | ... | @@ -10086,64 +10067,64 @@ pub fn printUnbuffered( |
| 10086 | 10067 | const vals = extra.trail.next(block_incoming_len, Value, &function); |
| 10087 | 10068 | const blocks = |
| 10088 | 10069 | extra.trail.next(block_incoming_len, Function.Block.Index, &function); |
| 10089 | try writer.print(" %{} = {s} {%} ", .{ | |
| 10070 | try w.print(" %{f} = {s} {f} ", .{ | |
| 10090 | 10071 | instruction_index.name(&function).fmt(self), |
| 10091 | 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 | 10075 | for (0.., vals, blocks) |incoming_index, incoming_val, incoming_block| { |
| 10095 | if (incoming_index > 0) try writer.writeAll(", "); | |
| 10096 | try writer.print("[ {}, {} ]", .{ | |
| 10097 | incoming_val.fmt(function_index, self), | |
| 10098 | incoming_block.toInst(&function).fmt(function_index, self), | |
| 10076 | if (incoming_index > 0) try w.writeAll(", "); | |
| 10077 | try w.print("[ {f}, {f} ]", .{ | |
| 10078 | incoming_val.fmt(function_index, self, .{}), | |
| 10079 | incoming_block.toInst(&function).fmt(function_index, self, .{}), | |
| 10099 | 10080 | }); |
| 10100 | 10081 | } |
| 10101 | 10082 | }, |
| 10102 | 10083 | .ret => |tag| { |
| 10103 | 10084 | const val: Value = @enumFromInt(instruction.data); |
| 10104 | try writer.print(" {s} {%}", .{ | |
| 10085 | try w.print(" {s} {f}", .{ | |
| 10105 | 10086 | @tagName(tag), |
| 10106 | val.fmt(function_index, self), | |
| 10087 | val.fmt(function_index, self, .{ .percent = true }), | |
| 10107 | 10088 | }); |
| 10108 | 10089 | }, |
| 10109 | 10090 | .@"ret void", |
| 10110 | 10091 | .@"unreachable", |
| 10111 | => |tag| try writer.print(" {s}", .{@tagName(tag)}), | |
| 10092 | => |tag| try w.print(" {s}", .{@tagName(tag)}), | |
| 10112 | 10093 | .select, |
| 10113 | 10094 | .@"select fast", |
| 10114 | 10095 | => |tag| { |
| 10115 | 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 | 10098 | instruction_index.name(&function).fmt(self), |
| 10118 | 10099 | @tagName(tag), |
| 10119 | extra.cond.fmt(function_index, self), | |
| 10120 | extra.lhs.fmt(function_index, self), | |
| 10121 | extra.rhs.fmt(function_index, self), | |
| 10100 | extra.cond.fmt(function_index, self, .{ .percent = true }), | |
| 10101 | extra.lhs.fmt(function_index, self, .{ .percent = true }), | |
| 10102 | extra.rhs.fmt(function_index, self, .{ .percent = true }), | |
| 10122 | 10103 | }); |
| 10123 | 10104 | }, |
| 10124 | 10105 | .shufflevector => |tag| { |
| 10125 | 10106 | const extra = |
| 10126 | 10107 | function.extraData(Function.Instruction.ShuffleVector, instruction.data); |
| 10127 | try writer.print(" %{} = {s} {%}, {%}, {%}", .{ | |
| 10108 | try w.print(" %{f} = {s} {f}, {f}, {f}", .{ | |
| 10128 | 10109 | instruction_index.name(&function).fmt(self), |
| 10129 | 10110 | @tagName(tag), |
| 10130 | extra.lhs.fmt(function_index, self), | |
| 10131 | extra.rhs.fmt(function_index, self), | |
| 10132 | extra.mask.fmt(function_index, self), | |
| 10111 | extra.lhs.fmt(function_index, self, .{ .percent = true }), | |
| 10112 | extra.rhs.fmt(function_index, self, .{ .percent = true }), | |
| 10113 | extra.mask.fmt(function_index, self, .{ .percent = true }), | |
| 10133 | 10114 | }); |
| 10134 | 10115 | }, |
| 10135 | 10116 | .store, |
| 10136 | 10117 | .@"store atomic", |
| 10137 | 10118 | => |tag| { |
| 10138 | 10119 | const extra = function.extraData(Function.Instruction.Store, instruction.data); |
| 10139 | try writer.print(" {s}{ } {%}, {%}{ }{ }{, }", .{ | |
| 10140 | @tagName(tag), | |
| 10141 | extra.info.access_kind, | |
| 10142 | extra.val.fmt(function_index, self), | |
| 10143 | extra.ptr.fmt(function_index, self), | |
| 10144 | extra.info.sync_scope, | |
| 10145 | extra.info.success_ordering, | |
| 10146 | extra.info.alignment, | |
| 10120 | try w.print(" {t}{f} {f}, {f}{f}{f}{f}", .{ | |
| 10121 | tag, | |
| 10122 | extra.info.access_kind.fmt(" "), | |
| 10123 | extra.val.fmt(function_index, self, .{ .percent = true }), | |
| 10124 | extra.ptr.fmt(function_index, self, .{ .percent = true }), | |
| 10125 | extra.info.sync_scope.fmt(" "), | |
| 10126 | extra.info.success_ordering.fmt(" "), | |
| 10127 | extra.info.alignment.fmt(", "), | |
| 10147 | 10128 | }); |
| 10148 | 10129 | }, |
| 10149 | 10130 | .@"switch" => |tag| { |
| ... | ... | @@ -10152,80 +10133,80 @@ pub fn printUnbuffered( |
| 10152 | 10133 | const vals = extra.trail.next(extra.data.cases_len, Constant, &function); |
| 10153 | 10134 | const blocks = |
| 10154 | 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 | 10137 | @tagName(tag), |
| 10157 | extra.data.val.fmt(function_index, self), | |
| 10158 | extra.data.default.toInst(&function).fmt(function_index, self), | |
| 10138 | extra.data.val.fmt(function_index, self, .{ .percent = true }), | |
| 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( | |
| 10161 | " {%}, {%}\n", | |
| 10141 | for (vals, blocks) |case_val, case_block| try w.print( | |
| 10142 | " {f}, {f}\n", | |
| 10162 | 10143 | .{ |
| 10163 | case_val.fmt(self), | |
| 10164 | case_block.toInst(&function).fmt(function_index, self), | |
| 10144 | case_val.fmt(self, .{ .percent = true }), | |
| 10145 | case_block.toInst(&function).fmt(function_index, self, .{ .percent = true }), | |
| 10165 | 10146 | }, |
| 10166 | 10147 | ); |
| 10167 | try writer.writeAll(" ]"); | |
| 10148 | try w.writeAll(" ]"); | |
| 10168 | 10149 | metadata_formatter.need_comma = true; |
| 10169 | 10150 | defer metadata_formatter.need_comma = undefined; |
| 10170 | 10151 | switch (extra.data.weights) { |
| 10171 | 10152 | .none => {}, |
| 10172 | .unpredictable => try writer.writeAll("!unpredictable !{}"), | |
| 10173 | _ => try writer.print("{}", .{ | |
| 10174 | try metadata_formatter.fmt("!prof ", @as(Metadata, @enumFromInt(@intFromEnum(extra.data.weights)))), | |
| 10153 | .unpredictable => try w.writeAll("!unpredictable !{}"), | |
| 10154 | _ => try w.print("{f}", .{ | |
| 10155 | try metadata_formatter.fmt("!prof ", @as(Metadata, @enumFromInt(@intFromEnum(extra.data.weights))), null), | |
| 10175 | 10156 | }), |
| 10176 | 10157 | } |
| 10177 | 10158 | }, |
| 10178 | 10159 | .va_arg => |tag| { |
| 10179 | 10160 | const extra = function.extraData(Function.Instruction.VaArg, instruction.data); |
| 10180 | try writer.print(" %{} = {s} {%}, {%}", .{ | |
| 10161 | try w.print(" %{f} = {s} {f}, {f}", .{ | |
| 10181 | 10162 | instruction_index.name(&function).fmt(self), |
| 10182 | 10163 | @tagName(tag), |
| 10183 | extra.list.fmt(function_index, self), | |
| 10184 | extra.type.fmt(self), | |
| 10164 | extra.list.fmt(function_index, self, .{ .percent = true }), | |
| 10165 | extra.type.fmt(self, .percent), | |
| 10185 | 10166 | }); |
| 10186 | 10167 | }, |
| 10187 | 10168 | } |
| 10188 | 10169 | |
| 10189 | 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 | } |
| 10198 | 10179 | |
| 10199 | 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 | 10182 | for (0.., attribute_groups.keys()) |attribute_group_index, attribute_group| |
| 10202 | try writer.print( | |
| 10203 | \\attributes #{d} = {{{#"} }} | |
| 10183 | try w.print( | |
| 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 | } |
| 10207 | 10188 | |
| 10208 | 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 | 10191 | for (self.metadata_named.keys(), self.metadata_named.values()) |name, data| { |
| 10211 | 10192 | const elements: []const Metadata = |
| 10212 | 10193 | @ptrCast(self.metadata_extra.items[data.index..][0..data.len]); |
| 10213 | try writer.writeByte('!'); | |
| 10214 | try printEscapedString(name.slice(self), .quote_unless_valid_identifier, writer); | |
| 10215 | try writer.writeAll(" = !{"); | |
| 10194 | try w.writeByte('!'); | |
| 10195 | try printEscapedString(name.slice(self), .quote_unless_valid_identifier, w); | |
| 10196 | try w.writeAll(" = !{"); | |
| 10216 | 10197 | metadata_formatter.need_comma = false; |
| 10217 | 10198 | defer metadata_formatter.need_comma = undefined; |
| 10218 | for (elements) |element| try writer.print("{}", .{try metadata_formatter.fmt("", element)}); | |
| 10219 | try writer.writeAll("}\n"); | |
| 10199 | for (elements) |element| try w.print("{f}", .{try metadata_formatter.fmt("", element, null)}); | |
| 10200 | try w.writeAll("}\n"); | |
| 10220 | 10201 | } |
| 10221 | 10202 | } |
| 10222 | 10203 | |
| 10223 | 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 | 10206 | var metadata_index: usize = 0; |
| 10226 | 10207 | while (metadata_index < metadata_formatter.map.count()) : (metadata_index += 1) { |
| 10227 | 10208 | @setEvalBranchQuota(10_000); |
| 10228 | try writer.print("!{} = ", .{metadata_index}); | |
| 10209 | try w.print("!{d} = ", .{metadata_index}); | |
| 10229 | 10210 | metadata_formatter.need_comma = false; |
| 10230 | 10211 | defer metadata_formatter.need_comma = undefined; |
| 10231 | 10212 | |
| ... | ... | @@ -10238,7 +10219,7 @@ pub fn printUnbuffered( |
| 10238 | 10219 | .scope = location.scope, |
| 10239 | 10220 | .inlinedAt = location.inlined_at, |
| 10240 | 10221 | .isImplicitCode = false, |
| 10241 | }, writer); | |
| 10222 | }, w); | |
| 10242 | 10223 | continue; |
| 10243 | 10224 | }, |
| 10244 | 10225 | .metadata => |metadata| self.metadata_items.get(@intFromEnum(metadata)), |
| ... | ... | @@ -10254,7 +10235,7 @@ pub fn printUnbuffered( |
| 10254 | 10235 | .checksumkind = null, |
| 10255 | 10236 | .checksum = null, |
| 10256 | 10237 | .source = null, |
| 10257 | }, writer); | |
| 10238 | }, w); | |
| 10258 | 10239 | }, |
| 10259 | 10240 | .compile_unit, |
| 10260 | 10241 | .@"compile_unit optimized", |
| ... | ... | @@ -10285,7 +10266,7 @@ pub fn printUnbuffered( |
| 10285 | 10266 | .rangesBaseAddress = null, |
| 10286 | 10267 | .sysroot = null, |
| 10287 | 10268 | .sdk = null, |
| 10288 | }, writer); | |
| 10269 | }, w); | |
| 10289 | 10270 | }, |
| 10290 | 10271 | .subprogram, |
| 10291 | 10272 | .@"subprogram local", |
| ... | ... | @@ -10319,7 +10300,7 @@ pub fn printUnbuffered( |
| 10319 | 10300 | .thrownTypes = null, |
| 10320 | 10301 | .annotations = null, |
| 10321 | 10302 | .targetFuncName = null, |
| 10322 | }, writer); | |
| 10303 | }, w); | |
| 10323 | 10304 | }, |
| 10324 | 10305 | .lexical_block => { |
| 10325 | 10306 | const extra = self.metadataExtraData(Metadata.LexicalBlock, metadata_item.data); |
| ... | ... | @@ -10328,7 +10309,7 @@ pub fn printUnbuffered( |
| 10328 | 10309 | .file = extra.file, |
| 10329 | 10310 | .line = extra.line, |
| 10330 | 10311 | .column = extra.column, |
| 10331 | }, writer); | |
| 10312 | }, w); | |
| 10332 | 10313 | }, |
| 10333 | 10314 | .location => { |
| 10334 | 10315 | const extra = self.metadataExtraData(Metadata.Location, metadata_item.data); |
| ... | ... | @@ -10338,7 +10319,7 @@ pub fn printUnbuffered( |
| 10338 | 10319 | .scope = extra.scope, |
| 10339 | 10320 | .inlinedAt = extra.inlined_at, |
| 10340 | 10321 | .isImplicitCode = false, |
| 10341 | }, writer); | |
| 10322 | }, w); | |
| 10342 | 10323 | }, |
| 10343 | 10324 | .basic_bool_type, |
| 10344 | 10325 | .basic_unsigned_type, |
| ... | ... | @@ -10367,7 +10348,7 @@ pub fn printUnbuffered( |
| 10367 | 10348 | else => unreachable, |
| 10368 | 10349 | }), |
| 10369 | 10350 | .flags = null, |
| 10370 | }, writer); | |
| 10351 | }, w); | |
| 10371 | 10352 | }, |
| 10372 | 10353 | .composite_struct_type, |
| 10373 | 10354 | .composite_union_type, |
| ... | ... | @@ -10412,7 +10393,7 @@ pub fn printUnbuffered( |
| 10412 | 10393 | .allocated = null, |
| 10413 | 10394 | .rank = null, |
| 10414 | 10395 | .annotations = null, |
| 10415 | }, writer); | |
| 10396 | }, w); | |
| 10416 | 10397 | }, |
| 10417 | 10398 | .derived_pointer_type, |
| 10418 | 10399 | .derived_member_type, |
| ... | ... | @@ -10445,7 +10426,7 @@ pub fn printUnbuffered( |
| 10445 | 10426 | .extraData = null, |
| 10446 | 10427 | .dwarfAddressSpace = null, |
| 10447 | 10428 | .annotations = null, |
| 10448 | }, writer); | |
| 10429 | }, w); | |
| 10449 | 10430 | }, |
| 10450 | 10431 | .subroutine_type => { |
| 10451 | 10432 | const extra = self.metadataExtraData(Metadata.SubroutineType, metadata_item.data); |
| ... | ... | @@ -10453,7 +10434,7 @@ pub fn printUnbuffered( |
| 10453 | 10434 | .flags = null, |
| 10454 | 10435 | .cc = null, |
| 10455 | 10436 | .types = extra.types_tuple, |
| 10456 | }, writer); | |
| 10437 | }, w); | |
| 10457 | 10438 | }, |
| 10458 | 10439 | .enumerator_unsigned, |
| 10459 | 10440 | .enumerator_signed_positive, |
| ... | ... | @@ -10503,7 +10484,7 @@ pub fn printUnbuffered( |
| 10503 | 10484 | => false, |
| 10504 | 10485 | else => unreachable, |
| 10505 | 10486 | }, |
| 10506 | }, writer); | |
| 10487 | }, w); | |
| 10507 | 10488 | }, |
| 10508 | 10489 | .subrange => { |
| 10509 | 10490 | const extra = self.metadataExtraData(Metadata.Subrange, metadata_item.data); |
| ... | ... | @@ -10512,34 +10493,34 @@ pub fn printUnbuffered( |
| 10512 | 10493 | .lowerBound = extra.lower_bound, |
| 10513 | 10494 | .upperBound = null, |
| 10514 | 10495 | .stride = null, |
| 10515 | }, writer); | |
| 10496 | }, w); | |
| 10516 | 10497 | }, |
| 10517 | 10498 | .tuple => { |
| 10518 | 10499 | var extra = self.metadataExtraDataTrail(Metadata.Tuple, metadata_item.data); |
| 10519 | 10500 | const elements = extra.trail.next(extra.data.elements_len, Metadata, self); |
| 10520 | try writer.writeAll("!{"); | |
| 10521 | for (elements) |element| try writer.print("{[element]%}", .{ | |
| 10522 | .element = try metadata_formatter.fmt("", element), | |
| 10501 | try w.writeAll("!{"); | |
| 10502 | for (elements) |element| try w.print("{[element]f}", .{ | |
| 10503 | .element = try metadata_formatter.fmt("", element, .{ .percent = true }), | |
| 10523 | 10504 | }); |
| 10524 | try writer.writeAll("}\n"); | |
| 10505 | try w.writeAll("}\n"); | |
| 10525 | 10506 | }, |
| 10526 | 10507 | .str_tuple => { |
| 10527 | 10508 | var extra = self.metadataExtraDataTrail(Metadata.StrTuple, metadata_item.data); |
| 10528 | 10509 | const elements = extra.trail.next(extra.data.elements_len, Metadata, self); |
| 10529 | try writer.print("!{{{[str]%}", .{ | |
| 10530 | .str = try metadata_formatter.fmt("", extra.data.str), | |
| 10510 | try w.print("!{{{[str]f}", .{ | |
| 10511 | .str = try metadata_formatter.fmt("", extra.data.str, .{ .percent = true }), | |
| 10531 | 10512 | }); |
| 10532 | for (elements) |element| try writer.print("{[element]%}", .{ | |
| 10533 | .element = try metadata_formatter.fmt("", element), | |
| 10513 | for (elements) |element| try w.print("{[element]f}", .{ | |
| 10514 | .element = try metadata_formatter.fmt("", element, .{ .percent = true }), | |
| 10534 | 10515 | }); |
| 10535 | try writer.writeAll("}\n"); | |
| 10516 | try w.writeAll("}\n"); | |
| 10536 | 10517 | }, |
| 10537 | 10518 | .module_flag => { |
| 10538 | 10519 | const extra = self.metadataExtraData(Metadata.ModuleFlag, metadata_item.data); |
| 10539 | try writer.print("!{{{[behavior]%}{[name]%}{[constant]%}}}\n", .{ | |
| 10540 | .behavior = try metadata_formatter.fmt("", extra.behavior), | |
| 10541 | .name = try metadata_formatter.fmt("", extra.name), | |
| 10542 | .constant = try metadata_formatter.fmt("", extra.constant), | |
| 10520 | try w.print("!{{{[behavior]f}{[name]f}{[constant]f}}}\n", .{ | |
| 10521 | .behavior = try metadata_formatter.fmt("", extra.behavior, .{ .percent = true }), | |
| 10522 | .name = try metadata_formatter.fmt("", extra.name, .{ .percent = true }), | |
| 10523 | .constant = try metadata_formatter.fmt("", extra.constant, .{ .percent = true }), | |
| 10543 | 10524 | }); |
| 10544 | 10525 | }, |
| 10545 | 10526 | .local_var => { |
| ... | ... | @@ -10554,7 +10535,7 @@ pub fn printUnbuffered( |
| 10554 | 10535 | .flags = null, |
| 10555 | 10536 | .@"align" = null, |
| 10556 | 10537 | .annotations = null, |
| 10557 | }, writer); | |
| 10538 | }, w); | |
| 10558 | 10539 | }, |
| 10559 | 10540 | .parameter => { |
| 10560 | 10541 | const extra = self.metadataExtraData(Metadata.Parameter, metadata_item.data); |
| ... | ... | @@ -10568,7 +10549,7 @@ pub fn printUnbuffered( |
| 10568 | 10549 | .flags = null, |
| 10569 | 10550 | .@"align" = null, |
| 10570 | 10551 | .annotations = null, |
| 10571 | }, writer); | |
| 10552 | }, w); | |
| 10572 | 10553 | }, |
| 10573 | 10554 | .global_var, |
| 10574 | 10555 | .@"global_var local", |
| ... | ... | @@ -10591,7 +10572,7 @@ pub fn printUnbuffered( |
| 10591 | 10572 | .templateParams = null, |
| 10592 | 10573 | .@"align" = null, |
| 10593 | 10574 | .annotations = null, |
| 10594 | }, writer); | |
| 10575 | }, w); | |
| 10595 | 10576 | }, |
| 10596 | 10577 | .global_var_expression => { |
| 10597 | 10578 | const extra = |
| ... | ... | @@ -10599,7 +10580,7 @@ pub fn printUnbuffered( |
| 10599 | 10580 | try metadata_formatter.specialized(.@"!", .DIGlobalVariableExpression, .{ |
| 10600 | 10581 | .@"var" = extra.variable, |
| 10601 | 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 | 10599 | } |
| 10619 | 10600 | |
| 10620 | 10601 | const QuoteBehavior = enum { always_quote, quote_unless_valid_identifier }; |
| 10621 | fn printEscapedString( | |
| 10622 | slice: []const u8, | |
| 10623 | quotes: QuoteBehavior, | |
| 10624 | writer: anytype, | |
| 10625 | ) @TypeOf(writer).Error!void { | |
| 10602 | fn printEscapedString(slice: []const u8, quotes: QuoteBehavior, w: *Writer) Writer.Error!void { | |
| 10626 | 10603 | const need_quotes = switch (quotes) { |
| 10627 | 10604 | .always_quote => true, |
| 10628 | 10605 | .quote_unless_valid_identifier => !isValidIdentifier(slice), |
| 10629 | 10606 | }; |
| 10630 | if (need_quotes) try writer.writeByte('"'); | |
| 10607 | if (need_quotes) try w.writeByte('"'); | |
| 10631 | 10608 | for (slice) |byte| switch (byte) { |
| 10632 | '\\' => try writer.writeAll("\\\\"), | |
| 10633 | ' '...'"' - 1, '"' + 1...'\\' - 1, '\\' + 1...'~' => try writer.writeByte(byte), | |
| 10634 | else => try writer.print("\\{X:0>2}", .{byte}), | |
| 10609 | '\\' => try w.writeAll("\\\\"), | |
| 10610 | ' '...'"' - 1, '"' + 1...'\\' - 1, '\\' + 1...'~' => try w.writeByte(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 | } |
| 10638 | 10615 | |
| 10639 | 10616 | fn 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 | 11995 | } |
| 12019 | 11996 | |
| 12020 | 11997 | pub 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 | 11999 | return self.trailingMetadataStringAssumeCapacity(); |
| 12023 | 12000 | } |
| 12024 | 12001 | |
| ... | ... | @@ -15261,12 +15238,12 @@ pub fn toBitcode(self: *Builder, allocator: Allocator, producer: Producer) bitco |
| 15261 | 15238 | return bitcode.toOwnedSlice(); |
| 15262 | 15239 | } |
| 15263 | 15240 | |
| 15264 | const Allocator = std.mem.Allocator; | |
| 15265 | const assert = std.debug.assert; | |
| 15266 | const bitcode_writer = @import("bitcode_writer.zig"); | |
| 15267 | const Builder = @This(); | |
| 15268 | const builtin = @import("builtin"); | |
| 15269 | const DW = std.dwarf; | |
| 15270 | const ir = @import("ir.zig"); | |
| 15271 | const log = std.log.scoped(.llvm); | |
| 15272 | const std = @import("../../std.zig"); | |
| 15241 | const FormatFlags = struct { | |
| 15242 | comma: bool = false, | |
| 15243 | space: bool = false, | |
| 15244 | percent: bool = false, | |
| 15245 | ||
| 15246 | fn onlyPercent(f: FormatFlags) bool { | |
| 15247 | return !f.comma and !f.space and f.percent; | |
| 15248 | } | |
| 15249 | }; |
lib/std/zig/parser_test.zig+11-11| ... | ... | @@ -1,3 +1,9 @@ |
| 1 | const std = @import("std"); | |
| 2 | const mem = std.mem; | |
| 3 | const print = std.debug.print; | |
| 4 | const io = std.io; | |
| 5 | const maxInt = std.math.maxInt; | |
| 6 | ||
| 1 | 7 | test "zig fmt: remove extra whitespace at start and end of file with comment between" { |
| 2 | 8 | try testTransform( |
| 3 | 9 | \\ |
| ... | ... | @@ -2738,11 +2744,11 @@ test "zig fmt: preserve spacing" { |
| 2738 | 2744 | \\const std = @import("std"); |
| 2739 | 2745 | \\ |
| 2740 | 2746 | \\pub fn main() !void { |
| 2741 | \\ var stdout_file = std.io.getStdOut; | |
| 2742 | \\ var stdout_file = std.io.getStdOut; | |
| 2747 | \\ var stdout_file = std.lol.abcd; | |
| 2748 | \\ var stdout_file = std.lol.abcd; | |
| 2743 | 2749 | \\ |
| 2744 | \\ var stdout_file = std.io.getStdOut; | |
| 2745 | \\ var stdout_file = std.io.getStdOut; | |
| 2750 | \\ var stdout_file = std.lol.abcd; | |
| 2751 | \\ var stdout_file = std.lol.abcd; | |
| 2746 | 2752 | \\} |
| 2747 | 2753 | \\ |
| 2748 | 2754 | ); |
| ... | ... | @@ -6315,16 +6321,10 @@ test "ampersand" { |
| 6315 | 6321 | , &.{}); |
| 6316 | 6322 | } |
| 6317 | 6323 | |
| 6318 | const std = @import("std"); | |
| 6319 | const mem = std.mem; | |
| 6320 | const print = std.debug.print; | |
| 6321 | const io = std.io; | |
| 6322 | const maxInt = std.math.maxInt; | |
| 6323 | ||
| 6324 | 6324 | var fixed_buffer_mem: [100 * 1024]u8 = undefined; |
| 6325 | 6325 | |
| 6326 | 6326 | fn 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(); | |
| 6328 | 6328 | |
| 6329 | 6329 | var tree = try std.zig.Ast.parse(allocator, source, .zig); |
| 6330 | 6330 | defer tree.deinit(allocator); |
lib/std/zig/perf_test.zig+2-2| ... | ... | @@ -22,8 +22,8 @@ pub fn main() !void { |
| 22 | 22 | const bytes_per_sec_float = @as(f64, @floatFromInt(source.len * iterations)) / elapsed_s; |
| 23 | 23 | const bytes_per_sec = @as(u64, @intFromFloat(@floor(bytes_per_sec_float))); |
| 24 | 24 | |
| 25 | var stdout_file = std.io.getStdOut(); | |
| 26 | const stdout = stdout_file.writer(); | |
| 25 | var stdout_file: std.fs.File = .stdout(); | |
| 26 | const stdout = stdout_file.deprecatedWriter(); | |
| 27 | 27 | try stdout.print("parsing speed: {:.2}/s, {:.2} used \n", .{ |
| 28 | 28 | fmtIntSizeBin(bytes_per_sec), |
| 29 | 29 | fmtIntSizeBin(memory_used), |
lib/std/zig/render.zig+4-4| ... | ... | @@ -1564,7 +1564,7 @@ fn renderBuiltinCall( |
| 1564 | 1564 | defer r.gpa.free(new_string); |
| 1565 | 1565 | |
| 1566 | 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 | 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 | 2872 | .success => |codepoint| { |
| 2873 | 2873 | if (codepoint <= 0x7f) { |
| 2874 | 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 | 2876 | } else { |
| 2877 | 2877 | try writer.writeAll(escape_sequence); |
| 2878 | 2878 | } |
| ... | ... | @@ -2884,7 +2884,7 @@ fn renderIdentifierContents(writer: anytype, bytes: []const u8) !void { |
| 2884 | 2884 | }, |
| 2885 | 2885 | 0x00...('\\' - 1), ('\\' + 1)...0x7f => { |
| 2886 | 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 | 2888 | pos += 1; |
| 2889 | 2889 | }, |
| 2890 | 2890 | 0x80...0xff => { |
| ... | ... | @@ -3245,7 +3245,7 @@ fn AutoIndentingStream(comptime UnderlyingWriter: type) type { |
| 3245 | 3245 | return struct { |
| 3246 | 3246 | const Self = @This(); |
| 3247 | 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); | |
| 3249 | 3249 | |
| 3250 | 3250 | pub const IndentType = enum { |
| 3251 | 3251 | normal, |
lib/std/zig/string_literal.zig+3-10| ... | ... | @@ -44,14 +44,7 @@ pub const Error = union(enum) { |
| 44 | 44 | raw_string: []const u8, |
| 45 | 45 | }; |
| 46 | 46 | |
| 47 | fn formatMessage( | |
| 48 | self: FormatMessage, | |
| 49 | comptime f: []const u8, | |
| 50 | options: std.fmt.FormatOptions, | |
| 51 | writer: anytype, | |
| 52 | ) !void { | |
| 53 | _ = f; | |
| 54 | _ = options; | |
| 47 | fn formatMessage(self: FormatMessage, writer: *std.io.Writer) std.io.Writer.Error!void { | |
| 55 | 48 | switch (self.err) { |
| 56 | 49 | .invalid_escape_character => |bad_index| try writer.print( |
| 57 | 50 | "invalid escape character: '{c}'", |
| ... | ... | @@ -93,7 +86,7 @@ pub const Error = union(enum) { |
| 93 | 86 | } |
| 94 | 87 | } |
| 95 | 88 | |
| 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 | 90 | return .{ .data = .{ |
| 98 | 91 | .err = self, |
| 99 | 92 | .raw_string = raw_string, |
| ... | ... | @@ -322,7 +315,7 @@ test parseCharLiteral { |
| 322 | 315 | ); |
| 323 | 316 | } |
| 324 | 317 | |
| 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 | 319 | /// Asserts `bytes` has '"' at beginning and end. |
| 327 | 320 | pub fn parseWrite(writer: anytype, bytes: []const u8) error{OutOfMemory}!Result { |
| 328 | 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 | 391 | const current_arch = builtin.cpu.arch; |
| 392 | 392 | switch (current_arch) { |
| 393 | 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 | 396 | .aarch64, .aarch64_be => { |
| 397 | 397 | const registers = [12]u64{ |
| ... | ... | @@ -413,13 +413,13 @@ pub fn detectNativeCpuAndFeatures() ?Target.Cpu { |
| 413 | 413 | return core; |
| 414 | 414 | }, |
| 415 | 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 | 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 | 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 | 424 | else => {}, |
| 425 | 425 | } |
lib/std/zip.zig+12-12| ... | ... | @@ -106,7 +106,7 @@ pub const EndRecord = extern struct { |
| 106 | 106 | /// Find and return the end record for the given seekable zip stream. |
| 107 | 107 | /// Note that `seekable_stream` must be an instance of `std.io.SeekableStream` and |
| 108 | 108 | /// its context must also have a `.reader()` method that returns an instance of |
| 109 | /// `std.io.Reader`. | |
| 109 | /// `std.io.GenericReader`. | |
| 110 | 110 | pub fn findEndRecord(seekable_stream: anytype, stream_len: u64) !EndRecord { |
| 111 | 111 | var buf: [@sizeOf(EndRecord) + std.math.maxInt(u16)]u8 = undefined; |
| 112 | 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 | 124 | |
| 125 | 125 | try seekable_stream.seekTo(stream_len - @as(u64, new_loaded_len)); |
| 126 | 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 | 128 | if (len != read_len) |
| 129 | 129 | return error.ZipTruncated; |
| 130 | 130 | loaded_len = new_loaded_len; |
| ... | ... | @@ -295,7 +295,7 @@ pub fn Iterator(comptime SeekableStream: type) type { |
| 295 | 295 | if (locator_end_offset > stream_len) |
| 296 | 296 | return error.ZipTruncated; |
| 297 | 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 | 299 | if (!std.mem.eql(u8, &locator.signature, &end_locator64_sig)) |
| 300 | 300 | return error.ZipBadLocatorSig; |
| 301 | 301 | if (locator.zip64_disk_count != 0) |
| ... | ... | @@ -305,7 +305,7 @@ pub fn Iterator(comptime SeekableStream: type) type { |
| 305 | 305 | |
| 306 | 306 | try stream.seekTo(locator.record_file_offset); |
| 307 | 307 | |
| 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); | |
| 309 | 309 | |
| 310 | 310 | if (!std.mem.eql(u8, &record64.signature, &end_record64_sig)) |
| 311 | 311 | return error.ZipBadEndRecord64Sig; |
| ... | ... | @@ -357,7 +357,7 @@ pub fn Iterator(comptime SeekableStream: type) type { |
| 357 | 357 | |
| 358 | 358 | const header_zip_offset = self.cd_zip_offset + self.cd_record_offset; |
| 359 | 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 | 361 | if (!std.mem.eql(u8, &header.signature, &central_file_header_sig)) |
| 362 | 362 | return error.ZipBadCdOffset; |
| 363 | 363 | |
| ... | ... | @@ -386,7 +386,7 @@ pub fn Iterator(comptime SeekableStream: type) type { |
| 386 | 386 | |
| 387 | 387 | { |
| 388 | 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 | 390 | if (len != extra.len) |
| 391 | 391 | return error.ZipTruncated; |
| 392 | 392 | } |
| ... | ... | @@ -449,7 +449,7 @@ pub fn Iterator(comptime SeekableStream: type) type { |
| 449 | 449 | try stream.seekTo(self.header_zip_offset + @sizeOf(CentralDirectoryFileHeader)); |
| 450 | 450 | |
| 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 | 453 | if (len != filename.len) |
| 454 | 454 | return error.ZipBadFileOffset; |
| 455 | 455 | } |
| ... | ... | @@ -457,7 +457,7 @@ pub fn Iterator(comptime SeekableStream: type) type { |
| 457 | 457 | const local_data_header_offset: u64 = local_data_header_offset: { |
| 458 | 458 | const local_header = blk: { |
| 459 | 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 | 462 | if (!std.mem.eql(u8, &local_header.signature, &local_file_header_sig)) |
| 463 | 463 | return error.ZipBadFileOffset; |
| ... | ... | @@ -483,7 +483,7 @@ pub fn Iterator(comptime SeekableStream: type) type { |
| 483 | 483 | |
| 484 | 484 | { |
| 485 | 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 | 487 | if (len != extra.len) |
| 488 | 488 | return error.ZipTruncated; |
| 489 | 489 | } |
| ... | ... | @@ -552,12 +552,12 @@ pub fn Iterator(comptime SeekableStream: type) type { |
| 552 | 552 | @as(u64, @sizeOf(LocalFileHeader)) + |
| 553 | 553 | local_data_header_offset; |
| 554 | 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 | 556 | const crc = try decompress( |
| 557 | 557 | self.compression_method, |
| 558 | 558 | self.uncompressed_size, |
| 559 | 559 | limited_reader.reader(), |
| 560 | out_file.writer(), | |
| 560 | out_file.deprecatedWriter(), | |
| 561 | 561 | ); |
| 562 | 562 | if (limited_reader.bytes_left != 0) |
| 563 | 563 | return error.ZipDecompressTruncated; |
| ... | ... | @@ -617,7 +617,7 @@ pub const ExtractOptions = struct { |
| 617 | 617 | /// Extract the zipped files inside `seekable_stream` to the given `dest` directory. |
| 618 | 618 | /// Note that `seekable_stream` must be an instance of `std.io.SeekableStream` and |
| 619 | 619 | /// its context must also have a `.reader()` method that returns an instance of |
| 620 | /// `std.io.Reader`. | |
| 620 | /// `std.io.GenericReader`. | |
| 621 | 621 | pub fn extract(dest: std.fs.Dir, seekable_stream: anytype, options: ExtractOptions) !void { |
| 622 | 622 | const SeekableStream = @TypeOf(seekable_stream); |
| 623 | 623 | var iter = try Iterator(SeekableStream).init(seekable_stream); |
lib/std/zip/test.zig+1-1| ... | ... | @@ -33,7 +33,7 @@ pub fn expectFiles( |
| 33 | 33 | var file = try dir.openFile(normalized_sub_path, .{}); |
| 34 | 34 | defer file.close(); |
| 35 | 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 | 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 | 64 | } |
| 65 | 65 | }; |
| 66 | 66 | |
| 67 | fn formatMessage( | |
| 68 | self: []const u8, | |
| 69 | comptime f: []const u8, | |
| 70 | options: std.fmt.FormatOptions, | |
| 71 | writer: anytype, | |
| 72 | ) !void { | |
| 73 | _ = f; | |
| 74 | _ = options; | |
| 75 | ||
| 67 | fn formatMessage(self: []const u8, w: *std.io.Writer) std.io.Writer.Error!void { | |
| 76 | 68 | // Just writes the string for now, but we're keeping this behind a formatter so we have |
| 77 | 69 | // the option to extend it in the future to print more advanced messages (like `Error` |
| 78 | 70 | // does) without breaking the API. |
| 79 | try writer.writeAll(self); | |
| 71 | try w.writeAll(self); | |
| 80 | 72 | } |
| 81 | 73 | |
| 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 | 75 | return .{ .data = switch (self) { |
| 84 | 76 | .zoir => |note| note.msg.get(diag.zoir), |
| 85 | 77 | .type_check => |note| note.msg, |
| ... | ... | @@ -155,21 +147,14 @@ pub const Error = union(enum) { |
| 155 | 147 | diag: *const Diagnostics, |
| 156 | 148 | }; |
| 157 | 149 | |
| 158 | fn formatMessage( | |
| 159 | self: FormatMessage, | |
| 160 | comptime f: []const u8, | |
| 161 | options: std.fmt.FormatOptions, | |
| 162 | writer: anytype, | |
| 163 | ) !void { | |
| 164 | _ = f; | |
| 165 | _ = options; | |
| 150 | fn formatMessage(self: FormatMessage, w: *std.io.Writer) std.io.Writer.Error!void { | |
| 166 | 151 | switch (self.err) { |
| 167 | .zoir => |err| try writer.writeAll(err.msg.get(self.diag.zoir)), | |
| 168 | .type_check => |tc| try writer.writeAll(tc.message), | |
| 152 | .zoir => |err| try w.writeAll(err.msg.get(self.diag.zoir)), | |
| 153 | .type_check => |tc| try w.writeAll(tc.message), | |
| 169 | 154 | } |
| 170 | 155 | } |
| 171 | 156 | |
| 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 | 158 | return .{ .data = .{ |
| 174 | 159 | .err = self, |
| 175 | 160 | .diag = diag, |
| ... | ... | @@ -241,25 +226,18 @@ pub const Diagnostics = struct { |
| 241 | 226 | return .{ .diag = self }; |
| 242 | 227 | } |
| 243 | 228 | |
| 244 | pub fn format( | |
| 245 | self: *const @This(), | |
| 246 | comptime fmt: []const u8, | |
| 247 | options: std.fmt.FormatOptions, | |
| 248 | writer: anytype, | |
| 249 | ) !void { | |
| 250 | _ = fmt; | |
| 251 | _ = options; | |
| 229 | pub fn format(self: *const @This(), w: *std.io.Writer) std.io.Writer.Error!void { | |
| 252 | 230 | var errors = self.iterateErrors(); |
| 253 | 231 | while (errors.next()) |err| { |
| 254 | 232 | const loc = err.getLocation(self); |
| 255 | 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 }); | |
| 257 | 235 | |
| 258 | 236 | var notes = err.iterateNotes(self); |
| 259 | 237 | while (notes.next()) |note| { |
| 260 | 238 | const note_loc = note.getLocation(self); |
| 261 | 239 | const note_msg = note.fmtMessage(self); |
| 262 | try writer.print("{}:{}: note: {s}\n", .{ | |
| 240 | try w.print("{d}:{d}: note: {f}\n", .{ | |
| 263 | 241 | note_loc.line + 1, |
| 264 | 242 | note_loc.column + 1, |
| 265 | 243 | note_msg, |
| ... | ... | @@ -646,7 +624,7 @@ const Parser = struct { |
| 646 | 624 | .failure => |err| { |
| 647 | 625 | const token = self.ast.nodeMainToken(ast_node); |
| 648 | 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 | } |
| 652 | 630 | |
| ... | ... | @@ -1087,7 +1065,10 @@ const Parser = struct { |
| 1087 | 1065 | try writer.writeAll(msg); |
| 1088 | 1066 | inline for (info.fields, 0..) |field_info, i| { |
| 1089 | 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 | 1073 | break :b .{ |
| 1093 | 1074 | .token = token, |
| ... | ... | @@ -1298,7 +1279,7 @@ test "std.zon ast errors" { |
| 1298 | 1279 | error.ParseZon, |
| 1299 | 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 | } |
| 1303 | 1284 | |
| 1304 | 1285 | test "std.zon comments" { |
| ... | ... | @@ -1320,7 +1301,7 @@ test "std.zon comments" { |
| 1320 | 1301 | , &diag, .{})); |
| 1321 | 1302 | try std.testing.expectFmt( |
| 1322 | 1303 | "1:1: error: expected expression, found 'a document comment'\n", |
| 1323 | "{}", | |
| 1304 | "{f}", | |
| 1324 | 1305 | .{diag}, |
| 1325 | 1306 | ); |
| 1326 | 1307 | } |
| ... | ... | @@ -1341,7 +1322,7 @@ test "std.zon failure/oom formatting" { |
| 1341 | 1322 | &diag, |
| 1342 | 1323 | .{}, |
| 1343 | 1324 | )); |
| 1344 | try std.testing.expectFmt("", "{}", .{diag}); | |
| 1325 | try std.testing.expectFmt("", "{f}", .{diag}); | |
| 1345 | 1326 | } |
| 1346 | 1327 | |
| 1347 | 1328 | test "std.zon fromSlice syntax error" { |
| ... | ... | @@ -1421,7 +1402,7 @@ test "std.zon unions" { |
| 1421 | 1402 | \\1:4: note: supported: 'x', 'y' |
| 1422 | 1403 | \\ |
| 1423 | 1404 | , |
| 1424 | "{}", | |
| 1405 | "{f}", | |
| 1425 | 1406 | .{diag}, |
| 1426 | 1407 | ); |
| 1427 | 1408 | } |
| ... | ... | @@ -1435,7 +1416,7 @@ test "std.zon unions" { |
| 1435 | 1416 | error.ParseZon, |
| 1436 | 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 | } |
| 1440 | 1421 | |
| 1441 | 1422 | // Extra field |
| ... | ... | @@ -1447,7 +1428,7 @@ test "std.zon unions" { |
| 1447 | 1428 | error.ParseZon, |
| 1448 | 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 | } |
| 1452 | 1433 | |
| 1453 | 1434 | // No fields |
| ... | ... | @@ -1459,7 +1440,7 @@ test "std.zon unions" { |
| 1459 | 1440 | error.ParseZon, |
| 1460 | 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 | } |
| 1464 | 1445 | |
| 1465 | 1446 | // Enum literals cannot coerce into untagged unions |
| ... | ... | @@ -1468,7 +1449,7 @@ test "std.zon unions" { |
| 1468 | 1449 | var diag: Diagnostics = .{}; |
| 1469 | 1450 | defer diag.deinit(gpa); |
| 1470 | 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 | } |
| 1473 | 1454 | |
| 1474 | 1455 | // Unknown field for enum literal coercion |
| ... | ... | @@ -1482,7 +1463,7 @@ test "std.zon unions" { |
| 1482 | 1463 | \\1:2: note: supported: 'x' |
| 1483 | 1464 | \\ |
| 1484 | 1465 | , |
| 1485 | "{}", | |
| 1466 | "{f}", | |
| 1486 | 1467 | .{diag}, |
| 1487 | 1468 | ); |
| 1488 | 1469 | } |
| ... | ... | @@ -1493,7 +1474,7 @@ test "std.zon unions" { |
| 1493 | 1474 | var diag: Diagnostics = .{}; |
| 1494 | 1475 | defer diag.deinit(gpa); |
| 1495 | 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 | } |
| 1499 | 1480 | |
| ... | ... | @@ -1549,7 +1530,7 @@ test "std.zon structs" { |
| 1549 | 1530 | \\1:12: note: supported: 'x', 'y' |
| 1550 | 1531 | \\ |
| 1551 | 1532 | , |
| 1552 | "{}", | |
| 1533 | "{f}", | |
| 1553 | 1534 | .{diag}, |
| 1554 | 1535 | ); |
| 1555 | 1536 | } |
| ... | ... | @@ -1567,7 +1548,7 @@ test "std.zon structs" { |
| 1567 | 1548 | \\1:4: error: duplicate struct field name |
| 1568 | 1549 | \\1:12: note: duplicate name here |
| 1569 | 1550 | \\ |
| 1570 | , "{}", .{diag}); | |
| 1551 | , "{f}", .{diag}); | |
| 1571 | 1552 | } |
| 1572 | 1553 | |
| 1573 | 1554 | // Ignore unknown fields |
| ... | ... | @@ -1592,7 +1573,7 @@ test "std.zon structs" { |
| 1592 | 1573 | \\1:4: error: unexpected field 'x' |
| 1593 | 1574 | \\1:4: note: none expected |
| 1594 | 1575 | \\ |
| 1595 | , "{}", .{diag}); | |
| 1576 | , "{f}", .{diag}); | |
| 1596 | 1577 | } |
| 1597 | 1578 | |
| 1598 | 1579 | // Missing field |
| ... | ... | @@ -1604,7 +1585,7 @@ test "std.zon structs" { |
| 1604 | 1585 | error.ParseZon, |
| 1605 | 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 | } |
| 1609 | 1590 | |
| 1610 | 1591 | // Default field |
| ... | ... | @@ -1631,7 +1612,7 @@ test "std.zon structs" { |
| 1631 | 1612 | try std.testing.expectFmt( |
| 1632 | 1613 | \\1:18: error: cannot initialize comptime field |
| 1633 | 1614 | \\ |
| 1634 | , "{}", .{diag}); | |
| 1615 | , "{f}", .{diag}); | |
| 1635 | 1616 | } |
| 1636 | 1617 | |
| 1637 | 1618 | // Enum field (regression test, we were previously getting the field name in an |
| ... | ... | @@ -1661,7 +1642,7 @@ test "std.zon structs" { |
| 1661 | 1642 | \\1:1: error: types are not available in ZON |
| 1662 | 1643 | \\1:1: note: replace the type with '.' |
| 1663 | 1644 | \\ |
| 1664 | , "{}", .{diag}); | |
| 1645 | , "{f}", .{diag}); | |
| 1665 | 1646 | } |
| 1666 | 1647 | |
| 1667 | 1648 | // Arrays |
| ... | ... | @@ -1674,7 +1655,7 @@ test "std.zon structs" { |
| 1674 | 1655 | \\1:1: error: types are not available in ZON |
| 1675 | 1656 | \\1:1: note: replace the type with '.' |
| 1676 | 1657 | \\ |
| 1677 | , "{}", .{diag}); | |
| 1658 | , "{f}", .{diag}); | |
| 1678 | 1659 | } |
| 1679 | 1660 | |
| 1680 | 1661 | // Slices |
| ... | ... | @@ -1687,7 +1668,7 @@ test "std.zon structs" { |
| 1687 | 1668 | \\1:1: error: types are not available in ZON |
| 1688 | 1669 | \\1:1: note: replace the type with '.' |
| 1689 | 1670 | \\ |
| 1690 | , "{}", .{diag}); | |
| 1671 | , "{f}", .{diag}); | |
| 1691 | 1672 | } |
| 1692 | 1673 | |
| 1693 | 1674 | // Tuples |
| ... | ... | @@ -1706,7 +1687,7 @@ test "std.zon structs" { |
| 1706 | 1687 | \\1:1: error: types are not available in ZON |
| 1707 | 1688 | \\1:1: note: replace the type with '.' |
| 1708 | 1689 | \\ |
| 1709 | , "{}", .{diag}); | |
| 1690 | , "{f}", .{diag}); | |
| 1710 | 1691 | } |
| 1711 | 1692 | |
| 1712 | 1693 | // Nested |
| ... | ... | @@ -1719,7 +1700,7 @@ test "std.zon structs" { |
| 1719 | 1700 | \\1:9: error: types are not available in ZON |
| 1720 | 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 | 1745 | error.ParseZon, |
| 1765 | 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 | } |
| 1769 | 1750 | |
| 1770 | 1751 | // Extra field |
| ... | ... | @@ -1778,7 +1759,7 @@ test "std.zon tuples" { |
| 1778 | 1759 | ); |
| 1779 | 1760 | try std.testing.expectFmt( |
| 1780 | 1761 | "1:2: error: missing tuple field with index 1\n", |
| 1781 | "{}", | |
| 1762 | "{f}", | |
| 1782 | 1763 | .{diag}, |
| 1783 | 1764 | ); |
| 1784 | 1765 | } |
| ... | ... | @@ -1792,7 +1773,7 @@ test "std.zon tuples" { |
| 1792 | 1773 | error.ParseZon, |
| 1793 | 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 | } |
| 1797 | 1778 | |
| 1798 | 1779 | // Struct with missing field names |
| ... | ... | @@ -1804,7 +1785,7 @@ test "std.zon tuples" { |
| 1804 | 1785 | error.ParseZon, |
| 1805 | 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 | } |
| 1809 | 1790 | |
| 1810 | 1791 | // Comptime field |
| ... | ... | @@ -1824,7 +1805,7 @@ test "std.zon tuples" { |
| 1824 | 1805 | try std.testing.expectFmt( |
| 1825 | 1806 | \\1:9: error: cannot initialize comptime field |
| 1826 | 1807 | \\ |
| 1827 | , "{}", .{diag}); | |
| 1808 | , "{f}", .{diag}); | |
| 1828 | 1809 | } |
| 1829 | 1810 | } |
| 1830 | 1811 | |
| ... | ... | @@ -1936,7 +1917,7 @@ test "std.zon arrays and slices" { |
| 1936 | 1917 | ); |
| 1937 | 1918 | try std.testing.expectFmt( |
| 1938 | 1919 | "1:3: error: index 0 outside of array of length 0\n", |
| 1939 | "{}", | |
| 1920 | "{f}", | |
| 1940 | 1921 | .{diag}, |
| 1941 | 1922 | ); |
| 1942 | 1923 | } |
| ... | ... | @@ -1951,7 +1932,7 @@ test "std.zon arrays and slices" { |
| 1951 | 1932 | ); |
| 1952 | 1933 | try std.testing.expectFmt( |
| 1953 | 1934 | "1:8: error: index 1 outside of array of length 1\n", |
| 1954 | "{}", | |
| 1935 | "{f}", | |
| 1955 | 1936 | .{diag}, |
| 1956 | 1937 | ); |
| 1957 | 1938 | } |
| ... | ... | @@ -1966,7 +1947,7 @@ test "std.zon arrays and slices" { |
| 1966 | 1947 | ); |
| 1967 | 1948 | try std.testing.expectFmt( |
| 1968 | 1949 | "1:2: error: expected 2 array elements; found 1\n", |
| 1969 | "{}", | |
| 1950 | "{f}", | |
| 1970 | 1951 | .{diag}, |
| 1971 | 1952 | ); |
| 1972 | 1953 | } |
| ... | ... | @@ -1981,7 +1962,7 @@ test "std.zon arrays and slices" { |
| 1981 | 1962 | ); |
| 1982 | 1963 | try std.testing.expectFmt( |
| 1983 | 1964 | "1:2: error: expected 3 array elements; found 0\n", |
| 1984 | "{}", | |
| 1965 | "{f}", | |
| 1985 | 1966 | .{diag}, |
| 1986 | 1967 | ); |
| 1987 | 1968 | } |
| ... | ... | @@ -1996,7 +1977,7 @@ test "std.zon arrays and slices" { |
| 1996 | 1977 | error.ParseZon, |
| 1997 | 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 | } |
| 2001 | 1982 | |
| 2002 | 1983 | // Slice |
| ... | ... | @@ -2007,7 +1988,7 @@ test "std.zon arrays and slices" { |
| 2007 | 1988 | error.ParseZon, |
| 2008 | 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 | } |
| 2013 | 1994 | |
| ... | ... | @@ -2021,7 +2002,7 @@ test "std.zon arrays and slices" { |
| 2021 | 2002 | error.ParseZon, |
| 2022 | 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 | } |
| 2026 | 2007 | |
| 2027 | 2008 | // Slice |
| ... | ... | @@ -2032,7 +2013,7 @@ test "std.zon arrays and slices" { |
| 2032 | 2013 | error.ParseZon, |
| 2033 | 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 | } |
| 2038 | 2019 | |
| ... | ... | @@ -2046,7 +2027,7 @@ test "std.zon arrays and slices" { |
| 2046 | 2027 | ); |
| 2047 | 2028 | try std.testing.expectFmt( |
| 2048 | 2029 | "1:3: error: pointers are not available in ZON\n", |
| 2049 | "{}", | |
| 2030 | "{f}", | |
| 2050 | 2031 | .{diag}, |
| 2051 | 2032 | ); |
| 2052 | 2033 | } |
| ... | ... | @@ -2085,7 +2066,7 @@ test "std.zon string literal" { |
| 2085 | 2066 | error.ParseZon, |
| 2086 | 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 | } |
| 2090 | 2071 | |
| 2091 | 2072 | { |
| ... | ... | @@ -2095,7 +2076,7 @@ test "std.zon string literal" { |
| 2095 | 2076 | error.ParseZon, |
| 2096 | 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 | } |
| 2101 | 2082 | |
| ... | ... | @@ -2112,7 +2093,7 @@ test "std.zon string literal" { |
| 2112 | 2093 | error.ParseZon, |
| 2113 | 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 | } |
| 2117 | 2098 | |
| 2118 | 2099 | { |
| ... | ... | @@ -2122,7 +2103,7 @@ test "std.zon string literal" { |
| 2122 | 2103 | error.ParseZon, |
| 2123 | 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 | } |
| 2128 | 2109 | |
| ... | ... | @@ -2164,7 +2145,7 @@ test "std.zon string literal" { |
| 2164 | 2145 | error.ParseZon, |
| 2165 | 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 | } |
| 2169 | 2150 | |
| 2170 | 2151 | { |
| ... | ... | @@ -2174,7 +2155,7 @@ test "std.zon string literal" { |
| 2174 | 2155 | error.ParseZon, |
| 2175 | 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 | } |
| 2180 | 2161 | |
| ... | ... | @@ -2186,7 +2167,7 @@ test "std.zon string literal" { |
| 2186 | 2167 | error.ParseZon, |
| 2187 | 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 | } |
| 2191 | 2172 | |
| 2192 | 2173 | // Expecting string literal, getting an incompatible tuple |
| ... | ... | @@ -2197,7 +2178,7 @@ test "std.zon string literal" { |
| 2197 | 2178 | error.ParseZon, |
| 2198 | 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 | } |
| 2202 | 2183 | |
| 2203 | 2184 | // Invalid string literal |
| ... | ... | @@ -2208,7 +2189,7 @@ test "std.zon string literal" { |
| 2208 | 2189 | error.ParseZon, |
| 2209 | 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 | } |
| 2213 | 2194 | |
| 2214 | 2195 | // Slice wrong child type |
| ... | ... | @@ -2220,7 +2201,7 @@ test "std.zon string literal" { |
| 2220 | 2201 | error.ParseZon, |
| 2221 | 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 | } |
| 2225 | 2206 | |
| 2226 | 2207 | { |
| ... | ... | @@ -2230,7 +2211,7 @@ test "std.zon string literal" { |
| 2230 | 2211 | error.ParseZon, |
| 2231 | 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 | } |
| 2236 | 2217 | |
| ... | ... | @@ -2243,7 +2224,7 @@ test "std.zon string literal" { |
| 2243 | 2224 | error.ParseZon, |
| 2244 | 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 | } |
| 2248 | 2229 | |
| 2249 | 2230 | { |
| ... | ... | @@ -2253,7 +2234,7 @@ test "std.zon string literal" { |
| 2253 | 2234 | error.ParseZon, |
| 2254 | 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 | } |
| 2259 | 2240 | |
| ... | ... | @@ -2327,7 +2308,7 @@ test "std.zon enum literals" { |
| 2327 | 2308 | \\1:2: note: supported: 'foo', 'bar', 'baz', '@"ab\nc"' |
| 2328 | 2309 | \\ |
| 2329 | 2310 | , |
| 2330 | "{}", | |
| 2311 | "{f}", | |
| 2331 | 2312 | .{diag}, |
| 2332 | 2313 | ); |
| 2333 | 2314 | } |
| ... | ... | @@ -2345,7 +2326,7 @@ test "std.zon enum literals" { |
| 2345 | 2326 | \\1:2: note: supported: 'foo', 'bar', 'baz', '@"ab\nc"' |
| 2346 | 2327 | \\ |
| 2347 | 2328 | , |
| 2348 | "{}", | |
| 2329 | "{f}", | |
| 2349 | 2330 | .{diag}, |
| 2350 | 2331 | ); |
| 2351 | 2332 | } |
| ... | ... | @@ -2358,7 +2339,7 @@ test "std.zon enum literals" { |
| 2358 | 2339 | error.ParseZon, |
| 2359 | 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 | } |
| 2363 | 2344 | |
| 2364 | 2345 | // Test embedded nulls in an identifier |
| ... | ... | @@ -2371,7 +2352,7 @@ test "std.zon enum literals" { |
| 2371 | 2352 | ); |
| 2372 | 2353 | try std.testing.expectFmt( |
| 2373 | 2354 | "1:2: error: identifier cannot contain null bytes\n", |
| 2374 | "{}", | |
| 2355 | "{f}", | |
| 2375 | 2356 | .{diag}, |
| 2376 | 2357 | ); |
| 2377 | 2358 | } |
| ... | ... | @@ -2397,13 +2378,13 @@ test "std.zon parse bool" { |
| 2397 | 2378 | \\1:2: note: ZON allows identifiers 'true', 'false', 'null', 'inf', and 'nan' |
| 2398 | 2379 | \\1:2: note: precede identifier with '.' for an enum literal |
| 2399 | 2380 | \\ |
| 2400 | , "{}", .{diag}); | |
| 2381 | , "{f}", .{diag}); | |
| 2401 | 2382 | } |
| 2402 | 2383 | { |
| 2403 | 2384 | var diag: Diagnostics = .{}; |
| 2404 | 2385 | defer diag.deinit(gpa); |
| 2405 | 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 | } |
| 2409 | 2390 | |
| ... | ... | @@ -2476,7 +2457,7 @@ test "std.zon parse int" { |
| 2476 | 2457 | )); |
| 2477 | 2458 | try std.testing.expectFmt( |
| 2478 | 2459 | "1:1: error: type 'i66' cannot represent value\n", |
| 2479 | "{}", | |
| 2460 | "{f}", | |
| 2480 | 2461 | .{diag}, |
| 2481 | 2462 | ); |
| 2482 | 2463 | } |
| ... | ... | @@ -2492,7 +2473,7 @@ test "std.zon parse int" { |
| 2492 | 2473 | )); |
| 2493 | 2474 | try std.testing.expectFmt( |
| 2494 | 2475 | "1:1: error: type 'i66' cannot represent value\n", |
| 2495 | "{}", | |
| 2476 | "{f}", | |
| 2496 | 2477 | .{diag}, |
| 2497 | 2478 | ); |
| 2498 | 2479 | } |
| ... | ... | @@ -2581,7 +2562,7 @@ test "std.zon parse int" { |
| 2581 | 2562 | try std.testing.expectError(error.ParseZon, fromSlice(u8, gpa, "32a32", &diag, .{})); |
| 2582 | 2563 | try std.testing.expectFmt( |
| 2583 | 2564 | "1:3: error: invalid digit 'a' for decimal base\n", |
| 2584 | "{}", | |
| 2565 | "{f}", | |
| 2585 | 2566 | .{diag}, |
| 2586 | 2567 | ); |
| 2587 | 2568 | } |
| ... | ... | @@ -2591,7 +2572,7 @@ test "std.zon parse int" { |
| 2591 | 2572 | var diag: Diagnostics = .{}; |
| 2592 | 2573 | defer diag.deinit(gpa); |
| 2593 | 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 | } |
| 2596 | 2577 | |
| 2597 | 2578 | // Failing because an int is out of range |
| ... | ... | @@ -2601,7 +2582,7 @@ test "std.zon parse int" { |
| 2601 | 2582 | try std.testing.expectError(error.ParseZon, fromSlice(u8, gpa, "256", &diag, .{})); |
| 2602 | 2583 | try std.testing.expectFmt( |
| 2603 | 2584 | "1:1: error: type 'u8' cannot represent value\n", |
| 2604 | "{}", | |
| 2585 | "{f}", | |
| 2605 | 2586 | .{diag}, |
| 2606 | 2587 | ); |
| 2607 | 2588 | } |
| ... | ... | @@ -2613,7 +2594,7 @@ test "std.zon parse int" { |
| 2613 | 2594 | try std.testing.expectError(error.ParseZon, fromSlice(i8, gpa, "-129", &diag, .{})); |
| 2614 | 2595 | try std.testing.expectFmt( |
| 2615 | 2596 | "1:1: error: type 'i8' cannot represent value\n", |
| 2616 | "{}", | |
| 2597 | "{f}", | |
| 2617 | 2598 | .{diag}, |
| 2618 | 2599 | ); |
| 2619 | 2600 | } |
| ... | ... | @@ -2625,7 +2606,7 @@ test "std.zon parse int" { |
| 2625 | 2606 | try std.testing.expectError(error.ParseZon, fromSlice(u8, gpa, "-1", &diag, .{})); |
| 2626 | 2607 | try std.testing.expectFmt( |
| 2627 | 2608 | "1:1: error: type 'u8' cannot represent value\n", |
| 2628 | "{}", | |
| 2609 | "{f}", | |
| 2629 | 2610 | .{diag}, |
| 2630 | 2611 | ); |
| 2631 | 2612 | } |
| ... | ... | @@ -2637,7 +2618,7 @@ test "std.zon parse int" { |
| 2637 | 2618 | try std.testing.expectError(error.ParseZon, fromSlice(u8, gpa, "1.5", &diag, .{})); |
| 2638 | 2619 | try std.testing.expectFmt( |
| 2639 | 2620 | "1:1: error: type 'u8' cannot represent value\n", |
| 2640 | "{}", | |
| 2621 | "{f}", | |
| 2641 | 2622 | .{diag}, |
| 2642 | 2623 | ); |
| 2643 | 2624 | } |
| ... | ... | @@ -2649,7 +2630,7 @@ test "std.zon parse int" { |
| 2649 | 2630 | try std.testing.expectError(error.ParseZon, fromSlice(u8, gpa, "-1.0", &diag, .{})); |
| 2650 | 2631 | try std.testing.expectFmt( |
| 2651 | 2632 | "1:1: error: type 'u8' cannot represent value\n", |
| 2652 | "{}", | |
| 2633 | "{f}", | |
| 2653 | 2634 | .{diag}, |
| 2654 | 2635 | ); |
| 2655 | 2636 | } |
| ... | ... | @@ -2664,7 +2645,7 @@ test "std.zon parse int" { |
| 2664 | 2645 | \\1:2: note: use '0' for an integer zero |
| 2665 | 2646 | \\1:2: note: use '-0.0' for a floating-point signed zero |
| 2666 | 2647 | \\ |
| 2667 | , "{}", .{diag}); | |
| 2648 | , "{f}", .{diag}); | |
| 2668 | 2649 | } |
| 2669 | 2650 | |
| 2670 | 2651 | // Negative integer zero casted to float |
| ... | ... | @@ -2677,7 +2658,7 @@ test "std.zon parse int" { |
| 2677 | 2658 | \\1:2: note: use '0' for an integer zero |
| 2678 | 2659 | \\1:2: note: use '-0.0' for a floating-point signed zero |
| 2679 | 2660 | \\ |
| 2680 | , "{}", .{diag}); | |
| 2661 | , "{f}", .{diag}); | |
| 2681 | 2662 | } |
| 2682 | 2663 | |
| 2683 | 2664 | // Negative float 0 is allowed |
| ... | ... | @@ -2693,7 +2674,7 @@ test "std.zon parse int" { |
| 2693 | 2674 | try std.testing.expectError(error.ParseZon, fromSlice(i8, gpa, "--2", &diag, .{})); |
| 2694 | 2675 | try std.testing.expectFmt( |
| 2695 | 2676 | "1:1: error: expected number or 'inf' after '-'\n", |
| 2696 | "{}", | |
| 2677 | "{f}", | |
| 2697 | 2678 | .{diag}, |
| 2698 | 2679 | ); |
| 2699 | 2680 | } |
| ... | ... | @@ -2707,7 +2688,7 @@ test "std.zon parse int" { |
| 2707 | 2688 | ); |
| 2708 | 2689 | try std.testing.expectFmt( |
| 2709 | 2690 | "1:1: error: expected number or 'inf' after '-'\n", |
| 2710 | "{}", | |
| 2691 | "{f}", | |
| 2711 | 2692 | .{diag}, |
| 2712 | 2693 | ); |
| 2713 | 2694 | } |
| ... | ... | @@ -2717,7 +2698,7 @@ test "std.zon parse int" { |
| 2717 | 2698 | var diag: Diagnostics = .{}; |
| 2718 | 2699 | defer diag.deinit(gpa); |
| 2719 | 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 | } |
| 2722 | 2703 | |
| 2723 | 2704 | // Notes on invalid int literal |
| ... | ... | @@ -2729,7 +2710,7 @@ test "std.zon parse int" { |
| 2729 | 2710 | \\1:1: error: number '0123' has leading zero |
| 2730 | 2711 | \\1:1: note: use '0o' prefix for octal literals |
| 2731 | 2712 | \\ |
| 2732 | , "{}", .{diag}); | |
| 2713 | , "{f}", .{diag}); | |
| 2733 | 2714 | } |
| 2734 | 2715 | } |
| 2735 | 2716 | |
| ... | ... | @@ -2742,7 +2723,7 @@ test "std.zon negative char" { |
| 2742 | 2723 | try std.testing.expectError(error.ParseZon, fromSlice(f32, gpa, "-'a'", &diag, .{})); |
| 2743 | 2724 | try std.testing.expectFmt( |
| 2744 | 2725 | "1:1: error: expected number or 'inf' after '-'\n", |
| 2745 | "{}", | |
| 2726 | "{f}", | |
| 2746 | 2727 | .{diag}, |
| 2747 | 2728 | ); |
| 2748 | 2729 | } |
| ... | ... | @@ -2752,7 +2733,7 @@ test "std.zon negative char" { |
| 2752 | 2733 | try std.testing.expectError(error.ParseZon, fromSlice(i16, gpa, "-'a'", &diag, .{})); |
| 2753 | 2734 | try std.testing.expectFmt( |
| 2754 | 2735 | "1:1: error: expected number or 'inf' after '-'\n", |
| 2755 | "{}", | |
| 2736 | "{f}", | |
| 2756 | 2737 | .{diag}, |
| 2757 | 2738 | ); |
| 2758 | 2739 | } |
| ... | ... | @@ -2841,7 +2822,7 @@ test "std.zon parse float" { |
| 2841 | 2822 | try std.testing.expectError(error.ParseZon, fromSlice(f32, gpa, "-nan", &diag, .{})); |
| 2842 | 2823 | try std.testing.expectFmt( |
| 2843 | 2824 | "1:1: error: expected number or 'inf' after '-'\n", |
| 2844 | "{}", | |
| 2825 | "{f}", | |
| 2845 | 2826 | .{diag}, |
| 2846 | 2827 | ); |
| 2847 | 2828 | } |
| ... | ... | @@ -2851,7 +2832,7 @@ test "std.zon parse float" { |
| 2851 | 2832 | var diag: Diagnostics = .{}; |
| 2852 | 2833 | defer diag.deinit(gpa); |
| 2853 | 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 | } |
| 2856 | 2837 | |
| 2857 | 2838 | // nan as int not allowed |
| ... | ... | @@ -2859,7 +2840,7 @@ test "std.zon parse float" { |
| 2859 | 2840 | var diag: Diagnostics = .{}; |
| 2860 | 2841 | defer diag.deinit(gpa); |
| 2861 | 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 | } |
| 2864 | 2845 | |
| 2865 | 2846 | // inf as int not allowed |
| ... | ... | @@ -2867,7 +2848,7 @@ test "std.zon parse float" { |
| 2867 | 2848 | var diag: Diagnostics = .{}; |
| 2868 | 2849 | defer diag.deinit(gpa); |
| 2869 | 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 | } |
| 2872 | 2853 | |
| 2873 | 2854 | // -inf as int not allowed |
| ... | ... | @@ -2875,7 +2856,7 @@ test "std.zon parse float" { |
| 2875 | 2856 | var diag: Diagnostics = .{}; |
| 2876 | 2857 | defer diag.deinit(gpa); |
| 2877 | 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 | } |
| 2880 | 2861 | |
| 2881 | 2862 | // Bad identifier as float |
| ... | ... | @@ -2888,7 +2869,7 @@ test "std.zon parse float" { |
| 2888 | 2869 | \\1:1: note: ZON allows identifiers 'true', 'false', 'null', 'inf', and 'nan' |
| 2889 | 2870 | \\1:1: note: precede identifier with '.' for an enum literal |
| 2890 | 2871 | \\ |
| 2891 | , "{}", .{diag}); | |
| 2872 | , "{f}", .{diag}); | |
| 2892 | 2873 | } |
| 2893 | 2874 | |
| 2894 | 2875 | { |
| ... | ... | @@ -2897,7 +2878,7 @@ test "std.zon parse float" { |
| 2897 | 2878 | try std.testing.expectError(error.ParseZon, fromSlice(f32, gpa, "-foo", &diag, .{})); |
| 2898 | 2879 | try std.testing.expectFmt( |
| 2899 | 2880 | "1:1: error: expected number or 'inf' after '-'\n", |
| 2900 | "{}", | |
| 2881 | "{f}", | |
| 2901 | 2882 | .{diag}, |
| 2902 | 2883 | ); |
| 2903 | 2884 | } |
| ... | ... | @@ -2910,7 +2891,7 @@ test "std.zon parse float" { |
| 2910 | 2891 | error.ParseZon, |
| 2911 | 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 | } |
| 2916 | 2897 | |
| ... | ... | @@ -3154,7 +3135,7 @@ test "std.zon vector" { |
| 3154 | 3135 | ); |
| 3155 | 3136 | try std.testing.expectFmt( |
| 3156 | 3137 | "1:2: error: expected 2 vector elements; found 1\n", |
| 3157 | "{}", | |
| 3138 | "{f}", | |
| 3158 | 3139 | .{diag}, |
| 3159 | 3140 | ); |
| 3160 | 3141 | } |
| ... | ... | @@ -3169,7 +3150,7 @@ test "std.zon vector" { |
| 3169 | 3150 | ); |
| 3170 | 3151 | try std.testing.expectFmt( |
| 3171 | 3152 | "1:2: error: expected 2 vector elements; found 3\n", |
| 3172 | "{}", | |
| 3153 | "{f}", | |
| 3173 | 3154 | .{diag}, |
| 3174 | 3155 | ); |
| 3175 | 3156 | } |
| ... | ... | @@ -3184,7 +3165,7 @@ test "std.zon vector" { |
| 3184 | 3165 | ); |
| 3185 | 3166 | try std.testing.expectFmt( |
| 3186 | 3167 | "1:8: error: expected type 'f32'\n", |
| 3187 | "{}", | |
| 3168 | "{f}", | |
| 3188 | 3169 | .{diag}, |
| 3189 | 3170 | ); |
| 3190 | 3171 | } |
| ... | ... | @@ -3197,7 +3178,7 @@ test "std.zon vector" { |
| 3197 | 3178 | error.ParseZon, |
| 3198 | 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 | } |
| 3202 | 3183 | |
| 3203 | 3184 | // Elements should get freed on error |
| ... | ... | @@ -3208,7 +3189,7 @@ test "std.zon vector" { |
| 3208 | 3189 | error.ParseZon, |
| 3209 | 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 | } |
| 3214 | 3195 | |
| ... | ... | @@ -3332,7 +3313,7 @@ test "std.zon add pointers" { |
| 3332 | 3313 | error.ParseZon, |
| 3333 | 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 | } |
| 3337 | 3318 | |
| 3338 | 3319 | { |
| ... | ... | @@ -3342,7 +3323,7 @@ test "std.zon add pointers" { |
| 3342 | 3323 | error.ParseZon, |
| 3343 | 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 | } |
| 3347 | 3328 | |
| 3348 | 3329 | { |
| ... | ... | @@ -3352,7 +3333,7 @@ test "std.zon add pointers" { |
| 3352 | 3333 | error.ParseZon, |
| 3353 | 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 | } |
| 3357 | 3338 | |
| 3358 | 3339 | { |
| ... | ... | @@ -3362,7 +3343,7 @@ test "std.zon add pointers" { |
| 3362 | 3343 | error.ParseZon, |
| 3363 | 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 | } |
| 3367 | 3348 | |
| 3368 | 3349 | { |
| ... | ... | @@ -3372,7 +3353,7 @@ test "std.zon add pointers" { |
| 3372 | 3353 | error.ParseZon, |
| 3373 | 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 | } |
| 3377 | 3358 | |
| 3378 | 3359 | { |
| ... | ... | @@ -3382,7 +3363,7 @@ test "std.zon add pointers" { |
| 3382 | 3363 | error.ParseZon, |
| 3383 | 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 | } |
| 3387 | 3368 | |
| 3388 | 3369 | { |
| ... | ... | @@ -3392,7 +3373,7 @@ test "std.zon add pointers" { |
| 3392 | 3373 | error.ParseZon, |
| 3393 | 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 | } |
| 3397 | 3378 | |
| 3398 | 3379 | { |
| ... | ... | @@ -3402,7 +3383,7 @@ test "std.zon add pointers" { |
| 3402 | 3383 | error.ParseZon, |
| 3403 | 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 | } |
| 3407 | 3388 | |
| 3408 | 3389 | { |
| ... | ... | @@ -3412,7 +3393,7 @@ test "std.zon add pointers" { |
| 3412 | 3393 | error.ParseZon, |
| 3413 | 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 | } |
| 3417 | 3398 | |
| 3418 | 3399 | { |
| ... | ... | @@ -3422,7 +3403,7 @@ test "std.zon add pointers" { |
| 3422 | 3403 | error.ParseZon, |
| 3423 | 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 | } |
| 3427 | 3408 | |
| 3428 | 3409 | { |
| ... | ... | @@ -3432,7 +3413,7 @@ test "std.zon add pointers" { |
| 3432 | 3413 | error.ParseZon, |
| 3433 | 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 | } |
| 3437 | 3418 | |
| 3438 | 3419 | { |
| ... | ... | @@ -3442,7 +3423,7 @@ test "std.zon add pointers" { |
| 3442 | 3423 | error.ParseZon, |
| 3443 | 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 | } |
| 3447 | 3428 | |
| 3448 | 3429 | { |
| ... | ... | @@ -3452,7 +3433,7 @@ test "std.zon add pointers" { |
| 3452 | 3433 | error.ParseZon, |
| 3453 | 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 | } |
| 3458 | 3439 |
lib/std/zon/stringify.zig+5-4| ... | ... | @@ -615,7 +615,8 @@ pub fn Serializer(Writer: type) type { |
| 615 | 615 | |
| 616 | 616 | /// Serialize an integer. |
| 617 | 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 | } |
| 620 | 621 | |
| 621 | 622 | /// Serialize a float. |
| ... | ... | @@ -645,7 +646,7 @@ pub fn Serializer(Writer: type) type { |
| 645 | 646 | /// |
| 646 | 647 | /// Escapes the identifier if necessary. |
| 647 | 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 | } |
| 650 | 651 | |
| 651 | 652 | /// Serialize `val` as a Unicode codepoint. |
| ... | ... | @@ -658,7 +659,7 @@ pub fn Serializer(Writer: type) type { |
| 658 | 659 | var buf: [8]u8 = undefined; |
| 659 | 660 | const len = std.unicode.utf8Encode(val, &buf) catch return error.InvalidCodepoint; |
| 660 | 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 | } |
| 663 | 664 | |
| 664 | 665 | /// Like `value`, but always serializes `val` as a tuple. |
| ... | ... | @@ -716,7 +717,7 @@ pub fn Serializer(Writer: type) type { |
| 716 | 717 | |
| 717 | 718 | /// Like `value`, but always serializes `val` as a string. |
| 718 | 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 | } |
| 721 | 722 | |
| 722 | 723 | /// Options for formatting multiline strings. |
lib/ubsan_rt.zig+37-60| ... | ... | @@ -119,14 +119,7 @@ const Value = extern struct { |
| 119 | 119 | } |
| 120 | 120 | } |
| 121 | 121 | |
| 122 | pub fn format( | |
| 123 | value: Value, | |
| 124 | comptime fmt: []const u8, | |
| 125 | _: std.fmt.FormatOptions, | |
| 126 | writer: anytype, | |
| 127 | ) !void { | |
| 128 | comptime assert(fmt.len == 0); | |
| 129 | ||
| 122 | pub fn format(value: Value, writer: *std.io.Writer) std.io.Writer.Error!void { | |
| 130 | 123 | // Work around x86_64 backend limitation. |
| 131 | 124 | if (builtin.zig_backend == .stage2_x86_64 and builtin.os.tag == .windows) { |
| 132 | 125 | try writer.writeAll("(unknown)"); |
| ... | ... | @@ -136,12 +129,12 @@ const Value = extern struct { |
| 136 | 129 | switch (value.td.kind) { |
| 137 | 130 | .integer => { |
| 138 | 131 | if (value.td.isSigned()) { |
| 139 | try writer.print("{}", .{value.getSignedInteger()}); | |
| 132 | try writer.print("{d}", .{value.getSignedInteger()}); | |
| 140 | 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 | 138 | .unknown => try writer.writeAll("(unknown)"), |
| 146 | 139 | } |
| 147 | 140 | } |
| ... | ... | @@ -172,17 +165,12 @@ fn overflowHandler( |
| 172 | 165 | ) callconv(.c) noreturn { |
| 173 | 166 | const lhs: Value = .{ .handle = lhs_handle, .td = data.td }; |
| 174 | 167 | const rhs: Value = .{ .handle = rhs_handle, .td = data.td }; |
| 175 | ||
| 176 | const is_signed = data.td.isSigned(); | |
| 177 | const fmt = "{s} integer overflow: " ++ "{} " ++ | |
| 178 | operator ++ " {} cannot be represented in type {s}"; | |
| 179 | ||
| 180 | panic(@returnAddress(), fmt, .{ | |
| 181 | if (is_signed) "signed" else "unsigned", | |
| 182 | lhs, | |
| 183 | rhs, | |
| 184 | data.td.getName(), | |
| 185 | }); | |
| 168 | const signed_str = if (data.td.isSigned()) "signed" else "unsigned"; | |
| 169 | panic( | |
| 170 | @returnAddress(), | |
| 171 | "{s} integer overflow: {f} " ++ operator ++ " {f} cannot be represented in type {s}", | |
| 172 | .{ signed_str, lhs, rhs, data.td.getName() }, | |
| 173 | ); | |
| 186 | 174 | } |
| 187 | 175 | }; |
| 188 | 176 | |
| ... | ... | @@ -201,11 +189,9 @@ fn negationHandler( |
| 201 | 189 | value_handle: ValueHandle, |
| 202 | 190 | ) callconv(.c) noreturn { |
| 203 | 191 | const value: Value = .{ .handle = value_handle, .td = data.td }; |
| 204 | panic( | |
| 205 | @returnAddress(), | |
| 206 | "negation of {} cannot be represented in type {s}", | |
| 207 | .{ value, data.td.getName() }, | |
| 208 | ); | |
| 192 | panic(@returnAddress(), "negation of {f} cannot be represented in type {s}", .{ | |
| 193 | value, data.td.getName(), | |
| 194 | }); | |
| 209 | 195 | } |
| 210 | 196 | |
| 211 | 197 | fn divRemHandlerAbort( |
| ... | ... | @@ -225,11 +211,9 @@ fn divRemHandler( |
| 225 | 211 | const rhs: Value = .{ .handle = rhs_handle, .td = data.td }; |
| 226 | 212 | |
| 227 | 213 | if (rhs.isMinusOne()) { |
| 228 | panic( | |
| 229 | @returnAddress(), | |
| 230 | "division of {} by -1 cannot be represented in type {s}", | |
| 231 | .{ lhs, data.td.getName() }, | |
| 232 | ); | |
| 214 | panic(@returnAddress(), "division of {f} by -1 cannot be represented in type {s}", .{ | |
| 215 | lhs, data.td.getName(), | |
| 216 | }); | |
| 233 | 217 | } else panic(@returnAddress(), "division by zero", .{}); |
| 234 | 218 | } |
| 235 | 219 | |
| ... | ... | @@ -269,8 +253,8 @@ fn alignmentAssumptionHandler( |
| 269 | 253 | if (maybe_offset) |offset| { |
| 270 | 254 | panic( |
| 271 | 255 | @returnAddress(), |
| 272 | "assumption of {} byte alignment (with offset of {} byte) for pointer of type {s} failed\n" ++ | |
| 273 | "offset address is {} aligned, misalignment offset is {} bytes", | |
| 256 | "assumption of {f} byte alignment (with offset of {d} byte) for pointer of type {s} failed\n" ++ | |
| 257 | "offset address is {d} aligned, misalignment offset is {d} bytes", | |
| 274 | 258 | .{ |
| 275 | 259 | alignment, |
| 276 | 260 | @intFromPtr(offset), |
| ... | ... | @@ -282,8 +266,8 @@ fn alignmentAssumptionHandler( |
| 282 | 266 | } else { |
| 283 | 267 | panic( |
| 284 | 268 | @returnAddress(), |
| 285 | "assumption of {} byte alignment for pointer of type {s} failed\n" ++ | |
| 286 | "address is {} aligned, misalignment offset is {} bytes", | |
| 269 | "assumption of {f} byte alignment for pointer of type {s} failed\n" ++ | |
| 270 | "address is {d} aligned, misalignment offset is {d} bytes", | |
| 287 | 271 | .{ |
| 288 | 272 | alignment, |
| 289 | 273 | data.td.getName(), |
| ... | ... | @@ -320,21 +304,21 @@ fn shiftOob( |
| 320 | 304 | rhs.getPositiveInteger() >= data.lhs_type.getIntegerSize()) |
| 321 | 305 | { |
| 322 | 306 | if (rhs.isNegative()) { |
| 323 | panic(@returnAddress(), "shift exponent {} is negative", .{rhs}); | |
| 307 | panic(@returnAddress(), "shift exponent {f} is negative", .{rhs}); | |
| 324 | 308 | } else { |
| 325 | 309 | panic( |
| 326 | 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 | 312 | .{ rhs, data.lhs_type.getIntegerSize(), data.lhs_type.getName() }, |
| 329 | 313 | ); |
| 330 | 314 | } |
| 331 | 315 | } else { |
| 332 | 316 | if (lhs.isNegative()) { |
| 333 | panic(@returnAddress(), "left shift of negative value {}", .{lhs}); | |
| 317 | panic(@returnAddress(), "left shift of negative value {f}", .{lhs}); | |
| 334 | 318 | } else { |
| 335 | 319 | panic( |
| 336 | 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 | 322 | .{ lhs, rhs, data.lhs_type.getName() }, |
| 339 | 323 | ); |
| 340 | 324 | } |
| ... | ... | @@ -359,11 +343,10 @@ fn outOfBounds( |
| 359 | 343 | index_handle: ValueHandle, |
| 360 | 344 | ) callconv(.c) noreturn { |
| 361 | 345 | const index: Value = .{ .handle = index_handle, .td = data.index_type }; |
| 362 | panic( | |
| 363 | @returnAddress(), | |
| 364 | "index {} out of bounds for type {s}", | |
| 365 | .{ index, data.array_type.getName() }, | |
| 366 | ); | |
| 346 | panic(@returnAddress(), "index {f} out of bounds for type {s}", .{ | |
| 347 | index, | |
| 348 | data.array_type.getName(), | |
| 349 | }); | |
| 367 | 350 | } |
| 368 | 351 | |
| 369 | 352 | const PointerOverflowData = extern struct { |
| ... | ... | @@ -387,7 +370,7 @@ fn pointerOverflow( |
| 387 | 370 | if (result == 0) { |
| 388 | 371 | panic(@returnAddress(), "applying zero offset to null pointer", .{}); |
| 389 | 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 | 375 | } else { |
| 393 | 376 | if (result == 0) { |
| ... | ... | @@ -483,7 +466,7 @@ fn typeMismatch( |
| 483 | 466 | } else if (!std.mem.isAligned(handle, alignment)) { |
| 484 | 467 | panic( |
| 485 | 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 | 470 | .{ data.kind.getName(), handle, data.td.getName(), alignment }, |
| 488 | 471 | ); |
| 489 | 472 | } else { |
| ... | ... | @@ -531,7 +514,7 @@ fn nonNullArgAbort(data: *const NonNullArgData) callconv(.c) noreturn { |
| 531 | 514 | fn nonNullArg(data: *const NonNullArgData) callconv(.c) noreturn { |
| 532 | 515 | panic( |
| 533 | 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 | 518 | .{data.arg_index}, |
| 536 | 519 | ); |
| 537 | 520 | } |
| ... | ... | @@ -553,11 +536,9 @@ fn loadInvalidValue( |
| 553 | 536 | value_handle: ValueHandle, |
| 554 | 537 | ) callconv(.c) noreturn { |
| 555 | 538 | const value: Value = .{ .handle = value_handle, .td = data.td }; |
| 556 | panic( | |
| 557 | @returnAddress(), | |
| 558 | "load of value {}, which is not valid for type {s}", | |
| 559 | .{ value, data.td.getName() }, | |
| 560 | ); | |
| 539 | panic(@returnAddress(), "load of value {f}, which is not valid for type {s}", .{ | |
| 540 | value, data.td.getName(), | |
| 541 | }); | |
| 561 | 542 | } |
| 562 | 543 | |
| 563 | 544 | const InvalidBuiltinData = extern struct { |
| ... | ... | @@ -596,11 +577,7 @@ fn vlaBoundNotPositive( |
| 596 | 577 | bound_handle: ValueHandle, |
| 597 | 578 | ) callconv(.c) noreturn { |
| 598 | 579 | const bound: Value = .{ .handle = bound_handle, .td = data.td }; |
| 599 | panic( | |
| 600 | @returnAddress(), | |
| 601 | "variable length array bound evaluates to non-positive value {}", | |
| 602 | .{bound}, | |
| 603 | ); | |
| 580 | panic(@returnAddress(), "variable length array bound evaluates to non-positive value {f}", .{bound}); | |
| 604 | 581 | } |
| 605 | 582 | |
| 606 | 583 | const FloatCastOverflowData = extern struct { |
| ... | ... | @@ -631,13 +608,13 @@ fn floatCastOverflow( |
| 631 | 608 | if (@as(u16, ptr[0]) + @as(u16, ptr[1]) < 2 or ptr[0] == 0xFF or ptr[1] == 0xFF) { |
| 632 | 609 | const data: *const FloatCastOverflowData = @ptrCast(data_handle); |
| 633 | 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 | 612 | from_value, data.to.getName(), |
| 636 | 613 | }); |
| 637 | 614 | } else { |
| 638 | 615 | const data: *const FloatCastOverflowDataV2 = @ptrCast(data_handle); |
| 639 | 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 | 618 | from_value, data.to.getName(), |
| 642 | 619 | }); |
| 643 | 620 | } |
src/Air.zig+8-9| ... | ... | @@ -746,7 +746,9 @@ pub const Inst = struct { |
| 746 | 746 | /// Dest slice may have any alignment; source pointer may have any alignment. |
| 747 | 747 | /// The two memory regions must not overlap. |
| 748 | 748 | /// Result type is always void. |
| 749 | /// | |
| 749 | 750 | /// Uses the `bin_op` field. LHS is the dest slice. RHS is the source pointer. |
| 751 | /// | |
| 750 | 752 | /// If the length is compile-time known (due to the destination or |
| 751 | 753 | /// source being a pointer-to-array), then it is guaranteed to be |
| 752 | 754 | /// greater than zero. |
| ... | ... | @@ -758,7 +760,9 @@ pub const Inst = struct { |
| 758 | 760 | /// Dest slice may have any alignment; source pointer may have any alignment. |
| 759 | 761 | /// The two memory regions may overlap. |
| 760 | 762 | /// Result type is always void. |
| 763 | /// | |
| 761 | 764 | /// Uses the `bin_op` field. LHS is the dest slice. RHS is the source pointer. |
| 765 | /// | |
| 762 | 766 | /// If the length is compile-time known (due to the destination or |
| 763 | 767 | /// source being a pointer-to-array), then it is guaranteed to be |
| 764 | 768 | /// greater than zero. |
| ... | ... | @@ -957,18 +961,13 @@ pub const Inst = struct { |
| 957 | 961 | return index.unwrap().target; |
| 958 | 962 | } |
| 959 | 963 | |
| 960 | pub fn format( | |
| 961 | index: Index, | |
| 962 | comptime _: []const u8, | |
| 963 | _: std.fmt.FormatOptions, | |
| 964 | writer: anytype, | |
| 965 | ) @TypeOf(writer).Error!void { | |
| 966 | try writer.writeByte('%'); | |
| 964 | pub fn format(index: Index, w: *std.io.Writer) std.io.Writer.Error!void { | |
| 965 | try w.writeByte('%'); | |
| 967 | 966 | switch (index.unwrap()) { |
| 968 | 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 | }; |
| 974 | 973 |
src/Air/Liveness.zig+25-25| ... | ... | @@ -1299,10 +1299,10 @@ fn analyzeOperands( |
| 1299 | 1299 | |
| 1300 | 1300 | // This logic must synchronize with `will_die_immediately` in `AnalyzeBigOperands.init`. |
| 1301 | 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 | 1303 | break :blk false; |
| 1304 | 1304 | } else blk: { |
| 1305 | log.debug("[{}] %{}: immediate death", .{ pass, @intFromEnum(inst) }); | |
| 1305 | log.debug("[{}] %{d}: immediate death", .{ pass, @intFromEnum(inst) }); | |
| 1306 | 1306 | break :blk true; |
| 1307 | 1307 | }; |
| 1308 | 1308 | |
| ... | ... | @@ -1323,7 +1323,7 @@ fn analyzeOperands( |
| 1323 | 1323 | const mask = @as(Bpi, 1) << @as(OperandInt, @intCast(i)); |
| 1324 | 1324 | |
| 1325 | 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 | 1327 | tomb_bits |= mask; |
| 1328 | 1328 | } |
| 1329 | 1329 | } |
| ... | ... | @@ -1462,19 +1462,19 @@ fn analyzeInstBlock( |
| 1462 | 1462 | }, |
| 1463 | 1463 | |
| 1464 | 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 | 1466 | // We can move the live set because the body should have a noreturn |
| 1467 | 1467 | // instruction which overrides the set. |
| 1468 | 1468 | try data.block_scopes.put(gpa, inst, .{ |
| 1469 | 1469 | .live_set = data.live_set.move(), |
| 1470 | 1470 | }); |
| 1471 | 1471 | defer { |
| 1472 | log.debug("[{}] %{}: popped block scope", .{ pass, inst }); | |
| 1472 | log.debug("[{}] %{f}: popped block scope", .{ pass, inst }); | |
| 1473 | 1473 | var scope = data.block_scopes.fetchRemove(inst).?.value; |
| 1474 | 1474 | scope.live_set.deinit(gpa); |
| 1475 | 1475 | } |
| 1476 | 1476 | |
| 1477 | log.debug("[{}] %{}: pushed new block scope", .{ pass, inst }); | |
| 1477 | log.debug("[{}] %{f}: pushed new block scope", .{ pass, inst }); | |
| 1478 | 1478 | try analyzeBody(a, pass, data, body); |
| 1479 | 1479 | |
| 1480 | 1480 | // If the block is noreturn, block deaths not only aren't useful, they're impossible to |
| ... | ... | @@ -1501,7 +1501,7 @@ fn analyzeInstBlock( |
| 1501 | 1501 | } |
| 1502 | 1502 | assert(measured_num == num_deaths); // post-live-set should be a subset of pre-live-set |
| 1503 | 1503 | try a.special.put(gpa, inst, extra_index); |
| 1504 | log.debug("[{}] %{}: block deaths are {}", .{ | |
| 1504 | log.debug("[{}] %{f}: block deaths are {f}", .{ | |
| 1505 | 1505 | pass, |
| 1506 | 1506 | inst, |
| 1507 | 1507 | fmtInstList(@ptrCast(a.extra.items[extra_index + 1 ..][0..num_deaths])), |
| ... | ... | @@ -1538,7 +1538,7 @@ fn writeLoopInfo( |
| 1538 | 1538 | const block_inst = key.*; |
| 1539 | 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) }); | |
| 1542 | 1542 | |
| 1543 | 1543 | // Now we put the live operands from the loop body in too |
| 1544 | 1544 | const num_live = data.live_set.count(); |
| ... | ... | @@ -1550,7 +1550,7 @@ fn writeLoopInfo( |
| 1550 | 1550 | const alive = key.*; |
| 1551 | 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) }); | |
| 1554 | 1554 | |
| 1555 | 1555 | try a.special.put(gpa, inst, extra_index); |
| 1556 | 1556 | |
| ... | ... | @@ -1591,7 +1591,7 @@ fn resolveLoopLiveSet( |
| 1591 | 1591 | try data.live_set.ensureUnusedCapacity(gpa, @intCast(loop_live.len)); |
| 1592 | 1592 | for (loop_live) |alive| data.live_set.putAssumeCapacity(alive, {}); |
| 1593 | 1593 | |
| 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) }); | |
| 1595 | 1595 | |
| 1596 | 1596 | for (breaks) |block_inst| { |
| 1597 | 1597 | // We might break to this block, so include every operand that the block needs alive |
| ... | ... | @@ -1604,7 +1604,7 @@ fn resolveLoopLiveSet( |
| 1604 | 1604 | } |
| 1605 | 1605 | } |
| 1606 | 1606 | |
| 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 | } |
| 1609 | 1609 | |
| 1610 | 1610 | fn analyzeInstLoop( |
| ... | ... | @@ -1642,7 +1642,7 @@ fn analyzeInstLoop( |
| 1642 | 1642 | .live_set = data.live_set.move(), |
| 1643 | 1643 | }); |
| 1644 | 1644 | defer { |
| 1645 | log.debug("[{}] %{}: popped loop block scop", .{ pass, inst }); | |
| 1645 | log.debug("[{}] %{f}: popped loop block scop", .{ pass, inst }); | |
| 1646 | 1646 | var scope = data.block_scopes.fetchRemove(inst).?.value; |
| 1647 | 1647 | scope.live_set.deinit(gpa); |
| 1648 | 1648 | } |
| ... | ... | @@ -1743,13 +1743,13 @@ fn analyzeInstCondBr( |
| 1743 | 1743 | } |
| 1744 | 1744 | } |
| 1745 | 1745 | |
| 1746 | log.debug("[{}] %{}: 'then' branch mirrored deaths are {}", .{ pass, inst, fmtInstList(then_mirrored_deaths.items) }); | |
| 1747 | log.debug("[{}] %{}: 'else' branch mirrored deaths are {}", .{ pass, inst, fmtInstList(else_mirrored_deaths.items) }); | |
| 1746 | log.debug("[{}] %{f}: 'then' branch mirrored deaths are {f}", .{ pass, inst, fmtInstList(then_mirrored_deaths.items) }); | |
| 1747 | log.debug("[{}] %{f}: 'else' branch mirrored deaths are {f}", .{ pass, inst, fmtInstList(else_mirrored_deaths.items) }); | |
| 1748 | 1748 | |
| 1749 | 1749 | data.live_set.deinit(gpa); |
| 1750 | 1750 | data.live_set = then_live.move(); // Really the union of both live sets |
| 1751 | 1751 | |
| 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) }); | |
| 1753 | 1753 | |
| 1754 | 1754 | // Write the mirrored deaths to `extra` |
| 1755 | 1755 | const then_death_count = @as(u32, @intCast(then_mirrored_deaths.items.len)); |
| ... | ... | @@ -1817,7 +1817,7 @@ fn analyzeInstSwitchBr( |
| 1817 | 1817 | }); |
| 1818 | 1818 | } |
| 1819 | 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 | 1821 | var scope = data.block_scopes.fetchRemove(inst).?.value; |
| 1822 | 1822 | scope.live_set.deinit(gpa); |
| 1823 | 1823 | }; |
| ... | ... | @@ -1875,13 +1875,13 @@ fn analyzeInstSwitchBr( |
| 1875 | 1875 | } |
| 1876 | 1876 | |
| 1877 | 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 | } |
| 1880 | 1880 | |
| 1881 | 1881 | data.live_set.deinit(gpa); |
| 1882 | 1882 | data.live_set = all_alive.move(); |
| 1883 | 1883 | |
| 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 | } |
| 1886 | 1886 | |
| 1887 | 1887 | const else_death_count = @as(u32, @intCast(mirrored_deaths[ncases].items.len)); |
| ... | ... | @@ -1980,7 +1980,7 @@ fn AnalyzeBigOperands(comptime pass: LivenessPass) type { |
| 1980 | 1980 | |
| 1981 | 1981 | .main_analysis => { |
| 1982 | 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 | 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 | 2036 | const FmtInstSet = struct { |
| 2037 | 2037 | set: *const std.AutoHashMapUnmanaged(Air.Inst.Index, void), |
| 2038 | 2038 | |
| 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 | 2040 | if (val.set.count() == 0) { |
| 2041 | 2041 | try w.writeAll("[no instructions]"); |
| 2042 | 2042 | return; |
| 2043 | 2043 | } |
| 2044 | 2044 | var it = val.set.keyIterator(); |
| 2045 | try w.print("%{}", .{it.next().?.*}); | |
| 2045 | try w.print("%{f}", .{it.next().?.*}); | |
| 2046 | 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 | 2056 | const FmtInstList = struct { |
| 2057 | 2057 | list: []const Air.Inst.Index, |
| 2058 | 2058 | |
| 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 | 2060 | if (val.list.len == 0) { |
| 2061 | 2061 | try w.writeAll("[no instructions]"); |
| 2062 | 2062 | return; |
| 2063 | 2063 | } |
| 2064 | try w.print("%{}", .{val.list[0]}); | |
| 2064 | try w.print("%{f}", .{val.list[0]}); | |
| 2065 | 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 | 73 | .trap, .unreach => { |
| 74 | 74 | try self.verifyInstOperands(inst, .{ .none, .none, .none }); |
| 75 | 75 | // 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 | }, |
| 78 | 78 | |
| 79 | 79 | // unary |
| ... | ... | @@ -166,7 +166,7 @@ fn verifyBody(self: *Verify, body: []const Air.Inst.Index) Error!void { |
| 166 | 166 | const un_op = data[@intFromEnum(inst)].un_op; |
| 167 | 167 | try self.verifyInstOperands(inst, .{ un_op, .none, .none }); |
| 168 | 168 | // 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 | 171 | .dbg_var_ptr, |
| 172 | 172 | .dbg_var_val, |
| ... | ... | @@ -450,7 +450,7 @@ fn verifyBody(self: *Verify, body: []const Air.Inst.Index) Error!void { |
| 450 | 450 | .repeat => { |
| 451 | 451 | const repeat = data[@intFromEnum(inst)].repeat; |
| 452 | 452 | 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) }); | |
| 454 | 454 | |
| 455 | 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 | 460 | try self.verifyOperand(inst, br.operand, self.liveness.operandDies(inst, 0)); |
| 461 | 461 | |
| 462 | 462 | 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) }); | |
| 464 | 464 | |
| 465 | 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 | 511 | |
| 512 | 512 | // The same stuff should be alive after the loop as before it. |
| 513 | 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 | 515 | defer { |
| 516 | 516 | var live = self.loops.fetchRemove(inst).?; |
| 517 | 517 | live.value.deinit(self.gpa); |
| ... | ... | @@ -560,7 +560,7 @@ fn verifyBody(self: *Verify, body: []const Air.Inst.Index) Error!void { |
| 560 | 560 | // after the loop as before it. |
| 561 | 561 | { |
| 562 | 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 | 564 | gop.value_ptr.* = self.live.move(); |
| 565 | 565 | } |
| 566 | 566 | defer { |
| ... | ... | @@ -601,9 +601,11 @@ fn verifyOperand(self: *Verify, inst: Air.Inst.Index, op_ref: Air.Inst.Ref, dies |
| 601 | 601 | return; |
| 602 | 602 | }; |
| 603 | 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 | 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 | } |
| 609 | 611 | |
| ... | ... | @@ -628,9 +630,9 @@ fn verifyInst(self: *Verify, inst: Air.Inst.Index) Error!void { |
| 628 | 630 | } |
| 629 | 631 | |
| 630 | 632 | fn 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 | 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 | } |
| 635 | 637 | |
| 636 | 638 | fn invalid(comptime fmt: []const u8, args: anytype) error{LivenessInvalid} { |
src/Air/print.zig+104-98| ... | ... | @@ -1,6 +1,5 @@ |
| 1 | 1 | const std = @import("std"); |
| 2 | 2 | const Allocator = std.mem.Allocator; |
| 3 | const fmtIntSizeBin = std.fmt.fmtIntSizeBin; | |
| 4 | 3 | |
| 5 | 4 | const build_options = @import("build_options"); |
| 6 | 5 | const Zcu = @import("../Zcu.zig"); |
| ... | ... | @@ -9,7 +8,7 @@ const Type = @import("../Type.zig"); |
| 9 | 8 | const Air = @import("../Air.zig"); |
| 10 | 9 | const InternPool = @import("../InternPool.zig"); |
| 11 | 10 | |
| 12 | pub fn write(air: Air, stream: anytype, pt: Zcu.PerThread, liveness: ?Air.Liveness) void { | |
| 11 | pub fn write(air: Air, stream: *std.io.Writer, pt: Zcu.PerThread, liveness: ?Air.Liveness) void { | |
| 13 | 12 | comptime std.debug.assert(build_options.enable_debug_extensions); |
| 14 | 13 | const instruction_bytes = air.instructions.len * |
| 15 | 14 | // 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 | 24 | |
| 26 | 25 | // zig fmt: off |
| 27 | 26 | stream.print( |
| 28 | \\# Total AIR+Liveness bytes: {} | |
| 29 | \\# AIR Instructions: {d} ({}) | |
| 30 | \\# AIR Extra Data: {d} ({}) | |
| 31 | \\# Liveness tomb_bits: {} | |
| 32 | \\# Liveness Extra Data: {d} ({}) | |
| 33 | \\# Liveness special table: {d} ({}) | |
| 27 | \\# Total AIR+Liveness bytes: {Bi} | |
| 28 | \\# AIR Instructions: {d} ({Bi}) | |
| 29 | \\# AIR Extra Data: {d} ({Bi}) | |
| 30 | \\# Liveness tomb_bits: {Bi} | |
| 31 | \\# Liveness Extra Data: {d} ({Bi}) | |
| 32 | \\# Liveness special table: {d} ({Bi}) | |
| 34 | 33 | \\ |
| 35 | 34 | , .{ |
| 36 | fmtIntSizeBin(total_bytes), | |
| 37 | air.instructions.len, fmtIntSizeBin(instruction_bytes), | |
| 38 | air.extra.items.len, fmtIntSizeBin(extra_bytes), | |
| 39 | fmtIntSizeBin(tomb_bytes), | |
| 40 | if (liveness) |l| l.extra.len else 0, fmtIntSizeBin(liveness_extra_bytes), | |
| 41 | if (liveness) |l| l.special.count() else 0, fmtIntSizeBin(liveness_special_bytes), | |
| 35 | total_bytes, | |
| 36 | air.instructions.len, instruction_bytes, | |
| 37 | air.extra.items.len, extra_bytes, | |
| 38 | tomb_bytes, | |
| 39 | if (liveness) |l| l.extra.len else 0, liveness_extra_bytes, | |
| 40 | if (liveness) |l| l.special.count() else 0, liveness_special_bytes, | |
| 42 | 41 | }) catch return; |
| 43 | 42 | // zig fmt: on |
| 44 | 43 | |
| ... | ... | @@ -55,7 +54,7 @@ pub fn write(air: Air, stream: anytype, pt: Zcu.PerThread, liveness: ?Air.Livene |
| 55 | 54 | |
| 56 | 55 | pub fn writeInst( |
| 57 | 56 | air: Air, |
| 58 | stream: anytype, | |
| 57 | stream: *std.io.Writer, | |
| 59 | 58 | inst: Air.Inst.Index, |
| 60 | 59 | pt: Zcu.PerThread, |
| 61 | 60 | liveness: ?Air.Liveness, |
| ... | ... | @@ -73,11 +72,15 @@ pub fn writeInst( |
| 73 | 72 | } |
| 74 | 73 | |
| 75 | 74 | pub 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 | } |
| 78 | 79 | |
| 79 | 80 | pub 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 | } |
| 82 | 85 | |
| 83 | 86 | const Writer = struct { |
| ... | ... | @@ -88,17 +91,19 @@ const Writer = struct { |
| 88 | 91 | indent: usize, |
| 89 | 92 | skip_body: bool, |
| 90 | 93 | |
| 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 | 97 | for (body) |inst| { |
| 93 | 98 | try w.writeInst(s, inst); |
| 94 | 99 | try s.writeByte('\n'); |
| 95 | 100 | } |
| 96 | 101 | } |
| 97 | 102 | |
| 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 | 104 | const tag = w.air.instructions.items(.tag)[@intFromEnum(inst)]; |
| 100 | try s.writeByteNTimes(' ', w.indent); | |
| 101 | try s.print("{}{c}= {s}(", .{ | |
| 105 | try s.splatByteAll(' ', w.indent); | |
| 106 | try s.print("{f}{c}= {s}(", .{ | |
| 102 | 107 | inst, |
| 103 | 108 | @as(u8, if (if (w.liveness) |liveness| liveness.isUnused(inst) else false) '!' else ' '), |
| 104 | 109 | @tagName(tag), |
| ... | ... | @@ -335,47 +340,48 @@ const Writer = struct { |
| 335 | 340 | try s.writeByte(')'); |
| 336 | 341 | } |
| 337 | 342 | |
| 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 | 344 | const bin_op = w.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; |
| 340 | 345 | try w.writeOperand(s, inst, 0, bin_op.lhs); |
| 341 | 346 | try s.writeAll(", "); |
| 342 | 347 | try w.writeOperand(s, inst, 1, bin_op.rhs); |
| 343 | 348 | } |
| 344 | 349 | |
| 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 | 351 | const un_op = w.air.instructions.items(.data)[@intFromEnum(inst)].un_op; |
| 347 | 352 | try w.writeOperand(s, inst, 0, un_op); |
| 348 | 353 | } |
| 349 | 354 | |
| 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 | 356 | _ = w; |
| 357 | _ = s; | |
| 352 | 358 | _ = inst; |
| 353 | 359 | // no-op, no argument to write |
| 354 | 360 | } |
| 355 | 361 | |
| 356 | fn writeType(w: *Writer, s: anytype, ty: Type) !void { | |
| 362 | fn writeType(w: *Writer, s: *std.io.Writer, ty: Type) !void { | |
| 357 | 363 | return ty.print(s, w.pt); |
| 358 | 364 | } |
| 359 | 365 | |
| 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 | 367 | const ty = w.air.instructions.items(.data)[@intFromEnum(inst)].ty; |
| 362 | 368 | try w.writeType(s, ty); |
| 363 | 369 | } |
| 364 | 370 | |
| 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 | 372 | const arg = w.air.instructions.items(.data)[@intFromEnum(inst)].arg; |
| 367 | 373 | try w.writeType(s, arg.ty.toType()); |
| 368 | 374 | try s.print(", {d}", .{arg.zir_param_index}); |
| 369 | 375 | } |
| 370 | 376 | |
| 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 | 378 | const ty_op = w.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| 373 | 379 | try w.writeType(s, ty_op.ty.toType()); |
| 374 | 380 | try s.writeAll(", "); |
| 375 | 381 | try w.writeOperand(s, inst, 0, ty_op.operand); |
| 376 | 382 | } |
| 377 | 383 | |
| 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 | 385 | const ty_pl = w.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; |
| 380 | 386 | try w.writeType(s, ty_pl.ty.toType()); |
| 381 | 387 | const body: []const Air.Inst.Index = @ptrCast(switch (tag) { |
| ... | ... | @@ -408,15 +414,15 @@ const Writer = struct { |
| 408 | 414 | w.indent += 2; |
| 409 | 415 | try w.writeBody(s, body); |
| 410 | 416 | w.indent = old_indent; |
| 411 | try s.writeByteNTimes(' ', w.indent); | |
| 417 | try s.splatByteAll(' ', w.indent); | |
| 412 | 418 | try s.writeAll("}"); |
| 413 | 419 | |
| 414 | 420 | for (liveness_block.deaths) |operand| { |
| 415 | try s.print(" {}!", .{operand}); | |
| 421 | try s.print(" {f}!", .{operand}); | |
| 416 | 422 | } |
| 417 | 423 | } |
| 418 | 424 | |
| 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 | 426 | const ty_pl = w.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; |
| 421 | 427 | const extra = w.air.extraData(Air.Block, ty_pl.payload); |
| 422 | 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 | 434 | w.indent += 2; |
| 429 | 435 | try w.writeBody(s, body); |
| 430 | 436 | w.indent = old_indent; |
| 431 | try s.writeByteNTimes(' ', w.indent); | |
| 437 | try s.splatByteAll(' ', w.indent); | |
| 432 | 438 | try s.writeAll("}"); |
| 433 | 439 | } |
| 434 | 440 | |
| 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 | 442 | const zcu = w.pt.zcu; |
| 437 | 443 | const ty_pl = w.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; |
| 438 | 444 | const vector_ty = ty_pl.ty.toType(); |
| ... | ... | @@ -448,7 +454,7 @@ const Writer = struct { |
| 448 | 454 | try s.writeAll("]"); |
| 449 | 455 | } |
| 450 | 456 | |
| 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 | 458 | const ty_pl = w.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; |
| 453 | 459 | const extra = w.air.extraData(Air.UnionInit, ty_pl.payload).data; |
| 454 | 460 | |
| ... | ... | @@ -456,7 +462,7 @@ const Writer = struct { |
| 456 | 462 | try w.writeOperand(s, inst, 0, extra.init); |
| 457 | 463 | } |
| 458 | 464 | |
| 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 | 466 | const ty_pl = w.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; |
| 461 | 467 | const extra = w.air.extraData(Air.StructField, ty_pl.payload).data; |
| 462 | 468 | |
| ... | ... | @@ -464,7 +470,7 @@ const Writer = struct { |
| 464 | 470 | try s.print(", {d}", .{extra.field_index}); |
| 465 | 471 | } |
| 466 | 472 | |
| 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 | 474 | const data = w.air.instructions.items(.data); |
| 469 | 475 | const ty_pl = data[@intFromEnum(inst)].ty_pl; |
| 470 | 476 | const extra = w.air.extraData(Air.Bin, ty_pl.payload).data; |
| ... | ... | @@ -477,7 +483,7 @@ const Writer = struct { |
| 477 | 483 | try w.writeOperand(s, inst, 1, extra.rhs); |
| 478 | 484 | } |
| 479 | 485 | |
| 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 | 487 | const ty_pl = w.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; |
| 482 | 488 | const extra = w.air.extraData(Air.Cmpxchg, ty_pl.payload).data; |
| 483 | 489 | |
| ... | ... | @@ -491,7 +497,7 @@ const Writer = struct { |
| 491 | 497 | }); |
| 492 | 498 | } |
| 493 | 499 | |
| 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 | 501 | const pl_op = w.air.instructions.items(.data)[@intFromEnum(inst)].pl_op; |
| 496 | 502 | const extra = w.air.extraData(Air.Bin, pl_op.payload).data; |
| 497 | 503 | |
| ... | ... | @@ -502,7 +508,7 @@ const Writer = struct { |
| 502 | 508 | try w.writeOperand(s, inst, 2, pl_op.operand); |
| 503 | 509 | } |
| 504 | 510 | |
| 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 | 512 | const unwrapped = w.air.unwrapShuffleOne(w.pt.zcu, inst); |
| 507 | 513 | try w.writeType(s, unwrapped.result_ty); |
| 508 | 514 | try s.writeAll(", "); |
| ... | ... | @@ -512,13 +518,13 @@ const Writer = struct { |
| 512 | 518 | if (mask_idx > 0) try s.writeAll(", "); |
| 513 | 519 | switch (mask_elem.unwrap()) { |
| 514 | 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 | 524 | try s.writeByte(']'); |
| 519 | 525 | } |
| 520 | 526 | |
| 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 | 528 | const unwrapped = w.air.unwrapShuffleTwo(w.pt.zcu, inst); |
| 523 | 529 | try w.writeType(s, unwrapped.result_ty); |
| 524 | 530 | try s.writeAll(", "); |
| ... | ... | @@ -537,7 +543,7 @@ const Writer = struct { |
| 537 | 543 | try s.writeByte(']'); |
| 538 | 544 | } |
| 539 | 545 | |
| 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 | 547 | const zcu = w.pt.zcu; |
| 542 | 548 | const pl_op = w.air.instructions.items(.data)[@intFromEnum(inst)].pl_op; |
| 543 | 549 | const extra = w.air.extraData(Air.Bin, pl_op.payload).data; |
| ... | ... | @@ -552,14 +558,14 @@ const Writer = struct { |
| 552 | 558 | try w.writeOperand(s, inst, 2, extra.rhs); |
| 553 | 559 | } |
| 554 | 560 | |
| 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 | 562 | const reduce = w.air.instructions.items(.data)[@intFromEnum(inst)].reduce; |
| 557 | 563 | |
| 558 | 564 | try w.writeOperand(s, inst, 0, reduce.operand); |
| 559 | 565 | try s.print(", {s}", .{@tagName(reduce.operation)}); |
| 560 | 566 | } |
| 561 | 567 | |
| 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 | 569 | const ty_pl = w.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; |
| 564 | 570 | const extra = w.air.extraData(Air.VectorCmp, ty_pl.payload).data; |
| 565 | 571 | |
| ... | ... | @@ -569,7 +575,7 @@ const Writer = struct { |
| 569 | 575 | try w.writeOperand(s, inst, 1, extra.rhs); |
| 570 | 576 | } |
| 571 | 577 | |
| 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 | 579 | const data = w.air.instructions.items(.data)[@intFromEnum(inst)].vector_store_elem; |
| 574 | 580 | const extra = w.air.extraData(Air.VectorCmp, data.payload).data; |
| 575 | 581 | |
| ... | ... | @@ -580,21 +586,21 @@ const Writer = struct { |
| 580 | 586 | try w.writeOperand(s, inst, 2, extra.rhs); |
| 581 | 587 | } |
| 582 | 588 | |
| 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 | 590 | const ip = &w.pt.zcu.intern_pool; |
| 585 | 591 | const ty_nav = w.air.instructions.items(.data)[@intFromEnum(inst)].ty_nav; |
| 586 | 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 | } |
| 589 | 595 | |
| 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 | 597 | const atomic_load = w.air.instructions.items(.data)[@intFromEnum(inst)].atomic_load; |
| 592 | 598 | |
| 593 | 599 | try w.writeOperand(s, inst, 0, atomic_load.ptr); |
| 594 | 600 | try s.print(", {s}", .{@tagName(atomic_load.order)}); |
| 595 | 601 | } |
| 596 | 602 | |
| 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 | 604 | const prefetch = w.air.instructions.items(.data)[@intFromEnum(inst)].prefetch; |
| 599 | 605 | |
| 600 | 606 | try w.writeOperand(s, inst, 0, prefetch.ptr); |
| ... | ... | @@ -605,10 +611,10 @@ const Writer = struct { |
| 605 | 611 | |
| 606 | 612 | fn writeAtomicStore( |
| 607 | 613 | w: *Writer, |
| 608 | s: anytype, | |
| 614 | s: *std.io.Writer, | |
| 609 | 615 | inst: Air.Inst.Index, |
| 610 | 616 | order: std.builtin.AtomicOrder, |
| 611 | ) @TypeOf(s).Error!void { | |
| 617 | ) Error!void { | |
| 612 | 618 | const bin_op = w.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; |
| 613 | 619 | try w.writeOperand(s, inst, 0, bin_op.lhs); |
| 614 | 620 | try s.writeAll(", "); |
| ... | ... | @@ -616,7 +622,7 @@ const Writer = struct { |
| 616 | 622 | try s.print(", {s}", .{@tagName(order)}); |
| 617 | 623 | } |
| 618 | 624 | |
| 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 | 626 | const pl_op = w.air.instructions.items(.data)[@intFromEnum(inst)].pl_op; |
| 621 | 627 | const extra = w.air.extraData(Air.AtomicRmw, pl_op.payload).data; |
| 622 | 628 | |
| ... | ... | @@ -626,7 +632,7 @@ const Writer = struct { |
| 626 | 632 | try s.print(", {s}, {s}", .{ @tagName(extra.op()), @tagName(extra.ordering()) }); |
| 627 | 633 | } |
| 628 | 634 | |
| 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 | 636 | const ty_pl = w.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; |
| 631 | 637 | const extra = w.air.extraData(Air.FieldParentPtr, ty_pl.payload).data; |
| 632 | 638 | |
| ... | ... | @@ -634,7 +640,7 @@ const Writer = struct { |
| 634 | 640 | try s.print(", {d}", .{extra.field_index}); |
| 635 | 641 | } |
| 636 | 642 | |
| 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 | 644 | const ty_pl = w.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; |
| 639 | 645 | const extra = w.air.extraData(Air.Asm, ty_pl.payload); |
| 640 | 646 | const is_volatile = @as(u1, @truncate(extra.data.flags >> 31)) != 0; |
| ... | ... | @@ -704,22 +710,22 @@ const Writer = struct { |
| 704 | 710 | } |
| 705 | 711 | } |
| 706 | 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 | } |
| 709 | 715 | |
| 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 | 717 | const dbg_stmt = w.air.instructions.items(.data)[@intFromEnum(inst)].dbg_stmt; |
| 712 | 718 | try s.print("{d}:{d}", .{ dbg_stmt.line + 1, dbg_stmt.column + 1 }); |
| 713 | 719 | } |
| 714 | 720 | |
| 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 | 722 | const pl_op = w.air.instructions.items(.data)[@intFromEnum(inst)].pl_op; |
| 717 | 723 | try w.writeOperand(s, inst, 0, pl_op.operand); |
| 718 | 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 | } |
| 721 | 727 | |
| 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 | 729 | const pl_op = w.air.instructions.items(.data)[@intFromEnum(inst)].pl_op; |
| 724 | 730 | const extra = w.air.extraData(Air.Call, pl_op.payload); |
| 725 | 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 | 738 | try s.writeAll("]"); |
| 733 | 739 | } |
| 734 | 740 | |
| 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 | 742 | const br = w.air.instructions.items(.data)[@intFromEnum(inst)].br; |
| 737 | 743 | try w.writeInstIndex(s, br.block_inst, false); |
| 738 | 744 | try s.writeAll(", "); |
| 739 | 745 | try w.writeOperand(s, inst, 0, br.operand); |
| 740 | 746 | } |
| 741 | 747 | |
| 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 | 749 | const repeat = w.air.instructions.items(.data)[@intFromEnum(inst)].repeat; |
| 744 | 750 | try w.writeInstIndex(s, repeat.loop_inst, false); |
| 745 | 751 | } |
| 746 | 752 | |
| 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 | 754 | const pl_op = w.air.instructions.items(.data)[@intFromEnum(inst)].pl_op; |
| 749 | 755 | const extra = w.air.extraData(Air.Try, pl_op.payload); |
| 750 | 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 | 766 | w.indent += 2; |
| 761 | 767 | |
| 762 | 768 | if (liveness_condbr.else_deaths.len != 0) { |
| 763 | try s.writeByteNTimes(' ', w.indent); | |
| 769 | try s.splatByteAll(' ', w.indent); | |
| 764 | 770 | for (liveness_condbr.else_deaths, 0..) |operand, i| { |
| 765 | 771 | if (i != 0) try s.writeAll(" "); |
| 766 | try s.print("{}!", .{operand}); | |
| 772 | try s.print("{f}!", .{operand}); | |
| 767 | 773 | } |
| 768 | 774 | try s.writeAll("\n"); |
| 769 | 775 | } |
| 770 | 776 | try w.writeBody(s, body); |
| 771 | 777 | |
| 772 | 778 | w.indent = old_indent; |
| 773 | try s.writeByteNTimes(' ', w.indent); | |
| 779 | try s.splatByteAll(' ', w.indent); | |
| 774 | 780 | try s.writeAll("}"); |
| 775 | 781 | |
| 776 | 782 | for (liveness_condbr.then_deaths) |operand| { |
| 777 | try s.print(" {}!", .{operand}); | |
| 783 | try s.print(" {f}!", .{operand}); | |
| 778 | 784 | } |
| 779 | 785 | } |
| 780 | 786 | |
| 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 | 788 | const ty_pl = w.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; |
| 783 | 789 | const extra = w.air.extraData(Air.TryPtr, ty_pl.payload); |
| 784 | 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 | 803 | w.indent += 2; |
| 798 | 804 | |
| 799 | 805 | if (liveness_condbr.else_deaths.len != 0) { |
| 800 | try s.writeByteNTimes(' ', w.indent); | |
| 806 | try s.splatByteAll(' ', w.indent); | |
| 801 | 807 | for (liveness_condbr.else_deaths, 0..) |operand, i| { |
| 802 | 808 | if (i != 0) try s.writeAll(" "); |
| 803 | try s.print("{}!", .{operand}); | |
| 809 | try s.print("{f}!", .{operand}); | |
| 804 | 810 | } |
| 805 | 811 | try s.writeAll("\n"); |
| 806 | 812 | } |
| 807 | 813 | try w.writeBody(s, body); |
| 808 | 814 | |
| 809 | 815 | w.indent = old_indent; |
| 810 | try s.writeByteNTimes(' ', w.indent); | |
| 816 | try s.splatByteAll(' ', w.indent); | |
| 811 | 817 | try s.writeAll("}"); |
| 812 | 818 | |
| 813 | 819 | for (liveness_condbr.then_deaths) |operand| { |
| 814 | try s.print(" {}!", .{operand}); | |
| 820 | try s.print(" {f}!", .{operand}); | |
| 815 | 821 | } |
| 816 | 822 | } |
| 817 | 823 | |
| 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 | 825 | const pl_op = w.air.instructions.items(.data)[@intFromEnum(inst)].pl_op; |
| 820 | 826 | const extra = w.air.extraData(Air.CondBr, pl_op.payload); |
| 821 | 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 | 845 | w.indent += 2; |
| 840 | 846 | |
| 841 | 847 | if (liveness_condbr.then_deaths.len != 0) { |
| 842 | try s.writeByteNTimes(' ', w.indent); | |
| 848 | try s.splatByteAll(' ', w.indent); | |
| 843 | 849 | for (liveness_condbr.then_deaths, 0..) |operand, i| { |
| 844 | 850 | if (i != 0) try s.writeAll(" "); |
| 845 | try s.print("{}!", .{operand}); | |
| 851 | try s.print("{f}!", .{operand}); | |
| 846 | 852 | } |
| 847 | 853 | try s.writeAll("\n"); |
| 848 | 854 | } |
| 849 | 855 | |
| 850 | 856 | try w.writeBody(s, then_body); |
| 851 | try s.writeByteNTimes(' ', old_indent); | |
| 857 | try s.splatByteAll(' ', old_indent); | |
| 852 | 858 | try s.writeAll("},"); |
| 853 | 859 | if (extra.data.branch_hints.false != .none) { |
| 854 | 860 | try s.print(" {s}", .{@tagName(extra.data.branch_hints.false)}); |
| ... | ... | @@ -859,10 +865,10 @@ const Writer = struct { |
| 859 | 865 | try s.writeAll(" {\n"); |
| 860 | 866 | |
| 861 | 867 | if (liveness_condbr.else_deaths.len != 0) { |
| 862 | try s.writeByteNTimes(' ', w.indent); | |
| 868 | try s.splatByteAll(' ', w.indent); | |
| 863 | 869 | for (liveness_condbr.else_deaths, 0..) |operand, i| { |
| 864 | 870 | if (i != 0) try s.writeAll(" "); |
| 865 | try s.print("{}!", .{operand}); | |
| 871 | try s.print("{f}!", .{operand}); | |
| 866 | 872 | } |
| 867 | 873 | try s.writeAll("\n"); |
| 868 | 874 | } |
| ... | ... | @@ -870,11 +876,11 @@ const Writer = struct { |
| 870 | 876 | try w.writeBody(s, else_body); |
| 871 | 877 | w.indent = old_indent; |
| 872 | 878 | |
| 873 | try s.writeByteNTimes(' ', old_indent); | |
| 879 | try s.splatByteAll(' ', old_indent); | |
| 874 | 880 | try s.writeAll("}"); |
| 875 | 881 | } |
| 876 | 882 | |
| 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 | 884 | const switch_br = w.air.unwrapSwitch(inst); |
| 879 | 885 | |
| 880 | 886 | const liveness: Air.Liveness.SwitchBrTable = if (w.liveness) |liveness| |
| ... | ... | @@ -916,17 +922,17 @@ const Writer = struct { |
| 916 | 922 | |
| 917 | 923 | const deaths = liveness.deaths[case.idx]; |
| 918 | 924 | if (deaths.len != 0) { |
| 919 | try s.writeByteNTimes(' ', w.indent); | |
| 925 | try s.splatByteAll(' ', w.indent); | |
| 920 | 926 | for (deaths, 0..) |operand, i| { |
| 921 | 927 | if (i != 0) try s.writeAll(" "); |
| 922 | try s.print("{}!", .{operand}); | |
| 928 | try s.print("{f}!", .{operand}); | |
| 923 | 929 | } |
| 924 | 930 | try s.writeAll("\n"); |
| 925 | 931 | } |
| 926 | 932 | |
| 927 | 933 | try w.writeBody(s, case.body); |
| 928 | 934 | w.indent -= 2; |
| 929 | try s.writeByteNTimes(' ', w.indent); | |
| 935 | try s.splatByteAll(' ', w.indent); | |
| 930 | 936 | try s.writeAll("}"); |
| 931 | 937 | } |
| 932 | 938 | |
| ... | ... | @@ -942,47 +948,47 @@ const Writer = struct { |
| 942 | 948 | |
| 943 | 949 | const deaths = liveness.deaths[liveness.deaths.len - 1]; |
| 944 | 950 | if (deaths.len != 0) { |
| 945 | try s.writeByteNTimes(' ', w.indent); | |
| 951 | try s.splatByteAll(' ', w.indent); | |
| 946 | 952 | for (deaths, 0..) |operand, i| { |
| 947 | 953 | if (i != 0) try s.writeAll(" "); |
| 948 | try s.print("{}!", .{operand}); | |
| 954 | try s.print("{f}!", .{operand}); | |
| 949 | 955 | } |
| 950 | 956 | try s.writeAll("\n"); |
| 951 | 957 | } |
| 952 | 958 | |
| 953 | 959 | try w.writeBody(s, else_body); |
| 954 | 960 | w.indent -= 2; |
| 955 | try s.writeByteNTimes(' ', w.indent); | |
| 961 | try s.splatByteAll(' ', w.indent); | |
| 956 | 962 | try s.writeAll("}"); |
| 957 | 963 | } |
| 958 | 964 | |
| 959 | 965 | try s.writeAll("\n"); |
| 960 | try s.writeByteNTimes(' ', old_indent); | |
| 966 | try s.splatByteAll(' ', old_indent); | |
| 961 | 967 | } |
| 962 | 968 | |
| 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 | 970 | const pl_op = w.air.instructions.items(.data)[@intFromEnum(inst)].pl_op; |
| 965 | 971 | try s.print("{d}", .{pl_op.payload}); |
| 966 | 972 | } |
| 967 | 973 | |
| 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 | 975 | const pl_op = w.air.instructions.items(.data)[@intFromEnum(inst)].pl_op; |
| 970 | 976 | try s.print("{d}, ", .{pl_op.payload}); |
| 971 | 977 | try w.writeOperand(s, inst, 0, pl_op.operand); |
| 972 | 978 | } |
| 973 | 979 | |
| 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 | 981 | const pl_op = w.air.instructions.items(.data)[@intFromEnum(inst)].pl_op; |
| 976 | 982 | try s.print("{d}", .{pl_op.payload}); |
| 977 | 983 | } |
| 978 | 984 | |
| 979 | 985 | fn writeOperand( |
| 980 | 986 | w: *Writer, |
| 981 | s: anytype, | |
| 987 | s: *std.io.Writer, | |
| 982 | 988 | inst: Air.Inst.Index, |
| 983 | 989 | op_index: usize, |
| 984 | 990 | operand: Air.Inst.Ref, |
| 985 | ) @TypeOf(s).Error!void { | |
| 991 | ) Error!void { | |
| 986 | 992 | const small_tomb_bits = Air.Liveness.bpi - 1; |
| 987 | 993 | const dies = if (w.liveness) |liveness| blk: { |
| 988 | 994 | if (op_index < small_tomb_bits) |
| ... | ... | @@ -1004,16 +1010,16 @@ const Writer = struct { |
| 1004 | 1010 | |
| 1005 | 1011 | fn writeInstRef( |
| 1006 | 1012 | w: *Writer, |
| 1007 | s: anytype, | |
| 1013 | s: *std.io.Writer, | |
| 1008 | 1014 | operand: Air.Inst.Ref, |
| 1009 | 1015 | dies: bool, |
| 1010 | ) @TypeOf(s).Error!void { | |
| 1016 | ) Error!void { | |
| 1011 | 1017 | if (@intFromEnum(operand) < InternPool.static_len) { |
| 1012 | 1018 | return s.print("@{}", .{operand}); |
| 1013 | 1019 | } else if (operand.toInterned()) |ip_index| { |
| 1014 | 1020 | const pt = w.pt; |
| 1015 | 1021 | const ty = Type.fromInterned(pt.zcu.intern_pool.indexToKey(ip_index).typeOf()); |
| 1016 | try s.print("<{}, {}>", .{ | |
| 1022 | try s.print("<{f}, {f}>", .{ | |
| 1017 | 1023 | ty.fmt(pt), |
| 1018 | 1024 | Value.fromInterned(ip_index).fmtValue(pt), |
| 1019 | 1025 | }); |
| ... | ... | @@ -1024,12 +1030,12 @@ const Writer = struct { |
| 1024 | 1030 | |
| 1025 | 1031 | fn writeInstIndex( |
| 1026 | 1032 | w: *Writer, |
| 1027 | s: anytype, | |
| 1033 | s: *std.io.Writer, | |
| 1028 | 1034 | inst: Air.Inst.Index, |
| 1029 | 1035 | dies: bool, |
| 1030 | ) @TypeOf(s).Error!void { | |
| 1036 | ) Error!void { | |
| 1031 | 1037 | _ = w; |
| 1032 | try s.print("{}", .{inst}); | |
| 1038 | try s.print("{f}", .{inst}); | |
| 1033 | 1039 | if (dies) try s.writeByte('!'); |
| 1034 | 1040 | } |
| 1035 | 1041 |
src/Builtin.zig+40-40| ... | ... | @@ -51,60 +51,60 @@ pub fn append(opts: @This(), buffer: *std.ArrayList(u8)) Allocator.Error!void { |
| 51 | 51 | const zig_backend = opts.zig_backend; |
| 52 | 52 | |
| 53 | 53 | @setEvalBranchQuota(4000); |
| 54 | try buffer.writer().print( | |
| 54 | try buffer.print( | |
| 55 | 55 | \\const std = @import("std"); |
| 56 | 56 | \\/// Zig version. When writing code that supports multiple versions of Zig, prefer |
| 57 | 57 | \\/// feature detection (i.e. with `@hasDecl` or `@hasField`) over version checks. |
| 58 | 58 | \\pub const zig_version = std.SemanticVersion.parse(zig_version_string) catch unreachable; |
| 59 | 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_}; | |
| 63 | \\pub const link_mode: std.builtin.LinkMode = .{p_}; | |
| 64 | \\pub const unwind_tables: std.builtin.UnwindTables = .{p_}; | |
| 62 | \\pub const output_mode: std.builtin.OutputMode = .{f}; | |
| 63 | \\pub const link_mode: std.builtin.LinkMode = .{f}; | |
| 64 | \\pub const unwind_tables: std.builtin.UnwindTables = .{f}; | |
| 65 | 65 | \\pub const is_test = {}; |
| 66 | 66 | \\pub const single_threaded = {}; |
| 67 | \\pub const abi: std.Target.Abi = .{p_}; | |
| 67 | \\pub const abi: std.Target.Abi = .{f}; | |
| 68 | 68 | \\pub const cpu: std.Target.Cpu = .{{ |
| 69 | \\ .arch = .{p_}, | |
| 70 | \\ .model = &std.Target.{p_}.cpu.{p_}, | |
| 71 | \\ .features = std.Target.{p_}.featureSet(&.{{ | |
| 69 | \\ .arch = .{f}, | |
| 70 | \\ .model = &std.Target.{f}.cpu.{f}, | |
| 71 | \\ .features = std.Target.{f}.featureSet(&.{{ | |
| 72 | 72 | \\ |
| 73 | 73 | , .{ |
| 74 | 74 | build_options.version, |
| 75 | std.zig.fmtId(@tagName(zig_backend)), | |
| 76 | std.zig.fmtId(@tagName(opts.output_mode)), | |
| 77 | std.zig.fmtId(@tagName(opts.link_mode)), | |
| 78 | std.zig.fmtId(@tagName(opts.unwind_tables)), | |
| 75 | std.zig.fmtIdPU(@tagName(zig_backend)), | |
| 76 | std.zig.fmtIdPU(@tagName(opts.output_mode)), | |
| 77 | std.zig.fmtIdPU(@tagName(opts.link_mode)), | |
| 78 | std.zig.fmtIdPU(@tagName(opts.unwind_tables)), | |
| 79 | 79 | opts.is_test, |
| 80 | 80 | opts.single_threaded, |
| 81 | std.zig.fmtId(@tagName(target.abi)), | |
| 82 | std.zig.fmtId(@tagName(target.cpu.arch)), | |
| 83 | std.zig.fmtId(arch_family_name), | |
| 84 | std.zig.fmtId(target.cpu.model.name), | |
| 85 | std.zig.fmtId(arch_family_name), | |
| 81 | std.zig.fmtIdPU(@tagName(target.abi)), | |
| 82 | std.zig.fmtIdPU(@tagName(target.cpu.arch)), | |
| 83 | std.zig.fmtIdPU(arch_family_name), | |
| 84 | std.zig.fmtIdPU(target.cpu.model.name), | |
| 85 | std.zig.fmtIdPU(arch_family_name), | |
| 86 | 86 | }); |
| 87 | 87 | |
| 88 | 88 | for (target.cpu.arch.allFeaturesList(), 0..) |feature, index_usize| { |
| 89 | 89 | const index = @as(std.Target.Cpu.Feature.Set.Index, @intCast(index_usize)); |
| 90 | 90 | const is_enabled = target.cpu.features.isEnabled(index); |
| 91 | 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 | 98 | \\pub const os: std.Target.Os = .{{ |
| 99 | \\ .tag = .{p_}, | |
| 99 | \\ .tag = .{f}, | |
| 100 | 100 | \\ .version_range = .{{ |
| 101 | 101 | , |
| 102 | .{std.zig.fmtId(@tagName(target.os.tag))}, | |
| 102 | .{std.zig.fmtIdPU(@tagName(target.os.tag))}, | |
| 103 | 103 | ); |
| 104 | 104 | |
| 105 | 105 | switch (target.os.versionRange()) { |
| 106 | 106 | .none => try buffer.appendSlice(" .none = {} },\n"), |
| 107 | .semver => |semver| try buffer.writer().print( | |
| 107 | .semver => |semver| try buffer.print( | |
| 108 | 108 | \\ .semver = .{{ |
| 109 | 109 | \\ .min = .{{ |
| 110 | 110 | \\ .major = {}, |
| ... | ... | @@ -127,7 +127,7 @@ pub fn append(opts: @This(), buffer: *std.ArrayList(u8)) Allocator.Error!void { |
| 127 | 127 | semver.max.minor, |
| 128 | 128 | semver.max.patch, |
| 129 | 129 | }), |
| 130 | .linux => |linux| try buffer.writer().print( | |
| 130 | .linux => |linux| try buffer.print( | |
| 131 | 131 | \\ .linux = .{{ |
| 132 | 132 | \\ .range = .{{ |
| 133 | 133 | \\ .min = .{{ |
| ... | ... | @@ -164,7 +164,7 @@ pub fn append(opts: @This(), buffer: *std.ArrayList(u8)) Allocator.Error!void { |
| 164 | 164 | |
| 165 | 165 | linux.android, |
| 166 | 166 | }), |
| 167 | .hurd => |hurd| try buffer.writer().print( | |
| 167 | .hurd => |hurd| try buffer.print( | |
| 168 | 168 | \\ .hurd = .{{ |
| 169 | 169 | \\ .range = .{{ |
| 170 | 170 | \\ .min = .{{ |
| ... | ... | @@ -198,10 +198,10 @@ pub fn append(opts: @This(), buffer: *std.ArrayList(u8)) Allocator.Error!void { |
| 198 | 198 | hurd.glibc.minor, |
| 199 | 199 | hurd.glibc.patch, |
| 200 | 200 | }), |
| 201 | .windows => |windows| try buffer.writer().print( | |
| 201 | .windows => |windows| try buffer.print( | |
| 202 | 202 | \\ .windows = .{{ |
| 203 | \\ .min = {c}, | |
| 204 | \\ .max = {c}, | |
| 203 | \\ .min = {f}, | |
| 204 | \\ .max = {f}, | |
| 205 | 205 | \\ }}}}, |
| 206 | 206 | \\ |
| 207 | 207 | , .{ windows.min, windows.max }), |
| ... | ... | @@ -217,7 +217,7 @@ pub fn append(opts: @This(), buffer: *std.ArrayList(u8)) Allocator.Error!void { |
| 217 | 217 | ); |
| 218 | 218 | |
| 219 | 219 | if (target.dynamic_linker.get()) |dl| { |
| 220 | try buffer.writer().print( | |
| 220 | try buffer.print( | |
| 221 | 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 | 237 | // knows libc will provide it, and likewise c.zig will not export memcpy. |
| 238 | 238 | const link_libc = opts.link_libc; |
| 239 | 239 | |
| 240 | try buffer.writer().print( | |
| 241 | \\pub const object_format: std.Target.ObjectFormat = .{p_}; | |
| 242 | \\pub const mode: std.builtin.OptimizeMode = .{p_}; | |
| 240 | try buffer.print( | |
| 241 | \\pub const object_format: std.Target.ObjectFormat = .{f}; | |
| 242 | \\pub const mode: std.builtin.OptimizeMode = .{f}; | |
| 243 | 243 | \\pub const link_libc = {}; |
| 244 | 244 | \\pub const link_libcpp = {}; |
| 245 | 245 | \\pub const have_error_return_tracing = {}; |
| ... | ... | @@ -249,12 +249,12 @@ pub fn append(opts: @This(), buffer: *std.ArrayList(u8)) Allocator.Error!void { |
| 249 | 249 | \\pub const position_independent_code = {}; |
| 250 | 250 | \\pub const position_independent_executable = {}; |
| 251 | 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 | 253 | \\pub const omit_frame_pointer = {}; |
| 254 | 254 | \\ |
| 255 | 255 | , .{ |
| 256 | std.zig.fmtId(@tagName(target.ofmt)), | |
| 257 | std.zig.fmtId(@tagName(opts.optimize_mode)), | |
| 256 | std.zig.fmtIdPU(@tagName(target.ofmt)), | |
| 257 | std.zig.fmtIdPU(@tagName(opts.optimize_mode)), | |
| 258 | 258 | link_libc, |
| 259 | 259 | opts.link_libcpp, |
| 260 | 260 | opts.error_tracing, |
| ... | ... | @@ -264,15 +264,15 @@ pub fn append(opts: @This(), buffer: *std.ArrayList(u8)) Allocator.Error!void { |
| 264 | 264 | opts.pic, |
| 265 | 265 | opts.pie, |
| 266 | 266 | opts.strip, |
| 267 | std.zig.fmtId(@tagName(opts.code_model)), | |
| 267 | std.zig.fmtIdPU(@tagName(opts.code_model)), | |
| 268 | 268 | opts.omit_frame_pointer, |
| 269 | 269 | }); |
| 270 | 270 | |
| 271 | 271 | if (target.os.tag == .wasi) { |
| 272 | try buffer.writer().print( | |
| 273 | \\pub const wasi_exec_model: std.builtin.WasiExecModel = .{p_}; | |
| 272 | try buffer.print( | |
| 273 | \\pub const wasi_exec_model: std.builtin.WasiExecModel = .{f}; | |
| 274 | 274 | \\ |
| 275 | , .{std.zig.fmtId(@tagName(opts.wasi_exec_model))}); | |
| 275 | , .{std.zig.fmtIdPU(@tagName(opts.wasi_exec_model))}); | |
| 276 | 276 | } |
| 277 | 277 | |
| 278 | 278 | if (opts.is_test) { |
| ... | ... | @@ -317,7 +317,7 @@ pub fn updateFileOnDisk(file: *File, comp: *Compilation) !void { |
| 317 | 317 | if (root_dir.statFile(sub_path)) |stat| { |
| 318 | 318 | if (stat.size != file.source.?.len) { |
| 319 | 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 | 321 | "Overwriting with correct file contents now", |
| 322 | 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 | 399 | const Formatter = struct { |
| 400 | 400 | p: Path, |
| 401 | 401 | comp: *Compilation, |
| 402 | pub fn format(f: Formatter, comptime unused_fmt: []const u8, options: std.fmt.FormatOptions, w: anytype) !void { | |
| 403 | comptime assert(unused_fmt.len == 0); | |
| 404 | _ = options; | |
| 402 | pub fn format(f: Formatter, w: *std.io.Writer) std.io.Writer.Error!void { | |
| 405 | 403 | const root_path: []const u8 = switch (f.p.root) { |
| 406 | 404 | .zig_lib => f.comp.dirs.zig_lib.path orelse ".", |
| 407 | 405 | .global_cache => f.comp.dirs.global_cache.path orelse ".", |
| ... | ... | @@ -730,10 +728,10 @@ pub const Directories = struct { |
| 730 | 728 | }; |
| 731 | 729 | |
| 732 | 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 | 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 | } |
| 738 | 736 | |
| 739 | 737 | return .{ |
| ... | ... | @@ -1001,7 +999,7 @@ pub const CObject = struct { |
| 1001 | 999 | |
| 1002 | 1000 | var line = std.ArrayList(u8).init(eb.gpa); |
| 1003 | 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; | |
| 1005 | 1003 | |
| 1006 | 1004 | break :source_line try eb.addString(line.items); |
| 1007 | 1005 | }; |
| ... | ... | @@ -1069,7 +1067,7 @@ pub const CObject = struct { |
| 1069 | 1067 | |
| 1070 | 1068 | const file = try std.fs.cwd().openFile(path, .{}); |
| 1071 | 1069 | defer file.close(); |
| 1072 | var br = std.io.bufferedReader(file.reader()); | |
| 1070 | var br = std.io.bufferedReader(file.deprecatedReader()); | |
| 1073 | 1071 | const reader = br.reader(); |
| 1074 | 1072 | var bc = std.zig.llvm.BitcodeReader.init(gpa, .{ .reader = reader.any() }); |
| 1075 | 1073 | defer bc.deinit(); |
| ... | ... | @@ -1875,7 +1873,7 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil |
| 1875 | 1873 | if (options.root_mod.resolved_target.llvm_cpu_features) |cf| print: { |
| 1876 | 1874 | std.debug.lockStdErr(); |
| 1877 | 1875 | defer std.debug.unlockStdErr(); |
| 1878 | const stderr = std.io.getStdErr().writer(); | |
| 1876 | const stderr = std.fs.File.stderr().deprecatedWriter(); | |
| 1879 | 1877 | nosuspend { |
| 1880 | 1878 | stderr.print("compilation: {s}\n", .{options.root_name}) catch break :print; |
| 1881 | 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 | 2687 | const is_hit = man.hit() catch |err| switch (err) { |
| 2690 | 2688 | error.CacheCheckFailed => switch (man.diagnostic) { |
| 2691 | 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 | 2691 | .check_whole_cache, |
| 2694 | 2692 | "failed to check cache: {s} {s}", |
| 2695 | 2693 | .{ @tagName(man.diagnostic), @errorName(e) }, |
| ... | ... | @@ -2699,7 +2697,7 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) !void { |
| 2699 | 2697 | const prefix = man.cache.prefixes()[pp.prefix]; |
| 2700 | 2698 | return comp.setMiscFailure( |
| 2701 | 2699 | .check_whole_cache, |
| 2702 | "failed to check cache: '{}{s}' {s} {s}", | |
| 2700 | "failed to check cache: '{f}{s}' {s} {s}", | |
| 2703 | 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 | 2914 | renameTmpIntoCache(comp.dirs.local_cache, tmp_dir_sub_path, o_sub_path) catch |err| { |
| 2917 | 2915 | return comp.setMiscFailure( |
| 2918 | 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 | 2919 | comp.dirs.local_cache, tmp_dir_sub_path, |
| 2922 | 2920 | comp.dirs.local_cache, o_sub_path, |
| ... | ... | @@ -2983,7 +2981,7 @@ pub fn appendFileSystemInput(comp: *Compilation, path: Compilation.Path) Allocat |
| 2983 | 2981 | break @intCast(i); |
| 2984 | 2982 | } |
| 2985 | 2983 | } else std.debug.panic( |
| 2986 | "missing prefix directory '{s}' ('{}') for '{s}'", | |
| 2984 | "missing prefix directory '{s}' ('{f}') for '{s}'", | |
| 2987 | 2985 | .{ @tagName(path.root), want_prefix_dir, path.sub_path }, |
| 2988 | 2986 | ); |
| 2989 | 2987 | |
| ... | ... | @@ -3322,7 +3320,7 @@ fn emitFromCObject( |
| 3322 | 3320 | emit_path.root_dir.handle, |
| 3323 | 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 | 3324 | src_path, |
| 3327 | 3325 | emit_path, |
| 3328 | 3326 | @errorName(err), |
| ... | ... | @@ -3670,7 +3668,7 @@ pub fn getAllErrorsAlloc(comp: *Compilation) !ErrorBundle { |
| 3670 | 3668 | .illegal_zig_import => try bundle.addString("this compiler implementation does not allow importing files from this directory"), |
| 3671 | 3669 | }, |
| 3672 | 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 | 3672 | .span_start = start, |
| 3675 | 3673 | .span_main = start, |
| 3676 | 3674 | .span_end = @intCast(end), |
| ... | ... | @@ -3717,7 +3715,7 @@ pub fn getAllErrorsAlloc(comp: *Compilation) !ErrorBundle { |
| 3717 | 3715 | assert(!is_retryable); |
| 3718 | 3716 | // AstGen/ZoirGen succeeded with errors. Note that this may include AST errors. |
| 3719 | 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 | 3719 | defer gpa.free(path); |
| 3722 | 3720 | if (file.zir != null) { |
| 3723 | 3721 | try bundle.addZirErrorMessages(file.zir.?, file.tree.?, file.source.?, path); |
| ... | ... | @@ -3772,9 +3770,8 @@ pub fn getAllErrorsAlloc(comp: *Compilation) !ErrorBundle { |
| 3772 | 3770 | if (!refs.contains(anal_unit)) continue; |
| 3773 | 3771 | } |
| 3774 | 3772 | |
| 3775 | std.log.scoped(.zcu).debug("analysis error '{s}' reported from unit '{}'", .{ | |
| 3776 | error_msg.msg, | |
| 3777 | zcu.fmtAnalUnit(anal_unit), | |
| 3773 | std.log.scoped(.zcu).debug("analysis error '{s}' reported from unit '{f}'", .{ | |
| 3774 | error_msg.msg, zcu.fmtAnalUnit(anal_unit), | |
| 3778 | 3775 | }); |
| 3779 | 3776 | |
| 3780 | 3777 | try addModuleErrorMsg(zcu, &bundle, error_msg.*, added_any_analysis_error); |
| ... | ... | @@ -3932,11 +3929,11 @@ pub fn getAllErrorsAlloc(comp: *Compilation) !ErrorBundle { |
| 3932 | 3929 | // This AU is referenced and has a transitive compile error, meaning it referenced something with a compile error. |
| 3933 | 3930 | // However, we haven't reported any such error. |
| 3934 | 3931 | // This is a compiler bug. |
| 3935 | const stderr = std.io.getStdErr().writer(); | |
| 3932 | const stderr = std.fs.File.stderr().deprecatedWriter(); | |
| 3936 | 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 | 3935 | while (ref) |r| { |
| 3939 | try stderr.print("referenced by: {}{s}\n", .{ | |
| 3936 | try stderr.print("referenced by: {f}{s}\n", .{ | |
| 3940 | 3937 | zcu.fmtAnalUnit(r.referencer), |
| 3941 | 3938 | if (zcu.transitive_failed_analysis.contains(r.referencer)) " [transitive failure]" else "", |
| 3942 | 3939 | }); |
| ... | ... | @@ -4035,7 +4032,7 @@ pub fn addModuleErrorMsg( |
| 4035 | 4032 | const err_src_loc = module_err_msg.src_loc.upgrade(zcu); |
| 4036 | 4033 | const err_source = err_src_loc.file_scope.getSource(zcu) catch |err| { |
| 4037 | 4034 | try eb.addRootErrorMessage(.{ |
| 4038 | .msg = try eb.printString("unable to load '{}': {s}", .{ | |
| 4035 | .msg = try eb.printString("unable to load '{f}': {s}", .{ | |
| 4039 | 4036 | err_src_loc.file_scope.path.fmt(zcu.comp), @errorName(err), |
| 4040 | 4037 | }), |
| 4041 | 4038 | }); |
| ... | ... | @@ -4098,7 +4095,7 @@ pub fn addModuleErrorMsg( |
| 4098 | 4095 | } |
| 4099 | 4096 | |
| 4100 | 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 | 4099 | .span_start = err_span.start, |
| 4103 | 4100 | .span_main = err_span.main, |
| 4104 | 4101 | .span_end = err_span.end, |
| ... | ... | @@ -4130,7 +4127,7 @@ pub fn addModuleErrorMsg( |
| 4130 | 4127 | const gop = try notes.getOrPutContext(gpa, .{ |
| 4131 | 4128 | .msg = try eb.addString(module_note.msg), |
| 4132 | 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 | 4131 | .span_start = span.start, |
| 4135 | 4132 | .span_main = span.main, |
| 4136 | 4133 | .span_end = span.end, |
| ... | ... | @@ -4175,7 +4172,7 @@ fn addReferenceTraceFrame( |
| 4175 | 4172 | try ref_traces.append(gpa, .{ |
| 4176 | 4173 | .decl_name = try eb.printString("{s}{s}", .{ name, if (inlined) " [inlined]" else "" }), |
| 4177 | 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 | 4176 | .span_start = span.start, |
| 4180 | 4177 | .span_main = span.main, |
| 4181 | 4178 | .span_end = span.end, |
| ... | ... | @@ -4836,7 +4833,7 @@ fn docsCopyFallible(comp: *Compilation) anyerror!void { |
| 4836 | 4833 | var out_dir = docs_path.root_dir.handle.makeOpenPath(docs_path.sub_path, .{}) catch |err| { |
| 4837 | 4834 | return comp.lockAndSetMiscFailure( |
| 4838 | 4835 | .docs_copy, |
| 4839 | "unable to create output directory '{}': {s}", | |
| 4836 | "unable to create output directory '{f}': {s}", | |
| 4840 | 4837 | .{ docs_path, @errorName(err) }, |
| 4841 | 4838 | ); |
| 4842 | 4839 | }; |
| ... | ... | @@ -4856,7 +4853,7 @@ fn docsCopyFallible(comp: *Compilation) anyerror!void { |
| 4856 | 4853 | var tar_file = out_dir.createFile("sources.tar", .{}) catch |err| { |
| 4857 | 4854 | return comp.lockAndSetMiscFailure( |
| 4858 | 4855 | .docs_copy, |
| 4859 | "unable to create '{}/sources.tar': {s}", | |
| 4856 | "unable to create '{f}/sources.tar': {s}", | |
| 4860 | 4857 | .{ docs_path, @errorName(err) }, |
| 4861 | 4858 | ); |
| 4862 | 4859 | }; |
| ... | ... | @@ -4885,7 +4882,7 @@ fn docsCopyModule(comp: *Compilation, module: *Package.Module, name: []const u8, |
| 4885 | 4882 | const root_dir, const sub_path = root.openInfo(comp.dirs); |
| 4886 | 4883 | break :d root_dir.openDir(sub_path, .{ .iterate = true }); |
| 4887 | 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 | 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 | 4891 | var walker = try mod_dir.walk(comp.gpa); |
| 4895 | 4892 | defer walker.deinit(); |
| 4896 | 4893 | |
| 4897 | var archiver = std.tar.writer(tar_file.writer().any()); | |
| 4894 | var archiver = std.tar.writer(tar_file.deprecatedWriter().any()); | |
| 4898 | 4895 | archiver.prefix = name; |
| 4899 | 4896 | |
| 4900 | 4897 | while (try walker.next()) |entry| { |
| ... | ... | @@ -4907,13 +4904,13 @@ fn docsCopyModule(comp: *Compilation, module: *Package.Module, name: []const u8, |
| 4907 | 4904 | else => continue, |
| 4908 | 4905 | } |
| 4909 | 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 | 4908 | root.fmt(comp), entry.path, @errorName(err), |
| 4912 | 4909 | }); |
| 4913 | 4910 | }; |
| 4914 | 4911 | defer file.close(); |
| 4915 | 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 | 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 | 5040 | var out_dir = docs_path.root_dir.handle.makeOpenPath(docs_path.sub_path, .{}) catch |err| { |
| 5044 | 5041 | return comp.lockAndSetMiscFailure( |
| 5045 | 5042 | .docs_copy, |
| 5046 | "unable to create output directory '{}': {s}", | |
| 5043 | "unable to create output directory '{f}': {s}", | |
| 5047 | 5044 | .{ docs_path, @errorName(err) }, |
| 5048 | 5045 | ); |
| 5049 | 5046 | }; |
| ... | ... | @@ -5055,10 +5052,8 @@ fn workerDocsWasmFallible(comp: *Compilation, prog_node: std.Progress.Node) anye |
| 5055 | 5052 | "main.wasm", |
| 5056 | 5053 | .{}, |
| 5057 | 5054 | ) catch |err| { |
| 5058 | return comp.lockAndSetMiscFailure(.docs_copy, "unable to copy '{}' to '{}': {s}", .{ | |
| 5059 | crt_file.full_object_path, | |
| 5060 | docs_path, | |
| 5061 | @errorName(err), | |
| 5055 | return comp.lockAndSetMiscFailure(.docs_copy, "unable to copy '{f}' to '{f}': {s}", .{ | |
| 5056 | crt_file.full_object_path, docs_path, @errorName(err), | |
| 5062 | 5057 | }); |
| 5063 | 5058 | }; |
| 5064 | 5059 | } |
| ... | ... | @@ -5131,7 +5126,7 @@ fn workerUpdateBuiltinFile(comp: *Compilation, file: *Zcu.File) void { |
| 5131 | 5126 | defer comp.mutex.unlock(); |
| 5132 | 5127 | comp.setMiscFailure( |
| 5133 | 5128 | .write_builtin_zig, |
| 5134 | "unable to write '{}': {s}", | |
| 5129 | "unable to write '{f}': {s}", | |
| 5135 | 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 | 5847 | |
| 5853 | 5848 | try child.spawn(); |
| 5854 | 5849 | |
| 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)); | |
| 5856 | 5851 | |
| 5857 | 5852 | const term = child.wait() catch |err| { |
| 5858 | 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 | 6007 | |
| 6013 | 6008 | // In .rc files, a " within a quoted string is escaped as "" |
| 6014 | 6009 | const fmtRcEscape = struct { |
| 6015 | fn formatRcEscape(bytes: []const u8, comptime fmt: []const u8, options: std.fmt.FormatOptions, writer: anytype) !void { | |
| 6016 | _ = fmt; | |
| 6017 | _ = options; | |
| 6010 | fn formatRcEscape(bytes: []const u8, writer: *std.io.Writer) std.io.Writer.Error!void { | |
| 6018 | 6011 | for (bytes) |byte| switch (byte) { |
| 6019 | 6012 | '"' => try writer.writeAll("\"\""), |
| 6020 | 6013 | '\\' => try writer.writeAll("\\\\"), |
| ... | ... | @@ -6022,7 +6015,7 @@ fn updateWin32Resource(comp: *Compilation, win32_resource: *Win32Resource, win32 |
| 6022 | 6015 | }; |
| 6023 | 6016 | } |
| 6024 | 6017 | |
| 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 | 6019 | return .{ .data = bytes }; |
| 6027 | 6020 | } |
| 6028 | 6021 | }.fmtRcEscape; |
| ... | ... | @@ -6036,7 +6029,9 @@ fn updateWin32Resource(comp: *Compilation, win32_resource: *Win32Resource, win32 |
| 6036 | 6029 | // 24 is RT_MANIFEST |
| 6037 | 6030 | const resource_type = 24; |
| 6038 | 6031 | |
| 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 | }); | |
| 6040 | 6035 | |
| 6041 | 6036 | try o_dir.writeFile(.{ .sub_path = rc_basename, .data = input }); |
| 6042 | 6037 | |
| ... | ... | @@ -6251,7 +6246,7 @@ fn spawnZigRc( |
| 6251 | 6246 | } |
| 6252 | 6247 | |
| 6253 | 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 | 6250 | const stderr = try stderr_reader.readAllAlloc(arena, 10 * 1024 * 1024); |
| 6256 | 6251 | |
| 6257 | 6252 | const term = child.wait() catch |err| { |
| ... | ... | @@ -7214,7 +7209,7 @@ pub fn lockAndSetMiscFailure( |
| 7214 | 7209 | pub fn dump_argv(argv: []const []const u8) void { |
| 7215 | 7210 | std.debug.lockStdErr(); |
| 7216 | 7211 | defer std.debug.unlockStdErr(); |
| 7217 | const stderr = std.io.getStdErr().writer(); | |
| 7212 | const stderr = std.fs.File.stderr().deprecatedWriter(); | |
| 7218 | 7213 | for (argv[0 .. argv.len - 1]) |arg| { |
| 7219 | 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 | 142 | const create_gen = zcu.incremental_debug_state.navs.get(nav_index) orelse return w.writeAll("unknown nav index"); |
| 143 | 143 | const nav = ip.getNav(nav_index); |
| 144 | 144 | try w.print( |
| 145 | \\name: '{}' | |
| 146 | \\fqn: '{}' | |
| 145 | \\name: '{f}' | |
| 146 | \\fqn: '{f}' | |
| 147 | 147 | \\status: {s} |
| 148 | 148 | \\created on generation: {d} |
| 149 | 149 | \\ |
| ... | ... | @@ -234,7 +234,7 @@ fn handleCommand(zcu: *Zcu, output: *std.ArrayListUnmanaged(u8), cmd_str: []cons |
| 234 | 234 | for (unit_info.deps.items, 0..) |dependee, i| { |
| 235 | 235 | try w.print("[{d}] ", .{i}); |
| 236 | 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 | 238 | .nav_val, .nav_ty => |nav| try w.print("{s} {d}", .{ @tagName(dependee), @intFromEnum(nav) }), |
| 239 | 239 | .interned => |ip_index| switch (ip.indexToKey(ip_index)) { |
| 240 | 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 | 260 | const ip_index: InternPool.Index = @enumFromInt(parseIndex(arg_str) orelse return w.writeAll("malformed ip index")); |
| 261 | 261 | const create_gen = zcu.incremental_debug_state.types.get(ip_index) orelse return w.writeAll("unknown type"); |
| 262 | 262 | try w.print( |
| 263 | \\name: '{}' | |
| 263 | \\name: '{f}' | |
| 264 | 264 | \\created on generation: {d} |
| 265 | 265 | \\ |
| 266 | 266 | , .{ |
| ... | ... | @@ -365,7 +365,7 @@ fn printType(ty: Type, zcu: *const Zcu, w: anytype) !void { |
| 365 | 365 | .union_type, |
| 366 | 366 | .enum_type, |
| 367 | 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()) }), | |
| 369 | 369 | |
| 370 | 370 | else => unreachable, |
| 371 | 371 | } |
src/InternPool.zig+30-31| ... | ... | @@ -1881,23 +1881,23 @@ pub const NullTerminatedString = enum(u32) { |
| 1881 | 1881 | const FormatData = struct { |
| 1882 | 1882 | string: NullTerminatedString, |
| 1883 | 1883 | ip: *const InternPool, |
| 1884 | id: bool, | |
| 1884 | 1885 | }; |
| 1885 | fn format( | |
| 1886 | data: FormatData, | |
| 1887 | comptime specifier: []const u8, | |
| 1888 | _: std.fmt.FormatOptions, | |
| 1889 | writer: anytype, | |
| 1890 | ) @TypeOf(writer).Error!void { | |
| 1886 | fn format(data: FormatData, writer: *std.io.Writer) std.io.Writer.Error!void { | |
| 1891 | 1887 | const slice = data.string.toSlice(data.ip); |
| 1892 | if (comptime std.mem.eql(u8, specifier, "")) { | |
| 1888 | if (!data.id) { | |
| 1893 | 1889 | try writer.writeAll(slice); |
| 1894 | } else if (comptime std.mem.eql(u8, specifier, "i")) { | |
| 1895 | try writer.print("{p}", .{std.zig.fmtId(slice)}); | |
| 1896 | } else @compileError("invalid format string '" ++ specifier ++ "' for '" ++ @typeName(NullTerminatedString) ++ "'"); | |
| 1890 | } else { | |
| 1891 | try writer.print("{f}", .{std.zig.fmtIdP(slice)}); | |
| 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 | } |
| 1898 | 1898 | |
| 1899 | pub fn fmt(string: NullTerminatedString, ip: *const InternPool) std.fmt.Formatter(format) { | |
| 1900 | return .{ .data = .{ .string = string, .ip = ip } }; | |
| 1899 | pub fn fmtId(string: NullTerminatedString, ip: *const InternPool) std.fmt.Formatter(FormatData, format) { | |
| 1900 | return .{ .data = .{ .string = string, .ip = ip, .id = true } }; | |
| 1901 | 1901 | } |
| 1902 | 1902 | |
| 1903 | 1903 | const debug_state = InternPool.debug_state; |
| ... | ... | @@ -9750,7 +9750,7 @@ fn finishFuncInstance( |
| 9750 | 9750 | const fn_namespace = fn_owner_nav.analysis.?.namespace; |
| 9751 | 9751 | |
| 9752 | 9752 | // 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 | 9754 | fn_owner_nav.name.fmt(ip), @intFromEnum(func_index), |
| 9755 | 9755 | }, .no_embedded_nulls); |
| 9756 | 9756 | const nav_index = try ip.createNav(gpa, tid, .{ |
| ... | ... | @@ -11259,8 +11259,9 @@ fn dumpStatsFallible(ip: *const InternPool, arena: Allocator) anyerror!void { |
| 11259 | 11259 | } |
| 11260 | 11260 | |
| 11261 | 11261 | fn dumpAllFallible(ip: *const InternPool) anyerror!void { |
| 11262 | var bw = std.io.bufferedWriter(std.io.getStdErr().writer()); | |
| 11263 | const w = bw.writer(); | |
| 11262 | var buffer: [4096]u8 = undefined; | |
| 11263 | const stderr_bw = std.debug.lockStderrWriter(&buffer); | |
| 11264 | defer std.debug.unlockStderrWriter(); | |
| 11264 | 11265 | for (ip.locals, 0..) |*local, tid| { |
| 11265 | 11266 | const items = local.shared.items.view(); |
| 11266 | 11267 | for ( |
| ... | ... | @@ -11269,12 +11270,12 @@ fn dumpAllFallible(ip: *const InternPool) anyerror!void { |
| 11269 | 11270 | 0.., |
| 11270 | 11271 | ) |tag, data, index| { |
| 11271 | 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 | 11274 | switch (tag) { |
| 11274 | 11275 | .removed => {}, |
| 11275 | 11276 | |
| 11276 | .simple_type => try w.print("{s}", .{@tagName(@as(SimpleType, @enumFromInt(@intFromEnum(i))))}), | |
| 11277 | .simple_value => try w.print("{s}", .{@tagName(@as(SimpleValue, @enumFromInt(@intFromEnum(i))))}), | |
| 11277 | .simple_type => try stderr_bw.print("{s}", .{@tagName(@as(SimpleType, @enumFromInt(@intFromEnum(i))))}), | |
| 11278 | .simple_value => try stderr_bw.print("{s}", .{@tagName(@as(SimpleValue, @enumFromInt(@intFromEnum(i))))}), | |
| 11278 | 11279 | |
| 11279 | 11280 | .type_int_signed, |
| 11280 | 11281 | .type_int_unsigned, |
| ... | ... | @@ -11347,17 +11348,16 @@ fn dumpAllFallible(ip: *const InternPool) anyerror!void { |
| 11347 | 11348 | .func_coerced, |
| 11348 | 11349 | .union_value, |
| 11349 | 11350 | .memoized_call, |
| 11350 | => try w.print("{d}", .{data}), | |
| 11351 | => try stderr_bw.print("{d}", .{data}), | |
| 11351 | 11352 | |
| 11352 | 11353 | .opt_null, |
| 11353 | 11354 | .type_slice, |
| 11354 | 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 | } |
| 11362 | 11362 | |
| 11363 | 11363 | pub fn dumpGenericInstances(ip: *const InternPool, allocator: Allocator) void { |
| ... | ... | @@ -11369,9 +11369,6 @@ pub fn dumpGenericInstancesFallible(ip: *const InternPool, allocator: Allocator) |
| 11369 | 11369 | defer arena_allocator.deinit(); |
| 11370 | 11370 | const arena = arena_allocator.allocator(); |
| 11371 | 11371 | |
| 11372 | var bw = std.io.bufferedWriter(std.io.getStdErr().writer()); | |
| 11373 | const w = bw.writer(); | |
| 11374 | ||
| 11375 | 11372 | var instances: std.AutoArrayHashMapUnmanaged(Index, std.ArrayListUnmanaged(Index)) = .empty; |
| 11376 | 11373 | for (ip.locals, 0..) |*local, tid| { |
| 11377 | 11374 | const items = local.shared.items.view().slice(); |
| ... | ... | @@ -11394,6 +11391,10 @@ pub fn dumpGenericInstancesFallible(ip: *const InternPool, allocator: Allocator) |
| 11394 | 11391 | } |
| 11395 | 11392 | } |
| 11396 | 11393 | |
| 11394 | var buffer: [4096]u8 = undefined; | |
| 11395 | const stderr_bw = std.debug.lockStderrWriter(&buffer); | |
| 11396 | defer std.debug.unlockStderrWriter(); | |
| 11397 | ||
| 11397 | 11398 | const SortContext = struct { |
| 11398 | 11399 | values: []std.ArrayListUnmanaged(Index), |
| 11399 | 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 | 11406 | var it = instances.iterator(); |
| 11406 | 11407 | while (it.next()) |entry| { |
| 11407 | 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 | 11410 | for (entry.value_ptr.items) |index| { |
| 11410 | 11411 | const unwrapped_index = index.unwrap(ip); |
| 11411 | 11412 | const func = ip.extraFuncInstance(unwrapped_index.tid, unwrapped_index.getExtra(ip), unwrapped_index.getData(ip)); |
| 11412 | 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 | 11415 | for (func.comptime_args.get(ip)) |arg| { |
| 11415 | 11416 | if (arg != .none) { |
| 11416 | 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 | } |
| 11426 | 11425 | |
| 11427 | 11426 | pub fn getNav(ip: *const InternPool, index: Nav.Index) Nav { |
src/Package.zig+1-1| ... | ... | @@ -134,7 +134,7 @@ pub const Hash = struct { |
| 134 | 134 | } |
| 135 | 135 | var bin_digest: [Algo.digest_length]u8 = undefined; |
| 136 | 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 | 138 | return result; |
| 139 | 139 | } |
| 140 | 140 | }; |
src/Package/Fetch.zig+64-61| ... | ... | @@ -27,6 +27,22 @@ |
| 27 | 27 | //! All of this must be done with only referring to the state inside this struct |
| 28 | 28 | //! because this work will be done in a dedicated thread. |
| 29 | 29 | |
| 30 | const builtin = @import("builtin"); | |
| 31 | const std = @import("std"); | |
| 32 | const fs = std.fs; | |
| 33 | const assert = std.debug.assert; | |
| 34 | const ascii = std.ascii; | |
| 35 | const Allocator = std.mem.Allocator; | |
| 36 | const Cache = std.Build.Cache; | |
| 37 | const ThreadPool = std.Thread.Pool; | |
| 38 | const WaitGroup = std.Thread.WaitGroup; | |
| 39 | const Fetch = @This(); | |
| 40 | const git = @import("Fetch/git.zig"); | |
| 41 | const Package = @import("../Package.zig"); | |
| 42 | const Manifest = Package.Manifest; | |
| 43 | const ErrorBundle = std.zig.ErrorBundle; | |
| 44 | const native_os = builtin.os.tag; | |
| 45 | ||
| 30 | 46 | arena: std.heap.ArenaAllocator, |
| 31 | 47 | location: Location, |
| 32 | 48 | location_tok: std.zig.Ast.TokenIndex, |
| ... | ... | @@ -185,7 +201,7 @@ pub const JobQueue = struct { |
| 185 | 201 | const hash_slice = hash.toSlice(); |
| 186 | 202 | |
| 187 | 203 | try buf.writer().print( |
| 188 | \\ pub const {} = struct {{ | |
| 204 | \\ pub const {f} = struct {{ | |
| 189 | 205 | \\ |
| 190 | 206 | , .{std.zig.fmtId(hash_slice)}); |
| 191 | 207 | |
| ... | ... | @@ -211,15 +227,15 @@ pub const JobQueue = struct { |
| 211 | 227 | } |
| 212 | 228 | |
| 213 | 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)}); | |
| 217 | 233 | |
| 218 | 234 | if (fetch.has_build_zig) { |
| 219 | 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 | } |
| 224 | 240 | |
| 225 | 241 | if (fetch.manifest) |*manifest| { |
| ... | ... | @@ -230,8 +246,8 @@ pub const JobQueue = struct { |
| 230 | 246 | for (manifest.dependencies.keys(), manifest.dependencies.values()) |name, dep| { |
| 231 | 247 | const h = depDigest(fetch.package_root, jq.global_cache, dep) orelse continue; |
| 232 | 248 | try buf.writer().print( |
| 233 | " .{{ \"{}\", \"{}\" }},\n", | |
| 234 | .{ std.zig.fmtEscapes(name), std.zig.fmtEscapes(h.toSlice()) }, | |
| 249 | " .{{ \"{f}\", \"{f}\" }},\n", | |
| 250 | .{ std.zig.fmtString(name), std.zig.fmtString(h.toSlice()) }, | |
| 235 | 251 | ); |
| 236 | 252 | } |
| 237 | 253 | |
| ... | ... | @@ -262,8 +278,8 @@ pub const JobQueue = struct { |
| 262 | 278 | for (root_manifest.dependencies.keys(), root_manifest.dependencies.values()) |name, dep| { |
| 263 | 279 | const h = depDigest(root_fetch.package_root, jq.global_cache, dep) orelse continue; |
| 264 | 280 | try buf.writer().print( |
| 265 | " .{{ \"{}\", \"{}\" }},\n", | |
| 266 | .{ std.zig.fmtEscapes(name), std.zig.fmtEscapes(h.toSlice()) }, | |
| 281 | " .{{ \"{f}\", \"{f}\" }},\n", | |
| 282 | .{ std.zig.fmtString(name), std.zig.fmtString(h.toSlice()) }, | |
| 267 | 283 | ); |
| 268 | 284 | } |
| 269 | 285 | try buf.appendSlice("};\n"); |
| ... | ... | @@ -353,7 +369,7 @@ pub fn run(f: *Fetch) RunError!void { |
| 353 | 369 | if (!std.mem.startsWith(u8, pkg_root.sub_path, expected_prefix)) { |
| 354 | 370 | return f.fail( |
| 355 | 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 | 436 | } |
| 421 | 437 | if (f.job_queue.read_only) return f.fail( |
| 422 | 438 | f.name_tok, |
| 423 | try eb.printString("package not found at '{}{s}'", .{ | |
| 439 | try eb.printString("package not found at '{f}{s}'", .{ | |
| 424 | 440 | cache_root, pkg_sub_path, |
| 425 | 441 | }), |
| 426 | 442 | ); |
| 427 | 443 | }, |
| 428 | 444 | else => |e| { |
| 429 | 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 | 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 | 620 | const saturated_size = std.math.cast(u32, f.computed_hash.total_size) orelse std.math.maxInt(u32); |
| 605 | 621 | if (f.manifest) |man| { |
| 606 | 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 | 624 | return .init(f.computed_hash.digest, man.name, version, man.id, saturated_size); |
| 609 | 625 | } |
| 610 | 626 | // 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 | 638 | error.FileNotFound => {}, |
| 623 | 639 | else => |e| { |
| 624 | 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 | 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 | 663 | else => |e| { |
| 648 | 664 | const file_path = try pkg_root.join(arena, Manifest.basename); |
| 649 | 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 | 667 | file_path, @errorName(e), |
| 652 | 668 | }), |
| 653 | 669 | }); |
| ... | ... | @@ -659,7 +675,7 @@ fn loadManifest(f: *Fetch, pkg_root: Cache.Path) RunError!void { |
| 659 | 675 | ast.* = try std.zig.Ast.parse(arena, manifest_bytes, .zon); |
| 660 | 676 | |
| 661 | 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 | 679 | try std.zig.putAstErrorsIntoBundle(arena, ast.*, file_path, eb); |
| 664 | 680 | return error.FetchFailed; |
| 665 | 681 | } |
| ... | ... | @@ -672,7 +688,7 @@ fn loadManifest(f: *Fetch, pkg_root: Cache.Path) RunError!void { |
| 672 | 688 | const manifest = &f.manifest.?; |
| 673 | 689 | |
| 674 | 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 | 692 | try manifest.copyErrorsIntoBundle(ast.*, src_path, eb); |
| 677 | 693 | return error.FetchFailed; |
| 678 | 694 | } |
| ... | ... | @@ -827,7 +843,7 @@ fn srcLoc( |
| 827 | 843 | const ast = f.parent_manifest_ast orelse return .none; |
| 828 | 844 | const eb = &f.error_bundle; |
| 829 | 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 | 847 | const msg_off = 0; |
| 832 | 848 | return eb.addSourceLocation(.{ |
| 833 | 849 | .src_path = src_path, |
| ... | ... | @@ -961,7 +977,7 @@ fn initResource(f: *Fetch, uri: std.Uri, server_header_buffer: []u8) RunError!Re |
| 961 | 977 | if (ascii.eqlIgnoreCase(uri.scheme, "file")) { |
| 962 | 978 | const path = try uri.path.toRawMaybeAlloc(arena); |
| 963 | 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 | 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 | 1079 | }); |
| 1064 | 1080 | const notes_start = try eb.reserveNotes(notes_len); |
| 1065 | 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 | 1087 | return error.FetchFailed; |
| 1069 | 1088 | } |
| 1070 | 1089 | |
| 1071 | 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 | 1092 | var fetch_stream = session.fetch(&.{&want_oid_buf}, server_header_buffer) catch |err| { |
| 1074 | 1093 | return f.fail(f.location_tok, try eb.printString( |
| 1075 | 1094 | "unable to create fetch stream: {s}", |
| ... | ... | @@ -1305,7 +1324,7 @@ fn unzip(f: *Fetch, out_dir: fs.Dir, reader: anytype) RunError!UnpackResult { |
| 1305 | 1324 | .{@errorName(err)}, |
| 1306 | 1325 | )); |
| 1307 | 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 | 1328 | "write temporary zip file failed: {s}", |
| 1310 | 1329 | .{@errorName(err)}, |
| 1311 | 1330 | )); |
| ... | ... | @@ -1358,7 +1377,7 @@ fn unpackGitPack(f: *Fetch, out_dir: fs.Dir, resource: *Resource.Git) anyerror!U |
| 1358 | 1377 | var pack_file = try pack_dir.createFile("pkg.pack", .{ .read = true }); |
| 1359 | 1378 | defer pack_file.close(); |
| 1360 | 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 | 1381 | try pack_file.sync(); |
| 1363 | 1382 | |
| 1364 | 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 | 1385 | { |
| 1367 | 1386 | const index_prog_node = f.prog_node.start("Index pack", 0); |
| 1368 | 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 | 1389 | try git.indexPack(gpa, object_format, pack_file, index_buffered_writer.writer()); |
| 1371 | 1390 | try index_buffered_writer.flush(); |
| 1372 | 1391 | try index_file.sync(); |
| ... | ... | @@ -1508,7 +1527,7 @@ fn computeHash(f: *Fetch, pkg_path: Cache.Path, filter: Filter) RunError!Compute |
| 1508 | 1527 | |
| 1509 | 1528 | while (walker.next() catch |err| { |
| 1510 | 1529 | try eb.addRootErrorMessage(.{ .msg = try eb.printString( |
| 1511 | "unable to walk temporary directory '{}': {s}", | |
| 1530 | "unable to walk temporary directory '{f}': {s}", | |
| 1512 | 1531 | .{ pkg_path, @errorName(err) }, |
| 1513 | 1532 | ) }); |
| 1514 | 1533 | return error.FetchFailed; |
| ... | ... | @@ -1638,14 +1657,14 @@ fn computeHash(f: *Fetch, pkg_path: Cache.Path, filter: Filter) RunError!Compute |
| 1638 | 1657 | } |
| 1639 | 1658 | |
| 1640 | 1659 | fn dumpHashInfo(all_files: []const *const HashedFile) !void { |
| 1641 | const stdout = std.io.getStdOut(); | |
| 1642 | var bw = std.io.bufferedWriter(stdout.writer()); | |
| 1660 | const stdout: std.fs.File = .stdout(); | |
| 1661 | var bw = std.io.bufferedWriter(stdout.deprecatedWriter()); | |
| 1643 | 1662 | const w = bw.writer(); |
| 1644 | 1663 | |
| 1645 | 1664 | for (all_files) |hashed_file| { |
| 1646 | try w.print("{s}: {s}: {s}\n", .{ | |
| 1665 | try w.print("{s}: {x}: {s}\n", .{ | |
| 1647 | 1666 | @tagName(hashed_file.kind), |
| 1648 | std.fmt.fmtSliceHexLower(&hashed_file.hash), | |
| 1667 | &hashed_file.hash, | |
| 1649 | 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 | 1836 | } |
| 1818 | 1837 | } |
| 1819 | 1838 | |
| 1820 | const builtin = @import("builtin"); | |
| 1821 | const std = @import("std"); | |
| 1822 | const fs = std.fs; | |
| 1823 | const assert = std.debug.assert; | |
| 1824 | const ascii = std.ascii; | |
| 1825 | const Allocator = std.mem.Allocator; | |
| 1826 | const Cache = std.Build.Cache; | |
| 1827 | const ThreadPool = std.Thread.Pool; | |
| 1828 | const WaitGroup = std.Thread.WaitGroup; | |
| 1829 | const Fetch = @This(); | |
| 1830 | const git = @import("Fetch/git.zig"); | |
| 1831 | const Package = @import("../Package.zig"); | |
| 1832 | const Manifest = Package.Manifest; | |
| 1833 | const ErrorBundle = std.zig.ErrorBundle; | |
| 1834 | const native_os = builtin.os.tag; | |
| 1835 | ||
| 1836 | test { | |
| 1837 | _ = Filter; | |
| 1838 | _ = FileType; | |
| 1839 | _ = UnpackResult; | |
| 1840 | } | |
| 1841 | ||
| 1842 | 1839 | // Detects executable header: ELF or Macho-O magic header or shebang line. |
| 1843 | 1840 | const FileHeader = struct { |
| 1844 | 1841 | header: [4]u8 = undefined, |
| ... | ... | @@ -2056,15 +2053,15 @@ const UnpackResult = struct { |
| 2056 | 2053 | // output errors to string |
| 2057 | 2054 | var errors = try fetch.error_bundle.toOwnedBundle(""); |
| 2058 | 2055 | defer errors.deinit(gpa); |
| 2059 | var out = std.ArrayList(u8).init(gpa); | |
| 2060 | defer out.deinit(); | |
| 2061 | try errors.renderToWriter(.{ .ttyconf = .no_color }, out.writer()); | |
| 2056 | var aw: std.io.Writer.Allocating = .init(gpa); | |
| 2057 | defer aw.deinit(); | |
| 2058 | try errors.renderToWriter(.{ .ttyconf = .no_color }, &aw.writer); | |
| 2062 | 2059 | try std.testing.expectEqualStrings( |
| 2063 | 2060 | \\error: unable to unpack |
| 2064 | 2061 | \\ note: unable to create symlink from 'dir2/file2' to 'filename': SymlinkError |
| 2065 | 2062 | \\ note: file 'dir2/file4' has unsupported type 'x' |
| 2066 | 2063 | \\ |
| 2067 | , out.items); | |
| 2064 | , aw.getWritten()); | |
| 2068 | 2065 | } |
| 2069 | 2066 | }; |
| 2070 | 2067 | |
| ... | ... | @@ -2080,7 +2077,7 @@ test "zip" { |
| 2080 | 2077 | { |
| 2081 | 2078 | var zip_file = try tmp.dir.createFile("test.zip", .{}); |
| 2082 | 2079 | defer zip_file.close(); |
| 2083 | var bw = std.io.bufferedWriter(zip_file.writer()); | |
| 2080 | var bw = std.io.bufferedWriter(zip_file.deprecatedWriter()); | |
| 2084 | 2081 | var store: [test_files.len]std.zip.testutil.FileStore = undefined; |
| 2085 | 2082 | try std.zip.testutil.writeZip(bw.writer(), &test_files, &store, .{}); |
| 2086 | 2083 | try bw.flush(); |
| ... | ... | @@ -2113,7 +2110,7 @@ test "zip with one root folder" { |
| 2113 | 2110 | { |
| 2114 | 2111 | var zip_file = try tmp.dir.createFile("test.zip", .{}); |
| 2115 | 2112 | defer zip_file.close(); |
| 2116 | var bw = std.io.bufferedWriter(zip_file.writer()); | |
| 2113 | var bw = std.io.bufferedWriter(zip_file.deprecatedWriter()); | |
| 2117 | 2114 | var store: [test_files.len]std.zip.testutil.FileStore = undefined; |
| 2118 | 2115 | try std.zip.testutil.writeZip(bw.writer(), &test_files, &store, .{}); |
| 2119 | 2116 | try bw.flush(); |
| ... | ... | @@ -2431,9 +2428,15 @@ const TestFetchBuilder = struct { |
| 2431 | 2428 | if (notes_len > 0) { |
| 2432 | 2429 | try std.testing.expectEqual(notes_len, em.notes_len); |
| 2433 | 2430 | } |
| 2434 | var al = std.ArrayList(u8).init(std.testing.allocator); | |
| 2435 | defer al.deinit(); | |
| 2436 | try errors.renderToWriter(.{ .ttyconf = .no_color }, al.writer()); | |
| 2437 | try std.testing.expectEqualStrings(msg, al.items); | |
| 2431 | var aw: std.io.Writer.Allocating = .init(std.testing.allocator); | |
| 2432 | defer aw.deinit(); | |
| 2433 | try errors.renderToWriter(.{ .ttyconf = .no_color }, &aw.writer); | |
| 2434 | try std.testing.expectEqualStrings(msg, aw.getWritten()); | |
| 2438 | 2435 | } |
| 2439 | 2436 | }; |
| 2437 | ||
| 2438 | test { | |
| 2439 | _ = Filter; | |
| 2440 | _ = FileType; | |
| 2441 | _ = UnpackResult; | |
| 2442 | } |
src/Package/Fetch/git.zig+40-31| ... | ... | @@ -119,15 +119,8 @@ pub const Oid = union(Format) { |
| 119 | 119 | } else error.InvalidOid; |
| 120 | 120 | } |
| 121 | 121 | |
| 122 | pub fn format( | |
| 123 | oid: Oid, | |
| 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())}); | |
| 122 | pub fn format(oid: Oid, writer: *std.io.Writer) std.io.Writer.Error!void { | |
| 123 | try writer.print("{x}", .{oid.slice()}); | |
| 131 | 124 | } |
| 132 | 125 | |
| 133 | 126 | pub fn slice(oid: *const Oid) []const u8 { |
| ... | ... | @@ -353,7 +346,7 @@ const Odb = struct { |
| 353 | 346 | fn init(allocator: Allocator, format: Oid.Format, pack_file: std.fs.File, index_file: std.fs.File) !Odb { |
| 354 | 347 | try pack_file.seekTo(0); |
| 355 | 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 | 350 | return .{ |
| 358 | 351 | .format = format, |
| 359 | 352 | .pack_file = pack_file, |
| ... | ... | @@ -377,7 +370,7 @@ const Odb = struct { |
| 377 | 370 | const base_object = while (true) { |
| 378 | 371 | if (odb.cache.get(base_offset)) |base_object| break base_object; |
| 379 | 372 | |
| 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 | 374 | switch (base_header) { |
| 382 | 375 | .ofs_delta => |ofs_delta| { |
| 383 | 376 | try delta_offsets.append(odb.allocator, base_offset); |
| ... | ... | @@ -390,7 +383,7 @@ const Odb = struct { |
| 390 | 383 | base_offset = try odb.pack_file.getPos(); |
| 391 | 384 | }, |
| 392 | 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 | 387 | errdefer odb.allocator.free(base_data); |
| 395 | 388 | const base_object: Object = .{ .type = base_header.objectType(), .data = base_data }; |
| 396 | 389 | try odb.cache.put(odb.allocator, base_offset, base_object); |
| ... | ... | @@ -420,7 +413,7 @@ const Odb = struct { |
| 420 | 413 | const found_index = while (start_index < end_index) { |
| 421 | 414 | const mid_index = start_index + (end_index - start_index) / 2; |
| 422 | 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 | 417 | switch (mem.order(u8, mid_oid.slice(), oid.slice())) { |
| 425 | 418 | .lt => start_index = mid_index + 1, |
| 426 | 419 | .gt => end_index = mid_index, |
| ... | ... | @@ -431,12 +424,12 @@ const Odb = struct { |
| 431 | 424 | const n_objects = odb.index_header.fan_out_table[255]; |
| 432 | 425 | const offset_values_start = IndexHeader.size + n_objects * (oid_length + 4); |
| 433 | 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 | 428 | const pack_offset = pack_offset: { |
| 436 | 429 | if (l1_offset.big) { |
| 437 | 430 | const l2_offset_values_start = offset_values_start + n_objects * 4; |
| 438 | 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 | 433 | } else { |
| 441 | 434 | break :pack_offset l1_offset.value; |
| 442 | 435 | } |
| ... | ... | @@ -669,13 +662,21 @@ pub const Session = struct { |
| 669 | 662 | fn init(allocator: Allocator, uri: std.Uri) !Location { |
| 670 | 663 | const scheme = try allocator.dupe(u8, uri.scheme); |
| 671 | 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 | 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 | 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 | 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 | 680 | errdefer allocator.free(path); |
| 680 | 681 | // The query and fragment are not used as part of the base server URI. |
| 681 | 682 | return .{ |
| ... | ... | @@ -706,7 +707,9 @@ pub const Session = struct { |
| 706 | 707 | fn getCapabilities(session: *Session, http_headers_buffer: []u8) !CapabilityIterator { |
| 707 | 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 | 713 | defer session.allocator.free(session_uri_path); |
| 711 | 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 | 733 | if (request.response.status != .ok) return error.ProtocolError; |
| 731 | 734 | const any_redirects_occurred = request.redirect_behavior.remaining() < max_redirects; |
| 732 | 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 | 739 | defer session.allocator.free(request_uri_path); |
| 735 | 740 | if (!mem.endsWith(u8, request_uri_path, "/info/refs")) return error.UnparseableRedirect; |
| 736 | 741 | var new_uri = request.uri; |
| ... | ... | @@ -817,7 +822,9 @@ pub const Session = struct { |
| 817 | 822 | pub fn listRefs(session: Session, options: ListRefsOptions) !RefIterator { |
| 818 | 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 | 828 | defer session.allocator.free(session_uri_path); |
| 822 | 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 | 939 | ) !FetchStream { |
| 933 | 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 | 945 | defer session.allocator.free(session_uri_path); |
| 937 | 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 | 1035 | ProtocolError, |
| 1027 | 1036 | UnexpectedPacket, |
| 1028 | 1037 | }; |
| 1029 | pub const Reader = std.io.Reader(*FetchStream, ReadError, read); | |
| 1038 | pub const Reader = std.io.GenericReader(*FetchStream, ReadError, read); | |
| 1030 | 1039 | |
| 1031 | 1040 | const StreamCode = enum(u8) { |
| 1032 | 1041 | pack_data = 1, |
| ... | ... | @@ -1320,7 +1329,7 @@ fn indexPackFirstPass( |
| 1320 | 1329 | index_entries: *std.AutoHashMapUnmanaged(Oid, IndexEntry), |
| 1321 | 1330 | pending_deltas: *std.ArrayListUnmanaged(IndexEntry), |
| 1322 | 1331 | ) !Oid { |
| 1323 | var pack_buffered_reader = std.io.bufferedReader(pack.reader()); | |
| 1332 | var pack_buffered_reader = std.io.bufferedReader(pack.deprecatedReader()); | |
| 1324 | 1333 | var pack_counting_reader = std.io.countingReader(pack_buffered_reader.reader()); |
| 1325 | 1334 | var pack_hashed_reader = std.compress.hashedReader(pack_counting_reader.reader(), Oid.Hasher.init(format)); |
| 1326 | 1335 | const pack_reader = pack_hashed_reader.reader(); |
| ... | ... | @@ -1400,7 +1409,7 @@ fn indexPackHashDelta( |
| 1400 | 1409 | if (cache.get(base_offset)) |base_object| break base_object; |
| 1401 | 1410 | |
| 1402 | 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 | 1413 | switch (base_header) { |
| 1405 | 1414 | .ofs_delta => |ofs_delta| { |
| 1406 | 1415 | try delta_offsets.append(allocator, base_offset); |
| ... | ... | @@ -1411,7 +1420,7 @@ fn indexPackHashDelta( |
| 1411 | 1420 | base_offset = (index_entries.get(ref_delta.base_object) orelse return null).offset; |
| 1412 | 1421 | }, |
| 1413 | 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 | 1424 | errdefer allocator.free(base_data); |
| 1416 | 1425 | const base_object: Object = .{ .type = base_header.objectType(), .data = base_data }; |
| 1417 | 1426 | try cache.put(allocator, base_offset, base_object); |
| ... | ... | @@ -1448,8 +1457,8 @@ fn resolveDeltaChain( |
| 1448 | 1457 | |
| 1449 | 1458 | const delta_offset = delta_offsets[i]; |
| 1450 | 1459 | try pack.seekTo(delta_offset); |
| 1451 | const delta_header = try EntryHeader.read(format, pack.reader()); | |
| 1452 | const delta_data = try readObjectRaw(allocator, pack.reader(), delta_header.uncompressedLength()); | |
| 1460 | const delta_header = try EntryHeader.read(format, pack.deprecatedReader()); | |
| 1461 | const delta_data = try readObjectRaw(allocator, pack.deprecatedReader(), delta_header.uncompressedLength()); | |
| 1453 | 1462 | defer allocator.free(delta_data); |
| 1454 | 1463 | var delta_stream = std.io.fixedBufferStream(delta_data); |
| 1455 | 1464 | const delta_reader = delta_stream.reader(); |
| ... | ... | @@ -1561,7 +1570,7 @@ fn runRepositoryTest(comptime format: Oid.Format, head_commit: []const u8) !void |
| 1561 | 1570 | |
| 1562 | 1571 | var index_file = try git_dir.dir.createFile("testrepo.idx", .{ .read = true }); |
| 1563 | 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()); | |
| 1565 | 1574 | |
| 1566 | 1575 | // Arbitrary size limit on files read while checking the repository contents |
| 1567 | 1576 | // (all files in the test repo are known to be smaller than this) |
| ... | ... | @@ -1678,7 +1687,7 @@ pub fn main() !void { |
| 1678 | 1687 | std.debug.print("Starting index...\n", .{}); |
| 1679 | 1688 | var index_file = try git_dir.createFile("idx", .{ .read = true }); |
| 1680 | 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 | 1691 | try indexPack(allocator, format, pack_file, index_buffered_writer.writer()); |
| 1683 | 1692 | try index_buffered_writer.flush(); |
| 1684 | 1693 | try index_file.sync(); |
src/Package/Manifest.zig+2-2| ... | ... | @@ -401,7 +401,7 @@ const Parse = struct { |
| 401 | 401 | return fail(p, main_token, "name must be a valid bare zig identifier (hint: switch from string to enum literal)", .{}); |
| 402 | 402 | |
| 403 | 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 | 405 | std.zig.fmtId(name), max_name_len, |
| 406 | 406 | }); |
| 407 | 407 | |
| ... | ... | @@ -416,7 +416,7 @@ const Parse = struct { |
| 416 | 416 | return fail(p, main_token, "name must be a valid bare zig identifier", .{}); |
| 417 | 417 | |
| 418 | 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 | 420 | std.zig.fmtId(ident_name), max_name_len, |
| 421 | 421 | }); |
| 422 | 422 |
src/Sema.zig+481-480| ... | ... | @@ -5,6 +5,39 @@ |
| 5 | 5 | //! Does type checking, comptime control flow, and safety-check generation. |
| 6 | 6 | //! This is the the heart of the Zig compiler. |
| 7 | 7 | |
| 8 | const std = @import("std"); | |
| 9 | const math = std.math; | |
| 10 | const mem = std.mem; | |
| 11 | const Allocator = mem.Allocator; | |
| 12 | const assert = std.debug.assert; | |
| 13 | const log = std.log.scoped(.sema); | |
| 14 | ||
| 15 | const Sema = @This(); | |
| 16 | const Value = @import("Value.zig"); | |
| 17 | const MutableValue = @import("mutable_value.zig").MutableValue; | |
| 18 | const Type = @import("Type.zig"); | |
| 19 | const Air = @import("Air.zig"); | |
| 20 | const Zir = std.zig.Zir; | |
| 21 | const Zcu = @import("Zcu.zig"); | |
| 22 | const trace = @import("tracy.zig").trace; | |
| 23 | const Namespace = Zcu.Namespace; | |
| 24 | const CompileError = Zcu.CompileError; | |
| 25 | const SemaError = Zcu.SemaError; | |
| 26 | const LazySrcLoc = Zcu.LazySrcLoc; | |
| 27 | const RangeSet = @import("RangeSet.zig"); | |
| 28 | const target_util = @import("target.zig"); | |
| 29 | const Package = @import("Package.zig"); | |
| 30 | const crash_report = @import("crash_report.zig"); | |
| 31 | const build_options = @import("build_options"); | |
| 32 | const Compilation = @import("Compilation.zig"); | |
| 33 | const InternPool = @import("InternPool.zig"); | |
| 34 | const Alignment = InternPool.Alignment; | |
| 35 | const AnalUnit = InternPool.AnalUnit; | |
| 36 | const ComptimeAllocIndex = InternPool.ComptimeAllocIndex; | |
| 37 | const Cache = std.Build.Cache; | |
| 38 | const LowerZon = @import("Sema/LowerZon.zig"); | |
| 39 | const arith = @import("Sema/arith.zig"); | |
| 40 | ||
| 8 | 41 | pt: Zcu.PerThread, |
| 9 | 42 | /// Alias to `zcu.gpa`. |
| 10 | 43 | gpa: Allocator, |
| ... | ... | @@ -157,39 +190,6 @@ pub fn getComptimeAlloc(sema: *Sema, idx: ComptimeAllocIndex) *ComptimeAlloc { |
| 157 | 190 | return &sema.comptime_allocs.items[@intFromEnum(idx)]; |
| 158 | 191 | } |
| 159 | 192 | |
| 160 | const std = @import("std"); | |
| 161 | const math = std.math; | |
| 162 | const mem = std.mem; | |
| 163 | const Allocator = mem.Allocator; | |
| 164 | const assert = std.debug.assert; | |
| 165 | const log = std.log.scoped(.sema); | |
| 166 | ||
| 167 | const Sema = @This(); | |
| 168 | const Value = @import("Value.zig"); | |
| 169 | const MutableValue = @import("mutable_value.zig").MutableValue; | |
| 170 | const Type = @import("Type.zig"); | |
| 171 | const Air = @import("Air.zig"); | |
| 172 | const Zir = std.zig.Zir; | |
| 173 | const Zcu = @import("Zcu.zig"); | |
| 174 | const trace = @import("tracy.zig").trace; | |
| 175 | const Namespace = Zcu.Namespace; | |
| 176 | const CompileError = Zcu.CompileError; | |
| 177 | const SemaError = Zcu.SemaError; | |
| 178 | const LazySrcLoc = Zcu.LazySrcLoc; | |
| 179 | const RangeSet = @import("RangeSet.zig"); | |
| 180 | const target_util = @import("target.zig"); | |
| 181 | const Package = @import("Package.zig"); | |
| 182 | const crash_report = @import("crash_report.zig"); | |
| 183 | const build_options = @import("build_options"); | |
| 184 | const Compilation = @import("Compilation.zig"); | |
| 185 | const InternPool = @import("InternPool.zig"); | |
| 186 | const Alignment = InternPool.Alignment; | |
| 187 | const AnalUnit = InternPool.AnalUnit; | |
| 188 | const ComptimeAllocIndex = InternPool.ComptimeAllocIndex; | |
| 189 | const Cache = std.Build.Cache; | |
| 190 | const LowerZon = @import("Sema/LowerZon.zig"); | |
| 191 | const arith = @import("Sema/arith.zig"); | |
| 192 | ||
| 193 | 193 | pub const default_branch_quota = 1000; |
| 194 | 194 | |
| 195 | 195 | pub const InferredErrorSet = struct { |
| ... | ... | @@ -888,7 +888,7 @@ const ComptimeReason = union(enum) { |
| 888 | 888 | /// Evaluating at comptime because of a comptime-only type. This field is separate so that |
| 889 | 889 | /// the type in question can be included in the error message. AstGen could never emit this |
| 890 | 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 | 892 | /// We will then explain why this type is comptime-only. |
| 893 | 893 | comptime_only: struct { |
| 894 | 894 | ty: Type, |
| ... | ... | @@ -930,17 +930,17 @@ const ComptimeReason = union(enum) { |
| 930 | 930 | .struct_init => .{ "initializer of comptime-only struct", "must be comptime-known" }, |
| 931 | 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 | 934 | try sema.explainWhyTypeIsComptime(err_msg, src, co.ty); |
| 935 | 935 | }, |
| 936 | 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 | 938 | try sema.errNote(co.param_ty_src, err_msg, "parameter type declared here", .{}); |
| 939 | 939 | try sema.explainWhyTypeIsComptime(err_msg, src, co.ty); |
| 940 | 940 | }, |
| 941 | 941 | .comptime_only_ret_ty => |co| { |
| 942 | 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 | 944 | try sema.errNote(co.ret_ty_src, err_msg, "return type declared here", .{}); |
| 945 | 945 | try sema.explainWhyTypeIsComptime(err_msg, src, co.ty); |
| 946 | 946 | }, |
| ... | ... | @@ -1144,7 +1144,7 @@ fn analyzeBodyInner( |
| 1144 | 1144 | |
| 1145 | 1145 | // The hashmap lookup in here is a little expensive, and LLVM fails to optimize it away. |
| 1146 | 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 | 1148 | const file_index = block.src_base_inst.resolveFile(&zcu.intern_pool); |
| 1149 | 1149 | const file = zcu.fileByIndex(file_index); |
| 1150 | 1150 | break :path file.path.fmt(zcu.comp); |
| ... | ... | @@ -1905,7 +1905,7 @@ fn analyzeBodyInner( |
| 1905 | 1905 | const err_union = try sema.resolveInst(extra.data.operand); |
| 1906 | 1906 | const err_union_ty = sema.typeOf(err_union); |
| 1907 | 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 | 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 | 2339 | |
| 2340 | 2340 | fn failWithModRemNegative(sema: *Sema, block: *Block, src: LazySrcLoc, lhs_ty: Type, rhs_ty: Type) CompileError { |
| 2341 | 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 | 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 | 2347 | fn failWithExpectedOptionalType(sema: *Sema, block: *Block, src: LazySrcLoc, non_optional_ty: Type) CompileError { |
| 2348 | 2348 | const pt = sema.pt; |
| 2349 | 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 | 2351 | non_optional_ty.fmt(pt), |
| 2352 | 2352 | }); |
| 2353 | 2353 | errdefer msg.destroy(sema.gpa); |
| ... | ... | @@ -2363,12 +2363,12 @@ fn failWithExpectedOptionalType(sema: *Sema, block: *Block, src: LazySrcLoc, non |
| 2363 | 2363 | fn failWithArrayInitNotSupported(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) CompileError { |
| 2364 | 2364 | const pt = sema.pt; |
| 2365 | 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 | 2367 | ty.fmt(pt), |
| 2368 | 2368 | }); |
| 2369 | 2369 | errdefer msg.destroy(sema.gpa); |
| 2370 | 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 | 2373 | break :msg msg; |
| 2374 | 2374 | }; |
| ... | ... | @@ -2377,7 +2377,7 @@ fn failWithArrayInitNotSupported(sema: *Sema, block: *Block, src: LazySrcLoc, ty |
| 2377 | 2377 | |
| 2378 | 2378 | fn failWithStructInitNotSupported(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) CompileError { |
| 2379 | 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 | 2381 | ty.fmt(pt), |
| 2382 | 2382 | }); |
| 2383 | 2383 | } |
| ... | ... | @@ -2390,7 +2390,7 @@ fn failWithErrorSetCodeMissing( |
| 2390 | 2390 | src_err_set_ty: Type, |
| 2391 | 2391 | ) CompileError { |
| 2392 | 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 | 2394 | dest_err_set_ty.fmt(pt), src_err_set_ty.fmt(pt), |
| 2395 | 2395 | }); |
| 2396 | 2396 | } |
| ... | ... | @@ -2398,7 +2398,7 @@ fn failWithErrorSetCodeMissing( |
| 2398 | 2398 | pub fn failWithIntegerOverflow(sema: *Sema, block: *Block, src: LazySrcLoc, int_ty: Type, val: Value, vector_index: ?usize) CompileError { |
| 2399 | 2399 | const pt = sema.pt; |
| 2400 | 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 | 2402 | int_ty.fmt(pt), val.fmtValueSema(pt, sema), |
| 2403 | 2403 | }); |
| 2404 | 2404 | errdefer msg.destroy(sema.gpa); |
| ... | ... | @@ -2448,7 +2448,7 @@ fn failWithInvalidFieldAccess( |
| 2448 | 2448 | const child_ty = inner_ty.optionalChild(zcu); |
| 2449 | 2449 | if (!typeSupportsFieldAccess(zcu, child_ty, field_name)) break :opt; |
| 2450 | 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 | 2452 | errdefer msg.destroy(sema.gpa); |
| 2453 | 2453 | try sema.errNote(src, msg, "consider using '.?', 'orelse', or 'if'", .{}); |
| 2454 | 2454 | break :msg msg; |
| ... | ... | @@ -2458,14 +2458,14 @@ fn failWithInvalidFieldAccess( |
| 2458 | 2458 | const child_ty = inner_ty.errorUnionPayload(zcu); |
| 2459 | 2459 | if (!typeSupportsFieldAccess(zcu, child_ty, field_name)) break :err; |
| 2460 | 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 | 2462 | errdefer msg.destroy(sema.gpa); |
| 2463 | 2463 | try sema.errNote(src, msg, "consider using 'try', 'catch', or 'if'", .{}); |
| 2464 | 2464 | break :msg msg; |
| 2465 | 2465 | }; |
| 2466 | 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 | } |
| 2470 | 2470 | |
| 2471 | 2471 | fn typeSupportsFieldAccess(zcu: *const Zcu, ty: Type, field_name: InternPool.NullTerminatedString) bool { |
| ... | ... | @@ -2494,7 +2494,7 @@ fn failWithComptimeErrorRetTrace( |
| 2494 | 2494 | const pt = sema.pt; |
| 2495 | 2495 | const zcu = pt.zcu; |
| 2496 | 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 | 2498 | errdefer msg.destroy(sema.gpa); |
| 2499 | 2499 | |
| 2500 | 2500 | for (sema.comptime_err_ret_trace.items) |src_loc| { |
| ... | ... | @@ -2763,7 +2763,7 @@ fn zirTupleDecl( |
| 2763 | 2763 | const coerced_field_init = try sema.coerce(block, field_type, uncoerced_field_init, init_src); |
| 2764 | 2764 | const field_init_val = try sema.resolveConstDefinedValue(block, init_src, coerced_field_init, .{ .simple = .tuple_field_default_value }); |
| 2765 | 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 | 2767 | return sema.failWithContainsReferenceToComptimeVar(block, init_src, field_name, "field default value", field_init_val); |
| 2768 | 2768 | } |
| 2769 | 2769 | break :init field_init_val.toIntern(); |
| ... | ... | @@ -3005,7 +3005,7 @@ pub fn createTypeName( |
| 3005 | 3005 | inst: ?Zir.Inst.Index, |
| 3006 | 3006 | /// This is used purely to give the type a unique name in the `anon` case. |
| 3007 | 3007 | type_index: InternPool.Index, |
| 3008 | ) !struct { | |
| 3008 | ) CompileError!struct { | |
| 3009 | 3009 | name: InternPool.NullTerminatedString, |
| 3010 | 3010 | nav: InternPool.Nav.Index.Optional, |
| 3011 | 3011 | } { |
| ... | ... | @@ -3024,11 +3024,10 @@ pub fn createTypeName( |
| 3024 | 3024 | const fn_info = sema.code.getFnInfo(ip.funcZirBodyInst(sema.func_index).resolve(ip) orelse return error.AnalysisFail); |
| 3025 | 3025 | const zir_tags = sema.code.instructions.items(.tag); |
| 3026 | 3026 | |
| 3027 | var buf: std.ArrayListUnmanaged(u8) = .empty; | |
| 3028 | defer buf.deinit(gpa); | |
| 3029 | ||
| 3030 | const writer = buf.writer(gpa); | |
| 3031 | try writer.print("{}(", .{block.type_name_ctx.fmt(ip)}); | |
| 3027 | var aw: std.io.Writer.Allocating = .init(gpa); | |
| 3028 | defer aw.deinit(); | |
| 3029 | const w = &aw.writer; | |
| 3030 | w.print("{f}(", .{block.type_name_ctx.fmt(ip)}) catch return error.OutOfMemory; | |
| 3032 | 3031 | |
| 3033 | 3032 | var arg_i: usize = 0; |
| 3034 | 3033 | for (fn_info.param_body) |zir_inst| switch (zir_tags[@intFromEnum(zir_inst)]) { |
| ... | ... | @@ -3041,18 +3040,18 @@ pub fn createTypeName( |
| 3041 | 3040 | // result in a compile error. |
| 3042 | 3041 | const arg_val = try sema.resolveValue(arg) orelse break :func_strat; // fall through to anon strat |
| 3043 | 3042 | |
| 3044 | if (arg_i != 0) try writer.writeByte(','); | |
| 3043 | if (arg_i != 0) w.writeByte(',') catch return error.OutOfMemory; | |
| 3045 | 3044 | |
| 3046 | 3045 | // Limiting the depth here helps avoid type names getting too long, which |
| 3047 | 3046 | // in turn helps to avoid unreasonably long symbol names for namespaced |
| 3048 | 3047 | // symbols. Such names should ideally be human-readable, and additionally, |
| 3049 | 3048 | // some tooling may not support very long symbol names. |
| 3050 | try writer.print("{}", .{Value.fmtValueSemaFull(.{ | |
| 3049 | w.print("{f}", .{Value.fmtValueSemaFull(.{ | |
| 3051 | 3050 | .val = arg_val, |
| 3052 | 3051 | .pt = pt, |
| 3053 | 3052 | .opt_sema = sema, |
| 3054 | 3053 | .depth = 1, |
| 3055 | })}); | |
| 3054 | })}) catch return error.OutOfMemory; | |
| 3056 | 3055 | |
| 3057 | 3056 | arg_i += 1; |
| 3058 | 3057 | continue; |
| ... | ... | @@ -3060,9 +3059,9 @@ pub fn createTypeName( |
| 3060 | 3059 | else => continue, |
| 3061 | 3060 | }; |
| 3062 | 3061 | |
| 3063 | try writer.writeByte(')'); | |
| 3062 | w.writeByte(')') catch return error.OutOfMemory; | |
| 3064 | 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 | 3065 | .nav = .none, |
| 3067 | 3066 | }; |
| 3068 | 3067 | }, |
| ... | ... | @@ -3074,7 +3073,7 @@ pub fn createTypeName( |
| 3074 | 3073 | for (@intFromEnum(inst.?)..zir_tags.len) |i| switch (zir_tags[i]) { |
| 3075 | 3074 | .dbg_var_ptr, .dbg_var_val => if (zir_data[i].str_op.operand == ref) { |
| 3076 | 3075 | return .{ |
| 3077 | .name = try ip.getOrPutStringFmt(gpa, pt.tid, "{}.{s}", .{ | |
| 3076 | .name = try ip.getOrPutStringFmt(gpa, pt.tid, "{f}.{s}", .{ | |
| 3078 | 3077 | block.type_name_ctx.fmt(ip), zir_data[i].str_op.getStr(sema.code), |
| 3079 | 3078 | }, .no_embedded_nulls), |
| 3080 | 3079 | .nav = .none, |
| ... | ... | @@ -3097,7 +3096,7 @@ pub fn createTypeName( |
| 3097 | 3096 | // that builtin from the language, we can consider this. |
| 3098 | 3097 | |
| 3099 | 3098 | return .{ |
| 3100 | .name = try ip.getOrPutStringFmt(gpa, pt.tid, "{}__{s}_{d}", .{ | |
| 3099 | .name = try ip.getOrPutStringFmt(gpa, pt.tid, "{f}__{s}_{d}", .{ | |
| 3101 | 3100 | block.type_name_ctx.fmt(ip), anon_prefix, @intFromEnum(type_index), |
| 3102 | 3101 | }, .no_embedded_nulls), |
| 3103 | 3102 | .nav = .none, |
| ... | ... | @@ -3581,7 +3580,7 @@ fn ensureResultUsed( |
| 3581 | 3580 | }, |
| 3582 | 3581 | else => { |
| 3583 | 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 | 3584 | errdefer msg.destroy(sema.gpa); |
| 3586 | 3585 | try sema.errNote(src, msg, "all non-void values must be used", .{}); |
| 3587 | 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 | 3850 | // The value was initialized through RLS, so we didn't detect the runtime condition earlier. |
| 3852 | 3851 | // TODO: source location of runtime control flow |
| 3853 | 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 | } |
| 3856 | 3855 | |
| 3857 | 3856 | // This is a runtime value. |
| ... | ... | @@ -4348,7 +4347,7 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com |
| 4348 | 4347 | // The alloc wasn't comptime-known per the above logic, so the |
| 4349 | 4348 | // type cannot be comptime-only. |
| 4350 | 4349 | // 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 | 4352 | if (sema.func_is_naked and try final_elem_ty.hasRuntimeBitsSema(pt)) { |
| 4354 | 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 | 4444 | if (!object_ty.isIndexable(zcu)) { |
| 4446 | 4445 | // Instead of using checkIndexable we customize this error. |
| 4447 | 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 | 4448 | errdefer msg.destroy(sema.gpa); |
| 4450 | 4449 | try sema.errNote(arg_src, msg, "for loop operand must be a range, array, slice, tuple, or vector", .{}); |
| 4451 | 4450 | |
| ... | ... | @@ -4480,10 +4479,10 @@ fn zirForLen(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. |
| 4480 | 4479 | .for_node_offset = inst_data.src_node, |
| 4481 | 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 | 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 | 4486 | arg_val.fmtValueSema(pt, sema), |
| 4488 | 4487 | }); |
| 4489 | 4488 | break :msg msg; |
| ... | ... | @@ -4515,7 +4514,7 @@ fn zirForLen(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. |
| 4515 | 4514 | .for_node_offset = inst_data.src_node, |
| 4516 | 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 | 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 | 4590 | switch (val_ty.zigTypeTag(zcu)) { |
| 4592 | 4591 | .array, .vector => {}, |
| 4593 | 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 | 4596 | const want_ty = try pt.arrayType(.{ |
| ... | ... | @@ -4665,7 +4664,7 @@ fn zirValidateRefTy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErr |
| 4665 | 4664 | const ty_operand = try sema.resolveTypeOrPoison(block, src, un_tok.operand) orelse return; |
| 4666 | 4665 | if (ty_operand.optEuBaseType(zcu).zigTypeTag(zcu) != .pointer) { |
| 4667 | 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 | 4668 | errdefer msg.destroy(sema.gpa); |
| 4670 | 4669 | try sema.errNote(src, msg, "address-of operator always returns a pointer", .{}); |
| 4671 | 4670 | break :msg msg; |
| ... | ... | @@ -5074,7 +5073,7 @@ fn validateStructInit( |
| 5074 | 5073 | } |
| 5075 | 5074 | continue; |
| 5076 | 5075 | }; |
| 5077 | const template = "missing struct field: {}"; | |
| 5076 | const template = "missing struct field: {f}"; | |
| 5078 | 5077 | const args = .{field_name.fmt(ip)}; |
| 5079 | 5078 | if (root_msg) |msg| { |
| 5080 | 5079 | try sema.errNote(init_src, msg, template, args); |
| ... | ... | @@ -5204,7 +5203,7 @@ fn validateStructInit( |
| 5204 | 5203 | } |
| 5205 | 5204 | continue; |
| 5206 | 5205 | }; |
| 5207 | const template = "missing struct field: {}"; | |
| 5206 | const template = "missing struct field: {f}"; | |
| 5208 | 5207 | const args = .{field_name.fmt(ip)}; |
| 5209 | 5208 | if (root_msg) |msg| { |
| 5210 | 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 | 5507 | const operand_ty = sema.typeOf(operand); |
| 5509 | 5508 | |
| 5510 | 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 | 5511 | } else switch (operand_ty.ptrSize(zcu)) { |
| 5513 | 5512 | .one, .c => {}, |
| 5514 | .many => return sema.fail(block, src, "index syntax required for unknown-length pointer type '{}'", .{operand_ty.fmt(pt)}), | |
| 5515 | .slice => return sema.fail(block, src, "index syntax required for slice type '{}'", .{operand_ty.fmt(pt)}), | |
| 5513 | .many => return sema.fail(block, src, "index syntax required for unknown-length pointer type '{f}'", .{operand_ty.fmt(pt)}), | |
| 5514 | .slice => return sema.fail(block, src, "index syntax required for slice type '{f}'", .{operand_ty.fmt(pt)}), | |
| 5516 | 5515 | } |
| 5517 | 5516 | |
| 5518 | 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 | 5528 | const msg = msg: { |
| 5530 | 5529 | const msg = try sema.errMsg( |
| 5531 | 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 | 5532 | .{elem_ty.fmt(pt)}, |
| 5534 | 5533 | ); |
| 5535 | 5534 | errdefer msg.destroy(sema.gpa); |
| ... | ... | @@ -5561,7 +5560,7 @@ fn zirValidateDestructure(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Comp |
| 5561 | 5560 | |
| 5562 | 5561 | if (!typeIsDestructurable(operand_ty, zcu)) { |
| 5563 | 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 | 5564 | errdefer msg.destroy(sema.gpa); |
| 5566 | 5565 | try sema.errNote(destructure_src, msg, "result destructured here", .{}); |
| 5567 | 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 | 5574 | |
| 5576 | 5575 | if (operand_ty.arrayLen(zcu) != extra.expect_len) { |
| 5577 | 5576 | return sema.failWithOwnedErrorMsg(block, msg: { |
| 5578 | const msg = try sema.errMsg(src, "expected {} elements for destructure, found {}", .{ | |
| 5579 | extra.expect_len, | |
| 5580 | operand_ty.arrayLen(zcu), | |
| 5577 | const msg = try sema.errMsg(src, "expected {d} elements for destructure, found {d}", .{ | |
| 5578 | extra.expect_len, operand_ty.arrayLen(zcu), | |
| 5581 | 5579 | }); |
| 5582 | 5580 | errdefer msg.destroy(sema.gpa); |
| 5583 | 5581 | try sema.errNote(destructure_src, msg, "result destructured here", .{}); |
| ... | ... | @@ -5604,12 +5602,12 @@ fn failWithBadMemberAccess( |
| 5604 | 5602 | else => unreachable, |
| 5605 | 5603 | }; |
| 5606 | 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 | 5606 | agg_ty.fmt(pt), field_name.fmt(ip), |
| 5609 | 5607 | }); |
| 5610 | 5608 | }; |
| 5611 | 5609 | |
| 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 | 5611 | kw_name, agg_ty.fmt(pt), field_name.fmt(ip), |
| 5614 | 5612 | }); |
| 5615 | 5613 | } |
| ... | ... | @@ -5629,7 +5627,7 @@ fn failWithBadStructFieldAccess( |
| 5629 | 5627 | const msg = msg: { |
| 5630 | 5628 | const msg = try sema.errMsg( |
| 5631 | 5629 | field_src, |
| 5632 | "no field named '{}' in struct '{}'", | |
| 5630 | "no field named '{f}' in struct '{f}'", | |
| 5633 | 5631 | .{ field_name.fmt(ip), struct_type.name.fmt(ip) }, |
| 5634 | 5632 | ); |
| 5635 | 5633 | errdefer msg.destroy(sema.gpa); |
| ... | ... | @@ -5655,7 +5653,7 @@ fn failWithBadUnionFieldAccess( |
| 5655 | 5653 | const msg = msg: { |
| 5656 | 5654 | const msg = try sema.errMsg( |
| 5657 | 5655 | field_src, |
| 5658 | "no field named '{}' in union '{}'", | |
| 5656 | "no field named '{f}' in union '{f}'", | |
| 5659 | 5657 | .{ field_name.fmt(ip), union_obj.name.fmt(ip) }, |
| 5660 | 5658 | ); |
| 5661 | 5659 | errdefer msg.destroy(gpa); |
| ... | ... | @@ -5907,30 +5905,29 @@ fn zirCompileLog( |
| 5907 | 5905 | const zcu = pt.zcu; |
| 5908 | 5906 | const gpa = zcu.gpa; |
| 5909 | 5907 | |
| 5910 | var buf: std.ArrayListUnmanaged(u8) = .empty; | |
| 5911 | defer buf.deinit(gpa); | |
| 5912 | ||
| 5913 | const writer = buf.writer(gpa); | |
| 5908 | var aw: std.io.Writer.Allocating = .init(gpa); | |
| 5909 | defer aw.deinit(); | |
| 5910 | const writer = &aw.writer; | |
| 5914 | 5911 | |
| 5915 | 5912 | const extra = sema.code.extraData(Zir.Inst.NodeMultiOp, extended.operand); |
| 5916 | 5913 | const src_node = extra.data.src_node; |
| 5917 | 5914 | const args = sema.code.refSlice(extra.end, extended.small); |
| 5918 | 5915 | |
| 5919 | 5916 | for (args, 0..) |arg_ref, i| { |
| 5920 | if (i != 0) try writer.print(", ", .{}); | |
| 5917 | if (i != 0) writer.writeAll(", ") catch return error.OutOfMemory; | |
| 5921 | 5918 | |
| 5922 | 5919 | const arg = try sema.resolveInst(arg_ref); |
| 5923 | 5920 | const arg_ty = sema.typeOf(arg); |
| 5924 | 5921 | if (try sema.resolveValueResolveLazy(arg)) |val| { |
| 5925 | try writer.print("@as({}, {})", .{ | |
| 5922 | writer.print("@as({f}, {f})", .{ | |
| 5926 | 5923 | arg_ty.fmt(pt), val.fmtValueSema(pt, sema), |
| 5927 | }); | |
| 5924 | }) catch return error.OutOfMemory; | |
| 5928 | 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 | } |
| 5932 | 5929 | |
| 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); | |
| 5934 | 5931 | |
| 5935 | 5932 | const line_idx: Zcu.CompileLogLine.Index = if (zcu.free_compile_log_lines.pop()) |idx| idx: { |
| 5936 | 5933 | zcu.compile_log_lines.items[@intFromEnum(idx)] = .{ |
| ... | ... | @@ -6472,7 +6469,7 @@ fn resolveAnalyzedBlock( |
| 6472 | 6469 | const type_src = src; // TODO: better source location |
| 6473 | 6470 | if (try resolved_ty.comptimeOnlySema(pt)) { |
| 6474 | 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 | 6473 | errdefer msg.destroy(sema.gpa); |
| 6477 | 6474 | |
| 6478 | 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 | 6585 | |
| 6589 | 6586 | { |
| 6590 | 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 | 6590 | const ptr_ty_info = ptr_ty.ptrInfo(zcu); |
| 6594 | 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 | 6608 | const export_ty = Value.fromInterned(uav.val).typeOf(zcu); |
| 6612 | 6609 | if (!try sema.validateExternType(export_ty, .other)) { |
| 6613 | 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 | 6612 | errdefer msg.destroy(sema.gpa); |
| 6616 | 6613 | try sema.explainWhyTypeIsNotExtern(msg, src, export_ty, .other); |
| 6617 | 6614 | try sema.addDeclaredHereNote(msg, export_ty); |
| ... | ... | @@ -6663,7 +6660,7 @@ pub fn analyzeExport( |
| 6663 | 6660 | |
| 6664 | 6661 | if (!try sema.validateExternType(export_ty, .other)) { |
| 6665 | 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 | 6664 | errdefer msg.destroy(gpa); |
| 6668 | 6665 | |
| 6669 | 6666 | try sema.explainWhyTypeIsNotExtern(msg, src, export_ty, .other); |
| ... | ... | @@ -7287,7 +7284,7 @@ fn checkCallArgumentCount( |
| 7287 | 7284 | opt_child.childType(zcu).zigTypeTag(zcu) == .@"fn")) |
| 7288 | 7285 | { |
| 7289 | 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 | 7288 | callee_ty.fmt(pt), |
| 7292 | 7289 | }); |
| 7293 | 7290 | errdefer msg.destroy(sema.gpa); |
| ... | ... | @@ -7299,7 +7296,7 @@ fn checkCallArgumentCount( |
| 7299 | 7296 | }, |
| 7300 | 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 | }; |
| 7304 | 7301 | |
| 7305 | 7302 | const func_ty_info = zcu.typeToFunc(func_ty).?; |
| ... | ... | @@ -7362,7 +7359,7 @@ fn callBuiltin( |
| 7362 | 7359 | }, |
| 7363 | 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 | }; |
| 7367 | 7364 | |
| 7368 | 7365 | const func_ty_info = zcu.typeToFunc(func_ty).?; |
| ... | ... | @@ -7746,7 +7743,7 @@ fn analyzeCall( |
| 7746 | 7743 | |
| 7747 | 7744 | if (!param_ty.isValidParamType(zcu)) { |
| 7748 | 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 | 7747 | opaque_str, param_ty.fmt(pt), |
| 7751 | 7748 | }); |
| 7752 | 7749 | } |
| ... | ... | @@ -7843,7 +7840,7 @@ fn analyzeCall( |
| 7843 | 7840 | |
| 7844 | 7841 | if (!full_ty.isValidReturnType(zcu)) { |
| 7845 | 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 | 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 | 8298 | } |
| 8302 | 8299 | const owner_func_ty: Type = .fromInterned(zcu.funcInfo(sema.owner.unwrap().func).ty); |
| 8303 | 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 | 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 | 8322 | const operand_src = block.src(.{ .node_offset_un_op = inst_data.src_node }); |
| 8326 | 8323 | const child_type = try sema.resolveType(block, operand_src, inst_data.operand); |
| 8327 | 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 | 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 | 8329 | const opt_type = try pt.optionalType(child_type.toIntern()); |
| 8333 | 8330 | |
| ... | ... | @@ -8388,7 +8385,7 @@ fn zirVecArrElemType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr |
| 8388 | 8385 | const vec_ty = try sema.resolveTypeOrPoison(block, LazySrcLoc.unneeded, un_node.operand) orelse return .generic_poison_type; |
| 8389 | 8386 | switch (vec_ty.zigTypeTag(zcu)) { |
| 8390 | 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 | 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 | 8453 | const pt = sema.pt; |
| 8457 | 8454 | const zcu = pt.zcu; |
| 8458 | 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 | 8457 | } else if (elem_type.zigTypeTag(zcu) == .noreturn) { |
| 8461 | 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 | 8489 | const payload = try sema.resolveType(block, rhs_src, extra.rhs); |
| 8493 | 8490 | |
| 8494 | 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 | 8493 | error_set.fmt(pt), |
| 8497 | 8494 | }); |
| 8498 | 8495 | } |
| ... | ... | @@ -8505,11 +8502,11 @@ fn validateErrorUnionPayloadType(sema: *Sema, block: *Block, payload_ty: Type, p |
| 8505 | 8502 | const pt = sema.pt; |
| 8506 | 8503 | const zcu = pt.zcu; |
| 8507 | 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 | 8506 | payload_ty.fmt(pt), |
| 8510 | 8507 | }); |
| 8511 | 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 | 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 | 8644 | const lhs_ty = try sema.analyzeAsType(block, lhs_src, lhs); |
| 8648 | 8645 | const rhs_ty = try sema.analyzeAsType(block, rhs_src, rhs); |
| 8649 | 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 | 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)}); | |
| 8653 | 8650 | |
| 8654 | 8651 | // Anything merged with anyerror is anyerror. |
| 8655 | 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 | 8756 | return sema.fail( |
| 8760 | 8757 | block, |
| 8761 | 8758 | operand_src, |
| 8762 | "untagged union '{}' cannot be converted to integer", | |
| 8759 | "untagged union '{f}' cannot be converted to integer", | |
| 8763 | 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 | 8764 | break :blk try sema.unionToTag(block, tag_ty, operand, operand_src); |
| 8768 | 8765 | }, |
| 8769 | 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 | 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 | 8775 | // TODO: use correct solution |
| 8779 | 8776 | // https://github.com/ziglang/zig/issues/15909 |
| 8780 | 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 | 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 | 8809 | const operand_ty = sema.typeOf(operand); |
| 8813 | 8810 | |
| 8814 | 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 | 8814 | _ = try sema.checkIntType(block, operand_src, operand_ty); |
| 8818 | 8815 | |
| ... | ... | @@ -8822,7 +8819,7 @@ fn zirEnumFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError |
| 8822 | 8819 | if (try sema.intFitsInType(int_val, int_tag_ty, null)) { |
| 8823 | 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 | 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 | 8827 | return sema.failWithUseOfUndef(block, operand_src); |
| 8831 | 8828 | } |
| 8832 | 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 | 8831 | dest_ty.fmt(pt), int_val.fmtValueSema(pt, sema), |
| 8835 | 8832 | }); |
| 8836 | 8833 | } |
| ... | ... | @@ -9024,7 +9021,7 @@ fn zirErrUnionPayload( |
| 9024 | 9021 | const operand_src = src; |
| 9025 | 9022 | const err_union_ty = sema.typeOf(operand); |
| 9026 | 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 | 9025 | err_union_ty.fmt(pt), |
| 9029 | 9026 | }); |
| 9030 | 9027 | } |
| ... | ... | @@ -9092,7 +9089,7 @@ fn analyzeErrUnionPayloadPtr( |
| 9092 | 9089 | assert(operand_ty.zigTypeTag(zcu) == .pointer); |
| 9093 | 9090 | |
| 9094 | 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 | 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 | 9166 | const zcu = pt.zcu; |
| 9170 | 9167 | const operand_ty = sema.typeOf(operand); |
| 9171 | 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 | 9170 | operand_ty.fmt(pt), |
| 9174 | 9171 | }); |
| 9175 | 9172 | } |
| ... | ... | @@ -9205,7 +9202,7 @@ fn analyzeErrUnionCodePtr(sema: *Sema, block: *Block, src: LazySrcLoc, operand: |
| 9205 | 9202 | assert(operand_ty.zigTypeTag(zcu) == .pointer); |
| 9206 | 9203 | |
| 9207 | 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 | 9206 | operand_ty.childType(zcu).fmt(pt), |
| 9210 | 9207 | }); |
| 9211 | 9208 | } |
| ... | ... | @@ -9450,19 +9447,17 @@ fn callConvSupportsVarArgs(cc: std.builtin.CallingConvention.Tag) bool { |
| 9450 | 9447 | fn checkCallConvSupportsVarArgs(sema: *Sema, block: *Block, src: LazySrcLoc, cc: std.builtin.CallingConvention.Tag) CompileError!void { |
| 9451 | 9448 | const CallingConventionsSupportingVarArgsList = struct { |
| 9452 | 9449 | arch: std.Target.Cpu.Arch, |
| 9453 | pub fn format(ctx: @This(), comptime fmt: []const u8, options: std.fmt.FormatOptions, writer: anytype) !void { | |
| 9454 | _ = fmt; | |
| 9455 | _ = options; | |
| 9450 | pub fn format(ctx: @This(), w: *std.io.Writer) std.io.Writer.Error!void { | |
| 9456 | 9451 | var first = true; |
| 9457 | 9452 | for (calling_conventions_supporting_var_args) |cc_inner| { |
| 9458 | 9453 | for (std.Target.Cpu.Arch.fromCallingConvention(cc_inner)) |supported_arch| { |
| 9459 | 9454 | if (supported_arch == ctx.arch) break; |
| 9460 | 9455 | } else continue; // callconv not supported by this arch |
| 9461 | 9456 | if (!first) { |
| 9462 | try writer.writeAll(", "); | |
| 9457 | try w.writeAll(", "); | |
| 9463 | 9458 | } |
| 9464 | 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 | 9467 | const msg = try sema.errMsg(src, "variadic function does not support '{s}' calling convention", .{@tagName(cc)}); |
| 9473 | 9468 | errdefer msg.destroy(sema.gpa); |
| 9474 | 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 | 9471 | break :msg msg; |
| 9477 | 9472 | }); |
| 9478 | 9473 | } |
| ... | ... | @@ -9520,7 +9515,7 @@ fn checkMergeAllowed(sema: *Sema, block: *Block, src: LazySrcLoc, peer_ty: Type) |
| 9520 | 9515 | } |
| 9521 | 9516 | |
| 9522 | 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 | 9519 | errdefer msg.destroy(sema.gpa); |
| 9525 | 9520 | |
| 9526 | 9521 | const runtime_src = block.runtime_cond orelse block.runtime_loop.?; |
| ... | ... | @@ -9598,13 +9593,13 @@ fn funcCommon( |
| 9598 | 9593 | } |
| 9599 | 9594 | if (!param_ty.isValidParamType(zcu)) { |
| 9600 | 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 | 9597 | opaque_str, param_ty.fmt(pt), |
| 9603 | 9598 | }); |
| 9604 | 9599 | } |
| 9605 | 9600 | if (!param_ty_generic and !target_util.fnCallConvAllowsZigTypes(cc) and !try sema.validateExternType(param_ty, .param_ty)) { |
| 9606 | 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 | 9603 | param_ty.fmt(pt), @tagName(cc), |
| 9609 | 9604 | }); |
| 9610 | 9605 | errdefer msg.destroy(sema.gpa); |
| ... | ... | @@ -9618,7 +9613,7 @@ fn funcCommon( |
| 9618 | 9613 | } |
| 9619 | 9614 | if (param_ty_comptime and !param_is_comptime and has_body and !block.isComptime()) { |
| 9620 | 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 | 9617 | param_ty.fmt(pt), |
| 9623 | 9618 | }); |
| 9624 | 9619 | errdefer msg.destroy(sema.gpa); |
| ... | ... | @@ -9798,7 +9793,7 @@ fn finishFunc( |
| 9798 | 9793 | |
| 9799 | 9794 | if (!return_type.isValidReturnType(zcu)) { |
| 9800 | 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 | 9797 | opaque_str, return_type.fmt(pt), |
| 9803 | 9798 | }); |
| 9804 | 9799 | } |
| ... | ... | @@ -9806,7 +9801,7 @@ fn finishFunc( |
| 9806 | 9801 | !try sema.validateExternType(return_type, .ret_ty)) |
| 9807 | 9802 | { |
| 9808 | 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 | 9805 | return_type.fmt(pt), @tagName(cc_resolved), |
| 9811 | 9806 | }); |
| 9812 | 9807 | errdefer msg.destroy(gpa); |
| ... | ... | @@ -9828,7 +9823,7 @@ fn finishFunc( |
| 9828 | 9823 | |
| 9829 | 9824 | const msg = try sema.errMsg( |
| 9830 | 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 | 9827 | .{return_type.fmt(pt)}, |
| 9833 | 9828 | ); |
| 9834 | 9829 | errdefer msg.destroy(sema.gpa); |
| ... | ... | @@ -9897,17 +9892,15 @@ fn finishFunc( |
| 9897 | 9892 | .bad_arch => |allowed_archs| { |
| 9898 | 9893 | const ArchListFormatter = struct { |
| 9899 | 9894 | archs: []const std.Target.Cpu.Arch, |
| 9900 | pub fn format(formatter: @This(), comptime fmt: []const u8, options: std.fmt.FormatOptions, writer: anytype) !void { | |
| 9901 | _ = fmt; | |
| 9902 | _ = options; | |
| 9895 | pub fn format(formatter: @This(), w: *std.io.Writer) std.io.Writer.Error!void { | |
| 9903 | 9896 | for (formatter.archs, 0..) |arch, i| { |
| 9904 | 9897 | if (i != 0) |
| 9905 | try writer.writeAll(", "); | |
| 9906 | try writer.print("'{s}'", .{@tagName(arch)}); | |
| 9898 | try w.writeAll(", "); | |
| 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 | 9904 | @tagName(cc_resolved), |
| 9912 | 9905 | ArchListFormatter{ .archs = allowed_archs }, |
| 9913 | 9906 | }); |
| ... | ... | @@ -10008,7 +10001,7 @@ fn analyzeAs( |
| 10008 | 10001 | const operand = try sema.resolveInst(zir_operand); |
| 10009 | 10002 | const dest_ty = try sema.resolveTypeOrPoison(block, src, zir_dest_type) orelse return operand; |
| 10010 | 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 | 10005 | .noreturn => return sema.fail(block, src, "cannot cast to noreturn", .{}), |
| 10013 | 10006 | else => {}, |
| 10014 | 10007 | } |
| ... | ... | @@ -10036,12 +10029,12 @@ fn zirIntFromPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError! |
| 10036 | 10029 | const ptr_ty = operand_ty.scalarType(zcu); |
| 10037 | 10030 | const is_vector = operand_ty.zigTypeTag(zcu) == .vector; |
| 10038 | 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 | 10034 | const pointee_ty = ptr_ty.childType(zcu); |
| 10042 | 10035 | if (try ptr_ty.comptimeOnlySema(pt)) { |
| 10043 | 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 | 10038 | errdefer msg.destroy(sema.gpa); |
| 10046 | 10039 | try sema.explainWhyTypeIsComptime(msg, ptr_src, pointee_ty); |
| 10047 | 10040 | break :msg msg; |
| ... | ... | @@ -10289,14 +10282,14 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air |
| 10289 | 10282 | .type, |
| 10290 | 10283 | .undefined, |
| 10291 | 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)}), | |
| 10293 | 10286 | |
| 10294 | 10287 | .@"enum" => { |
| 10295 | 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 | 10290 | errdefer msg.destroy(sema.gpa); |
| 10298 | 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 | 10293 | else => {}, |
| 10301 | 10294 | } |
| 10302 | 10295 | |
| ... | ... | @@ -10307,11 +10300,11 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air |
| 10307 | 10300 | |
| 10308 | 10301 | .pointer => { |
| 10309 | 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 | 10304 | errdefer msg.destroy(sema.gpa); |
| 10312 | 10305 | switch (operand_ty.zigTypeTag(zcu)) { |
| 10313 | .int, .comptime_int => try sema.errNote(src, msg, "use @ptrFromInt to cast from '{}'", .{operand_ty.fmt(pt)}), | |
| 10314 | .pointer => try sema.errNote(src, msg, "use @ptrCast to cast from '{}'", .{operand_ty.fmt(pt)}), | |
| 10306 | .int, .comptime_int => try sema.errNote(src, msg, "use @ptrFromInt to cast from '{f}'", .{operand_ty.fmt(pt)}), | |
| 10307 | .pointer => try sema.errNote(src, msg, "use @ptrCast to cast from '{f}'", .{operand_ty.fmt(pt)}), | |
| 10315 | 10308 | else => {}, |
| 10316 | 10309 | } |
| 10317 | 10310 | |
| ... | ... | @@ -10325,7 +10318,7 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air |
| 10325 | 10318 | .@"union" => "union", |
| 10326 | 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 | 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 | 10346 | .type, |
| 10354 | 10347 | .undefined, |
| 10355 | 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)}), | |
| 10357 | 10350 | |
| 10358 | 10351 | .@"enum" => { |
| 10359 | 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 | 10354 | errdefer msg.destroy(sema.gpa); |
| 10362 | 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 | 10357 | else => {}, |
| 10365 | 10358 | } |
| 10366 | 10359 | |
| ... | ... | @@ -10370,11 +10363,11 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air |
| 10370 | 10363 | }, |
| 10371 | 10364 | .pointer => { |
| 10372 | 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 | 10367 | errdefer msg.destroy(sema.gpa); |
| 10375 | 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)}), | |
| 10377 | .pointer => try sema.errNote(operand_src, msg, "use @ptrCast 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)}), | |
| 10370 | .pointer => try sema.errNote(operand_src, msg, "use @ptrCast to cast to '{f}'", .{dest_ty.fmt(pt)}), | |
| 10378 | 10371 | else => {}, |
| 10379 | 10372 | } |
| 10380 | 10373 | |
| ... | ... | @@ -10388,7 +10381,7 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air |
| 10388 | 10381 | .@"union" => "union", |
| 10389 | 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 | 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 | 10424 | else => return sema.fail( |
| 10432 | 10425 | block, |
| 10433 | 10426 | src, |
| 10434 | "expected float or vector type, found '{}'", | |
| 10427 | "expected float or vector type, found '{f}'", | |
| 10435 | 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 | 10434 | else => return sema.fail( |
| 10442 | 10435 | block, |
| 10443 | 10436 | operand_src, |
| 10444 | "expected float or vector type, found '{}'", | |
| 10437 | "expected float or vector type, found '{f}'", | |
| 10445 | 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 | 10518 | if (indexable_ty.zigTypeTag(zcu) != .pointer) { |
| 10526 | 10519 | const capture_src = block.src(.{ .for_capture_from_input = inst_data.src_node }); |
| 10527 | 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 | 10522 | indexable_ty.fmt(pt), |
| 10530 | 10523 | }); |
| 10531 | 10524 | errdefer msg.destroy(sema.gpa); |
| ... | ... | @@ -10667,7 +10660,7 @@ fn zirSliceSentinelTy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE |
| 10667 | 10660 | const lhs_ptr_ty = sema.typeOf(try sema.resolveInst(inst_data.operand)); |
| 10668 | 10661 | const lhs_ty = switch (lhs_ptr_ty.zigTypeTag(zcu)) { |
| 10669 | 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 | }; |
| 10672 | 10665 | |
| 10673 | 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 | 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 | }; |
| 10687 | 10680 | |
| 10688 | 10681 | return Air.internedToRef(sentinel_ty.toIntern()); |
| ... | ... | @@ -10877,7 +10870,7 @@ const SwitchProngAnalysis = struct { |
| 10877 | 10870 | .base_node_inst = capture_src.base_node_inst, |
| 10878 | 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 | 10874 | operand_ty.fmt(pt), |
| 10882 | 10875 | }); |
| 10883 | 10876 | } |
| ... | ... | @@ -11309,7 +11302,7 @@ fn switchCond( |
| 11309 | 11302 | .@"enum", |
| 11310 | 11303 | => { |
| 11311 | 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 | 11307 | if ((try sema.typeHasOnePossibleValue(operand_ty))) |opv| { |
| 11315 | 11308 | return Air.internedToRef(opv.toIntern()); |
| ... | ... | @@ -11344,7 +11337,7 @@ fn switchCond( |
| 11344 | 11337 | .vector, |
| 11345 | 11338 | .frame, |
| 11346 | 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 | } |
| 11350 | 11343 | |
| ... | ... | @@ -11445,7 +11438,7 @@ fn zirSwitchBlockErrUnion(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Comp |
| 11445 | 11438 | operand_ty; |
| 11446 | 11439 | |
| 11447 | 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 | 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 | 11692 | // Even if the operand is comptime-known, this `switch` is runtime. |
| 11700 | 11693 | if (try operand_ty.comptimeOnlySema(pt)) { |
| 11701 | 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 | 11696 | errdefer msg.destroy(gpa); |
| 11704 | 11697 | try sema.errNote(operand_src, msg, "switch loops are evaluated at runtime outside of comptime scopes", .{}); |
| 11705 | 11698 | break :msg msg; |
| ... | ... | @@ -11923,14 +11916,14 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r |
| 11923 | 11916 | cond_ty, |
| 11924 | 11917 | i, |
| 11925 | 11918 | msg, |
| 11926 | "unhandled enumeration value: '{}'", | |
| 11919 | "unhandled enumeration value: '{f}'", | |
| 11927 | 11920 | .{field_name.fmt(&zcu.intern_pool)}, |
| 11928 | 11921 | ); |
| 11929 | 11922 | } |
| 11930 | 11923 | try sema.errNote( |
| 11931 | 11924 | cond_ty.srcLoc(zcu), |
| 11932 | 11925 | msg, |
| 11933 | "enum '{}' declared here", | |
| 11926 | "enum '{f}' declared here", | |
| 11934 | 11927 | .{cond_ty.fmt(pt)}, |
| 11935 | 11928 | ); |
| 11936 | 11929 | break :msg msg; |
| ... | ... | @@ -12142,7 +12135,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r |
| 12142 | 12135 | return sema.fail( |
| 12143 | 12136 | block, |
| 12144 | 12137 | src, |
| 12145 | "else prong required when switching on type '{}'", | |
| 12138 | "else prong required when switching on type '{f}'", | |
| 12146 | 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 | 12211 | .@"anyframe", |
| 12219 | 12212 | .comptime_float, |
| 12220 | 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 | 12215 | raw_operand_ty.fmt(pt), |
| 12223 | 12216 | }), |
| 12224 | 12217 | } |
| ... | ... | @@ -12747,7 +12740,7 @@ fn analyzeSwitchRuntimeBlock( |
| 12747 | 12740 | if (special.is_inline) switch (operand_ty.zigTypeTag(zcu)) { |
| 12748 | 12741 | .@"enum" => { |
| 12749 | 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 | 12744 | operand_ty.fmt(pt), |
| 12752 | 12745 | }); |
| 12753 | 12746 | } |
| ... | ... | @@ -12803,7 +12796,7 @@ fn analyzeSwitchRuntimeBlock( |
| 12803 | 12796 | }, |
| 12804 | 12797 | .error_set => { |
| 12805 | 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 | 12800 | operand_ty.fmt(pt), |
| 12808 | 12801 | }); |
| 12809 | 12802 | } |
| ... | ... | @@ -12964,7 +12957,7 @@ fn analyzeSwitchRuntimeBlock( |
| 12964 | 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 | 12961 | operand_ty.fmt(pt), |
| 12969 | 12962 | }), |
| 12970 | 12963 | }; |
| ... | ... | @@ -13478,7 +13471,7 @@ fn validateErrSetSwitch( |
| 13478 | 13471 | try sema.errNote( |
| 13479 | 13472 | src, |
| 13480 | 13473 | msg, |
| 13481 | "unhandled error value: 'error.{}'", | |
| 13474 | "unhandled error value: 'error.{f}'", | |
| 13482 | 13475 | .{error_name.fmt(ip)}, |
| 13483 | 13476 | ); |
| 13484 | 13477 | } |
| ... | ... | @@ -13704,7 +13697,7 @@ fn validateSwitchNoRange( |
| 13704 | 13697 | const msg = msg: { |
| 13705 | 13698 | const msg = try sema.errMsg( |
| 13706 | 13699 | operand_src, |
| 13707 | "ranges not allowed when switching on type '{}'", | |
| 13700 | "ranges not allowed when switching on type '{f}'", | |
| 13708 | 13701 | .{operand_ty.fmt(sema.pt)}, |
| 13709 | 13702 | ); |
| 13710 | 13703 | errdefer msg.destroy(sema.gpa); |
| ... | ... | @@ -13862,7 +13855,7 @@ fn zirHasField(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 13862 | 13855 | .array_type => break :hf field_name.eqlSlice("len", ip), |
| 13863 | 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 | 13859 | ty.fmt(pt), |
| 13867 | 13860 | }); |
| 13868 | 13861 | }; |
| ... | ... | @@ -14050,7 +14043,7 @@ fn zirShl( |
| 14050 | 14043 | while (i < rhs_ty.vectorLen(zcu)) : (i += 1) { |
| 14051 | 14044 | const rhs_elem = try rhs_val.elemValue(pt, i); |
| 14052 | 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 | 14047 | rhs_elem.fmtValueSema(pt, sema), |
| 14055 | 14048 | i, |
| 14056 | 14049 | scalar_ty.fmt(pt), |
| ... | ... | @@ -14058,7 +14051,7 @@ fn zirShl( |
| 14058 | 14051 | } |
| 14059 | 14052 | } |
| 14060 | 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 | 14055 | rhs_val.fmtValueSema(pt, sema), |
| 14063 | 14056 | scalar_ty.fmt(pt), |
| 14064 | 14057 | }); |
| ... | ... | @@ -14069,19 +14062,19 @@ fn zirShl( |
| 14069 | 14062 | while (i < rhs_ty.vectorLen(zcu)) : (i += 1) { |
| 14070 | 14063 | const rhs_elem = try rhs_val.elemValue(pt, i); |
| 14071 | 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 | 14066 | rhs_elem.fmtValueSema(pt, sema), |
| 14074 | 14067 | i, |
| 14075 | 14068 | }); |
| 14076 | 14069 | } |
| 14077 | 14070 | } |
| 14078 | 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 | 14073 | rhs_val.fmtValueSema(pt, sema), |
| 14081 | 14074 | }); |
| 14082 | 14075 | } |
| 14083 | 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 | } |
| 14086 | 14079 | |
| 14087 | 14080 | const runtime_src = if (maybe_lhs_val) |lhs_val| rs: { |
| ... | ... | @@ -14231,7 +14224,7 @@ fn zirShr( |
| 14231 | 14224 | while (i < rhs_ty.vectorLen(zcu)) : (i += 1) { |
| 14232 | 14225 | const rhs_elem = try rhs_val.elemValue(pt, i); |
| 14233 | 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 | 14228 | rhs_elem.fmtValueSema(pt, sema), |
| 14236 | 14229 | i, |
| 14237 | 14230 | scalar_ty.fmt(pt), |
| ... | ... | @@ -14239,7 +14232,7 @@ fn zirShr( |
| 14239 | 14232 | } |
| 14240 | 14233 | } |
| 14241 | 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 | 14236 | rhs_val.fmtValueSema(pt, sema), |
| 14244 | 14237 | scalar_ty.fmt(pt), |
| 14245 | 14238 | }); |
| ... | ... | @@ -14250,14 +14243,14 @@ fn zirShr( |
| 14250 | 14243 | while (i < rhs_ty.vectorLen(zcu)) : (i += 1) { |
| 14251 | 14244 | const rhs_elem = try rhs_val.elemValue(pt, i); |
| 14252 | 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 | 14247 | rhs_elem.fmtValueSema(pt, sema), |
| 14255 | 14248 | i, |
| 14256 | 14249 | }); |
| 14257 | 14250 | } |
| 14258 | 14251 | } |
| 14259 | 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 | 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 | 14379 | const scalar_tag = scalar_ty.zigTypeTag(zcu); |
| 14387 | 14380 | |
| 14388 | 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)}); | |
| 14390 | 14383 | |
| 14391 | 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 | 14536 | |
| 14544 | 14537 | const lhs_info = try sema.getArrayCatInfo(block, lhs_src, lhs, rhs_ty) orelse lhs_info: { |
| 14545 | 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 | 14541 | const rhs_info = try sema.getArrayCatInfo(block, rhs_src, rhs, lhs_ty) orelse { |
| 14549 | 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 | }; |
| 14552 | 14545 | |
| 14553 | 14546 | const resolved_elem_ty = t: { |
| ... | ... | @@ -15000,7 +14993,7 @@ fn zirArrayMul(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 15000 | 14993 | // Analyze the lhs first, to catch the case that someone tried to do exponentiation |
| 15001 | 14994 | const lhs_info = try sema.getArrayCatInfo(block, lhs_src, lhs, lhs_ty) orelse { |
| 15002 | 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 | 14997 | errdefer msg.destroy(sema.gpa); |
| 15005 | 14998 | switch (lhs_ty.zigTypeTag(zcu)) { |
| 15006 | 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 | 15125 | .int, .comptime_int, .float, .comptime_float => false, |
| 15133 | 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 | } |
| 15137 | 15130 | |
| 15138 | 15131 | if (rhs_scalar_ty.isAnyFloat()) { |
| ... | ... | @@ -15163,7 +15156,7 @@ fn zirNegateWrap(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError! |
| 15163 | 15156 | |
| 15164 | 15157 | switch (rhs_scalar_ty.zigTypeTag(zcu)) { |
| 15165 | 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 | } |
| 15168 | 15161 | |
| 15169 | 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 | 15230 | return sema.fail( |
| 15238 | 15231 | block, |
| 15239 | 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 | 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 | 15282 | return sema.fail( |
| 15290 | 15283 | block, |
| 15291 | 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 | 15286 | .{ lhs_ty.fmt(pt), rhs_ty.fmt(pt) }, |
| 15294 | 15287 | ); |
| 15295 | 15288 | } |
| ... | ... | @@ -15951,7 +15944,7 @@ fn zirOverflowArithmetic( |
| 15951 | 15944 | const rhs = try sema.coerce(block, rhs_dest_ty, uncasted_rhs, rhs_src); |
| 15952 | 15945 | |
| 15953 | 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 | } |
| 15956 | 15949 | |
| 15957 | 15950 | const maybe_lhs_val = try sema.resolveValue(lhs); |
| ... | ... | @@ -16157,14 +16150,14 @@ fn analyzeArithmetic( |
| 16157 | 16150 | return sema.failWithInvalidPtrArithmetic(block, src, "pointer-pointer", "subtraction"); |
| 16158 | 16151 | } |
| 16159 | 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 | 16154 | lhs_ty.fmt(pt), rhs_ty.fmt(pt), |
| 16162 | 16155 | }); |
| 16163 | 16156 | } |
| 16164 | 16157 | |
| 16165 | 16158 | const elem_size = lhs_ty.elemType2(zcu).abiSize(zcu); |
| 16166 | 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 | 16161 | lhs_ty.elemType2(zcu).fmt(pt), |
| 16169 | 16162 | }); |
| 16170 | 16163 | } |
| ... | ... | @@ -16215,7 +16208,7 @@ fn analyzeArithmetic( |
| 16215 | 16208 | }; |
| 16216 | 16209 | |
| 16217 | 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 | 16212 | lhs_ty.elemType2(zcu).fmt(pt), |
| 16220 | 16213 | }); |
| 16221 | 16214 | } |
| ... | ... | @@ -16619,7 +16612,7 @@ fn zirCmpEq( |
| 16619 | 16612 | |
| 16620 | 16613 | if (lhs_ty_tag == .null or rhs_ty_tag == .null) { |
| 16621 | 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 | } |
| 16624 | 16617 | |
| 16625 | 16618 | if (lhs_ty_tag == .@"union" and (rhs_ty_tag == .enum_literal or rhs_ty_tag == .@"enum")) { |
| ... | ... | @@ -16676,7 +16669,7 @@ fn analyzeCmpUnionTag( |
| 16676 | 16669 | const msg = msg: { |
| 16677 | 16670 | const msg = try sema.errMsg(un_src, "comparison of union and enum literal is only valid for tagged union types", .{}); |
| 16678 | 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 | 16673 | break :msg msg; |
| 16681 | 16674 | }; |
| 16682 | 16675 | return sema.failWithOwnedErrorMsg(block, msg); |
| ... | ... | @@ -16762,7 +16755,7 @@ fn analyzeCmp( |
| 16762 | 16755 | const instructions = &[_]Air.Inst.Ref{ lhs, rhs }; |
| 16763 | 16756 | const resolved_type = try sema.resolvePeerTypes(block, src, instructions, .{ .override = &[_]?LazySrcLoc{ lhs_src, rhs_src } }); |
| 16764 | 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 | 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 | 16864 | .undefined, |
| 16872 | 16865 | .null, |
| 16873 | 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)}), | |
| 16875 | 16868 | |
| 16876 | 16869 | .type, |
| 16877 | 16870 | .enum_literal, |
| ... | ... | @@ -16912,7 +16905,7 @@ fn zirBitSizeOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A |
| 16912 | 16905 | .undefined, |
| 16913 | 16906 | .null, |
| 16914 | 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)}), | |
| 16916 | 16909 | |
| 16917 | 16910 | .type, |
| 16918 | 16911 | .enum_literal, |
| ... | ... | @@ -17002,7 +16995,7 @@ fn zirClosureGet(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDat |
| 17002 | 16995 | const file, const src_base_node = Zcu.LazySrcLoc.resolveBaseNode(block.src_base_inst, zcu).?; |
| 17003 | 16996 | const tree = file.getTree(zcu) catch |err| { |
| 17004 | 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 | 16999 | file.path.fmt(zcu.comp), @errorName(err), |
| 17007 | 17000 | }); |
| 17008 | 17001 | break :name null; |
| ... | ... | @@ -17030,7 +17023,7 @@ fn zirClosureGet(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDat |
| 17030 | 17023 | const file, const src_base_node = Zcu.LazySrcLoc.resolveBaseNode(block.src_base_inst, zcu).?; |
| 17031 | 17024 | const tree = file.getTree(zcu) catch |err| { |
| 17032 | 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 | 17027 | file.path.fmt(zcu.comp), @errorName(err), |
| 17035 | 17028 | }); |
| 17036 | 17029 | break :name null; |
| ... | ... | @@ -18212,7 +18205,7 @@ fn log2IntType(sema: *Sema, block: *Block, operand: Type, src: LazySrcLoc) Compi |
| 18212 | 18205 | return sema.fail( |
| 18213 | 18206 | block, |
| 18214 | 18207 | src, |
| 18215 | "bit shifting operation expected integer type, found '{}'", | |
| 18208 | "bit shifting operation expected integer type, found '{f}'", | |
| 18216 | 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 | 18264 | const uncasted_ty = sema.typeOf(uncasted_operand); |
| 18272 | 18265 | if (uncasted_ty.isVector(zcu)) { |
| 18273 | 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 | 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 | 18444 | const pt = sema.pt; |
| 18452 | 18445 | const zcu = pt.zcu; |
| 18453 | 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 | } |
| 18457 | 18450 | |
| ... | ... | @@ -18501,7 +18494,7 @@ fn checkErrorType(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) !void { |
| 18501 | 18494 | const zcu = pt.zcu; |
| 18502 | 18495 | switch (ty.zigTypeTag(zcu)) { |
| 18503 | 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 | 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 | 18638 | const pt = sema.pt; |
| 18646 | 18639 | const zcu = pt.zcu; |
| 18647 | 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 | 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 | 18698 | const pt = sema.pt; |
| 18706 | 18699 | const zcu = pt.zcu; |
| 18707 | 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 | 18702 | err_union_ty.fmt(pt), |
| 18710 | 18703 | }); |
| 18711 | 18704 | } |
| ... | ... | @@ -18903,7 +18896,7 @@ fn zirRetImplicit( |
| 18903 | 18896 | const base_tag = sema.fn_ret_ty.baseZigTypeTag(zcu); |
| 18904 | 18897 | if (base_tag == .noreturn) { |
| 18905 | 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 | 18900 | sema.fn_ret_ty.fmt(pt), |
| 18908 | 18901 | }); |
| 18909 | 18902 | errdefer msg.destroy(sema.gpa); |
| ... | ... | @@ -18913,7 +18906,7 @@ fn zirRetImplicit( |
| 18913 | 18906 | return sema.failWithOwnedErrorMsg(block, msg); |
| 18914 | 18907 | } else if (base_tag != .void) { |
| 18915 | 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 | 18910 | sema.fn_ret_ty.fmt(pt), |
| 18918 | 18911 | }); |
| 18919 | 18912 | errdefer msg.destroy(sema.gpa); |
| ... | ... | @@ -19302,13 +19295,13 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air |
| 19302 | 19295 | |
| 19303 | 19296 | if (host_size != 0) { |
| 19304 | 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 | 19299 | elem_ty.fmt(pt), bit_offset, bit_offset - host_size * 8, host_size, |
| 19307 | 19300 | }); |
| 19308 | 19301 | } |
| 19309 | 19302 | const elem_bit_size = try elem_ty.bitSizeSema(pt); |
| 19310 | 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 | 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 | 19316 | } else if (inst_data.size == .c) { |
| 19324 | 19317 | if (!try sema.validateExternType(elem_ty, .other)) { |
| 19325 | 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 | 19320 | errdefer msg.destroy(sema.gpa); |
| 19328 | 19321 | |
| 19329 | 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 | 19333 | |
| 19341 | 19334 | if (host_size != 0 and !try sema.validatePackedType(elem_ty)) { |
| 19342 | 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 | 19337 | errdefer msg.destroy(sema.gpa); |
| 19345 | 19338 | try sema.explainWhyTypeIsNotPacked(msg, elem_ty_src, elem_ty); |
| 19346 | 19339 | break :msg msg; |
| ... | ... | @@ -19509,7 +19502,7 @@ fn zirUnionInit(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A |
| 19509 | 19502 | const extra = sema.code.extraData(Zir.Inst.UnionInit, inst_data.payload_index).data; |
| 19510 | 19503 | const union_ty = try sema.resolveType(block, ty_src, extra.union_type); |
| 19511 | 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 | 19507 | const field_name = try sema.resolveConstStringIntern(block, field_src, extra.field_name, .{ .simple = .union_field_name }); |
| 19515 | 19508 | const init = try sema.resolveInst(extra.init); |
| ... | ... | @@ -19672,7 +19665,7 @@ fn zirStructInit( |
| 19672 | 19665 | const msg = try sema.errMsg(src, "cannot initialize 'noreturn' field of union", .{}); |
| 19673 | 19666 | errdefer msg.destroy(sema.gpa); |
| 19674 | 19667 | |
| 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 | 19669 | field_name.fmt(ip), |
| 19677 | 19670 | }); |
| 19678 | 19671 | try sema.addDeclaredHereNote(msg, resolved_ty); |
| ... | ... | @@ -19791,7 +19784,7 @@ fn finishStructInit( |
| 19791 | 19784 | const field_init = struct_type.fieldInit(ip, i); |
| 19792 | 19785 | if (field_init == .none) { |
| 19793 | 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 | 19788 | const args = .{field_name.fmt(ip)}; |
| 19796 | 19789 | if (root_msg) |msg| { |
| 19797 | 19790 | try sema.errNote(init_src, msg, template, args); |
| ... | ... | @@ -20406,7 +20399,7 @@ fn fieldType( |
| 20406 | 20399 | }, |
| 20407 | 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 | 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 | 20446 | const operand_src = block.builtinCallArgSrc(inst_data.src_node, 0); |
| 20454 | 20447 | const ty = try sema.resolveType(block, operand_src, inst_data.operand); |
| 20455 | 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 | 20451 | const val = try ty.lazyAbiAlignment(sema.pt); |
| 20459 | 20452 | return Air.internedToRef(val.toIntern()); |
| ... | ... | @@ -20469,7 +20462,7 @@ fn zirIntFromBool(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError |
| 20469 | 20462 | const is_vector = operand_ty.zigTypeTag(zcu) == .vector; |
| 20470 | 20463 | const operand_scalar_ty = operand_ty.scalarType(zcu); |
| 20471 | 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 | 20467 | const len = if (is_vector) operand_ty.vectorLen(zcu) else undefined; |
| 20475 | 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 | 20524 | else => return sema.fail( |
| 20532 | 20525 | block, |
| 20533 | 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 | 20528 | .{operand_ty.fmt(pt)}, |
| 20536 | 20529 | ), |
| 20537 | 20530 | }; |
| ... | ... | @@ -20600,7 +20593,7 @@ fn zirUnaryMath( |
| 20600 | 20593 | else => return sema.fail( |
| 20601 | 20594 | block, |
| 20602 | 20595 | operand_src, |
| 20603 | "expected vector of floats or float type, found '{}'", | |
| 20596 | "expected vector of floats or float type, found '{f}'", | |
| 20604 | 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 | 20622 | }, |
| 20630 | 20623 | .@"enum" => operand_ty, |
| 20631 | 20624 | .@"union" => operand_ty.unionTagType(zcu) orelse |
| 20632 | return sema.fail(block, src, "union '{}' is untagged", .{operand_ty.fmt(pt)}), | |
| 20633 | else => return sema.fail(block, operand_src, "expected enum or union; found '{}'", .{ | |
| 20625 | return sema.fail(block, src, "union '{f}' is untagged", .{operand_ty.fmt(pt)}), | |
| 20626 | else => return sema.fail(block, operand_src, "expected enum or union; found '{f}'", .{ | |
| 20634 | 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 | 20631 | // TODO I don't think this is the correct way to handle this but |
| 20639 | 20632 | // it prevents a crash. |
| 20640 | 20633 | // 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 | 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 | 20639 | if (try sema.resolveDefinedValue(block, operand_src, casted_operand)) |val| { |
| 20647 | 20640 | const field_index = enum_ty.enumTagFieldIndex(val, zcu) orelse { |
| 20648 | 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 | 20643 | val.fmtValueSema(pt, sema), enum_ty.fmt(pt), |
| 20651 | 20644 | }); |
| 20652 | 20645 | errdefer msg.destroy(sema.gpa); |
| ... | ... | @@ -20752,7 +20745,7 @@ fn zirReify( |
| 20752 | 20745 | 64 => .f64, |
| 20753 | 20746 | 80 => .f80, |
| 20754 | 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 | 20750 | return Air.internedToRef(ty.toIntern()); |
| 20758 | 20751 | }, |
| ... | ... | @@ -20833,7 +20826,7 @@ fn zirReify( |
| 20833 | 20826 | } else if (ptr_size == .c) { |
| 20834 | 20827 | if (!try sema.validateExternType(elem_ty, .other)) { |
| 20835 | 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 | 20830 | errdefer msg.destroy(gpa); |
| 20838 | 20831 | |
| 20839 | 20832 | try sema.explainWhyTypeIsNotExtern(msg, src, elem_ty, .other); |
| ... | ... | @@ -20946,7 +20939,7 @@ fn zirReify( |
| 20946 | 20939 | _ = try pt.getErrorValue(name); |
| 20947 | 20940 | const gop = names.getOrPutAssumeCapacity(name); |
| 20948 | 20941 | if (gop.found_existing) { |
| 20949 | return sema.fail(block, src, "duplicate error '{}'", .{ | |
| 20942 | return sema.fail(block, src, "duplicate error '{f}'", .{ | |
| 20950 | 20943 | name.fmt(ip), |
| 20951 | 20944 | }); |
| 20952 | 20945 | } |
| ... | ... | @@ -21294,7 +21287,7 @@ fn reifyEnum( |
| 21294 | 21287 | |
| 21295 | 21288 | if (!try sema.intFitsInType(field_value_val, tag_ty, null)) { |
| 21296 | 21289 | // 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 | 21291 | field_name.fmt(ip), |
| 21299 | 21292 | field_value_val.fmtValueSema(pt, sema), |
| 21300 | 21293 | tag_ty.fmt(pt), |
| ... | ... | @@ -21305,14 +21298,14 @@ fn reifyEnum( |
| 21305 | 21298 | if (wip_ty.nextField(ip, field_name, coerced_field_val.toIntern())) |conflict| { |
| 21306 | 21299 | return sema.failWithOwnedErrorMsg(block, switch (conflict.kind) { |
| 21307 | 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 | 21302 | errdefer msg.destroy(gpa); |
| 21310 | 21303 | _ = conflict.prev_field_idx; // TODO: this note is incorrect |
| 21311 | 21304 | try sema.errNote(src, msg, "other field here", .{}); |
| 21312 | 21305 | break :msg msg; |
| 21313 | 21306 | }, |
| 21314 | 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 | 21309 | errdefer msg.destroy(gpa); |
| 21317 | 21310 | _ = conflict.prev_field_idx; // TODO: this note is incorrect |
| 21318 | 21311 | try sema.errNote(src, msg, "other enum tag value here", .{}); |
| ... | ... | @@ -21460,13 +21453,13 @@ fn reifyUnion( |
| 21460 | 21453 | |
| 21461 | 21454 | const enum_index = enum_tag_ty.enumFieldIndex(field_name, zcu) orelse { |
| 21462 | 21455 | // 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 | 21457 | field_name.fmt(ip), enum_tag_ty.fmt(pt), |
| 21465 | 21458 | }); |
| 21466 | 21459 | }; |
| 21467 | 21460 | if (seen_tags.isSet(enum_index)) { |
| 21468 | 21461 | // 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 | 21464 | seen_tags.set(enum_index); |
| 21472 | 21465 | |
| ... | ... | @@ -21487,7 +21480,7 @@ fn reifyUnion( |
| 21487 | 21480 | var it = seen_tags.iterator(.{ .kind = .unset }); |
| 21488 | 21481 | while (it.next()) |enum_index| { |
| 21489 | 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 | 21484 | field_name.fmt(ip), |
| 21492 | 21485 | }); |
| 21493 | 21486 | } |
| ... | ... | @@ -21512,7 +21505,7 @@ fn reifyUnion( |
| 21512 | 21505 | const gop = field_names.getOrPutAssumeCapacity(field_name); |
| 21513 | 21506 | if (gop.found_existing) { |
| 21514 | 21507 | // 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 | } |
| 21517 | 21510 | |
| 21518 | 21511 | field_ty.* = field_type_val.toIntern(); |
| ... | ... | @@ -21544,7 +21537,7 @@ fn reifyUnion( |
| 21544 | 21537 | } |
| 21545 | 21538 | if (layout == .@"extern" and !try sema.validateExternType(field_ty, .union_field)) { |
| 21546 | 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 | 21541 | errdefer msg.destroy(gpa); |
| 21549 | 21542 | |
| 21550 | 21543 | try sema.explainWhyTypeIsNotExtern(msg, src, field_ty, .union_field); |
| ... | ... | @@ -21554,7 +21547,7 @@ fn reifyUnion( |
| 21554 | 21547 | }); |
| 21555 | 21548 | } else if (layout == .@"packed" and !try sema.validatePackedType(field_ty)) { |
| 21556 | 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 | 21551 | errdefer msg.destroy(gpa); |
| 21559 | 21552 | |
| 21560 | 21553 | try sema.explainWhyTypeIsNotPacked(msg, src, field_ty); |
| ... | ... | @@ -21636,14 +21629,14 @@ fn reifyTuple( |
| 21636 | 21629 | const field_name_index = field_name.toUnsigned(ip) orelse return sema.fail( |
| 21637 | 21630 | block, |
| 21638 | 21631 | src, |
| 21639 | "tuple cannot have non-numeric field '{}'", | |
| 21632 | "tuple cannot have non-numeric field '{f}'", | |
| 21640 | 21633 | .{field_name.fmt(ip)}, |
| 21641 | 21634 | ); |
| 21642 | 21635 | if (field_name_index != field_idx) { |
| 21643 | 21636 | return sema.fail( |
| 21644 | 21637 | block, |
| 21645 | 21638 | src, |
| 21646 | "tuple field name '{}' does not match field index {}", | |
| 21639 | "tuple field name '{d}' does not match field index {d}", | |
| 21647 | 21640 | .{ field_name_index, field_idx }, |
| 21648 | 21641 | ); |
| 21649 | 21642 | } |
| ... | ... | @@ -21814,7 +21807,7 @@ fn reifyStruct( |
| 21814 | 21807 | const field_name = try sema.sliceToIpString(block, src, field_name_val, undefined); |
| 21815 | 21808 | if (struct_type.addFieldName(ip, field_name)) |prev_index| { |
| 21816 | 21809 | _ = 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 | } |
| 21819 | 21812 | |
| 21820 | 21813 | if (any_aligned_fields) { |
| ... | ... | @@ -21883,7 +21876,7 @@ fn reifyStruct( |
| 21883 | 21876 | } |
| 21884 | 21877 | if (layout == .@"extern" and !try sema.validateExternType(field_ty, .struct_field)) { |
| 21885 | 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 | 21880 | errdefer msg.destroy(gpa); |
| 21888 | 21881 | |
| 21889 | 21882 | try sema.explainWhyTypeIsNotExtern(msg, src, field_ty, .struct_field); |
| ... | ... | @@ -21893,7 +21886,7 @@ fn reifyStruct( |
| 21893 | 21886 | }); |
| 21894 | 21887 | } else if (layout == .@"packed" and !try sema.validatePackedType(field_ty)) { |
| 21895 | 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 | 21890 | errdefer msg.destroy(gpa); |
| 21898 | 21891 | |
| 21899 | 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 | 21963 | |
| 21971 | 21964 | if (!try sema.validateExternType(arg_ty, .param_ty)) { |
| 21972 | 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 | 21967 | errdefer msg.destroy(sema.gpa); |
| 21975 | 21968 | |
| 21976 | 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 | 22022 | const ty_src = block.builtinCallArgSrc(inst_data.src_node, 0); |
| 22030 | 22023 | const ty = try sema.resolveType(block, ty_src, inst_data.operand); |
| 22031 | 22024 | |
| 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 | 22026 | return sema.addNullTerminatedStrLit(type_name); |
| 22034 | 22027 | } |
| 22035 | 22028 | |
| ... | ... | @@ -22157,7 +22150,7 @@ fn zirPtrFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError! |
| 22157 | 22150 | |
| 22158 | 22151 | if (ptr_ty.isSlice(zcu)) { |
| 22159 | 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 | 22154 | errdefer msg.destroy(sema.gpa); |
| 22162 | 22155 | try sema.errNote(src, msg, "slice length cannot be inferred from address", .{}); |
| 22163 | 22156 | break :msg msg; |
| ... | ... | @@ -22184,7 +22177,7 @@ fn zirPtrFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError! |
| 22184 | 22177 | } |
| 22185 | 22178 | if (try ptr_ty.comptimeOnlySema(pt)) { |
| 22186 | 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 | 22181 | errdefer msg.destroy(sema.gpa); |
| 22189 | 22182 | |
| 22190 | 22183 | try sema.explainWhyTypeIsComptime(msg, src, ptr_ty); |
| ... | ... | @@ -22241,7 +22234,7 @@ fn ptrFromIntVal( |
| 22241 | 22234 | } |
| 22242 | 22235 | const addr = try operand_val.toUnsignedIntSema(pt); |
| 22243 | 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 | 22238 | if (addr != 0 and ptr_align != .none) { |
| 22246 | 22239 | const masked_addr = if (ptr_ty.childType(zcu).fnPtrMaskOrNull(zcu)) |mask| |
| 22247 | 22240 | addr & mask |
| ... | ... | @@ -22249,7 +22242,7 @@ fn ptrFromIntVal( |
| 22249 | 22242 | addr; |
| 22250 | 22243 | |
| 22251 | 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 | } |
| 22255 | 22248 | |
| ... | ... | @@ -22294,8 +22287,8 @@ fn zirErrorCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData |
| 22294 | 22287 | errdefer msg.destroy(sema.gpa); |
| 22295 | 22288 | const dest_payload_ty = dest_ty.errorUnionPayload(zcu); |
| 22296 | 22289 | const operand_payload_ty = operand_ty.errorUnionPayload(zcu); |
| 22297 | try sema.errNote(src, msg, "destination payload is '{}'", .{dest_payload_ty.fmt(pt)}); | |
| 22298 | try sema.errNote(src, msg, "operand payload is '{}'", .{operand_payload_ty.fmt(pt)}); | |
| 22290 | try sema.errNote(src, msg, "destination payload is '{f}'", .{dest_payload_ty.fmt(pt)}); | |
| 22291 | try sema.errNote(src, msg, "operand payload is '{f}'", .{operand_payload_ty.fmt(pt)}); | |
| 22299 | 22292 | try addDeclaredHereNote(sema, msg, dest_ty); |
| 22300 | 22293 | try addDeclaredHereNote(sema, msg, operand_ty); |
| 22301 | 22294 | break :msg msg; |
| ... | ... | @@ -22340,7 +22333,7 @@ fn zirErrorCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData |
| 22340 | 22333 | break :disjoint true; |
| 22341 | 22334 | }; |
| 22342 | 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 | 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 | 22353 | }; |
| 22361 | 22354 | |
| 22362 | 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 | 22357 | err_name.fmt(ip), dest_err_ty.fmt(pt), |
| 22365 | 22358 | }); |
| 22366 | 22359 | } |
| ... | ... | @@ -22520,13 +22513,15 @@ fn ptrCastFull( |
| 22520 | 22513 | const src_elem_size = src_elem_ty.abiSize(zcu); |
| 22521 | 22514 | const dest_elem_size = dest_elem_ty.abiSize(zcu); |
| 22522 | 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 | 22520 | if (opt_src_len) |src_len| { |
| 22526 | 22521 | const bytes = src_len * src_elem_size; |
| 22527 | 22522 | const dest_len = std.math.divExact(u64, bytes, dest_elem_size) catch switch (src_info.flags.size) { |
| 22528 | 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 | 22525 | else => unreachable, |
| 22531 | 22526 | }; |
| 22532 | 22527 | break :len .{ .constant = dest_len }; |
| ... | ... | @@ -22544,7 +22539,9 @@ fn ptrCastFull( |
| 22544 | 22539 | // The source value has `src_len * src_base_per_elem` values of type `src_base_ty`. |
| 22545 | 22540 | // The result value will have `dest_len * dest_base_per_elem` values of type `dest_base_ty`. |
| 22546 | 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 | 22546 | // `src_base_ty` is comptime-only, so `src_elem_ty` is comptime-only, so `operand_ty` is |
| 22550 | 22547 | // comptime-only, so `operand` is comptime-known, so `opt_src_len` is non-`null`. |
| ... | ... | @@ -22552,7 +22549,7 @@ fn ptrCastFull( |
| 22552 | 22549 | const base_len = src_len * src_base_per_elem; |
| 22553 | 22550 | const dest_len = std.math.divExact(u64, base_len, dest_base_per_elem) catch switch (src_info.flags.size) { |
| 22554 | 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 | 22553 | else => unreachable, |
| 22557 | 22554 | }; |
| 22558 | 22555 | break :len .{ .constant = dest_len }; |
| ... | ... | @@ -22613,7 +22610,7 @@ fn ptrCastFull( |
| 22613 | 22610 | ); |
| 22614 | 22611 | if (imc_res == .ok) break :check_child; |
| 22615 | 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 | 22614 | src_child.fmt(pt), dest_child.fmt(pt), |
| 22618 | 22615 | }); |
| 22619 | 22616 | errdefer msg.destroy(sema.gpa); |
| ... | ... | @@ -22640,11 +22637,11 @@ fn ptrCastFull( |
| 22640 | 22637 | } |
| 22641 | 22638 | return sema.failWithOwnedErrorMsg(block, msg: { |
| 22642 | 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 | 22641 | Value.fromInterned(dest_info.sentinel).fmtValueSema(pt, sema), |
| 22645 | 22642 | }); |
| 22646 | 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 | 22645 | Value.fromInterned(src_info.sentinel).fmtValueSema(pt, sema), |
| 22649 | 22646 | Value.fromInterned(dest_info.sentinel).fmtValueSema(pt, sema), |
| 22650 | 22647 | }); |
| ... | ... | @@ -22657,7 +22654,7 @@ fn ptrCastFull( |
| 22657 | 22654 | |
| 22658 | 22655 | if (src_info.packed_offset.host_size != dest_info.packed_offset.host_size) { |
| 22659 | 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 | 22658 | src_info.packed_offset.host_size, |
| 22662 | 22659 | dest_info.packed_offset.host_size, |
| 22663 | 22660 | }); |
| ... | ... | @@ -22669,7 +22666,7 @@ fn ptrCastFull( |
| 22669 | 22666 | |
| 22670 | 22667 | if (src_info.packed_offset.bit_offset != dest_info.packed_offset.bit_offset) { |
| 22671 | 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 | 22670 | src_info.packed_offset.bit_offset, |
| 22674 | 22671 | dest_info.packed_offset.bit_offset, |
| 22675 | 22672 | }); |
| ... | ... | @@ -22686,7 +22683,7 @@ fn ptrCastFull( |
| 22686 | 22683 | if (dest_allows_zero) break :check_allowzero; |
| 22687 | 22684 | |
| 22688 | 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 | 22687 | operand_ty.fmt(pt), |
| 22691 | 22688 | dest_ty.fmt(pt), |
| 22692 | 22689 | }); |
| ... | ... | @@ -22714,10 +22711,10 @@ fn ptrCastFull( |
| 22714 | 22711 | return sema.failWithOwnedErrorMsg(block, msg: { |
| 22715 | 22712 | const msg = try sema.errMsg(src, "{s} increases pointer alignment", .{operation}); |
| 22716 | 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 | 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 | 22718 | dest_ty.fmt(pt), dest_align.toByteUnits() orelse 0, |
| 22722 | 22719 | }); |
| 22723 | 22720 | try sema.errNote(src, msg, "use @alignCast to assert pointer alignment", .{}); |
| ... | ... | @@ -22731,10 +22728,10 @@ fn ptrCastFull( |
| 22731 | 22728 | return sema.failWithOwnedErrorMsg(block, msg: { |
| 22732 | 22729 | const msg = try sema.errMsg(src, "{s} changes pointer address space", .{operation}); |
| 22733 | 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 | 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 | 22735 | dest_ty.fmt(pt), @tagName(dest_info.flags.address_space), |
| 22739 | 22736 | }); |
| 22740 | 22737 | try sema.errNote(src, msg, "use @addrSpaceCast to cast pointer address space", .{}); |
| ... | ... | @@ -22801,7 +22798,7 @@ fn ptrCastFull( |
| 22801 | 22798 | |
| 22802 | 22799 | if (operand_val.isNull(zcu)) { |
| 22803 | 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 | 22803 | if (dest_ty.zigTypeTag(zcu) == .optional) { |
| 22807 | 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 | 23089 | const operand_is_vector = operand_ty.zigTypeTag(zcu) == .vector; |
| 23093 | 23090 | const dest_is_vector = dest_ty.zigTypeTag(zcu) == .vector; |
| 23094 | 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 | } |
| 23097 | 23094 | |
| 23098 | 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 | 23109 | } |
| 23113 | 23110 | |
| 23114 | 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 | 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 | 23118 | const msg = msg: { |
| 23122 | 23119 | const msg = try sema.errMsg( |
| 23123 | 23120 | src, |
| 23124 | "destination type '{}' has more bits than source type '{}'", | |
| 23121 | "destination type '{f}' has more bits than source type '{f}'", | |
| 23125 | 23122 | .{ dest_ty.fmt(pt), operand_ty.fmt(pt) }, |
| 23126 | 23123 | ); |
| 23127 | 23124 | errdefer msg.destroy(sema.gpa); |
| ... | ... | @@ -23239,7 +23236,7 @@ fn zirByteSwap(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 23239 | 23236 | return sema.fail( |
| 23240 | 23237 | block, |
| 23241 | 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 | 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 | 23356 | try ty.resolveLayout(pt); |
| 23360 | 23357 | switch (ty.zigTypeTag(zcu)) { |
| 23361 | 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 | } |
| 23364 | 23361 | |
| 23365 | 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 | 23391 | const zcu = pt.zcu; |
| 23395 | 23392 | switch (ty.zigTypeTag(zcu)) { |
| 23396 | 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 | } |
| 23400 | 23397 | |
| ... | ... | @@ -23405,7 +23402,7 @@ fn checkIntType(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) CompileEr |
| 23405 | 23402 | switch (ty.zigTypeTag(zcu)) { |
| 23406 | 23403 | .comptime_int => return true, |
| 23407 | 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 | } |
| 23411 | 23408 | |
| ... | ... | @@ -23459,7 +23456,7 @@ fn checkPtrOperand( |
| 23459 | 23456 | const msg = msg: { |
| 23460 | 23457 | const msg = try sema.errMsg( |
| 23461 | 23458 | ty_src, |
| 23462 | "expected pointer, found '{}'", | |
| 23459 | "expected pointer, found '{f}'", | |
| 23463 | 23460 | .{ty.fmt(pt)}, |
| 23464 | 23461 | ); |
| 23465 | 23462 | errdefer msg.destroy(sema.gpa); |
| ... | ... | @@ -23473,7 +23470,7 @@ fn checkPtrOperand( |
| 23473 | 23470 | .optional => if (ty.childType(zcu).zigTypeTag(zcu) == .pointer) return, |
| 23474 | 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 | } |
| 23478 | 23475 | |
| 23479 | 23476 | fn checkPtrType( |
| ... | ... | @@ -23491,7 +23488,7 @@ fn checkPtrType( |
| 23491 | 23488 | const msg = msg: { |
| 23492 | 23489 | const msg = try sema.errMsg( |
| 23493 | 23490 | ty_src, |
| 23494 | "expected pointer type, found '{}'", | |
| 23491 | "expected pointer type, found '{f}'", | |
| 23495 | 23492 | .{ty.fmt(pt)}, |
| 23496 | 23493 | ); |
| 23497 | 23494 | errdefer msg.destroy(sema.gpa); |
| ... | ... | @@ -23505,7 +23502,7 @@ fn checkPtrType( |
| 23505 | 23502 | .optional => if (ty.childType(zcu).zigTypeTag(zcu) == .pointer) return, |
| 23506 | 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 | } |
| 23510 | 23507 | |
| 23511 | 23508 | fn 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 | 23513 | const as = ty.ptrAddressSpace(zcu); |
| 23517 | 23514 | if (target_util.arePointersLogical(target, as)) { |
| 23518 | 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 | 23517 | errdefer msg.destroy(sema.gpa); |
| 23521 | 23518 | try sema.errNote( |
| 23522 | 23519 | src, |
| ... | ... | @@ -23547,7 +23544,7 @@ fn checkVectorElemType( |
| 23547 | 23544 | .optional, .pointer => if (ty.isPtrAtRuntime(zcu)) return, |
| 23548 | 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 | } |
| 23552 | 23549 | |
| 23553 | 23550 | fn checkFloatType( |
| ... | ... | @@ -23560,7 +23557,7 @@ fn checkFloatType( |
| 23560 | 23557 | const zcu = pt.zcu; |
| 23561 | 23558 | switch (ty.zigTypeTag(zcu)) { |
| 23562 | 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 | } |
| 23566 | 23563 | |
| ... | ... | @@ -23576,9 +23573,9 @@ fn checkNumericType( |
| 23576 | 23573 | .comptime_float, .float, .comptime_int, .int => {}, |
| 23577 | 23574 | .vector => switch (ty.childType(zcu).zigTypeTag(zcu)) { |
| 23578 | 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 | } |
| 23584 | 23581 | |
| ... | ... | @@ -23612,7 +23609,7 @@ fn checkAtomicPtrOperand( |
| 23612 | 23609 | error.BadType => return sema.fail( |
| 23613 | 23610 | block, |
| 23614 | 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 | 23613 | .{elem_ty.fmt(pt)}, |
| 23617 | 23614 | ), |
| 23618 | 23615 | }; |
| ... | ... | @@ -23673,12 +23670,12 @@ fn checkIntOrVector( |
| 23673 | 23670 | const elem_ty = operand_ty.childType(zcu); |
| 23674 | 23671 | switch (elem_ty.zigTypeTag(zcu)) { |
| 23675 | 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 | 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 | 23679 | operand_ty.fmt(pt), |
| 23683 | 23680 | }), |
| 23684 | 23681 | } |
| ... | ... | @@ -23698,12 +23695,12 @@ fn checkIntOrVectorAllowComptime( |
| 23698 | 23695 | const elem_ty = operand_ty.childType(zcu); |
| 23699 | 23696 | switch (elem_ty.zigTypeTag(zcu)) { |
| 23700 | 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 | 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 | 23704 | operand_ty.fmt(pt), |
| 23708 | 23705 | }), |
| 23709 | 23706 | } |
| ... | ... | @@ -23794,7 +23791,7 @@ fn checkVectorizableBinaryOperands( |
| 23794 | 23791 | } |
| 23795 | 23792 | } else { |
| 23796 | 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 | 23795 | lhs_ty.fmt(pt), rhs_ty.fmt(pt), |
| 23799 | 23796 | }); |
| 23800 | 23797 | errdefer msg.destroy(sema.gpa); |
| ... | ... | @@ -23928,7 +23925,7 @@ fn zirCmpxchg( |
| 23928 | 23925 | return sema.fail( |
| 23929 | 23926 | block, |
| 23930 | 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 | 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 | 24009 | |
| 24013 | 24010 | switch (dest_ty.zigTypeTag(zcu)) { |
| 24014 | 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 | } |
| 24017 | 24014 | |
| 24018 | 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 | 24085 | const zcu = pt.zcu; |
| 24089 | 24086 | |
| 24090 | 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 | } |
| 24093 | 24090 | |
| 24094 | 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 | 24094 | switch (operation) { |
| 24098 | 24095 | .And, .Or, .Xor => switch (scalar_ty.zigTypeTag(zcu)) { |
| 24099 | 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 | 24098 | @tagName(operation), operand_ty.fmt(pt), |
| 24102 | 24099 | }), |
| 24103 | 24100 | }, |
| 24104 | 24101 | .Min, .Max, .Add, .Mul => switch (scalar_ty.zigTypeTag(zcu)) { |
| 24105 | 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 | 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 | 24154 | |
| 24158 | 24155 | const mask_len = switch (sema.typeOf(mask).zigTypeTag(zcu)) { |
| 24159 | 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 | 24159 | mask_ty = try pt.vectorType(.{ |
| 24163 | 24160 | .len = @intCast(mask_len), |
| ... | ... | @@ -24184,11 +24181,14 @@ fn analyzeShuffle( |
| 24184 | 24181 | const b_src = block.builtinCallArgSrc(src_node, 2); |
| 24185 | 24182 | const mask_src = block.builtinCallArgSrc(src_node, 3); |
| 24186 | 24183 | |
| 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 | 24186 | const a_len: u32 = switch (sema.typeOf(a_uncoerced).zigTypeTag(zcu)) { |
| 24189 | 24187 | .array, .vector => @intCast(sema.typeOf(a_uncoerced).arrayLen(zcu)), |
| 24190 | 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 | 24193 | const a_ty = try pt.vectorType(.{ .len = a_len, .child = elem_ty.toIntern() }); |
| 24194 | 24194 | const a_coerced = try sema.coerce(block, a_ty, a_uncoerced, a_src); |
| ... | ... | @@ -24197,7 +24197,9 @@ fn analyzeShuffle( |
| 24197 | 24197 | const b_len: u32 = switch (sema.typeOf(b_uncoerced).zigTypeTag(zcu)) { |
| 24198 | 24198 | .array, .vector => @intCast(sema.typeOf(b_uncoerced).arrayLen(zcu)), |
| 24199 | 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 | 24204 | const b_ty = try pt.vectorType(.{ .len = b_len, .child = elem_ty.toIntern() }); |
| 24203 | 24205 | const b_coerced = try sema.coerce(block, b_ty, b_uncoerced, b_src); |
| ... | ... | @@ -24235,7 +24237,7 @@ fn analyzeShuffle( |
| 24235 | 24237 | if (idx >= a_len) return sema.failWithOwnedErrorMsg(block, msg: { |
| 24236 | 24238 | const msg = try sema.errMsg(mask_src, "mask element at index '{d}' selects out-of-bounds index", .{mask_idx}); |
| 24237 | 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 | 24241 | if (idx < b_len) { |
| 24240 | 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 | 24250 | if (idx >= b_len) return sema.failWithOwnedErrorMsg(block, msg: { |
| 24249 | 24251 | const msg = try sema.errMsg(mask_src, "mask element at index '{d}' selects out-of-bounds index", .{mask_idx}); |
| 24250 | 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 | 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 | 24353 | |
| 24352 | 24354 | const vec_len_u64 = switch (pred_ty.zigTypeTag(zcu)) { |
| 24353 | 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 | 24358 | const vec_len: u32 = @intCast(try sema.usizeCast(block, pred_src, vec_len_u64)); |
| 24357 | 24359 | |
| ... | ... | @@ -24611,7 +24613,7 @@ fn zirMulAdd(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. |
| 24611 | 24613 | |
| 24612 | 24614 | switch (ty.scalarType(zcu).zigTypeTag(zcu)) { |
| 24613 | 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 | } |
| 24616 | 24618 | |
| 24617 | 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 | 24714 | |
| 24713 | 24715 | const args_ty = sema.typeOf(args); |
| 24714 | 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 | } |
| 24717 | 24719 | |
| 24718 | 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 | 24759 | try sema.checkPtrType(block, inst_src, parent_ptr_ty, true); |
| 24758 | 24760 | const parent_ptr_info = parent_ptr_ty.ptrInfo(zcu); |
| 24759 | 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 | 24764 | const parent_ty: Type = .fromInterned(parent_ptr_info.child); |
| 24763 | 24765 | switch (parent_ty.zigTypeTag(zcu)) { |
| 24764 | 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 | 24769 | try parent_ty.resolveLayout(pt); |
| 24768 | 24770 | |
| ... | ... | @@ -24912,7 +24914,7 @@ fn zirFieldParentPtr(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.Ins |
| 24912 | 24914 | } |
| 24913 | 24915 | |
| 24914 | 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 | 24918 | field_name.fmt(ip), field_index, field.index, parent_ty.fmt(pt), |
| 24917 | 24919 | }); |
| 24918 | 24920 | } |
| ... | ... | @@ -25033,7 +25035,7 @@ fn analyzeMinMax( |
| 25033 | 25035 | try sema.checkNumericType(block, operand_src, operand_ty); |
| 25034 | 25036 | if (operand_ty.zigTypeTag(zcu) != .vector) { |
| 25035 | 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 | 25039 | errdefer msg.destroy(zcu.gpa); |
| 25038 | 25040 | try sema.errNote(operand_srcs[0], msg, "vector operand here", .{}); |
| 25039 | 25041 | break :msg msg; |
| ... | ... | @@ -25041,7 +25043,7 @@ fn analyzeMinMax( |
| 25041 | 25043 | } |
| 25042 | 25044 | if (operand_ty.vectorLen(zcu) != vec_len) { |
| 25043 | 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 | 25047 | errdefer msg.destroy(zcu.gpa); |
| 25046 | 25048 | try sema.errNote(operand_srcs[0], msg, "vector of length '{d}' here", .{vec_len}); |
| 25047 | 25049 | break :msg msg; |
| ... | ... | @@ -25054,7 +25056,7 @@ fn analyzeMinMax( |
| 25054 | 25056 | const operand_ty = sema.typeOf(operand); |
| 25055 | 25057 | if (operand_ty.zigTypeTag(zcu) == .vector) { |
| 25056 | 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 | 25060 | errdefer msg.destroy(zcu.gpa); |
| 25059 | 25061 | try sema.errNote(operand_src, msg, "vector operand here", .{}); |
| 25060 | 25062 | break :msg msg; |
| ... | ... | @@ -25371,10 +25373,10 @@ fn zirMemcpy( |
| 25371 | 25373 | const msg = msg: { |
| 25372 | 25374 | const msg = try sema.errMsg(src, "unknown copy length", .{}); |
| 25373 | 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 | 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 | 25380 | src_ty.fmt(pt), |
| 25379 | 25381 | }); |
| 25380 | 25382 | break :msg msg; |
| ... | ... | @@ -25398,7 +25400,7 @@ fn zirMemcpy( |
| 25398 | 25400 | if (imc != .ok) return sema.failWithOwnedErrorMsg(block, msg: { |
| 25399 | 25401 | const msg = try sema.errMsg( |
| 25400 | 25402 | src, |
| 25401 | "pointer element type '{}' cannot coerce into element type '{}'", | |
| 25403 | "pointer element type '{f}' cannot coerce into element type '{f}'", | |
| 25402 | 25404 | .{ src_elem_ty.fmt(pt), dest_elem_ty.fmt(pt) }, |
| 25403 | 25405 | ); |
| 25404 | 25406 | errdefer msg.destroy(sema.gpa); |
| ... | ... | @@ -25417,10 +25419,10 @@ fn zirMemcpy( |
| 25417 | 25419 | const msg = msg: { |
| 25418 | 25420 | const msg = try sema.errMsg(src, "non-matching copy lengths", .{}); |
| 25419 | 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 | 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 | 25426 | src_len_val.fmtValueSema(pt, sema), |
| 25425 | 25427 | }); |
| 25426 | 25428 | break :msg msg; |
| ... | ... | @@ -25635,7 +25637,7 @@ fn zirMemset(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void |
| 25635 | 25637 | return sema.failWithOwnedErrorMsg(block, msg: { |
| 25636 | 25638 | const msg = try sema.errMsg(src, "unknown @memset length", .{}); |
| 25637 | 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 | 25641 | dest_ptr_ty.fmt(pt), |
| 25640 | 25642 | }); |
| 25641 | 25643 | break :msg msg; |
| ... | ... | @@ -25815,7 +25817,7 @@ fn zirCUndef( |
| 25815 | 25817 | const src = block.builtinCallArgSrc(extra.node, 0); |
| 25816 | 25818 | |
| 25817 | 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 | 25821 | return .void_value; |
| 25820 | 25822 | } |
| 25821 | 25823 | |
| ... | ... | @@ -25828,7 +25830,7 @@ fn zirCInclude( |
| 25828 | 25830 | const src = block.builtinCallArgSrc(extra.node, 0); |
| 25829 | 25831 | |
| 25830 | 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 | 25834 | return .void_value; |
| 25833 | 25835 | } |
| 25834 | 25836 | |
| ... | ... | @@ -25847,9 +25849,9 @@ fn zirCDefine( |
| 25847 | 25849 | const rhs = try sema.resolveInst(extra.rhs); |
| 25848 | 25850 | if (sema.typeOf(rhs).zigTypeTag(zcu) != .void) { |
| 25849 | 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 | 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 | 25856 | return .void_value; |
| 25855 | 25857 | } |
| ... | ... | @@ -26067,7 +26069,7 @@ fn zirBuiltinExtern( |
| 26067 | 26069 | } |
| 26068 | 26070 | if (!try sema.validateExternType(ty, .other)) { |
| 26069 | 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 | 26073 | errdefer msg.destroy(sema.gpa); |
| 26072 | 26074 | try sema.explainWhyTypeIsNotExtern(msg, ty_src, ty, .other); |
| 26073 | 26075 | break :msg msg; |
| ... | ... | @@ -26307,7 +26309,7 @@ pub fn validateVarType( |
| 26307 | 26309 | if (is_extern) { |
| 26308 | 26310 | if (!try sema.validateExternType(var_ty, .other)) { |
| 26309 | 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 | 26313 | errdefer msg.destroy(sema.gpa); |
| 26312 | 26314 | try sema.explainWhyTypeIsNotExtern(msg, src, var_ty, .other); |
| 26313 | 26315 | break :msg msg; |
| ... | ... | @@ -26319,7 +26321,7 @@ pub fn validateVarType( |
| 26319 | 26321 | return sema.fail( |
| 26320 | 26322 | block, |
| 26321 | 26323 | src, |
| 26322 | "non-extern variable with opaque type '{}'", | |
| 26324 | "non-extern variable with opaque type '{f}'", | |
| 26323 | 26325 | .{var_ty.fmt(pt)}, |
| 26324 | 26326 | ); |
| 26325 | 26327 | } |
| ... | ... | @@ -26328,7 +26330,7 @@ pub fn validateVarType( |
| 26328 | 26330 | if (!try var_ty.comptimeOnlySema(pt)) return; |
| 26329 | 26331 | |
| 26330 | 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 | 26334 | errdefer msg.destroy(sema.gpa); |
| 26333 | 26335 | |
| 26334 | 26336 | try sema.explainWhyTypeIsComptime(msg, src, var_ty); |
| ... | ... | @@ -26378,7 +26380,7 @@ fn explainWhyTypeIsComptimeInner( |
| 26378 | 26380 | => return, |
| 26379 | 26381 | |
| 26380 | 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 | }, |
| 26383 | 26385 | |
| 26384 | 26386 | .type => { |
| ... | ... | @@ -26394,7 +26396,7 @@ fn explainWhyTypeIsComptimeInner( |
| 26394 | 26396 | => return, |
| 26395 | 26397 | |
| 26396 | 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 | }, |
| 26399 | 26401 | |
| 26400 | 26402 | .array, .vector => { |
| ... | ... | @@ -26581,7 +26583,7 @@ fn explainWhyTypeIsNotExtern( |
| 26581 | 26583 | if (!ty.isConstPtr(zcu) and pointee_ty.zigTypeTag(zcu) == .@"fn") { |
| 26582 | 26584 | try sema.errNote(src_loc, msg, "pointer to extern function must be 'const'", .{}); |
| 26583 | 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 | 26587 | try sema.explainWhyTypeIsComptime(msg, src_loc, ty); |
| 26586 | 26588 | } |
| 26587 | 26589 | try sema.explainWhyTypeIsNotExtern(msg, src_loc, pointee_ty, .other); |
| ... | ... | @@ -26609,7 +26611,7 @@ fn explainWhyTypeIsNotExtern( |
| 26609 | 26611 | }, |
| 26610 | 26612 | .@"enum" => { |
| 26611 | 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 | 26615 | try sema.explainWhyTypeIsNotExtern(msg, src_loc, tag_ty, position); |
| 26614 | 26616 | }, |
| 26615 | 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 | 27047 | return sema.fail( |
| 27046 | 27048 | block, |
| 27047 | 27049 | field_name_src, |
| 27048 | "no member named '{}' in '{}'", | |
| 27050 | "no member named '{f}' in '{f}'", | |
| 27049 | 27051 | .{ field_name.fmt(ip), object_ty.fmt(pt) }, |
| 27050 | 27052 | ); |
| 27051 | 27053 | } |
| ... | ... | @@ -27069,7 +27071,7 @@ fn fieldVal( |
| 27069 | 27071 | return sema.fail( |
| 27070 | 27072 | block, |
| 27071 | 27073 | field_name_src, |
| 27072 | "no member named '{}' in '{}'", | |
| 27074 | "no member named '{f}' in '{f}'", | |
| 27073 | 27075 | .{ field_name.fmt(ip), object_ty.fmt(pt) }, |
| 27074 | 27076 | ); |
| 27075 | 27077 | } |
| ... | ... | @@ -27089,7 +27091,7 @@ fn fieldVal( |
| 27089 | 27091 | switch (ip.indexToKey(child_type.toIntern())) { |
| 27090 | 27092 | .error_set_type => |error_set_type| blk: { |
| 27091 | 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 | 27095 | field_name.fmt(ip), child_type.fmt(pt), |
| 27094 | 27096 | }); |
| 27095 | 27097 | }, |
| ... | ... | @@ -27144,7 +27146,7 @@ fn fieldVal( |
| 27144 | 27146 | return sema.failWithBadMemberAccess(block, child_type, src, field_name); |
| 27145 | 27147 | }, |
| 27146 | 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 | 27150 | errdefer msg.destroy(sema.gpa); |
| 27149 | 27151 | if (child_type.isSlice(zcu)) try sema.errNote(src, msg, "slice values have 'len' and 'ptr' members", .{}); |
| 27150 | 27152 | if (child_type.zigTypeTag(zcu) == .array) try sema.errNote(src, msg, "array values have 'len' member", .{}); |
| ... | ... | @@ -27190,7 +27192,7 @@ fn fieldPtr( |
| 27190 | 27192 | const object_ptr_ty = sema.typeOf(object_ptr); |
| 27191 | 27193 | const object_ty = switch (object_ptr_ty.zigTypeTag(zcu)) { |
| 27192 | 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 | }; |
| 27195 | 27197 | |
| 27196 | 27198 | // Zig allows dereferencing a single pointer during field lookup. Note that |
| ... | ... | @@ -27243,7 +27245,7 @@ fn fieldPtr( |
| 27243 | 27245 | return sema.fail( |
| 27244 | 27246 | block, |
| 27245 | 27247 | field_name_src, |
| 27246 | "no member named '{}' in '{}'", | |
| 27248 | "no member named '{f}' in '{f}'", | |
| 27247 | 27249 | .{ field_name.fmt(ip), object_ty.fmt(pt) }, |
| 27248 | 27250 | ); |
| 27249 | 27251 | } |
| ... | ... | @@ -27298,7 +27300,7 @@ fn fieldPtr( |
| 27298 | 27300 | return sema.fail( |
| 27299 | 27301 | block, |
| 27300 | 27302 | field_name_src, |
| 27301 | "no member named '{}' in '{}'", | |
| 27303 | "no member named '{f}' in '{f}'", | |
| 27302 | 27304 | .{ field_name.fmt(ip), object_ty.fmt(pt) }, |
| 27303 | 27305 | ); |
| 27304 | 27306 | } |
| ... | ... | @@ -27321,7 +27323,7 @@ fn fieldPtr( |
| 27321 | 27323 | if (error_set_type.nameIndex(ip, field_name) != null) { |
| 27322 | 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 | 27327 | field_name.fmt(ip), child_type.fmt(pt), |
| 27326 | 27328 | }); |
| 27327 | 27329 | }, |
| ... | ... | @@ -27375,7 +27377,7 @@ fn fieldPtr( |
| 27375 | 27377 | } |
| 27376 | 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 | 27383 | .@"struct" => { |
| ... | ... | @@ -27430,7 +27432,7 @@ fn fieldCallBind( |
| 27430 | 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 | 27433 | raw_ptr_ty.childType(zcu) |
| 27432 | 27434 | 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)}); | |
| 27434 | 27436 | |
| 27435 | 27437 | // Optionally dereference a second pointer to get the concrete type. |
| 27436 | 27438 | const is_double_ptr = inner_ty.zigTypeTag(zcu) == .pointer and inner_ty.ptrSize(zcu) == .one; |
| ... | ... | @@ -27549,7 +27551,7 @@ fn fieldCallBind( |
| 27549 | 27551 | }; |
| 27550 | 27552 | |
| 27551 | 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 | 27555 | field_name.fmt(ip), |
| 27554 | 27556 | concrete_ty.fmt(pt), |
| 27555 | 27557 | }); |
| ... | ... | @@ -27559,7 +27561,7 @@ fn fieldCallBind( |
| 27559 | 27561 | try sema.errNote( |
| 27560 | 27562 | zcu.navSrcLoc(nav_index), |
| 27561 | 27563 | msg, |
| 27562 | "'{}' is not a member function", | |
| 27564 | "'{f}' is not a member function", | |
| 27563 | 27565 | .{field_name.fmt(ip)}, |
| 27564 | 27566 | ); |
| 27565 | 27567 | } |
| ... | ... | @@ -27627,7 +27629,7 @@ fn namespaceLookup( |
| 27627 | 27629 | if (try sema.lookupInNamespace(block, namespace, decl_name)) |lookup| { |
| 27628 | 27630 | if (!lookup.accessible) { |
| 27629 | 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 | 27633 | decl_name.fmt(&zcu.intern_pool), |
| 27632 | 27634 | }); |
| 27633 | 27635 | errdefer msg.destroy(gpa); |
| ... | ... | @@ -27865,12 +27867,12 @@ fn tupleFieldIndex( |
| 27865 | 27867 | assert(!field_name.eqlSlice("len", ip)); |
| 27866 | 27868 | if (field_name.toUnsigned(ip)) |field_index| { |
| 27867 | 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 | 27871 | field_name.fmt(ip), tuple_ty.fmt(pt), |
| 27870 | 27872 | }); |
| 27871 | 27873 | } |
| 27872 | 27874 | |
| 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 | 27876 | field_name.fmt(ip), tuple_ty.fmt(pt), |
| 27875 | 27877 | }); |
| 27876 | 27878 | } |
| ... | ... | @@ -27957,7 +27959,7 @@ fn unionFieldPtr( |
| 27957 | 27959 | const msg = try sema.errMsg(src, "cannot initialize 'noreturn' field of union", .{}); |
| 27958 | 27960 | errdefer msg.destroy(sema.gpa); |
| 27959 | 27961 | |
| 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 | 27963 | field_name.fmt(ip), |
| 27962 | 27964 | }); |
| 27963 | 27965 | try sema.addDeclaredHereNote(msg, union_ty); |
| ... | ... | @@ -27991,7 +27993,7 @@ fn unionFieldPtr( |
| 27991 | 27993 | const msg = msg: { |
| 27992 | 27994 | const active_index = Type.fromInterned(union_obj.enum_tag_ty).enumTagFieldIndex(Value.fromInterned(un.tag), zcu).?; |
| 27993 | 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 | 27997 | field_name.fmt(ip), |
| 27996 | 27998 | active_field_name.fmt(ip), |
| 27997 | 27999 | }); |
| ... | ... | @@ -28059,7 +28061,7 @@ fn unionFieldVal( |
| 28059 | 28061 | const msg = msg: { |
| 28060 | 28062 | const active_index = Type.fromInterned(union_obj.enum_tag_ty).enumTagFieldIndex(Value.fromInterned(un.tag), zcu).?; |
| 28061 | 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 | 28065 | field_name.fmt(ip), active_field_name.fmt(ip), |
| 28064 | 28066 | }); |
| 28065 | 28067 | errdefer msg.destroy(sema.gpa); |
| ... | ... | @@ -28117,7 +28119,7 @@ fn elemPtr( |
| 28117 | 28119 | |
| 28118 | 28120 | const indexable_ty = switch (indexable_ptr_ty.zigTypeTag(zcu)) { |
| 28119 | 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 | 28124 | try sema.checkIndexable(block, src, indexable_ty); |
| 28123 | 28125 | |
| ... | ... | @@ -28288,7 +28290,7 @@ fn validateRuntimeElemAccess( |
| 28288 | 28290 | const msg = msg: { |
| 28289 | 28291 | const msg = try sema.errMsg( |
| 28290 | 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 | 28294 | .{parent_ty.fmt(sema.pt)}, |
| 28293 | 28295 | ); |
| 28294 | 28296 | errdefer msg.destroy(sema.gpa); |
| ... | ... | @@ -28304,7 +28306,7 @@ fn validateRuntimeElemAccess( |
| 28304 | 28306 | const target = zcu.getTarget(); |
| 28305 | 28307 | const as = parent_ty.ptrAddressSpace(zcu); |
| 28306 | 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 | 29002 | return sema.fail( |
| 29001 | 29003 | block, |
| 29002 | 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 | 29006 | .{dest_ty.fmt(pt)}, |
| 29005 | 29007 | ); |
| 29006 | 29008 | } |
| ... | ... | @@ -29027,7 +29029,7 @@ fn coerceExtra( |
| 29027 | 29029 | // pointer to tuple to slice |
| 29028 | 29030 | if (!dest_info.flags.is_const) { |
| 29029 | 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 | 29033 | errdefer err_msg.destroy(sema.gpa); |
| 29032 | 29034 | try sema.errNote(dest_ty_src, err_msg, "pointers to tuples can only coerce to constant pointers", .{}); |
| 29033 | 29035 | break :err_msg err_msg; |
| ... | ... | @@ -29082,7 +29084,7 @@ fn coerceExtra( |
| 29082 | 29084 | // comptime-known integer to other number |
| 29083 | 29085 | if (!(try sema.intFitsInType(val, dest_ty, null))) { |
| 29084 | 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 | 29089 | return switch (zcu.intern_pool.indexToKey(val.toIntern())) { |
| 29088 | 29090 | .undef => try pt.undefRef(dest_ty), |
| ... | ... | @@ -29124,7 +29126,7 @@ fn coerceExtra( |
| 29124 | 29126 | return sema.fail( |
| 29125 | 29127 | block, |
| 29126 | 29128 | inst_src, |
| 29127 | "type '{}' cannot represent float value '{}'", | |
| 29129 | "type '{f}' cannot represent float value '{f}'", | |
| 29128 | 29130 | .{ dest_ty.fmt(pt), val.fmtValueSema(pt, sema) }, |
| 29129 | 29131 | ); |
| 29130 | 29132 | } |
| ... | ... | @@ -29157,7 +29159,7 @@ fn coerceExtra( |
| 29157 | 29159 | // return sema.fail( |
| 29158 | 29160 | // block, |
| 29159 | 29161 | // inst_src, |
| 29160 | // "type '{}' cannot represent integer value '{}'", | |
| 29162 | // "type '{f}' cannot represent integer value '{f}'", | |
| 29161 | 29163 | // .{ dest_ty.fmt(pt), val }, |
| 29162 | 29164 | // ); |
| 29163 | 29165 | //} |
| ... | ... | @@ -29171,7 +29173,7 @@ fn coerceExtra( |
| 29171 | 29173 | const val = try sema.resolveConstDefinedValue(block, LazySrcLoc.unneeded, inst, undefined); |
| 29172 | 29174 | const string = zcu.intern_pool.indexToKey(val.toIntern()).enum_literal; |
| 29173 | 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 | 29177 | string.fmt(&zcu.intern_pool), dest_ty.fmt(pt), |
| 29176 | 29178 | }); |
| 29177 | 29179 | }; |
| ... | ... | @@ -29320,11 +29322,11 @@ fn coerceExtra( |
| 29320 | 29322 | } |
| 29321 | 29323 | |
| 29322 | 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 | 29326 | errdefer msg.destroy(sema.gpa); |
| 29325 | 29327 | |
| 29326 | 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 | } |
| 29329 | 29331 | |
| 29330 | 29332 | // E!T to T |
| ... | ... | @@ -29364,7 +29366,7 @@ fn coerceExtra( |
| 29364 | 29366 | try sema.errNote(param_src, msg, "parameter type declared here", .{}); |
| 29365 | 29367 | } |
| 29366 | 29368 | |
| 29367 | // TODO maybe add "cannot store an error in type '{}'" note | |
| 29369 | // TODO maybe add "cannot store an error in type '{f}'" note | |
| 29368 | 29370 | |
| 29369 | 29371 | break :msg msg; |
| 29370 | 29372 | }; |
| ... | ... | @@ -29513,13 +29515,13 @@ const InMemoryCoercionResult = union(enum) { |
| 29513 | 29515 | break; |
| 29514 | 29516 | }, |
| 29515 | 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 | 29519 | int.wanted.fmt(pt), int.actual.fmtValueSema(pt, sema), |
| 29518 | 29520 | }); |
| 29519 | 29521 | break; |
| 29520 | 29522 | }, |
| 29521 | 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 | 29525 | pair.actual.fmt(pt), pair.wanted.fmt(pt), |
| 29524 | 29526 | }); |
| 29525 | 29527 | cur = pair.child; |
| ... | ... | @@ -29532,18 +29534,18 @@ const InMemoryCoercionResult = union(enum) { |
| 29532 | 29534 | }, |
| 29533 | 29535 | .array_sentinel => |sentinel| { |
| 29534 | 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 | 29538 | sentinel.actual.fmtValueSema(pt, sema), sentinel.wanted.fmtValueSema(pt, sema), |
| 29537 | 29539 | }); |
| 29538 | 29540 | } else { |
| 29539 | try sema.errNote(src, msg, "destination array requires '{}' sentinel", .{ | |
| 29541 | try sema.errNote(src, msg, "destination array requires '{f}' sentinel", .{ | |
| 29540 | 29542 | sentinel.wanted.fmtValueSema(pt, sema), |
| 29541 | 29543 | }); |
| 29542 | 29544 | } |
| 29543 | 29545 | break; |
| 29544 | 29546 | }, |
| 29545 | 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 | 29549 | pair.actual.fmt(pt), pair.wanted.fmt(pt), |
| 29548 | 29550 | }); |
| 29549 | 29551 | cur = pair.child; |
| ... | ... | @@ -29555,19 +29557,19 @@ const InMemoryCoercionResult = union(enum) { |
| 29555 | 29557 | break; |
| 29556 | 29558 | }, |
| 29557 | 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 | 29561 | pair.actual.fmt(pt), pair.wanted.fmt(pt), |
| 29560 | 29562 | }); |
| 29561 | 29563 | cur = pair.child; |
| 29562 | 29564 | }, |
| 29563 | 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 | 29567 | pair.actual.optionalChild(pt.zcu).fmt(pt), pair.wanted.optionalChild(pt.zcu).fmt(pt), |
| 29566 | 29568 | }); |
| 29567 | 29569 | break; |
| 29568 | 29570 | }, |
| 29569 | 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 | 29573 | pair.actual.fmt(pt), pair.wanted.fmt(pt), |
| 29572 | 29574 | }); |
| 29573 | 29575 | cur = pair.child; |
| ... | ... | @@ -29578,7 +29580,7 @@ const InMemoryCoercionResult = union(enum) { |
| 29578 | 29580 | }, |
| 29579 | 29581 | .missing_error => |missing_errors| { |
| 29580 | 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 | 29585 | break; |
| 29584 | 29586 | }, |
| ... | ... | @@ -29631,7 +29633,7 @@ const InMemoryCoercionResult = union(enum) { |
| 29631 | 29633 | break; |
| 29632 | 29634 | }, |
| 29633 | 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 | 29637 | param.index, param.actual.fmt(pt), param.wanted.fmt(pt), |
| 29636 | 29638 | }); |
| 29637 | 29639 | cur = param.child; |
| ... | ... | @@ -29641,13 +29643,13 @@ const InMemoryCoercionResult = union(enum) { |
| 29641 | 29643 | break; |
| 29642 | 29644 | }, |
| 29643 | 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 | 29647 | pair.actual.fmt(pt), pair.wanted.fmt(pt), |
| 29646 | 29648 | }); |
| 29647 | 29649 | cur = pair.child; |
| 29648 | 29650 | }, |
| 29649 | 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 | 29653 | pair.actual.fmt(pt), pair.wanted.fmt(pt), |
| 29652 | 29654 | }); |
| 29653 | 29655 | cur = pair.child; |
| ... | ... | @@ -29658,11 +29660,11 @@ const InMemoryCoercionResult = union(enum) { |
| 29658 | 29660 | }, |
| 29659 | 29661 | .ptr_sentinel => |sentinel| { |
| 29660 | 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 | 29664 | sentinel.actual.fmtValueSema(pt, sema), sentinel.wanted.fmtValueSema(pt, sema), |
| 29663 | 29665 | }); |
| 29664 | 29666 | } else { |
| 29665 | try sema.errNote(src, msg, "destination pointer requires '{}' sentinel", .{ | |
| 29667 | try sema.errNote(src, msg, "destination pointer requires '{f}' sentinel", .{ | |
| 29666 | 29668 | sentinel.wanted.fmtValueSema(pt, sema), |
| 29667 | 29669 | }); |
| 29668 | 29670 | } |
| ... | ... | @@ -29676,11 +29678,11 @@ const InMemoryCoercionResult = union(enum) { |
| 29676 | 29678 | const wanted_allow_zero = pair.wanted.ptrAllowsZero(pt.zcu); |
| 29677 | 29679 | const actual_allow_zero = pair.actual.ptrAllowsZero(pt.zcu); |
| 29678 | 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 | 29682 | pair.actual.fmt(pt), pair.wanted.fmt(pt), |
| 29681 | 29683 | }); |
| 29682 | 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 | 29686 | pair.wanted.fmt(pt), pair.actual.fmt(pt), |
| 29685 | 29687 | }); |
| 29686 | 29688 | } |
| ... | ... | @@ -29692,7 +29694,7 @@ const InMemoryCoercionResult = union(enum) { |
| 29692 | 29694 | if (actual_const and !wanted_const) { |
| 29693 | 29695 | try sema.errNote(src, msg, "cast discards const qualifier", .{}); |
| 29694 | 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 | 29698 | pair.wanted.fmt(pt), pair.actual.fmt(pt), |
| 29697 | 29699 | }); |
| 29698 | 29700 | } |
| ... | ... | @@ -29704,7 +29706,7 @@ const InMemoryCoercionResult = union(enum) { |
| 29704 | 29706 | if (actual_volatile and !wanted_volatile) { |
| 29705 | 29707 | try sema.errNote(src, msg, "cast discards volatile qualifier", .{}); |
| 29706 | 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 | 29710 | pair.wanted.fmt(pt), pair.actual.fmt(pt), |
| 29709 | 29711 | }); |
| 29710 | 29712 | } |
| ... | ... | @@ -29712,12 +29714,12 @@ const InMemoryCoercionResult = union(enum) { |
| 29712 | 29714 | }, |
| 29713 | 29715 | .ptr_bit_range => |bit_range| { |
| 29714 | 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 | 29718 | bit_range.actual_host, bit_range.wanted_host, |
| 29717 | 29719 | }); |
| 29718 | 29720 | } |
| 29719 | 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 | 29723 | bit_range.actual_offset, bit_range.wanted_offset, |
| 29722 | 29724 | }); |
| 29723 | 29725 | } |
| ... | ... | @@ -29730,13 +29732,13 @@ const InMemoryCoercionResult = union(enum) { |
| 29730 | 29732 | break; |
| 29731 | 29733 | }, |
| 29732 | 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 | 29736 | pair.actual.fmt(pt), pair.wanted.fmt(pt), |
| 29735 | 29737 | }); |
| 29736 | 29738 | break; |
| 29737 | 29739 | }, |
| 29738 | 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 | 29742 | pair.actual.fmt(pt), pair.wanted.fmt(pt), |
| 29741 | 29743 | }); |
| 29742 | 29744 | try sema.errNote(src, msg, "consider using '.ptr'", .{}); |
| ... | ... | @@ -30510,7 +30512,7 @@ fn coerceVarArgParam( |
| 30510 | 30512 | const coerced_ty = sema.typeOf(coerced); |
| 30511 | 30513 | if (!try sema.validateExternType(coerced_ty, .param_ty)) { |
| 30512 | 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 | 30516 | errdefer msg.destroy(sema.gpa); |
| 30515 | 30517 | |
| 30516 | 30518 | try sema.explainWhyTypeIsNotExtern(msg, inst_src, coerced_ty, .param_ty); |
| ... | ... | @@ -30613,7 +30615,7 @@ fn storePtr2( |
| 30613 | 30615 | // is not comptime-only. We can hit this case with a `@ptrFromInt` pointer. |
| 30614 | 30616 | if (try elem_ty.comptimeOnlySema(pt)) { |
| 30615 | 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 | 30619 | errdefer msg.destroy(sema.gpa); |
| 30618 | 30620 | try sema.errNote(ptr_src, msg, "operation is runtime due to this pointer", .{}); |
| 30619 | 30621 | break :msg msg; |
| ... | ... | @@ -30646,7 +30648,7 @@ fn storePtr2( |
| 30646 | 30648 | }); |
| 30647 | 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 | 30652 | ptr_ty.fmt(pt), |
| 30651 | 30653 | }); |
| 30652 | 30654 | } |
| ... | ... | @@ -30815,19 +30817,19 @@ fn storePtrVal( |
| 30815 | 30817 | .{}, |
| 30816 | 30818 | ), |
| 30817 | 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 | 30821 | .null_payload => return sema.fail(block, src, "attempt to use null value", .{}), |
| 30820 | 30822 | .inactive_union_field => return sema.fail(block, src, "access of inactive union field", .{}), |
| 30821 | 30823 | .needed_well_defined => |ty| return sema.fail( |
| 30822 | 30824 | block, |
| 30823 | 30825 | src, |
| 30824 | "comptime dereference requires '{}' to have a well-defined layout", | |
| 30826 | "comptime dereference requires '{f}' to have a well-defined layout", | |
| 30825 | 30827 | .{ty.fmt(pt)}, |
| 30826 | 30828 | ), |
| 30827 | 30829 | .out_of_bounds => |ty| return sema.fail( |
| 30828 | 30830 | block, |
| 30829 | 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 | 30833 | .{ ptr_ty.fmt(pt), ty.fmt(pt) }, |
| 30832 | 30834 | ), |
| 30833 | 30835 | .exceeds_host_size => return sema.fail(block, src, "bit-pointer target exceeds host size", .{}), |
| ... | ... | @@ -30853,7 +30855,7 @@ fn bitCast( |
| 30853 | 30855 | const old_bits = old_ty.bitSize(zcu); |
| 30854 | 30856 | |
| 30855 | 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 | 30859 | dest_ty.fmt(pt), |
| 30858 | 30860 | dest_bits, |
| 30859 | 30861 | old_ty.fmt(pt), |
| ... | ... | @@ -30971,7 +30973,7 @@ fn coerceCompatiblePtrs( |
| 30971 | 30973 | const inst_ty = sema.typeOf(inst); |
| 30972 | 30974 | if (try sema.resolveValue(inst)) |val| { |
| 30973 | 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 | 30978 | // The comptime Value representation is compatible with both types. |
| 30977 | 30979 | return Air.internedToRef( |
| ... | ... | @@ -31017,7 +31019,7 @@ fn coerceEnumToUnion( |
| 31017 | 31019 | |
| 31018 | 31020 | const tag_ty = union_ty.unionTagType(zcu) orelse { |
| 31019 | 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 | 31023 | union_ty.fmt(pt), inst_ty.fmt(pt), |
| 31022 | 31024 | }); |
| 31023 | 31025 | errdefer msg.destroy(sema.gpa); |
| ... | ... | @@ -31031,7 +31033,7 @@ fn coerceEnumToUnion( |
| 31031 | 31033 | const enum_tag = try sema.coerce(block, tag_ty, inst, inst_src); |
| 31032 | 31034 | if (try sema.resolveDefinedValue(block, inst_src, enum_tag)) |val| { |
| 31033 | 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 | 31037 | union_ty.fmt(pt), val.fmtValueSema(pt, sema), |
| 31036 | 31038 | }); |
| 31037 | 31039 | }; |
| ... | ... | @@ -31045,7 +31047,7 @@ fn coerceEnumToUnion( |
| 31045 | 31047 | errdefer msg.destroy(sema.gpa); |
| 31046 | 31048 | |
| 31047 | 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 | 31051 | field_name.fmt(ip), |
| 31050 | 31052 | }); |
| 31051 | 31053 | try sema.addDeclaredHereNote(msg, union_ty); |
| ... | ... | @@ -31056,13 +31058,13 @@ fn coerceEnumToUnion( |
| 31056 | 31058 | const opv = (try sema.typeHasOnePossibleValue(field_ty)) orelse { |
| 31057 | 31059 | const msg = msg: { |
| 31058 | 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 | 31062 | inst_ty.fmt(pt), union_ty.fmt(pt), |
| 31061 | 31063 | field_ty.fmt(pt), field_name.fmt(ip), |
| 31062 | 31064 | }); |
| 31063 | 31065 | errdefer msg.destroy(sema.gpa); |
| 31064 | 31066 | |
| 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 | 31068 | field_name.fmt(ip), |
| 31067 | 31069 | }); |
| 31068 | 31070 | try sema.addDeclaredHereNote(msg, union_ty); |
| ... | ... | @@ -31078,7 +31080,7 @@ fn coerceEnumToUnion( |
| 31078 | 31080 | |
| 31079 | 31081 | if (tag_ty.isNonexhaustiveEnum(zcu)) { |
| 31080 | 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 | 31084 | union_ty.fmt(pt), |
| 31083 | 31085 | }); |
| 31084 | 31086 | errdefer msg.destroy(sema.gpa); |
| ... | ... | @@ -31097,7 +31099,7 @@ fn coerceEnumToUnion( |
| 31097 | 31099 | if (Type.fromInterned(field_ty).zigTypeTag(zcu) == .noreturn) { |
| 31098 | 31100 | const err_msg = msg orelse try sema.errMsg( |
| 31099 | 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 | 31103 | .{ tag_ty.fmt(pt), union_ty.fmt(pt) }, |
| 31102 | 31104 | ); |
| 31103 | 31105 | msg = err_msg; |
| ... | ... | @@ -31120,7 +31122,7 @@ fn coerceEnumToUnion( |
| 31120 | 31122 | const msg = msg: { |
| 31121 | 31123 | const msg = try sema.errMsg( |
| 31122 | 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 | 31126 | .{ tag_ty.fmt(pt), union_ty.fmt(pt) }, |
| 31125 | 31127 | ); |
| 31126 | 31128 | errdefer msg.destroy(sema.gpa); |
| ... | ... | @@ -31129,7 +31131,7 @@ fn coerceEnumToUnion( |
| 31129 | 31131 | const field_name = union_obj.loadTagType(ip).names.get(ip)[field_index]; |
| 31130 | 31132 | const field_ty: Type = .fromInterned(union_obj.field_types.get(ip)[field_index]); |
| 31131 | 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 | 31135 | field_name.fmt(ip), |
| 31134 | 31136 | field_ty.fmt(pt), |
| 31135 | 31137 | }); |
| ... | ... | @@ -31170,7 +31172,7 @@ fn coerceArrayLike( |
| 31170 | 31172 | const dest_len = try sema.usizeCast(block, dest_ty_src, dest_ty.arrayLen(zcu)); |
| 31171 | 31173 | if (dest_len != inst_len) { |
| 31172 | 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 | 31176 | dest_ty.fmt(pt), inst_ty.fmt(pt), |
| 31175 | 31177 | }); |
| 31176 | 31178 | errdefer msg.destroy(sema.gpa); |
| ... | ... | @@ -31258,7 +31260,7 @@ fn coerceTupleToArray( |
| 31258 | 31260 | |
| 31259 | 31261 | if (dest_len != inst_len) { |
| 31260 | 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 | 31264 | dest_ty.fmt(pt), inst_ty.fmt(pt), |
| 31263 | 31265 | }); |
| 31264 | 31266 | errdefer msg.destroy(sema.gpa); |
| ... | ... | @@ -31734,10 +31736,10 @@ fn analyzeLoad( |
| 31734 | 31736 | const ptr_ty = sema.typeOf(ptr); |
| 31735 | 31737 | const elem_ty = switch (ptr_ty.zigTypeTag(zcu)) { |
| 31736 | 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 | 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 | } |
| 31742 | 31744 | |
| 31743 | 31745 | if (try sema.typeHasOnePossibleValue(elem_ty)) |opv| { |
| ... | ... | @@ -31758,7 +31760,7 @@ fn analyzeLoad( |
| 31758 | 31760 | const bin_op = sema.getTmpAir().extraData(Air.Bin, ty_pl.payload).data; |
| 31759 | 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 | 31764 | ptr_ty.fmt(pt), |
| 31763 | 31765 | }); |
| 31764 | 31766 | } |
| ... | ... | @@ -32046,7 +32048,7 @@ fn analyzeSlice( |
| 32046 | 32048 | const ptr_ptr_ty = sema.typeOf(ptr_ptr); |
| 32047 | 32049 | const ptr_ptr_child_ty = switch (ptr_ptr_ty.zigTypeTag(zcu)) { |
| 32048 | 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 | }; |
| 32051 | 32053 | |
| 32052 | 32054 | var array_ty = ptr_ptr_child_ty; |
| ... | ... | @@ -32095,7 +32097,7 @@ fn analyzeSlice( |
| 32095 | 32097 | try sema.errNote( |
| 32096 | 32098 | start_src, |
| 32097 | 32099 | msg, |
| 32098 | "expected '{}', found '{}'", | |
| 32100 | "expected '{f}', found '{f}'", | |
| 32099 | 32101 | .{ |
| 32100 | 32102 | Value.zero_comptime_int.fmtValueSema(pt, sema), |
| 32101 | 32103 | start_value.fmtValueSema(pt, sema), |
| ... | ... | @@ -32111,7 +32113,7 @@ fn analyzeSlice( |
| 32111 | 32113 | try sema.errNote( |
| 32112 | 32114 | end_src, |
| 32113 | 32115 | msg, |
| 32114 | "expected '{}', found '{}'", | |
| 32116 | "expected '{f}', found '{f}'", | |
| 32115 | 32117 | .{ |
| 32116 | 32118 | Value.one_comptime_int.fmtValueSema(pt, sema), |
| 32117 | 32119 | end_value.fmtValueSema(pt, sema), |
| ... | ... | @@ -32126,7 +32128,7 @@ fn analyzeSlice( |
| 32126 | 32128 | return sema.fail( |
| 32127 | 32129 | block, |
| 32128 | 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 | 32132 | .{end_value.fmtValueSema(pt, sema)}, |
| 32131 | 32133 | ); |
| 32132 | 32134 | } |
| ... | ... | @@ -32173,7 +32175,7 @@ fn analyzeSlice( |
| 32173 | 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 | } |
| 32178 | 32180 | |
| 32179 | 32181 | const ptr = if (slice_ty.isSlice(zcu)) |
| ... | ... | @@ -32220,7 +32222,7 @@ fn analyzeSlice( |
| 32220 | 32222 | return sema.fail( |
| 32221 | 32223 | block, |
| 32222 | 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 | 32227 | end_val.fmtValueSema(pt, sema), |
| 32226 | 32228 | len_val.fmtValueSema(pt, sema), |
| ... | ... | @@ -32265,7 +32267,7 @@ fn analyzeSlice( |
| 32265 | 32267 | return sema.fail( |
| 32266 | 32268 | block, |
| 32267 | 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 | 32272 | end_val.fmtValueSema(pt, sema), |
| 32271 | 32273 | try slice_val.sliceLen(pt), |
| ... | ... | @@ -32324,7 +32326,7 @@ fn analyzeSlice( |
| 32324 | 32326 | return sema.fail( |
| 32325 | 32327 | block, |
| 32326 | 32328 | start_src, |
| 32327 | "start index {} is larger than end index {}", | |
| 32329 | "start index {f} is larger than end index {f}", | |
| 32328 | 32330 | .{ |
| 32329 | 32331 | start_val.fmtValueSema(pt, sema), |
| 32330 | 32332 | end_val.fmtValueSema(pt, sema), |
| ... | ... | @@ -32348,13 +32350,13 @@ fn analyzeSlice( |
| 32348 | 32350 | .needed_well_defined => |ty| return sema.fail( |
| 32349 | 32351 | block, |
| 32350 | 32352 | src, |
| 32351 | "comptime dereference requires '{}' to have a well-defined layout", | |
| 32353 | "comptime dereference requires '{f}' to have a well-defined layout", | |
| 32352 | 32354 | .{ty.fmt(pt)}, |
| 32353 | 32355 | ), |
| 32354 | 32356 | .out_of_bounds => |ty| return sema.fail( |
| 32355 | 32357 | block, |
| 32356 | 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 | 32360 | .{ end_int, ty.fmt(pt) }, |
| 32359 | 32361 | ), |
| 32360 | 32362 | }; |
| ... | ... | @@ -32363,7 +32365,7 @@ fn analyzeSlice( |
| 32363 | 32365 | const msg = msg: { |
| 32364 | 32366 | const msg = try sema.errMsg(src, "value in memory does not match slice sentinel", .{}); |
| 32365 | 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 | 32369 | expected_sentinel.fmtValueSema(pt, sema), |
| 32368 | 32370 | actual_sentinel.fmtValueSema(pt, sema), |
| 32369 | 32371 | }); |
| ... | ... | @@ -33251,7 +33253,7 @@ const PeerResolveResult = union(enum) { |
| 33251 | 33253 | }; |
| 33252 | 33254 | }, |
| 33253 | 33255 | .field_error => |field_error| { |
| 33254 | const fmt = "struct field '{}' has conflicting types"; | |
| 33256 | const fmt = "struct field '{f}' has conflicting types"; | |
| 33255 | 33257 | const args = .{field_error.field_name.fmt(&pt.zcu.intern_pool)}; |
| 33256 | 33258 | if (opt_msg) |msg| { |
| 33257 | 33259 | try sema.errNote(src, msg, fmt, args); |
| ... | ... | @@ -33282,7 +33284,7 @@ const PeerResolveResult = union(enum) { |
| 33282 | 33284 | candidate_srcs.resolve(block, conflict_idx[1]), |
| 33283 | 33285 | }; |
| 33284 | 33286 | |
| 33285 | const fmt = "incompatible types: '{}' and '{}'"; | |
| 33287 | const fmt = "incompatible types: '{f}' and '{f}'"; | |
| 33286 | 33288 | const args = .{ |
| 33287 | 33289 | conflict_tys[0].fmt(pt), |
| 33288 | 33290 | conflict_tys[1].fmt(pt), |
| ... | ... | @@ -33296,8 +33298,8 @@ const PeerResolveResult = union(enum) { |
| 33296 | 33298 | break :msg msg; |
| 33297 | 33299 | }; |
| 33298 | 33300 | |
| 33299 | if (conflict_srcs[0]) |src_loc| try sema.errNote(src_loc, msg, "type '{}' here", .{conflict_tys[0].fmt(pt)}); | |
| 33300 | if (conflict_srcs[1]) |src_loc| try sema.errNote(src_loc, msg, "type '{}' here", .{conflict_tys[1].fmt(pt)}); | |
| 33301 | if (conflict_srcs[0]) |src_loc| try sema.errNote(src_loc, msg, "type '{f}' here", .{conflict_tys[0].fmt(pt)}); | |
| 33302 | if (conflict_srcs[1]) |src_loc| try sema.errNote(src_loc, msg, "type '{f}' here", .{conflict_tys[1].fmt(pt)}); | |
| 33301 | 33303 | |
| 33302 | 33304 | // No child error |
| 33303 | 33305 | break; |
| ... | ... | @@ -34609,7 +34611,7 @@ pub fn resolveStructLayout(sema: *Sema, ty: Type) SemaError!void { |
| 34609 | 34611 | if (struct_type.setLayoutWip(ip)) { |
| 34610 | 34612 | const msg = try sema.errMsg( |
| 34611 | 34613 | ty.srcLoc(zcu), |
| 34612 | "struct '{}' depends on itself", | |
| 34614 | "struct '{f}' depends on itself", | |
| 34613 | 34615 | .{ty.fmt(pt)}, |
| 34614 | 34616 | ); |
| 34615 | 34617 | return sema.failWithOwnedErrorMsg(null, msg); |
| ... | ... | @@ -34828,13 +34830,13 @@ fn checkBackingIntType(sema: *Sema, block: *Block, src: LazySrcLoc, backing_int_ |
| 34828 | 34830 | const zcu = pt.zcu; |
| 34829 | 34831 | |
| 34830 | 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 | 34835 | if (backing_int_ty.bitSize(zcu) != fields_bit_sum) { |
| 34834 | 34836 | return sema.fail( |
| 34835 | 34837 | block, |
| 34836 | 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 | 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 | 34846 | const pt = sema.pt; |
| 34845 | 34847 | if (!ty.isIndexable(pt.zcu)) { |
| 34846 | 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 | 34850 | errdefer msg.destroy(sema.gpa); |
| 34849 | 34851 | try sema.errNote(src, msg, "operand must be an array, slice, tuple, or vector", .{}); |
| 34850 | 34852 | break :msg msg; |
| ... | ... | @@ -34868,7 +34870,7 @@ fn checkMemOperand(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) !void |
| 34868 | 34870 | } |
| 34869 | 34871 | } |
| 34870 | 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 | 34874 | errdefer msg.destroy(sema.gpa); |
| 34873 | 34875 | try sema.errNote(src, msg, "operand must be a slice, a many pointer or a pointer to an array", .{}); |
| 34874 | 34876 | break :msg msg; |
| ... | ... | @@ -34936,7 +34938,7 @@ pub fn resolveUnionLayout(sema: *Sema, ty: Type) SemaError!void { |
| 34936 | 34938 | .field_types_wip, .layout_wip => { |
| 34937 | 34939 | const msg = try sema.errMsg( |
| 34938 | 34940 | ty.srcLoc(pt.zcu), |
| 34939 | "union '{}' depends on itself", | |
| 34941 | "union '{f}' depends on itself", | |
| 34940 | 34942 | .{ty.fmt(pt)}, |
| 34941 | 34943 | ); |
| 34942 | 34944 | return sema.failWithOwnedErrorMsg(null, msg); |
| ... | ... | @@ -35124,7 +35126,7 @@ pub fn resolveStructFieldTypes( |
| 35124 | 35126 | if (struct_type.setFieldTypesWip(ip)) { |
| 35125 | 35127 | const msg = try sema.errMsg( |
| 35126 | 35128 | Type.fromInterned(ty).srcLoc(zcu), |
| 35127 | "struct '{}' depends on itself", | |
| 35129 | "struct '{f}' depends on itself", | |
| 35128 | 35130 | .{Type.fromInterned(ty).fmt(pt)}, |
| 35129 | 35131 | ); |
| 35130 | 35132 | return sema.failWithOwnedErrorMsg(null, msg); |
| ... | ... | @@ -35153,7 +35155,7 @@ pub fn resolveStructFieldInits(sema: *Sema, ty: Type) SemaError!void { |
| 35153 | 35155 | if (struct_type.setInitsWip(ip)) { |
| 35154 | 35156 | const msg = try sema.errMsg( |
| 35155 | 35157 | ty.srcLoc(zcu), |
| 35156 | "struct '{}' depends on itself", | |
| 35158 | "struct '{f}' depends on itself", | |
| 35157 | 35159 | .{ty.fmt(pt)}, |
| 35158 | 35160 | ); |
| 35159 | 35161 | return sema.failWithOwnedErrorMsg(null, msg); |
| ... | ... | @@ -35177,11 +35179,7 @@ pub fn resolveUnionFieldTypes(sema: *Sema, ty: Type, union_type: InternPool.Load |
| 35177 | 35179 | switch (union_type.flagsUnordered(ip).status) { |
| 35178 | 35180 | .none => {}, |
| 35179 | 35181 | .field_types_wip => { |
| 35180 | const msg = try sema.errMsg( | |
| 35181 | ty.srcLoc(zcu), | |
| 35182 | "union '{}' depends on itself", | |
| 35183 | .{ty.fmt(pt)}, | |
| 35184 | ); | |
| 35182 | const msg = try sema.errMsg(ty.srcLoc(zcu), "union '{f}' depends on itself", .{ty.fmt(pt)}); | |
| 35185 | 35183 | return sema.failWithOwnedErrorMsg(null, msg); |
| 35186 | 35184 | }, |
| 35187 | 35185 | .have_field_types, |
| ... | ... | @@ -35549,7 +35547,7 @@ fn structFields( |
| 35549 | 35547 | switch (struct_type.layout) { |
| 35550 | 35548 | .@"extern" => if (!try sema.validateExternType(field_ty, .struct_field)) { |
| 35551 | 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 | 35551 | errdefer msg.destroy(sema.gpa); |
| 35554 | 35552 | |
| 35555 | 35553 | try sema.explainWhyTypeIsNotExtern(msg, ty_src, field_ty, .struct_field); |
| ... | ... | @@ -35561,7 +35559,7 @@ fn structFields( |
| 35561 | 35559 | }, |
| 35562 | 35560 | .@"packed" => if (!try sema.validatePackedType(field_ty)) { |
| 35563 | 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 | 35563 | errdefer msg.destroy(sema.gpa); |
| 35566 | 35564 | |
| 35567 | 35565 | try sema.explainWhyTypeIsNotPacked(msg, ty_src, field_ty); |
| ... | ... | @@ -35808,7 +35806,7 @@ fn unionFields( |
| 35808 | 35806 | // The provided type is an integer type and we must construct the enum tag type here. |
| 35809 | 35807 | int_tag_ty = provided_ty; |
| 35810 | 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 | } |
| 35813 | 35811 | |
| 35814 | 35812 | if (fields_len > 0) { |
| ... | ... | @@ -35817,7 +35815,7 @@ fn unionFields( |
| 35817 | 35815 | const msg = msg: { |
| 35818 | 35816 | const msg = try sema.errMsg(tag_ty_src, "specified integer tag type cannot represent every field", .{}); |
| 35819 | 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 | 35819 | int_tag_ty.fmt(pt), |
| 35822 | 35820 | fields_len - 1, |
| 35823 | 35821 | }); |
| ... | ... | @@ -35832,7 +35830,7 @@ fn unionFields( |
| 35832 | 35830 | // The provided type is the enum tag type. |
| 35833 | 35831 | const enum_type = switch (ip.indexToKey(provided_ty.toIntern())) { |
| 35834 | 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 | 35835 | union_type.setTagType(ip, provided_ty.toIntern()); |
| 35838 | 35836 | // The fields of the union must match the enum exactly. |
| ... | ... | @@ -35929,7 +35927,7 @@ fn unionFields( |
| 35929 | 35927 | if (result.overflow) return sema.fail( |
| 35930 | 35928 | &block_scope, |
| 35931 | 35929 | value_src, |
| 35932 | "enumeration value '{}' too large for type '{}'", | |
| 35930 | "enumeration value '{f}' too large for type '{f}'", | |
| 35933 | 35931 | .{ result.val.fmtValueSema(pt, sema), int_tag_ty.fmt(pt) }, |
| 35934 | 35932 | ); |
| 35935 | 35933 | last_tag_val = result.val; |
| ... | ... | @@ -35947,7 +35945,7 @@ fn unionFields( |
| 35947 | 35945 | const msg = msg: { |
| 35948 | 35946 | const msg = try sema.errMsg( |
| 35949 | 35947 | value_src, |
| 35950 | "enum tag value {} already taken", | |
| 35948 | "enum tag value {f} already taken", | |
| 35951 | 35949 | .{enum_tag_val.fmtValueSema(pt, sema)}, |
| 35952 | 35950 | ); |
| 35953 | 35951 | errdefer msg.destroy(gpa); |
| ... | ... | @@ -35975,7 +35973,7 @@ fn unionFields( |
| 35975 | 35973 | const tag_ty = union_type.tagTypeUnordered(ip); |
| 35976 | 35974 | const tag_info = ip.loadEnumType(tag_ty); |
| 35977 | 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 | 35977 | field_name.fmt(ip), Type.fromInterned(tag_ty).fmt(pt), |
| 35980 | 35978 | }); |
| 35981 | 35979 | }; |
| ... | ... | @@ -35992,7 +35990,7 @@ fn unionFields( |
| 35992 | 35990 | .base_node_inst = Type.fromInterned(tag_ty).typeDeclInstAllowGeneratedTag(zcu).?, |
| 35993 | 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 | 35994 | field_name.fmt(ip), |
| 35997 | 35995 | }); |
| 35998 | 35996 | errdefer msg.destroy(sema.gpa); |
| ... | ... | @@ -36018,7 +36016,7 @@ fn unionFields( |
| 36018 | 36016 | !try sema.validateExternType(field_ty, .union_field)) |
| 36019 | 36017 | { |
| 36020 | 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 | 36020 | errdefer msg.destroy(sema.gpa); |
| 36023 | 36021 | |
| 36024 | 36022 | try sema.explainWhyTypeIsNotExtern(msg, type_src, field_ty, .union_field); |
| ... | ... | @@ -36029,7 +36027,7 @@ fn unionFields( |
| 36029 | 36027 | return sema.failWithOwnedErrorMsg(&block_scope, msg); |
| 36030 | 36028 | } else if (layout == .@"packed" and !try sema.validatePackedType(field_ty)) { |
| 36031 | 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 | 36031 | errdefer msg.destroy(sema.gpa); |
| 36034 | 36032 | |
| 36035 | 36033 | try sema.explainWhyTypeIsNotPacked(msg, type_src, field_ty); |
| ... | ... | @@ -36065,7 +36063,7 @@ fn unionFields( |
| 36065 | 36063 | |
| 36066 | 36064 | for (tag_info.names.get(ip), 0..) |field_name, field_index| { |
| 36067 | 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 | 36067 | field_name.fmt(ip), |
| 36070 | 36068 | }); |
| 36071 | 36069 | } |
| ... | ... | @@ -36101,7 +36099,7 @@ fn generateUnionTagTypeNumbered( |
| 36101 | 36099 | const name = try ip.getOrPutStringFmt( |
| 36102 | 36100 | gpa, |
| 36103 | 36101 | pt.tid, |
| 36104 | "@typeInfo({}).@\"union\".tag_type.?", | |
| 36102 | "@typeInfo({f}).@\"union\".tag_type.?", | |
| 36105 | 36103 | .{union_name.fmt(ip)}, |
| 36106 | 36104 | .no_embedded_nulls, |
| 36107 | 36105 | ); |
| ... | ... | @@ -36137,7 +36135,7 @@ fn generateUnionTagTypeSimple( |
| 36137 | 36135 | const name = try ip.getOrPutStringFmt( |
| 36138 | 36136 | gpa, |
| 36139 | 36137 | pt.tid, |
| 36140 | "@typeInfo({}).@\"union\".tag_type.?", | |
| 36138 | "@typeInfo({f}).@\"union\".tag_type.?", | |
| 36141 | 36139 | .{union_name.fmt(ip)}, |
| 36142 | 36140 | .no_embedded_nulls, |
| 36143 | 36141 | ); |
| ... | ... | @@ -36671,13 +36669,13 @@ fn pointerDeref(sema: *Sema, block: *Block, src: LazySrcLoc, ptr_val: Value, ptr |
| 36671 | 36669 | .needed_well_defined => |ty| return sema.fail( |
| 36672 | 36670 | block, |
| 36673 | 36671 | src, |
| 36674 | "comptime dereference requires '{}' to have a well-defined layout", | |
| 36672 | "comptime dereference requires '{f}' to have a well-defined layout", | |
| 36675 | 36673 | .{ty.fmt(pt)}, |
| 36676 | 36674 | ), |
| 36677 | 36675 | .out_of_bounds => |ty| return sema.fail( |
| 36678 | 36676 | block, |
| 36679 | 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 | 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 | 36695 | .success => |mv| return .{ .val = try mv.intern(pt, sema.arena) }, |
| 36698 | 36696 | .runtime_load => return .runtime_load, |
| 36699 | 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 | 36699 | .null_payload => return sema.fail(block, src, "attempt to use null value", .{}), |
| 36702 | 36700 | .inactive_union_field => return sema.fail(block, src, "access of inactive union field", .{}), |
| 36703 | 36701 | .needed_well_defined => |ty| return .{ .needed_well_defined = ty }, |
| ... | ... | @@ -36822,12 +36820,12 @@ fn intFromFloatScalar( |
| 36822 | 36820 | |
| 36823 | 36821 | const float = val.toFloat(f128, zcu); |
| 36824 | 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 | 36824 | int_ty.fmt(pt), |
| 36827 | 36825 | }); |
| 36828 | 36826 | } |
| 36829 | 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 | 36829 | int_ty.fmt(pt), |
| 36832 | 36830 | }); |
| 36833 | 36831 | } |
| ... | ... | @@ -36842,7 +36840,7 @@ fn intFromFloatScalar( |
| 36842 | 36840 | .exact => return sema.fail( |
| 36843 | 36841 | block, |
| 36844 | 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 | 36844 | .{ val.fmtValueSema(pt, sema), int_ty.fmt(pt) }, |
| 36847 | 36845 | ), |
| 36848 | 36846 | .truncate => {}, |
| ... | ... | @@ -36854,7 +36852,7 @@ fn intFromFloatScalar( |
| 36854 | 36852 | |
| 36855 | 36853 | const int_info = int_ty.intInfo(zcu); |
| 36856 | 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 | 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 | 37173 | } |
| 37176 | 37174 | } |
| 37177 | 37175 | |
| 37178 | fn notePathToComptimeAllocPtr(sema: *Sema, msg: *Zcu.ErrorMsg, src: LazySrcLoc, val: Value, intermediate_value_count: u32, start_value_name: InternPool.NullTerminatedString) Allocator.Error!union(enum) { | |
| 37176 | fn 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 | 37184 | done, |
| 37180 | 37185 | new_val: Value, |
| 37181 | 37186 | } { |
| ... | ... | @@ -37186,9 +37191,9 @@ fn notePathToComptimeAllocPtr(sema: *Sema, msg: *Zcu.ErrorMsg, src: LazySrcLoc, |
| 37186 | 37191 | |
| 37187 | 37192 | var first_path: std.ArrayListUnmanaged(u8) = .empty; |
| 37188 | 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 | 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 | } |
| 37193 | 37198 | |
| 37194 | 37199 | const comptime_ptr = try sema.notePathToComptimeAllocPtrInner(val, &first_path); |
| ... | ... | @@ -37213,30 +37218,26 @@ fn notePathToComptimeAllocPtr(sema: *Sema, msg: *Zcu.ErrorMsg, src: LazySrcLoc, |
| 37213 | 37218 | error.AnalysisFail => unreachable, |
| 37214 | 37219 | }; |
| 37215 | 37220 | |
| 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 | 37223 | const inter_name = try std.fmt.allocPrint(arena, "v{d}", .{intermediate_value_count}); |
| 37218 | 37224 | const deriv_start = @import("print_value.zig").printPtrDerivation( |
| 37219 | 37225 | derivation, |
| 37220 | second_path.writer(arena), | |
| 37226 | &second_path_aw.writer, | |
| 37221 | 37227 | pt, |
| 37222 | 37228 | .lvalue, |
| 37223 | 37229 | .{ .str = inter_name }, |
| 37224 | 37230 | 20, |
| 37225 | ) catch |err| switch (err) { | |
| 37226 | error.OutOfMemory => |e| return e, | |
| 37227 | error.AnalysisFail => unreachable, | |
| 37228 | error.ComptimeReturn => unreachable, | |
| 37229 | error.ComptimeBreak => unreachable, | |
| 37230 | }; | |
| 37231 | ) catch return error.OutOfMemory; | |
| 37231 | 37232 | |
| 37232 | 37233 | switch (deriv_start) { |
| 37233 | 37234 | .int, .nav_ptr => unreachable, |
| 37234 | 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 | 37237 | return .{ .new_val = .fromInterned(uav.val) }; |
| 37237 | 37238 | }, |
| 37238 | 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 | 37241 | const cta = sema.getComptimeAlloc(cta_info.idx); |
| 37241 | 37242 | if (cta.is_const) { |
| 37242 | 37243 | return .{ .new_val = cta_info.val }; |
| ... | ... | @@ -37246,7 +37247,7 @@ fn notePathToComptimeAllocPtr(sema: *Sema, msg: *Zcu.ErrorMsg, src: LazySrcLoc, |
| 37246 | 37247 | } |
| 37247 | 37248 | }, |
| 37248 | 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 | 37251 | try sema.errNote(src, msg, "'{s}' is a comptime field", .{inter_name}); |
| 37251 | 37252 | return .done; |
| 37252 | 37253 | }, |
| ... | ... | @@ -37286,7 +37287,7 @@ fn notePathToComptimeAllocPtrInner(sema: *Sema, val: Value, path: *std.ArrayList |
| 37286 | 37287 | const backing_enum = union_ty.unionTagTypeHypothetical(zcu); |
| 37287 | 37288 | const field_idx = backing_enum.enumTagFieldIndex(.fromInterned(un.tag), zcu).?; |
| 37288 | 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 | 37291 | return sema.notePathToComptimeAllocPtrInner(.fromInterned(un.val), path); |
| 37291 | 37292 | }, |
| 37292 | 37293 | .aggregate => |agg| { |
| ... | ... | @@ -37301,17 +37302,17 @@ fn notePathToComptimeAllocPtrInner(sema: *Sema, val: Value, path: *std.ArrayList |
| 37301 | 37302 | }; |
| 37302 | 37303 | const agg_ty: Type = .fromInterned(agg.ty); |
| 37303 | 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 | 37306 | .pointer => switch (elem_idx) { |
| 37306 | 37307 | Value.slice_ptr_index => try path.appendSlice(arena, ".ptr"), |
| 37307 | 37308 | Value.slice_len_index => try path.appendSlice(arena, ".len"), |
| 37308 | 37309 | else => unreachable, |
| 37309 | 37310 | }, |
| 37310 | 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 | 37313 | } else { |
| 37313 | 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 | 37317 | else => unreachable, |
| 37317 | 37318 | } |
| ... | ... | @@ -37588,7 +37589,7 @@ fn resolveDeclaredEnumInner( |
| 37588 | 37589 | if (tag_type_ref != .none) { |
| 37589 | 37590 | const ty = try sema.resolveType(block, tag_ty_src, tag_type_ref); |
| 37590 | 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 | 37594 | break :ty ty; |
| 37594 | 37595 | } else if (fields_len == 0) { |
| ... | ... | @@ -37642,7 +37643,7 @@ fn resolveDeclaredEnumInner( |
| 37642 | 37643 | .offset = .{ .container_field_value = conflict.prev_field_idx }, |
| 37643 | 37644 | }; |
| 37644 | 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 | 37647 | errdefer msg.destroy(gpa); |
| 37647 | 37648 | try sema.errNote(other_field_src, msg, "other occurrence here", .{}); |
| 37648 | 37649 | break :msg msg; |
| ... | ... | @@ -37665,7 +37666,7 @@ fn resolveDeclaredEnumInner( |
| 37665 | 37666 | .offset = .{ .container_field_value = conflict.prev_field_idx }, |
| 37666 | 37667 | }; |
| 37667 | 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 | 37670 | errdefer msg.destroy(gpa); |
| 37670 | 37671 | try sema.errNote(other_field_src, msg, "other occurrence here", .{}); |
| 37671 | 37672 | break :msg msg; |
| ... | ... | @@ -37682,7 +37683,7 @@ fn resolveDeclaredEnumInner( |
| 37682 | 37683 | }; |
| 37683 | 37684 | |
| 37684 | 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 | 37687 | last_tag_val.?.fmtValueSema(pt, sema), int_tag_ty.fmt(pt), |
| 37687 | 37688 | }); |
| 37688 | 37689 | return sema.failWithOwnedErrorMsg(block, msg); |
src/Sema/LowerZon.zig+17-21| ... | ... | @@ -338,7 +338,7 @@ fn failUnsupportedResultType( |
| 338 | 338 | const gpa = sema.gpa; |
| 339 | 339 | const pt = sema.pt; |
| 340 | 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 | 342 | errdefer msg.destroy(gpa); |
| 343 | 343 | if (opt_note) |n| try sema.errNote(self.import_loc, msg, "{s}", .{n}); |
| 344 | 344 | break :msg msg; |
| ... | ... | @@ -360,11 +360,7 @@ fn fail( |
| 360 | 360 | fn lowerExprKnownResTy(self: *LowerZon, node: Zoir.Node.Index, res_ty: Type) CompileError!InternPool.Index { |
| 361 | 361 | const pt = self.sema.pt; |
| 362 | 362 | return self.lowerExprKnownResTyInner(node, res_ty) catch |err| switch (err) { |
| 363 | error.WrongType => return self.fail( | |
| 364 | node, | |
| 365 | "expected type '{}'", | |
| 366 | .{res_ty.fmt(pt)}, | |
| 367 | ), | |
| 363 | error.WrongType => return self.fail(node, "expected type '{f}'", .{res_ty.fmt(pt)}), | |
| 368 | 364 | else => |e| return e, |
| 369 | 365 | }; |
| 370 | 366 | } |
| ... | ... | @@ -428,7 +424,7 @@ fn lowerExprKnownResTyInner( |
| 428 | 424 | .frame, |
| 429 | 425 | .@"anyframe", |
| 430 | 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 | } |
| 434 | 430 | |
| ... | ... | @@ -458,7 +454,7 @@ fn lowerInt( |
| 458 | 454 | // If lhs is unsigned and rhs is less than 0, we're out of bounds |
| 459 | 455 | if (lhs_info.signedness == .unsigned and rhs < 0) return self.fail( |
| 460 | 456 | node, |
| 461 | "type '{}' cannot represent integer value '{}'", | |
| 457 | "type '{f}' cannot represent integer value '{d}'", | |
| 462 | 458 | .{ res_ty.fmt(self.sema.pt), rhs }, |
| 463 | 459 | ); |
| 464 | 460 | |
| ... | ... | @@ -478,7 +474,7 @@ fn lowerInt( |
| 478 | 474 | if (rhs < min_int or rhs > max_int) { |
| 479 | 475 | return self.fail( |
| 480 | 476 | node, |
| 481 | "type '{}' cannot represent integer value '{}'", | |
| 477 | "type '{f}' cannot represent integer value '{d}'", | |
| 482 | 478 | .{ res_ty.fmt(self.sema.pt), rhs }, |
| 483 | 479 | ); |
| 484 | 480 | } |
| ... | ... | @@ -496,7 +492,7 @@ fn lowerInt( |
| 496 | 492 | if (!val.fitsInTwosComp(int_info.signedness, int_info.bits)) { |
| 497 | 493 | return self.fail( |
| 498 | 494 | node, |
| 499 | "type '{}' cannot represent integer value '{}'", | |
| 495 | "type '{f}' cannot represent integer value '{d}'", | |
| 500 | 496 | .{ res_ty.fmt(self.sema.pt), val }, |
| 501 | 497 | ); |
| 502 | 498 | } |
| ... | ... | @@ -517,7 +513,7 @@ fn lowerInt( |
| 517 | 513 | switch (big_int.setFloat(val, .trunc)) { |
| 518 | 514 | .inexact => return self.fail( |
| 519 | 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 | 517 | .{ val, res_ty.fmt(self.sema.pt) }, |
| 522 | 518 | ), |
| 523 | 519 | .exact => {}, |
| ... | ... | @@ -528,8 +524,8 @@ fn lowerInt( |
| 528 | 524 | if (!big_int.toConst().fitsInTwosComp(int_info.signedness, int_info.bits)) { |
| 529 | 525 | return self.fail( |
| 530 | 526 | node, |
| 531 | "type '{}' cannot represent integer value '{}'", | |
| 532 | .{ val, res_ty.fmt(self.sema.pt) }, | |
| 527 | "type '{f}' cannot represent integer value '{d}'", | |
| 528 | .{ res_ty.fmt(self.sema.pt), val }, | |
| 533 | 529 | ); |
| 534 | 530 | } |
| 535 | 531 | |
| ... | ... | @@ -550,7 +546,7 @@ fn lowerInt( |
| 550 | 546 | if (val >= out_of_range) { |
| 551 | 547 | return self.fail( |
| 552 | 548 | node, |
| 553 | "type '{}' cannot represent integer value '{}'", | |
| 549 | "type '{f}' cannot represent integer value '{d}'", | |
| 554 | 550 | .{ res_ty.fmt(self.sema.pt), val }, |
| 555 | 551 | ); |
| 556 | 552 | } |
| ... | ... | @@ -584,7 +580,7 @@ fn lowerFloat( |
| 584 | 580 | .pos_inf => b: { |
| 585 | 581 | if (res_ty.toIntern() == .comptime_float_type) return self.fail( |
| 586 | 582 | node, |
| 587 | "expected type '{}'", | |
| 583 | "expected type '{f}'", | |
| 588 | 584 | .{res_ty.fmt(self.sema.pt)}, |
| 589 | 585 | ); |
| 590 | 586 | break :b try self.sema.pt.floatValue(res_ty, std.math.inf(f128)); |
| ... | ... | @@ -592,7 +588,7 @@ fn lowerFloat( |
| 592 | 588 | .neg_inf => b: { |
| 593 | 589 | if (res_ty.toIntern() == .comptime_float_type) return self.fail( |
| 594 | 590 | node, |
| 595 | "expected type '{}'", | |
| 591 | "expected type '{f}'", | |
| 596 | 592 | .{res_ty.fmt(self.sema.pt)}, |
| 597 | 593 | ); |
| 598 | 594 | break :b try self.sema.pt.floatValue(res_ty, -std.math.inf(f128)); |
| ... | ... | @@ -600,7 +596,7 @@ fn lowerFloat( |
| 600 | 596 | .nan => b: { |
| 601 | 597 | if (res_ty.toIntern() == .comptime_float_type) return self.fail( |
| 602 | 598 | node, |
| 603 | "expected type '{}'", | |
| 599 | "expected type '{f}'", | |
| 604 | 600 | .{res_ty.fmt(self.sema.pt)}, |
| 605 | 601 | ); |
| 606 | 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 | 657 | const field_index = res_ty.enumFieldIndex(field_name_interned, self.sema.pt.zcu) orelse { |
| 662 | 658 | return self.fail( |
| 663 | 659 | node, |
| 664 | "enum {} has no member named '{}'", | |
| 660 | "enum {f} has no member named '{f}'", | |
| 665 | 661 | .{ |
| 666 | 662 | res_ty.fmt(self.sema.pt), |
| 667 | 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 | 791 | const field_node = fields.vals.at(@intCast(i)); |
| 796 | 792 | |
| 797 | 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 | }; |
| 800 | 796 | |
| 801 | 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 | 812 | |
| 817 | 813 | const field_names = struct_info.field_names.get(ip); |
| 818 | 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 | } |
| 821 | 817 | |
| 822 | 818 | return self.sema.pt.intern(.{ .aggregate = .{ |
| ... | ... | @@ -934,7 +930,7 @@ fn lowerUnion(self: *LowerZon, node: Zoir.Node.Index, res_ty: Type) !InternPool. |
| 934 | 930 | .struct_literal => b: { |
| 935 | 931 | const fields: @FieldType(Zoir.Node, "struct_literal") = switch (node.get(self.file.zoir.?)) { |
| 936 | 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 | 935 | if (fields.names.len != 1) { |
| 940 | 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 | 121 | return a.toIntern() == b.toIntern(); |
| 122 | 122 | } |
| 123 | 123 | |
| 124 | pub fn format(ty: Type, comptime unused_fmt_string: []const u8, options: std.fmt.FormatOptions, writer: anytype) !void { | |
| 124 | pub fn format(ty: Type, writer: *std.io.Writer) !void { | |
| 125 | 125 | _ = ty; |
| 126 | _ = unused_fmt_string; | |
| 127 | _ = options; | |
| 128 | 126 | _ = writer; |
| 129 | 127 | @compileError("do not format types directly; use either ty.fmtDebug() or ty.fmt()"); |
| 130 | 128 | } |
| 131 | 129 | |
| 132 | pub const Formatter = std.fmt.Formatter(format2); | |
| 130 | pub const Formatter = std.fmt.Formatter(Format, Format.default); | |
| 133 | 131 | |
| 134 | 132 | pub fn fmt(ty: Type, pt: Zcu.PerThread) Formatter { |
| 135 | 133 | return .{ .data = .{ |
| ... | ... | @@ -138,42 +136,28 @@ pub fn fmt(ty: Type, pt: Zcu.PerThread) Formatter { |
| 138 | 136 | } }; |
| 139 | 137 | } |
| 140 | 138 | |
| 141 | const FormatContext = struct { | |
| 139 | const Format = struct { | |
| 142 | 140 | ty: Type, |
| 143 | 141 | pt: Zcu.PerThread, |
| 144 | }; | |
| 145 | 142 | |
| 146 | fn format2( | |
| 147 | ctx: FormatContext, | |
| 148 | comptime unused_format_string: []const u8, | |
| 149 | options: std.fmt.FormatOptions, | |
| 150 | writer: anytype, | |
| 151 | ) !void { | |
| 152 | comptime assert(unused_format_string.len == 0); | |
| 153 | _ = options; | |
| 154 | return print(ctx.ty, writer, ctx.pt); | |
| 155 | } | |
| 143 | fn default(f: Format, writer: *std.io.Writer) std.io.Writer.Error!void { | |
| 144 | return print(f.ty, writer, f.pt); | |
| 145 | } | |
| 146 | }; | |
| 156 | 147 | |
| 157 | pub fn fmtDebug(ty: Type) std.fmt.Formatter(dump) { | |
| 148 | pub fn fmtDebug(ty: Type) std.fmt.Formatter(Type, dump) { | |
| 158 | 149 | return .{ .data = ty }; |
| 159 | 150 | } |
| 160 | 151 | |
| 161 | 152 | /// This is a debug function. In order to print types in a meaningful way |
| 162 | 153 | /// we also need access to the module. |
| 163 | pub fn dump( | |
| 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); | |
| 154 | pub fn dump(start_type: Type, writer: *std.io.Writer) std.io.Writer.Error!void { | |
| 171 | 155 | return writer.print("{any}", .{start_type.ip_index}); |
| 172 | 156 | } |
| 173 | 157 | |
| 174 | 158 | /// Prints a name suitable for `@typeName`. |
| 175 | 159 | /// TODO: take an `opt_sema` to pass to `fmtValue` when printing sentinels. |
| 176 | pub fn print(ty: Type, writer: anytype, pt: Zcu.PerThread) @TypeOf(writer).Error!void { | |
| 160 | pub fn print(ty: Type, writer: *std.io.Writer, pt: Zcu.PerThread) std.io.Writer.Error!void { | |
| 177 | 161 | const zcu = pt.zcu; |
| 178 | 162 | const ip = &zcu.intern_pool; |
| 179 | 163 | switch (ip.indexToKey(ty.toIntern())) { |
| ... | ... | @@ -190,8 +174,8 @@ pub fn print(ty: Type, writer: anytype, pt: Zcu.PerThread) @TypeOf(writer).Error |
| 190 | 174 | |
| 191 | 175 | if (info.sentinel != .none) switch (info.flags.size) { |
| 192 | 176 | .one, .c => unreachable, |
| 193 | .many => try writer.print("[*:{}]", .{Value.fromInterned(info.sentinel).fmtValue(pt)}), | |
| 194 | .slice => try writer.print("[:{}]", .{Value.fromInterned(info.sentinel).fmtValue(pt)}), | |
| 177 | .many => try writer.print("[*:{f}]", .{Value.fromInterned(info.sentinel).fmtValue(pt)}), | |
| 178 | .slice => try writer.print("[:{f}]", .{Value.fromInterned(info.sentinel).fmtValue(pt)}), | |
| 195 | 179 | } else switch (info.flags.size) { |
| 196 | 180 | .one => try writer.writeAll("*"), |
| 197 | 181 | .many => try writer.writeAll("[*]"), |
| ... | ... | @@ -235,7 +219,7 @@ pub fn print(ty: Type, writer: anytype, pt: Zcu.PerThread) @TypeOf(writer).Error |
| 235 | 219 | try writer.print("[{d}]", .{array_type.len}); |
| 236 | 220 | try print(Type.fromInterned(array_type.child), writer, pt); |
| 237 | 221 | } else { |
| 238 | try writer.print("[{d}:{}]", .{ | |
| 222 | try writer.print("[{d}:{f}]", .{ | |
| 239 | 223 | array_type.len, |
| 240 | 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 | 249 | }, |
| 266 | 250 | .inferred_error_set_type => |func_index| { |
| 267 | 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 | 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 | 258 | try writer.writeAll("error{"); |
| 275 | 259 | for (names.get(ip), 0..) |name, i| { |
| 276 | 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 | 263 | try writer.writeAll("}"); |
| 280 | 264 | }, |
| ... | ... | @@ -317,7 +301,7 @@ pub fn print(ty: Type, writer: anytype, pt: Zcu.PerThread) @TypeOf(writer).Error |
| 317 | 301 | }, |
| 318 | 302 | .struct_type => { |
| 319 | 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 | 306 | .tuple_type => |tuple| { |
| 323 | 307 | if (tuple.types.len == 0) { |
| ... | ... | @@ -328,22 +312,22 @@ pub fn print(ty: Type, writer: anytype, pt: Zcu.PerThread) @TypeOf(writer).Error |
| 328 | 312 | try writer.writeAll(if (i == 0) " " else ", "); |
| 329 | 313 | if (val != .none) try writer.writeAll("comptime "); |
| 330 | 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 | 317 | try writer.writeAll(" }"); |
| 334 | 318 | }, |
| 335 | 319 | |
| 336 | 320 | .union_type => { |
| 337 | 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 | 324 | .opaque_type => { |
| 341 | 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 | 328 | .enum_type => { |
| 345 | 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 | 332 | .func_type => |fn_info| { |
| 349 | 333 | if (fn_info.is_noinline) { |
| ... | ... | @@ -382,7 +366,9 @@ pub fn print(ty: Type, writer: anytype, pt: Zcu.PerThread) @TypeOf(writer).Error |
| 382 | 366 | } |
| 383 | 367 | } |
| 384 | 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 | 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 | 15 | |
| 16 | 16 | ip_index: InternPool.Index, |
| 17 | 17 | |
| 18 | pub fn format(val: Value, comptime fmt: []const u8, options: std.fmt.FormatOptions, writer: anytype) !void { | |
| 18 | pub fn format(val: Value, writer: *std.io.Writer) !void { | |
| 19 | 19 | _ = val; |
| 20 | _ = fmt; | |
| 21 | _ = options; | |
| 22 | 20 | _ = writer; |
| 23 | 21 | @compileError("do not use format values directly; use either fmtDebug or fmtValue"); |
| 24 | 22 | } |
| 25 | 23 | |
| 26 | 24 | /// This is a debug function. In order to print values in a meaningful way |
| 27 | 25 | /// we also need access to the type. |
| 28 | pub fn dump( | |
| 29 | start_val: Value, | |
| 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()}); | |
| 26 | pub fn dump(start_val: Value, w: std.io.Writer) std.io.Writer.Error!void { | |
| 27 | try w.print("(interned: {})", .{start_val.toIntern()}); | |
| 36 | 28 | } |
| 37 | 29 | |
| 38 | pub fn fmtDebug(val: Value) std.fmt.Formatter(dump) { | |
| 30 | pub fn fmtDebug(val: Value) std.fmt.Formatter(Value, dump) { | |
| 39 | 31 | return .{ .data = val }; |
| 40 | 32 | } |
| 41 | 33 | |
| 42 | pub fn fmtValue(val: Value, pt: Zcu.PerThread) std.fmt.Formatter(print_value.format) { | |
| 34 | pub fn fmtValue(val: Value, pt: Zcu.PerThread) std.fmt.Formatter(print_value.FormatContext, print_value.format) { | |
| 43 | 35 | return .{ .data = .{ |
| 44 | 36 | .val = val, |
| 45 | 37 | .pt = pt, |
| ... | ... | @@ -48,7 +40,7 @@ pub fn fmtValue(val: Value, pt: Zcu.PerThread) std.fmt.Formatter(print_value.for |
| 48 | 40 | } }; |
| 49 | 41 | } |
| 50 | 42 | |
| 51 | pub fn fmtValueSema(val: Value, pt: Zcu.PerThread, sema: *Sema) std.fmt.Formatter(print_value.formatSema) { | |
| 43 | pub fn fmtValueSema(val: Value, pt: Zcu.PerThread, sema: *Sema) std.fmt.Formatter(print_value.FormatContext, print_value.formatSema) { | |
| 52 | 44 | return .{ .data = .{ |
| 53 | 45 | .val = val, |
| 54 | 46 | .pt = pt, |
| ... | ... | @@ -57,7 +49,7 @@ pub fn fmtValueSema(val: Value, pt: Zcu.PerThread, sema: *Sema) std.fmt.Formatte |
| 57 | 49 | } }; |
| 58 | 50 | } |
| 59 | 51 | |
| 60 | pub fn fmtValueSemaFull(ctx: print_value.FormatContext) std.fmt.Formatter(print_value.formatSema) { | |
| 52 | pub fn fmtValueSemaFull(ctx: print_value.FormatContext) std.fmt.Formatter(print_value.FormatContext, print_value.formatSema) { | |
| 61 | 53 | return .{ .data = ctx }; |
| 62 | 54 | } |
| 63 | 55 |
src/Zcu.zig+123-206| ... | ... | @@ -15,6 +15,7 @@ const BigIntConst = std.math.big.int.Const; |
| 15 | 15 | const BigIntMutable = std.math.big.int.Mutable; |
| 16 | 16 | const Target = std.Target; |
| 17 | 17 | const Ast = std.zig.Ast; |
| 18 | const Writer = std.io.Writer; | |
| 18 | 19 | |
| 19 | 20 | const Zcu = @This(); |
| 20 | 21 | const Compilation = @import("Compilation.zig"); |
| ... | ... | @@ -858,7 +859,7 @@ pub const Namespace = struct { |
| 858 | 859 | try ns.fileScope(zcu).renderFullyQualifiedDebugName(writer); |
| 859 | 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 | } |
| 863 | 864 | |
| 864 | 865 | pub fn internFullyQualifiedName( |
| ... | ... | @@ -870,7 +871,7 @@ pub const Namespace = struct { |
| 870 | 871 | ) !InternPool.NullTerminatedString { |
| 871 | 872 | const ns_name = Type.fromInterned(ns.owner_type).containerTypeName(ip); |
| 872 | 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 | }; |
| 876 | 877 | |
| ... | ... | @@ -1039,12 +1040,12 @@ pub const File = struct { |
| 1039 | 1040 | if (stat.size > std.math.maxInt(u32)) |
| 1040 | 1041 | return error.FileTooBig; |
| 1041 | 1042 | |
| 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 | 1044 | errdefer gpa.free(source); |
| 1044 | 1045 | |
| 1045 | const amt = try f.readAll(source); | |
| 1046 | if (amt != stat.size) | |
| 1047 | return error.UnexpectedEndOfFile; | |
| 1046 | var file_reader = f.reader(&.{}); | |
| 1047 | file_reader.size = stat.size; | |
| 1048 | try file_reader.interface.readSliceAll(source); | |
| 1048 | 1049 | |
| 1049 | 1050 | // Here we do not modify stat fields because this function is the one |
| 1050 | 1051 | // used for error reporting. We need to keep the stat fields stale so that |
| ... | ... | @@ -1097,11 +1098,10 @@ pub const File = struct { |
| 1097 | 1098 | const gpa = pt.zcu.gpa; |
| 1098 | 1099 | const ip = &pt.zcu.intern_pool; |
| 1099 | 1100 | const strings = ip.getLocal(pt.tid).getMutableStrings(gpa); |
| 1100 | const slice = try strings.addManyAsSlice(file.fullyQualifiedNameLen()); | |
| 1101 | var fbs = std.io.fixedBufferStream(slice[0]); | |
| 1102 | file.renderFullyQualifiedName(fbs.writer()) catch unreachable; | |
| 1103 | assert(fbs.pos == slice[0].len); | |
| 1104 | return ip.getOrPutTrailingString(gpa, pt.tid, @intCast(slice[0].len), .no_embedded_nulls); | |
| 1101 | var w: Writer = .fixed((try strings.addManyAsSlice(file.fullyQualifiedNameLen()))[0]); | |
| 1102 | file.renderFullyQualifiedName(&w) catch unreachable; | |
| 1103 | assert(w.end == w.buffer.len); | |
| 1104 | return ip.getOrPutTrailingString(gpa, pt.tid, @intCast(w.end), .no_embedded_nulls); | |
| 1105 | 1105 | } |
| 1106 | 1106 | |
| 1107 | 1107 | pub const Index = InternPool.FileIndex; |
| ... | ... | @@ -1112,7 +1112,7 @@ pub const File = struct { |
| 1112 | 1112 | eb: *std.zig.ErrorBundle.Wip, |
| 1113 | 1113 | ) !std.zig.ErrorBundle.SourceLocationIndex { |
| 1114 | 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 | 1116 | .span_start = 0, |
| 1117 | 1117 | .span_main = 0, |
| 1118 | 1118 | .span_end = 0, |
| ... | ... | @@ -1133,7 +1133,7 @@ pub const File = struct { |
| 1133 | 1133 | const end = start + tree.tokenSlice(tok).len; |
| 1134 | 1134 | const loc = std.zig.findLineColumn(source.bytes, start); |
| 1135 | 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 | 1137 | .span_start = start, |
| 1138 | 1138 | .span_main = start, |
| 1139 | 1139 | .span_end = @intCast(end), |
| ... | ... | @@ -1190,13 +1190,8 @@ pub const ErrorMsg = struct { |
| 1190 | 1190 | gpa.destroy(err_msg); |
| 1191 | 1191 | } |
| 1192 | 1192 | |
| 1193 | pub fn init( | |
| 1194 | gpa: Allocator, | |
| 1195 | src_loc: LazySrcLoc, | |
| 1196 | comptime format: []const u8, | |
| 1197 | args: anytype, | |
| 1198 | ) !ErrorMsg { | |
| 1199 | return ErrorMsg{ | |
| 1193 | pub fn init(gpa: Allocator, src_loc: LazySrcLoc, comptime format: []const u8, args: anytype) !ErrorMsg { | |
| 1194 | return .{ | |
| 1200 | 1195 | .src_loc = src_loc, |
| 1201 | 1196 | .msg = try std.fmt.allocPrint(gpa, format, args), |
| 1202 | 1197 | }; |
| ... | ... | @@ -2811,10 +2806,18 @@ comptime { |
| 2811 | 2806 | } |
| 2812 | 2807 | |
| 2813 | 2808 | pub 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 | } |
| 2816 | 2819 | |
| 2817 | pub fn loadZirCacheBody(gpa: Allocator, header: Zir.Header, cache_file: std.fs.File) !Zir { | |
| 2820 | pub fn loadZirCacheBody(gpa: Allocator, header: Zir.Header, cache_br: *std.io.Reader) !Zir { | |
| 2818 | 2821 | var instructions: std.MultiArrayList(Zir.Inst) = .{}; |
| 2819 | 2822 | errdefer instructions.deinit(gpa); |
| 2820 | 2823 | |
| ... | ... | @@ -2837,34 +2840,16 @@ pub fn loadZirCacheBody(gpa: Allocator, header: Zir.Header, cache_file: std.fs.F |
| 2837 | 2840 | undefined; |
| 2838 | 2841 | defer if (data_has_safety_tag) gpa.free(safety_buffer); |
| 2839 | 2842 | |
| 2840 | const data_ptr = if (data_has_safety_tag) | |
| 2841 | @as([*]u8, @ptrCast(safety_buffer.ptr)) | |
| 2842 | else | |
| 2843 | @as([*]u8, @ptrCast(zir.instructions.items(.data).ptr)); | |
| 2844 | ||
| 2845 | var iovecs = [_]std.posix.iovec{ | |
| 2846 | .{ | |
| 2847 | .base = @as([*]u8, @ptrCast(zir.instructions.items(.tag).ptr)), | |
| 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 | }, | |
| 2843 | var vecs = [_][]u8{ | |
| 2844 | @ptrCast(zir.instructions.items(.tag)), | |
| 2845 | if (data_has_safety_tag) | |
| 2846 | @ptrCast(safety_buffer) | |
| 2847 | else | |
| 2848 | @ptrCast(zir.instructions.items(.data)), | |
| 2849 | zir.string_bytes, | |
| 2850 | @ptrCast(zir.extra), | |
| 2862 | 2851 | }; |
| 2863 | const amt_read = try cache_file.readvAll(&iovecs); | |
| 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; | |
| 2852 | try cache_br.readVecAll(&vecs); | |
| 2868 | 2853 | if (data_has_safety_tag) { |
| 2869 | 2854 | const tags = zir.instructions.items(.tag); |
| 2870 | 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 | 2861 | }; |
| 2877 | 2862 | } |
| 2878 | 2863 | } |
| 2879 | ||
| 2880 | 2864 | return zir; |
| 2881 | 2865 | } |
| 2882 | 2866 | |
| ... | ... | @@ -2887,14 +2871,6 @@ pub fn saveZirCache(gpa: Allocator, cache_file: std.fs.File, stat: std.fs.File.S |
| 2887 | 2871 | undefined; |
| 2888 | 2872 | defer if (data_has_safety_tag) gpa.free(safety_buffer); |
| 2889 | 2873 | |
| 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 | 2874 | if (data_has_safety_tag) { |
| 2899 | 2875 | // The `Data` union has a safety tag but in the file format we store it without. |
| 2900 | 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 | 2888 | .stat_inode = stat.inode, |
| 2913 | 2889 | .stat_mtime = stat.mtime, |
| 2914 | 2890 | }; |
| 2915 | var iovecs: [5]std.posix.iovec_const = .{ | |
| 2916 | .{ | |
| 2917 | .base = @ptrCast(&header), | |
| 2918 | .len = @sizeOf(Zir.Header), | |
| 2919 | }, | |
| 2920 | .{ | |
| 2921 | .base = @ptrCast(zir.instructions.items(.tag).ptr), | |
| 2922 | .len = zir.instructions.len, | |
| 2923 | }, | |
| 2924 | .{ | |
| 2925 | .base = data_ptr, | |
| 2926 | .len = zir.instructions.len * 8, | |
| 2927 | }, | |
| 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 | }, | |
| 2891 | var vecs = [_][]const u8{ | |
| 2892 | @ptrCast((&header)[0..1]), | |
| 2893 | @ptrCast(zir.instructions.items(.tag)), | |
| 2894 | if (data_has_safety_tag) | |
| 2895 | @ptrCast(safety_buffer) | |
| 2896 | else | |
| 2897 | @ptrCast(zir.instructions.items(.data)), | |
| 2898 | zir.string_bytes, | |
| 2899 | @ptrCast(zir.extra), | |
| 2900 | }; | |
| 2901 | var cache_fw = cache_file.writer(&.{}); | |
| 2902 | cache_fw.interface.writeVecAll(&vecs) catch |err| switch (err) { | |
| 2903 | error.WriteFailed => return cache_fw.err.?, | |
| 2936 | 2904 | }; |
| 2937 | try cache_file.writevAll(&iovecs); | |
| 2938 | 2905 | } |
| 2939 | 2906 | |
| 2940 | 2907 | pub 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 | 2917 | .stat_inode = stat.inode, |
| 2951 | 2918 | .stat_mtime = stat.mtime, |
| 2952 | 2919 | }; |
| 2953 | var iovecs: [9]std.posix.iovec_const = .{ | |
| 2954 | .{ | |
| 2955 | .base = @ptrCast(&header), | |
| 2956 | .len = @sizeOf(Zoir.Header), | |
| 2957 | }, | |
| 2958 | .{ | |
| 2959 | .base = @ptrCast(zoir.nodes.items(.tag)), | |
| 2960 | .len = zoir.nodes.len * @sizeOf(Zoir.Node.Repr.Tag), | |
| 2961 | }, | |
| 2962 | .{ | |
| 2963 | .base = @ptrCast(zoir.nodes.items(.data)), | |
| 2964 | .len = zoir.nodes.len * 4, | |
| 2965 | }, | |
| 2966 | .{ | |
| 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 | }, | |
| 2920 | var vecs = [_][]const u8{ | |
| 2921 | @ptrCast((&header)[0..1]), | |
| 2922 | @ptrCast(zoir.nodes.items(.tag)), | |
| 2923 | @ptrCast(zoir.nodes.items(.data)), | |
| 2924 | @ptrCast(zoir.nodes.items(.ast_node)), | |
| 2925 | @ptrCast(zoir.extra), | |
| 2926 | @ptrCast(zoir.limbs), | |
| 2927 | zoir.string_bytes, | |
| 2928 | @ptrCast(zoir.compile_errors), | |
| 2929 | @ptrCast(zoir.error_notes), | |
| 2930 | }; | |
| 2931 | var cache_fw = cache_file.writer(&.{}); | |
| 2932 | cache_fw.interface.writeVecAll(&vecs) catch |err| switch (err) { | |
| 2933 | error.WriteFailed => return cache_fw.err.?, | |
| 2990 | 2934 | }; |
| 2991 | try cache_file.writevAll(&iovecs); | |
| 2992 | 2935 | } |
| 2993 | 2936 | |
| 2994 | pub fn loadZoirCacheBody(gpa: Allocator, header: Zoir.Header, cache_file: std.fs.File) !Zoir { | |
| 2937 | pub fn loadZoirCacheBody(gpa: Allocator, header: Zoir.Header, cache_br: *std.io.Reader) !Zoir { | |
| 2995 | 2938 | var zoir: Zoir = .{ |
| 2996 | 2939 | .nodes = .empty, |
| 2997 | 2940 | .extra = &.{}, |
| ... | ... | @@ -3017,49 +2960,17 @@ pub fn loadZoirCacheBody(gpa: Allocator, header: Zoir.Header, cache_file: std.fs |
| 3017 | 2960 | zoir.compile_errors = try gpa.alloc(Zoir.CompileError, header.compile_errors_len); |
| 3018 | 2961 | zoir.error_notes = try gpa.alloc(Zoir.CompileError.Note, header.error_notes_len); |
| 3019 | 2962 | |
| 3020 | var iovecs: [8]std.posix.iovec = .{ | |
| 3021 | .{ | |
| 3022 | .base = @ptrCast(zoir.nodes.items(.tag)), | |
| 3023 | .len = header.nodes_len * @sizeOf(Zoir.Node.Repr.Tag), | |
| 3024 | }, | |
| 3025 | .{ | |
| 3026 | .base = @ptrCast(zoir.nodes.items(.data)), | |
| 3027 | .len = header.nodes_len * 4, | |
| 3028 | }, | |
| 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; | |
| 2963 | var vecs = [_][]u8{ | |
| 2964 | @ptrCast(zoir.nodes.items(.tag)), | |
| 2965 | @ptrCast(zoir.nodes.items(.data)), | |
| 2966 | @ptrCast(zoir.nodes.items(.ast_node)), | |
| 2967 | @ptrCast(zoir.extra), | |
| 2968 | @ptrCast(zoir.limbs), | |
| 2969 | zoir.string_bytes, | |
| 2970 | @ptrCast(zoir.compile_errors), | |
| 2971 | @ptrCast(zoir.error_notes), | |
| 3059 | 2972 | }; |
| 3060 | ||
| 3061 | const bytes_read = try cache_file.readvAll(&iovecs); | |
| 3062 | if (bytes_read != bytes_expected) return error.UnexpectedFileSize; | |
| 2973 | try cache_br.readVecAll(&vecs); | |
| 3063 | 2974 | return zoir; |
| 3064 | 2975 | } |
| 3065 | 2976 | |
| ... | ... | @@ -3071,7 +2982,7 @@ pub fn markDependeeOutdated( |
| 3071 | 2982 | marked_po: enum { not_marked_po, marked_po }, |
| 3072 | 2983 | dependee: InternPool.Dependee, |
| 3073 | 2984 | ) !void { |
| 3074 | log.debug("outdated dependee: {}", .{zcu.fmtDependee(dependee)}); | |
| 2985 | log.debug("outdated dependee: {f}", .{zcu.fmtDependee(dependee)}); | |
| 3075 | 2986 | var it = zcu.intern_pool.dependencyIterator(dependee); |
| 3076 | 2987 | while (it.next()) |depender| { |
| 3077 | 2988 | if (zcu.outdated.getPtr(depender)) |po_dep_count| { |
| ... | ... | @@ -3079,9 +2990,9 @@ pub fn markDependeeOutdated( |
| 3079 | 2990 | .not_marked_po => {}, |
| 3080 | 2991 | .marked_po => { |
| 3081 | 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 | 2994 | if (po_dep_count.* == 0) { |
| 3084 | log.debug("outdated ready: {}", .{zcu.fmtAnalUnit(depender)}); | |
| 2995 | log.debug("outdated ready: {f}", .{zcu.fmtAnalUnit(depender)}); | |
| 3085 | 2996 | try zcu.outdated_ready.put(zcu.gpa, depender, {}); |
| 3086 | 2997 | } |
| 3087 | 2998 | }, |
| ... | ... | @@ -3102,9 +3013,9 @@ pub fn markDependeeOutdated( |
| 3102 | 3013 | depender, |
| 3103 | 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 | 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 | 3019 | try zcu.outdated_ready.put(zcu.gpa, depender, {}); |
| 3109 | 3020 | } |
| 3110 | 3021 | // If this is a Decl and was not previously PO, we must recursively |
| ... | ... | @@ -3117,16 +3028,16 @@ pub fn markDependeeOutdated( |
| 3117 | 3028 | } |
| 3118 | 3029 | |
| 3119 | 3030 | pub 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 | 3032 | var it = zcu.intern_pool.dependencyIterator(dependee); |
| 3122 | 3033 | while (it.next()) |depender| { |
| 3123 | 3034 | if (zcu.outdated.getPtr(depender)) |po_dep_count| { |
| 3124 | 3035 | // This depender is already outdated, but it now has one |
| 3125 | 3036 | // less PO dependency! |
| 3126 | 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 | 3039 | if (po_dep_count.* == 0) { |
| 3129 | log.debug("outdated ready: {}", .{zcu.fmtAnalUnit(depender)}); | |
| 3040 | log.debug("outdated ready: {f}", .{zcu.fmtAnalUnit(depender)}); | |
| 3130 | 3041 | try zcu.outdated_ready.put(zcu.gpa, depender, {}); |
| 3131 | 3042 | } |
| 3132 | 3043 | continue; |
| ... | ... | @@ -3140,11 +3051,11 @@ pub fn markPoDependeeUpToDate(zcu: *Zcu, dependee: InternPool.Dependee) !void { |
| 3140 | 3051 | }; |
| 3141 | 3052 | if (ptr.* > 1) { |
| 3142 | 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 | 3055 | continue; |
| 3145 | 3056 | } |
| 3146 | 3057 | |
| 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) }); | |
| 3148 | 3059 | |
| 3149 | 3060 | // This dependency is no longer PO, i.e. is known to be up-to-date. |
| 3150 | 3061 | assert(zcu.potentially_outdated.swapRemove(depender)); |
| ... | ... | @@ -3173,7 +3084,7 @@ fn markTransitiveDependersPotentiallyOutdated(zcu: *Zcu, maybe_outdated: AnalUni |
| 3173 | 3084 | .func => |func_index| .{ .interned = func_index }, // IES |
| 3174 | 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 | 3088 | var it = ip.dependencyIterator(dependee); |
| 3178 | 3089 | while (it.next()) |po| { |
| 3179 | 3090 | if (zcu.outdated.getPtr(po)) |po_dep_count| { |
| ... | ... | @@ -3183,17 +3094,17 @@ fn markTransitiveDependersPotentiallyOutdated(zcu: *Zcu, maybe_outdated: AnalUni |
| 3183 | 3094 | _ = zcu.outdated_ready.swapRemove(po); |
| 3184 | 3095 | } |
| 3185 | 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 | 3098 | continue; |
| 3188 | 3099 | } |
| 3189 | 3100 | if (zcu.potentially_outdated.getPtr(po)) |n| { |
| 3190 | 3101 | // There is now one more PO dependency. |
| 3191 | 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 | 3104 | continue; |
| 3194 | 3105 | } |
| 3195 | 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 | 3108 | // This AnalUnit was not already PO, so we must recursively mark its dependers as also PO. |
| 3198 | 3109 | try zcu.markTransitiveDependersPotentiallyOutdated(po); |
| 3199 | 3110 | } |
| ... | ... | @@ -3222,7 +3133,7 @@ pub fn findOutdatedToAnalyze(zcu: *Zcu) Allocator.Error!?AnalUnit { |
| 3222 | 3133 | |
| 3223 | 3134 | if (zcu.outdated_ready.count() > 0) { |
| 3224 | 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 | 3137 | return unit; |
| 3227 | 3138 | } |
| 3228 | 3139 | |
| ... | ... | @@ -3273,7 +3184,7 @@ pub fn findOutdatedToAnalyze(zcu: *Zcu) Allocator.Error!?AnalUnit { |
| 3273 | 3184 | } |
| 3274 | 3185 | } |
| 3275 | 3186 | |
| 3276 | log.debug("findOutdatedToAnalyze: heuristic returned '{}' ({d} dependers)", .{ | |
| 3187 | log.debug("findOutdatedToAnalyze: heuristic returned '{f}' ({d} dependers)", .{ | |
| 3277 | 3188 | zcu.fmtAnalUnit(chosen_unit.?), |
| 3278 | 3189 | chosen_unit_dependers, |
| 3279 | 3190 | }); |
| ... | ... | @@ -4072,7 +3983,7 @@ fn resolveReferencesInner(zcu: *Zcu) !std.AutoHashMapUnmanaged(AnalUnit, ?Resolv |
| 4072 | 3983 | const referencer = kv.value; |
| 4073 | 3984 | try checked_types.putNoClobber(gpa, ty, {}); |
| 4074 | 3985 | |
| 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)}); | |
| 4076 | 3987 | |
| 4077 | 3988 | // If this type undergoes type resolution, the corresponding `AnalUnit` is automatically referenced. |
| 4078 | 3989 | const has_resolution: bool = switch (ip.indexToKey(ty)) { |
| ... | ... | @@ -4108,7 +4019,7 @@ fn resolveReferencesInner(zcu: *Zcu) !std.AutoHashMapUnmanaged(AnalUnit, ?Resolv |
| 4108 | 4019 | // `comptime` decls are always analyzed. |
| 4109 | 4020 | const unit: AnalUnit = .wrap(.{ .@"comptime" = cu }); |
| 4110 | 4021 | if (!result.contains(unit)) { |
| 4111 | log.debug("type '{}': ref comptime %{}", .{ | |
| 4022 | log.debug("type '{f}': ref comptime %{}", .{ | |
| 4112 | 4023 | Type.fromInterned(ty).containerTypeName(ip).fmt(ip), |
| 4113 | 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 | 4050 | }, |
| 4140 | 4051 | }; |
| 4141 | 4052 | if (want_analysis) { |
| 4142 | log.debug("type '{}': ref test %{}", .{ | |
| 4053 | log.debug("type '{f}': ref test %{}", .{ | |
| 4143 | 4054 | Type.fromInterned(ty).containerTypeName(ip).fmt(ip), |
| 4144 | 4055 | @intFromEnum(inst_info.inst), |
| 4145 | 4056 | }); |
| ... | ... | @@ -4158,7 +4069,7 @@ fn resolveReferencesInner(zcu: *Zcu) !std.AutoHashMapUnmanaged(AnalUnit, ?Resolv |
| 4158 | 4069 | if (decl.linkage == .@"export") { |
| 4159 | 4070 | const unit: AnalUnit = .wrap(.{ .nav_val = nav }); |
| 4160 | 4071 | if (!result.contains(unit)) { |
| 4161 | log.debug("type '{}': ref named %{}", .{ | |
| 4072 | log.debug("type '{f}': ref named %{}", .{ | |
| 4162 | 4073 | Type.fromInterned(ty).containerTypeName(ip).fmt(ip), |
| 4163 | 4074 | @intFromEnum(inst_info.inst), |
| 4164 | 4075 | }); |
| ... | ... | @@ -4174,7 +4085,7 @@ fn resolveReferencesInner(zcu: *Zcu) !std.AutoHashMapUnmanaged(AnalUnit, ?Resolv |
| 4174 | 4085 | if (decl.linkage == .@"export") { |
| 4175 | 4086 | const unit: AnalUnit = .wrap(.{ .nav_val = nav }); |
| 4176 | 4087 | if (!result.contains(unit)) { |
| 4177 | log.debug("type '{}': ref named %{}", .{ | |
| 4088 | log.debug("type '{f}': ref named %{}", .{ | |
| 4178 | 4089 | Type.fromInterned(ty).containerTypeName(ip).fmt(ip), |
| 4179 | 4090 | @intFromEnum(inst_info.inst), |
| 4180 | 4091 | }); |
| ... | ... | @@ -4199,7 +4110,7 @@ fn resolveReferencesInner(zcu: *Zcu) !std.AutoHashMapUnmanaged(AnalUnit, ?Resolv |
| 4199 | 4110 | try unit_queue.put(gpa, other, kv.value); // same reference location |
| 4200 | 4111 | } |
| 4201 | 4112 | |
| 4202 | log.debug("handle unit '{}'", .{zcu.fmtAnalUnit(unit)}); | |
| 4113 | log.debug("handle unit '{f}'", .{zcu.fmtAnalUnit(unit)}); | |
| 4203 | 4114 | |
| 4204 | 4115 | if (zcu.reference_table.get(unit)) |first_ref_idx| { |
| 4205 | 4116 | assert(first_ref_idx != std.math.maxInt(u32)); |
| ... | ... | @@ -4207,7 +4118,7 @@ fn resolveReferencesInner(zcu: *Zcu) !std.AutoHashMapUnmanaged(AnalUnit, ?Resolv |
| 4207 | 4118 | while (ref_idx != std.math.maxInt(u32)) { |
| 4208 | 4119 | const ref = zcu.all_references.items[ref_idx]; |
| 4209 | 4120 | if (!result.contains(ref.referenced)) { |
| 4210 | log.debug("unit '{}': ref unit '{}'", .{ | |
| 4121 | log.debug("unit '{f}': ref unit '{f}'", .{ | |
| 4211 | 4122 | zcu.fmtAnalUnit(unit), |
| 4212 | 4123 | zcu.fmtAnalUnit(ref.referenced), |
| 4213 | 4124 | }); |
| ... | ... | @@ -4226,7 +4137,7 @@ fn resolveReferencesInner(zcu: *Zcu) !std.AutoHashMapUnmanaged(AnalUnit, ?Resolv |
| 4226 | 4137 | while (ref_idx != std.math.maxInt(u32)) { |
| 4227 | 4138 | const ref = zcu.all_type_references.items[ref_idx]; |
| 4228 | 4139 | if (!checked_types.contains(ref.referenced)) { |
| 4229 | log.debug("unit '{}': ref type '{}'", .{ | |
| 4140 | log.debug("unit '{f}': ref type '{f}'", .{ | |
| 4230 | 4141 | zcu.fmtAnalUnit(unit), |
| 4231 | 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 | 4218 | return zcu.fileByIndex(zcu.navFileScopeIndex(nav)); |
| 4308 | 4219 | } |
| 4309 | 4220 | |
| 4310 | pub fn fmtAnalUnit(zcu: *Zcu, unit: AnalUnit) std.fmt.Formatter(formatAnalUnit) { | |
| 4221 | pub fn fmtAnalUnit(zcu: *Zcu, unit: AnalUnit) std.fmt.Formatter(FormatAnalUnit, formatAnalUnit) { | |
| 4311 | 4222 | return .{ .data = .{ .unit = unit, .zcu = zcu } }; |
| 4312 | 4223 | } |
| 4313 | pub fn fmtDependee(zcu: *Zcu, d: InternPool.Dependee) std.fmt.Formatter(formatDependee) { | |
| 4224 | pub fn fmtDependee(zcu: *Zcu, d: InternPool.Dependee) std.fmt.Formatter(FormatDependee, formatDependee) { | |
| 4314 | 4225 | return .{ .data = .{ .dependee = d, .zcu = zcu } }; |
| 4315 | 4226 | } |
| 4316 | 4227 | |
| 4317 | fn formatAnalUnit(data: struct { unit: AnalUnit, zcu: *Zcu }, comptime fmt: []const u8, options: std.fmt.FormatOptions, writer: anytype) !void { | |
| 4318 | _ = .{ fmt, options }; | |
| 4228 | const FormatAnalUnit = struct { | |
| 4229 | unit: AnalUnit, | |
| 4230 | zcu: *Zcu, | |
| 4231 | }; | |
| 4232 | ||
| 4233 | fn formatAnalUnit(data: FormatAnalUnit, writer: *std.io.Writer) std.io.Writer.Error!void { | |
| 4319 | 4234 | const zcu = data.zcu; |
| 4320 | 4235 | const ip = &zcu.intern_pool; |
| 4321 | 4236 | switch (data.unit.unwrap()) { |
| ... | ... | @@ -4323,23 +4238,25 @@ fn formatAnalUnit(data: struct { unit: AnalUnit, zcu: *Zcu }, comptime fmt: []co |
| 4323 | 4238 | const cu = ip.getComptimeUnit(cu_id); |
| 4324 | 4239 | if (cu.zir_index.resolveFull(ip)) |resolved| { |
| 4325 | 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 | 4242 | } else { |
| 4328 | 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) }), | |
| 4332 | .nav_ty => |nav| return writer.print("nav_ty('{}' [{}])", .{ ip.getNav(nav).fqn.fmt(ip), @intFromEnum(nav) }), | |
| 4333 | .type => |ty| return writer.print("ty('{}' [{}])", .{ Type.fromInterned(ty).containerTypeName(ip).fmt(ip), @intFromEnum(ty) }), | |
| 4246 | .nav_val => |nav| return writer.print("nav_val('{f}' [{}])", .{ 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) }), | |
| 4248 | .type => |ty| return writer.print("ty('{f}' [{}])", .{ Type.fromInterned(ty).containerTypeName(ip).fmt(ip), @intFromEnum(ty) }), | |
| 4334 | 4249 | .func => |func| { |
| 4335 | 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 | 4253 | .memoized_state => return writer.writeAll("memoized_state"), |
| 4339 | 4254 | } |
| 4340 | 4255 | } |
| 4341 | fn formatDependee(data: struct { dependee: InternPool.Dependee, zcu: *Zcu }, comptime fmt: []const u8, options: std.fmt.FormatOptions, writer: anytype) !void { | |
| 4342 | _ = .{ fmt, options }; | |
| 4256 | ||
| 4257 | const FormatDependee = struct { dependee: InternPool.Dependee, zcu: *Zcu }; | |
| 4258 | ||
| 4259 | fn formatDependee(data: FormatDependee, writer: *std.io.Writer) std.io.Writer.Error!void { | |
| 4343 | 4260 | const zcu = data.zcu; |
| 4344 | 4261 | const ip = &zcu.intern_pool; |
| 4345 | 4262 | switch (data.dependee) { |
| ... | ... | @@ -4348,42 +4265,42 @@ fn formatDependee(data: struct { dependee: InternPool.Dependee, zcu: *Zcu }, com |
| 4348 | 4265 | return writer.writeAll("inst(<lost>)"); |
| 4349 | 4266 | }; |
| 4350 | 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 | 4270 | .nav_val => |nav| { |
| 4354 | 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 | 4274 | .nav_ty => |nav| { |
| 4358 | 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 | 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)}), | |
| 4363 | .func => |f| return writer.print("ies('{}')", .{ip.getNav(f.owner_nav).fqn.fmt(ip)}), | |
| 4279 | .struct_type, .union_type, .enum_type => return writer.print("type('{f}')", .{Type.fromInterned(ip_index).containerTypeName(ip).fmt(ip)}), | |
| 4280 | .func => |f| return writer.print("ies('{f}')", .{ip.getNav(f.owner_nav).fqn.fmt(ip)}), | |
| 4364 | 4281 | else => unreachable, |
| 4365 | 4282 | }, |
| 4366 | 4283 | .zon_file => |file| { |
| 4367 | 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 | 4287 | .embed_file => |ef_idx| { |
| 4371 | 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 | 4291 | .namespace => |ti| { |
| 4375 | 4292 | const info = ti.resolveFull(ip) orelse { |
| 4376 | 4293 | return writer.writeAll("namespace(<lost>)"); |
| 4377 | 4294 | }; |
| 4378 | 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 | 4298 | .namespace_name => |k| { |
| 4382 | 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 | 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 | 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 | 53 | const zcu = pt.zcu; |
| 54 | 54 | const gpa = zcu.gpa; |
| 55 | 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 | 57 | file.path.deinit(gpa); |
| 58 | 58 | file.unload(gpa); |
| 59 | 59 | if (file.prev_zir) |prev_zir| { |
| ... | ... | @@ -117,7 +117,7 @@ pub fn updateFile( |
| 117 | 117 | var lock: std.fs.File.Lock = switch (file.status) { |
| 118 | 118 | .never_loaded, .retryable_failure => lock: { |
| 119 | 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 | 121 | file.path.fmt(comp), want_local_cache, &hex_digest, |
| 122 | 122 | }); |
| 123 | 123 | |
| ... | ... | @@ -130,11 +130,11 @@ pub fn updateFile( |
| 130 | 130 | stat.inode == file.stat.inode; |
| 131 | 131 | |
| 132 | 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 | 134 | return; |
| 135 | 135 | } |
| 136 | 136 | |
| 137 | log.debug("metadata changed: {}", .{file.path.fmt(comp)}); | |
| 137 | log.debug("metadata changed: {f}", .{file.path.fmt(comp)}); | |
| 138 | 138 | |
| 139 | 139 | break :lock .exclusive; |
| 140 | 140 | }, |
| ... | ... | @@ -190,7 +190,7 @@ pub fn updateFile( |
| 190 | 190 | // failure was a race, or ENOENT, indicating deletion of the |
| 191 | 191 | // directory of our open handle. |
| 192 | 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 | 194 | cache_directory, |
| 195 | 195 | }); |
| 196 | 196 | } |
| ... | ... | @@ -202,7 +202,7 @@ pub fn updateFile( |
| 202 | 202 | }) catch |excl_err| switch (excl_err) { |
| 203 | 203 | error.PathAlreadyExists => continue, |
| 204 | 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 | 206 | cache_directory, |
| 207 | 207 | }); |
| 208 | 208 | }, |
| ... | ... | @@ -221,12 +221,12 @@ pub fn updateFile( |
| 221 | 221 | }; |
| 222 | 222 | switch (result) { |
| 223 | 223 | .success => { |
| 224 | log.debug("AstGen cached success: {}", .{file.path.fmt(comp)}); | |
| 224 | log.debug("AstGen cached success: {f}", .{file.path.fmt(comp)}); | |
| 225 | 225 | break false; |
| 226 | 226 | }, |
| 227 | 227 | .invalid => {}, |
| 228 | .truncated => log.warn("unexpected EOF reading cached ZIR for {}", .{file.path.fmt(comp)}), | |
| 229 | .stale => log.debug("AstGen cache stale: {}", .{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: {f}", .{file.path.fmt(comp)}), | |
| 230 | 230 | } |
| 231 | 231 | |
| 232 | 232 | // If we already have the exclusive lock then it is our job to update. |
| ... | ... | @@ -249,11 +249,14 @@ pub fn updateFile( |
| 249 | 249 | if (stat.size > std.math.maxInt(u32)) |
| 250 | 250 | return error.FileTooBig; |
| 251 | 251 | |
| 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 | 253 | defer if (file.source == null) gpa.free(source); |
| 254 | const amt = try source_file.readAll(source); | |
| 255 | if (amt != stat.size) | |
| 256 | return error.UnexpectedEndOfFile; | |
| 254 | var source_fr = source_file.reader(&.{}); | |
| 255 | source_fr.size = stat.size; | |
| 256 | source_fr.interface.readSliceAll(source) catch |err| switch (err) { | |
| 257 | error.ReadFailed => return source_fr.err.?, | |
| 258 | error.EndOfStream => return error.UnexpectedEndOfFile, | |
| 259 | }; | |
| 257 | 260 | |
| 258 | 261 | file.source = source; |
| 259 | 262 | |
| ... | ... | @@ -265,7 +268,7 @@ pub fn updateFile( |
| 265 | 268 | file.zir = try AstGen.generate(gpa, file.tree.?); |
| 266 | 269 | Zcu.saveZirCache(gpa, cache_file, stat, file.zir.?) catch |err| switch (err) { |
| 267 | 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 | 272 | file.path.fmt(comp), cache_directory, &hex_digest, @errorName(err), |
| 270 | 273 | }), |
| 271 | 274 | }; |
| ... | ... | @@ -273,14 +276,14 @@ pub fn updateFile( |
| 273 | 276 | .zon => { |
| 274 | 277 | file.zoir = try ZonGen.generate(gpa, file.tree.?, .{}); |
| 275 | 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 | 280 | file.path.fmt(comp), cache_directory, &hex_digest, @errorName(err), |
| 278 | 281 | }); |
| 279 | 282 | }; |
| 280 | 283 | }, |
| 281 | 284 | } |
| 282 | 285 | |
| 283 | log.debug("AstGen fresh success: {}", .{file.path.fmt(comp)}); | |
| 286 | log.debug("AstGen fresh success: {f}", .{file.path.fmt(comp)}); | |
| 284 | 287 | } |
| 285 | 288 | |
| 286 | 289 | file.stat = .{ |
| ... | ... | @@ -340,13 +343,19 @@ fn loadZirZoirCache( |
| 340 | 343 | .zon => Zoir.Header, |
| 341 | 344 | }; |
| 342 | 345 | |
| 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 | 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 | 354 | // This can happen if Zig bails out of this function between creating |
| 346 | 355 | // the cached file and writing it. |
| 347 | 356 | error.EndOfStream => return .invalid, |
| 348 | 357 | else => |e| return e, |
| 349 | }; | |
| 358 | }).*; | |
| 350 | 359 | |
| 351 | 360 | const unchanged_metadata = |
| 352 | 361 | stat.size == header.stat_size and |
| ... | ... | @@ -358,17 +367,15 @@ fn loadZirZoirCache( |
| 358 | 367 | } |
| 359 | 368 | |
| 360 | 369 | switch (mode) { |
| 361 | .zig => { | |
| 362 | file.zir = Zcu.loadZirCacheBody(gpa, header, cache_file) catch |err| switch (err) { | |
| 363 | error.UnexpectedFileSize => return .truncated, | |
| 364 | else => |e| return e, | |
| 365 | }; | |
| 370 | .zig => file.zir = Zcu.loadZirCacheBody(gpa, header, cache_br) catch |err| switch (err) { | |
| 371 | error.ReadFailed => return cache_fr.err.?, | |
| 372 | error.EndOfStream => return .truncated, | |
| 373 | else => |e| return e, | |
| 366 | 374 | }, |
| 367 | .zon => { | |
| 368 | file.zoir = Zcu.loadZoirCacheBody(gpa, header, cache_file) catch |err| switch (err) { | |
| 369 | error.UnexpectedFileSize => return .truncated, | |
| 370 | else => |e| return e, | |
| 371 | }; | |
| 375 | .zon => file.zoir = Zcu.loadZoirCacheBody(gpa, header, cache_br) catch |err| switch (err) { | |
| 376 | error.ReadFailed => return cache_fr.err.?, | |
| 377 | error.EndOfStream => return .truncated, | |
| 378 | else => |e| return e, | |
| 372 | 379 | }, |
| 373 | 380 | } |
| 374 | 381 | |
| ... | ... | @@ -477,11 +484,8 @@ pub fn updateZirRefs(pt: Zcu.PerThread) Allocator.Error!void { |
| 477 | 484 | if (std.zig.srcHashEql(old_hash, new_hash)) { |
| 478 | 485 | break :hash_changed; |
| 479 | 486 | } |
| 480 | log.debug("hash for (%{d} -> %{d}) changed: {} -> {}", .{ | |
| 481 | old_inst, | |
| 482 | new_inst, | |
| 483 | std.fmt.fmtSliceHexLower(&old_hash), | |
| 484 | std.fmt.fmtSliceHexLower(&new_hash), | |
| 487 | log.debug("hash for (%{d} -> %{d}) changed: {x} -> {x}", .{ | |
| 488 | old_inst, new_inst, &old_hash, &new_hash, | |
| 485 | 489 | }); |
| 486 | 490 | } |
| 487 | 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 | 653 | // If this unit caused the error, it would have an entry in `failed_analysis`. |
| 650 | 654 | // Since it does not, this must be a transitive failure. |
| 651 | 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 | 658 | break :res .{ !prev_failed, true }; |
| 655 | 659 | }, |
| ... | ... | @@ -754,7 +758,7 @@ pub fn ensureComptimeUnitUpToDate(pt: Zcu.PerThread, cu_id: InternPool.ComptimeU |
| 754 | 758 | |
| 755 | 759 | const anal_unit: AnalUnit = .wrap(.{ .@"comptime" = cu_id }); |
| 756 | 760 | |
| 757 | log.debug("ensureComptimeUnitUpToDate {}", .{zcu.fmtAnalUnit(anal_unit)}); | |
| 761 | log.debug("ensureComptimeUnitUpToDate {f}", .{zcu.fmtAnalUnit(anal_unit)}); | |
| 758 | 762 | |
| 759 | 763 | assert(!zcu.analysis_in_progress.contains(anal_unit)); |
| 760 | 764 | |
| ... | ... | @@ -805,7 +809,7 @@ pub fn ensureComptimeUnitUpToDate(pt: Zcu.PerThread, cu_id: InternPool.ComptimeU |
| 805 | 809 | // If this unit caused the error, it would have an entry in `failed_analysis`. |
| 806 | 810 | // Since it does not, this must be a transitive failure. |
| 807 | 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 | 814 | return error.AnalysisFail; |
| 811 | 815 | }, |
| ... | ... | @@ -835,7 +839,7 @@ fn analyzeComptimeUnit(pt: Zcu.PerThread, cu_id: InternPool.ComptimeUnit.Id) Zcu |
| 835 | 839 | const anal_unit: AnalUnit = .wrap(.{ .@"comptime" = cu_id }); |
| 836 | 840 | const comptime_unit = ip.getComptimeUnit(cu_id); |
| 837 | 841 | |
| 838 | log.debug("analyzeComptimeUnit {}", .{zcu.fmtAnalUnit(anal_unit)}); | |
| 842 | log.debug("analyzeComptimeUnit {f}", .{zcu.fmtAnalUnit(anal_unit)}); | |
| 839 | 843 | |
| 840 | 844 | const inst_resolved = comptime_unit.zir_index.resolveFull(ip) orelse return error.AnalysisFail; |
| 841 | 845 | const file = zcu.fileByIndex(inst_resolved.file); |
| ... | ... | @@ -881,7 +885,7 @@ fn analyzeComptimeUnit(pt: Zcu.PerThread, cu_id: InternPool.ComptimeUnit.Id) Zcu |
| 881 | 885 | .r = .{ .simple = .comptime_keyword }, |
| 882 | 886 | } }, |
| 883 | 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 | 889 | Type.fromInterned(zcu.namespacePtr(comptime_unit.namespace).owner_type).containerTypeName(ip).fmt(ip), |
| 886 | 890 | }, .no_embedded_nulls), |
| 887 | 891 | }; |
| ... | ... | @@ -933,7 +937,7 @@ pub fn ensureNavValUpToDate(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu |
| 933 | 937 | const anal_unit: AnalUnit = .wrap(.{ .nav_val = nav_id }); |
| 934 | 938 | const nav = ip.getNav(nav_id); |
| 935 | 939 | |
| 936 | log.debug("ensureNavValUpToDate {}", .{zcu.fmtAnalUnit(anal_unit)}); | |
| 940 | log.debug("ensureNavValUpToDate {f}", .{zcu.fmtAnalUnit(anal_unit)}); | |
| 937 | 941 | |
| 938 | 942 | // Determine whether or not this `Nav`'s value is outdated. This also includes checking if the |
| 939 | 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 | 995 | // If this unit caused the error, it would have an entry in `failed_analysis`. |
| 992 | 996 | // Since it does not, this must be a transitive failure. |
| 993 | 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 | 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 | 1066 | const anal_unit: AnalUnit = .wrap(.{ .nav_val = nav_id }); |
| 1063 | 1067 | const old_nav = ip.getNav(nav_id); |
| 1064 | 1068 | |
| 1065 | log.debug("analyzeNavVal {}", .{zcu.fmtAnalUnit(anal_unit)}); | |
| 1069 | log.debug("analyzeNavVal {f}", .{zcu.fmtAnalUnit(anal_unit)}); | |
| 1066 | 1070 | |
| 1067 | 1071 | const inst_resolved = old_nav.analysis.?.zir_index.resolveFull(ip) orelse return error.AnalysisFail; |
| 1068 | 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 | 1325 | const anal_unit: AnalUnit = .wrap(.{ .nav_ty = nav_id }); |
| 1322 | 1326 | const nav = ip.getNav(nav_id); |
| 1323 | 1327 | |
| 1324 | log.debug("ensureNavTypeUpToDate {}", .{zcu.fmtAnalUnit(anal_unit)}); | |
| 1328 | log.debug("ensureNavTypeUpToDate {f}", .{zcu.fmtAnalUnit(anal_unit)}); | |
| 1325 | 1329 | |
| 1326 | 1330 | const type_resolved_by_value: bool = from_val: { |
| 1327 | 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 | 1395 | // If this unit caused the error, it would have an entry in `failed_analysis`. |
| 1392 | 1396 | // Since it does not, this must be a transitive failure. |
| 1393 | 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 | 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 | 1437 | const anal_unit: AnalUnit = .wrap(.{ .nav_ty = nav_id }); |
| 1434 | 1438 | const old_nav = ip.getNav(nav_id); |
| 1435 | 1439 | |
| 1436 | log.debug("analyzeNavType {}", .{zcu.fmtAnalUnit(anal_unit)}); | |
| 1440 | log.debug("analyzeNavType {f}", .{zcu.fmtAnalUnit(anal_unit)}); | |
| 1437 | 1441 | |
| 1438 | 1442 | const inst_resolved = old_nav.analysis.?.zir_index.resolveFull(ip) orelse return error.AnalysisFail; |
| 1439 | 1443 | const file = zcu.fileByIndex(inst_resolved.file); |
| ... | ... | @@ -1563,7 +1567,7 @@ pub fn ensureFuncBodyUpToDate(pt: Zcu.PerThread, maybe_coerced_func_index: Inter |
| 1563 | 1567 | const func_index = ip.unwrapCoercedFunc(maybe_coerced_func_index); |
| 1564 | 1568 | const anal_unit: AnalUnit = .wrap(.{ .func = func_index }); |
| 1565 | 1569 | |
| 1566 | log.debug("ensureFuncBodyUpToDate {}", .{zcu.fmtAnalUnit(anal_unit)}); | |
| 1570 | log.debug("ensureFuncBodyUpToDate {f}", .{zcu.fmtAnalUnit(anal_unit)}); | |
| 1567 | 1571 | |
| 1568 | 1572 | const func = zcu.funcInfo(maybe_coerced_func_index); |
| 1569 | 1573 | |
| ... | ... | @@ -1607,7 +1611,7 @@ pub fn ensureFuncBodyUpToDate(pt: Zcu.PerThread, maybe_coerced_func_index: Inter |
| 1607 | 1611 | // If this function caused the error, it would have an entry in `failed_analysis`. |
| 1608 | 1612 | // Since it does not, this must be a transitive failure. |
| 1609 | 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 | 1616 | // We consider the IES to be outdated if the function previously succeeded analysis; in this case, |
| 1613 | 1617 | // we need to re-analyze dependants to ensure they hit a transitive error here, rather than reporting |
| ... | ... | @@ -1677,7 +1681,7 @@ fn analyzeFuncBody( |
| 1677 | 1681 | else |
| 1678 | 1682 | .none; |
| 1679 | 1683 | |
| 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)}); | |
| 1681 | 1685 | |
| 1682 | 1686 | var air = try pt.analyzeFnBodyInner(func_index); |
| 1683 | 1687 | errdefer air.deinit(gpa); |
| ... | ... | @@ -2299,7 +2303,7 @@ pub fn updateBuiltinModule(pt: Zcu.PerThread, opts: Builtin) Allocator.Error!voi |
| 2299 | 2303 | |
| 2300 | 2304 | Builtin.updateFileOnDisk(file, comp) catch |err| comp.setMiscFailure( |
| 2301 | 2305 | .write_builtin_zig, |
| 2302 | "unable to write '{}': {s}", | |
| 2306 | "unable to write '{f}': {s}", | |
| 2303 | 2307 | .{ file.path.fmt(comp), @errorName(err) }, |
| 2304 | 2308 | ); |
| 2305 | 2309 | } |
| ... | ... | @@ -2414,8 +2418,12 @@ fn updateEmbedFileInner( |
| 2414 | 2418 | const old_len = strings.mutate.len; |
| 2415 | 2419 | errdefer strings.shrinkRetainingCapacity(old_len); |
| 2416 | 2420 | const bytes = (try strings.addManyAsSlice(size_plus_one))[0]; |
| 2417 | const actual_read = try file.readAll(bytes[0..size]); | |
| 2418 | if (actual_read != size) return error.UnexpectedEof; | |
| 2421 | var fr = file.reader(&.{}); | |
| 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 | 2427 | bytes[size] = 0; |
| 2420 | 2428 | break :str try ip.getOrPutTrailingString(gpa, tid, @intCast(bytes.len), .maybe_embedded_nulls); |
| 2421 | 2429 | }; |
| ... | ... | @@ -2584,7 +2592,7 @@ const ScanDeclIter = struct { |
| 2584 | 2592 | var gop = try iter.seen_decls.getOrPut(gpa, name); |
| 2585 | 2593 | var next_suffix: u32 = 0; |
| 2586 | 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 | 2596 | gop = try iter.seen_decls.getOrPut(gpa, name); |
| 2589 | 2597 | next_suffix += 1; |
| 2590 | 2598 | } |
| ... | ... | @@ -2716,7 +2724,7 @@ const ScanDeclIter = struct { |
| 2716 | 2724 | |
| 2717 | 2725 | if (existing_unit == null and (want_analysis or decl.linkage == .@"export")) { |
| 2718 | 2726 | log.debug( |
| 2719 | "scanDecl queue analyze_comptime_unit file='{s}' unit={}", | |
| 2727 | "scanDecl queue analyze_comptime_unit file='{s}' unit={f}", | |
| 2720 | 2728 | .{ namespace.fileScope(zcu).sub_file_path, zcu.fmtAnalUnit(unit) }, |
| 2721 | 2729 | ); |
| 2722 | 2730 | try comp.queueJob(.{ .analyze_comptime_unit = unit }); |
| ... | ... | @@ -3134,7 +3142,7 @@ fn processExportsInner( |
| 3134 | 3142 | if (gop.found_existing) { |
| 3135 | 3143 | new_export.status = .failed_retryable; |
| 3136 | 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 | 3146 | new_export.opts.name.fmt(ip), |
| 3139 | 3147 | }); |
| 3140 | 3148 | errdefer msg.destroy(gpa); |
| ... | ... | @@ -4376,12 +4384,11 @@ fn runCodegenInner(pt: Zcu.PerThread, func_index: InternPool.Index, air: *Air) e |
| 4376 | 4384 | defer liveness.deinit(gpa); |
| 4377 | 4385 | |
| 4378 | 4386 | if (build_options.enable_debug_extensions and comp.verbose_air) { |
| 4379 | std.debug.lockStdErr(); | |
| 4380 | defer std.debug.unlockStdErr(); | |
| 4381 | const stderr = std.io.getStdErr().writer(); | |
| 4382 | stderr.print("# Begin Function AIR: {}:\n", .{fqn.fmt(ip)}) catch {}; | |
| 4387 | const stderr = std.debug.lockStderrWriter(&.{}); | |
| 4388 | defer std.debug.unlockStderrWriter(); | |
| 4389 | stderr.print("# Begin Function AIR: {f}:\n", .{fqn.fmt(ip)}) catch {}; | |
| 4383 | 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 | } |
| 4386 | 4393 | |
| 4387 | 4394 | if (std.debug.runtime_safety) { |
src/arch/riscv64/CodeGen.zig+53-74| ... | ... | @@ -435,7 +435,7 @@ const InstTracking = struct { |
| 435 | 435 | fn trackSpill(inst_tracking: *InstTracking, function: *Func, inst: Air.Inst.Index) !void { |
| 436 | 436 | try function.freeValue(inst_tracking.short); |
| 437 | 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 | } |
| 440 | 440 | |
| 441 | 441 | fn verifyMaterialize(inst_tracking: InstTracking, target: InstTracking) void { |
| ... | ... | @@ -499,14 +499,14 @@ const InstTracking = struct { |
| 499 | 499 | else => target.long, |
| 500 | 500 | } else target.long; |
| 501 | 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 | } |
| 504 | 504 | |
| 505 | 505 | fn resurrect(inst_tracking: *InstTracking, inst: Air.Inst.Index, scope_generation: u32) void { |
| 506 | 506 | switch (inst_tracking.short) { |
| 507 | 507 | .dead => |die_generation| if (die_generation >= scope_generation) { |
| 508 | 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 | 511 | else => {}, |
| 512 | 512 | } |
| ... | ... | @@ -516,7 +516,7 @@ const InstTracking = struct { |
| 516 | 516 | if (inst_tracking.short == .dead) return; |
| 517 | 517 | try function.freeValue(inst_tracking.short); |
| 518 | 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 | } |
| 521 | 521 | |
| 522 | 522 | fn reuse( |
| ... | ... | @@ -527,15 +527,15 @@ const InstTracking = struct { |
| 527 | 527 | ) void { |
| 528 | 528 | inst_tracking.short = .{ .dead = function.scope_generation }; |
| 529 | 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 | 531 | 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 | } |
| 534 | 534 | |
| 535 | 535 | fn liveOut(inst_tracking: *InstTracking, function: *Func, inst: Air.Inst.Index) void { |
| 536 | 536 | for (inst_tracking.getRegs()) |reg| { |
| 537 | 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 | 539 | continue; |
| 540 | 540 | } |
| 541 | 541 | |
| ... | ... | @@ -562,16 +562,11 @@ const InstTracking = struct { |
| 562 | 562 | // Perform side-effects of freeValue manually. |
| 563 | 563 | function.register_manager.freeReg(reg); |
| 564 | 564 | |
| 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 | } |
| 568 | 568 | |
| 569 | pub fn format( | |
| 570 | inst_tracking: InstTracking, | |
| 571 | comptime _: []const u8, | |
| 572 | _: std.fmt.FormatOptions, | |
| 573 | writer: anytype, | |
| 574 | ) @TypeOf(writer).Error!void { | |
| 569 | pub fn format(inst_tracking: InstTracking, writer: *std.io.Writer) std.io.Writer.Error!void { | |
| 575 | 570 | if (!std.meta.eql(inst_tracking.long, inst_tracking.short)) try writer.print("|{}| ", .{inst_tracking.long}); |
| 576 | 571 | try writer.print("{}", .{inst_tracking.short}); |
| 577 | 572 | } |
| ... | ... | @@ -802,7 +797,7 @@ pub fn generate( |
| 802 | 797 | function.mir_instructions.deinit(gpa); |
| 803 | 798 | } |
| 804 | 799 | |
| 805 | wip_mir_log.debug("{}:", .{fmtNav(func.owner_nav, ip)}); | |
| 800 | wip_mir_log.debug("{f}:", .{fmtNav(func.owner_nav, ip)}); | |
| 806 | 801 | |
| 807 | 802 | try function.frame_allocs.resize(gpa, FrameIndex.named_count); |
| 808 | 803 | function.frame_allocs.set( |
| ... | ... | @@ -937,12 +932,7 @@ const FormatWipMirData = struct { |
| 937 | 932 | func: *Func, |
| 938 | 933 | inst: Mir.Inst.Index, |
| 939 | 934 | }; |
| 940 | fn formatWipMir( | |
| 941 | data: FormatWipMirData, | |
| 942 | comptime _: []const u8, | |
| 943 | _: std.fmt.FormatOptions, | |
| 944 | writer: anytype, | |
| 945 | ) @TypeOf(writer).Error!void { | |
| 935 | fn formatWipMir(data: FormatWipMirData, writer: *std.io.Writer) std.io.Writer.Error!void { | |
| 946 | 936 | const pt = data.func.pt; |
| 947 | 937 | const comp = pt.zcu.comp; |
| 948 | 938 | var lower: Lower = .{ |
| ... | ... | @@ -982,7 +972,7 @@ fn formatWipMir( |
| 982 | 972 | first = false; |
| 983 | 973 | } |
| 984 | 974 | } |
| 985 | fn fmtWipMir(func: *Func, inst: Mir.Inst.Index) std.fmt.Formatter(formatWipMir) { | |
| 975 | fn fmtWipMir(func: *Func, inst: Mir.Inst.Index) std.fmt.Formatter(FormatWipMirData, formatWipMir) { | |
| 986 | 976 | return .{ .data = .{ .func = func, .inst = inst } }; |
| 987 | 977 | } |
| 988 | 978 | |
| ... | ... | @@ -990,15 +980,10 @@ const FormatNavData = struct { |
| 990 | 980 | ip: *const InternPool, |
| 991 | 981 | nav_index: InternPool.Nav.Index, |
| 992 | 982 | }; |
| 993 | fn formatNav( | |
| 994 | data: FormatNavData, | |
| 995 | comptime _: []const u8, | |
| 996 | _: std.fmt.FormatOptions, | |
| 997 | writer: anytype, | |
| 998 | ) @TypeOf(writer).Error!void { | |
| 999 | try writer.print("{}", .{data.ip.getNav(data.nav_index).fqn.fmt(data.ip)}); | |
| 1000 | } | |
| 1001 | fn fmtNav(nav_index: InternPool.Nav.Index, ip: *const InternPool) std.fmt.Formatter(formatNav) { | |
| 983 | fn formatNav(data: FormatNavData, writer: *std.io.Writer) std.io.Writer.Error!void { | |
| 984 | try writer.print("{f}", .{data.ip.getNav(data.nav_index).fqn.fmt(data.ip)}); | |
| 985 | } | |
| 986 | fn fmtNav(nav_index: InternPool.Nav.Index, ip: *const InternPool) std.fmt.Formatter(FormatNavData, formatNav) { | |
| 1002 | 987 | return .{ .data = .{ |
| 1003 | 988 | .ip = ip, |
| 1004 | 989 | .nav_index = nav_index, |
| ... | ... | @@ -1009,31 +994,25 @@ const FormatAirData = struct { |
| 1009 | 994 | func: *Func, |
| 1010 | 995 | inst: Air.Inst.Index, |
| 1011 | 996 | }; |
| 1012 | fn formatAir( | |
| 1013 | data: FormatAirData, | |
| 1014 | comptime _: []const u8, | |
| 1015 | _: std.fmt.FormatOptions, | |
| 1016 | writer: anytype, | |
| 1017 | ) @TypeOf(writer).Error!void { | |
| 1018 | data.func.air.dumpInst(data.inst, data.func.pt, data.func.liveness); | |
| 1019 | } | |
| 1020 | fn fmtAir(func: *Func, inst: Air.Inst.Index) std.fmt.Formatter(formatAir) { | |
| 997 | fn formatAir(data: FormatAirData, writer: *std.io.Writer) std.io.Writer.Error!void { | |
| 998 | // Not acceptable implementation because it ignores `writer`: | |
| 999 | //data.func.air.dumpInst(data.inst, data.func.pt, data.func.liveness); | |
| 1000 | _ = data; | |
| 1001 | _ = writer; | |
| 1002 | @panic("unimplemented"); | |
| 1003 | } | |
| 1004 | fn fmtAir(func: *Func, inst: Air.Inst.Index) std.fmt.Formatter(FormatAirData, formatAir) { | |
| 1021 | 1005 | return .{ .data = .{ .func = func, .inst = inst } }; |
| 1022 | 1006 | } |
| 1023 | 1007 | |
| 1024 | 1008 | const FormatTrackingData = struct { |
| 1025 | 1009 | func: *Func, |
| 1026 | 1010 | }; |
| 1027 | fn formatTracking( | |
| 1028 | data: FormatTrackingData, | |
| 1029 | comptime _: []const u8, | |
| 1030 | _: std.fmt.FormatOptions, | |
| 1031 | writer: anytype, | |
| 1032 | ) @TypeOf(writer).Error!void { | |
| 1011 | fn formatTracking(data: FormatTrackingData, writer: *std.io.Writer) std.io.Writer.Error!void { | |
| 1033 | 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 | } |
| 1036 | fn fmtTracking(func: *Func) std.fmt.Formatter(formatTracking) { | |
| 1015 | fn fmtTracking(func: *Func) std.fmt.Formatter(FormatTrackingData, formatTracking) { | |
| 1037 | 1016 | return .{ .data = .{ .func = func } }; |
| 1038 | 1017 | } |
| 1039 | 1018 | |
| ... | ... | @@ -1049,7 +1028,7 @@ fn addInst(func: *Func, inst: Mir.Inst) error{OutOfMemory}!Mir.Inst.Index { |
| 1049 | 1028 | .pseudo_dbg_epilogue_begin, |
| 1050 | 1029 | .pseudo_dead, |
| 1051 | 1030 | => false, |
| 1052 | }) wip_mir_log.debug("{}", .{func.fmtWipMir(result_index)}); | |
| 1031 | }) wip_mir_log.debug("{f}", .{func.fmtWipMir(result_index)}); | |
| 1053 | 1032 | return result_index; |
| 1054 | 1033 | } |
| 1055 | 1034 | |
| ... | ... | @@ -1303,7 +1282,7 @@ fn genLazy(func: *Func, lazy_sym: link.File.LazySymbol) InnerError!void { |
| 1303 | 1282 | switch (Type.fromInterned(lazy_sym.ty).zigTypeTag(zcu)) { |
| 1304 | 1283 | .@"enum" => { |
| 1305 | 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)}); | |
| 1307 | 1286 | |
| 1308 | 1287 | const param_regs = abi.Registers.Integer.function_arg_regs; |
| 1309 | 1288 | const ret_reg = param_regs[0]; |
| ... | ... | @@ -1385,7 +1364,7 @@ fn genLazy(func: *Func, lazy_sym: link.File.LazySymbol) InnerError!void { |
| 1385 | 1364 | }); |
| 1386 | 1365 | }, |
| 1387 | 1366 | else => return func.fail( |
| 1388 | "TODO implement {s} for {}", | |
| 1367 | "TODO implement {s} for {f}", | |
| 1389 | 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 | 1378 | |
| 1400 | 1379 | for (body) |inst| { |
| 1401 | 1380 | if (func.liveness.isUnused(inst) and !func.air.mustLower(inst, ip)) continue; |
| 1402 | wip_mir_log.debug("{}", .{func.fmtAir(inst)}); | |
| 1403 | verbose_tracking_log.debug("{}", .{func.fmtTracking()}); | |
| 1381 | wip_mir_log.debug("{f}", .{func.fmtAir(inst)}); | |
| 1382 | verbose_tracking_log.debug("{f}", .{func.fmtTracking()}); | |
| 1404 | 1383 | |
| 1405 | 1384 | const old_air_bookkeeping = func.air_bookkeeping; |
| 1406 | 1385 | try func.ensureProcessDeathCapacity(Air.Liveness.bpi); |
| ... | ... | @@ -1679,18 +1658,18 @@ fn genBody(func: *Func, body: []const Air.Inst.Index) InnerError!void { |
| 1679 | 1658 | var it = func.register_manager.free_registers.iterator(.{ .kind = .unset }); |
| 1680 | 1659 | while (it.next()) |index| { |
| 1681 | 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 | 1662 | const tracking = func.getResolvedInstValue(tracked_inst); |
| 1684 | 1663 | for (tracking.getRegs()) |reg| { |
| 1685 | 1664 | if (RegisterManager.indexOfRegIntoTracked(reg).? == index) break; |
| 1686 | 1665 | } else return std.debug.panic( |
| 1687 | \\%{} takes up these regs: {any}, however this regs {any}, don't use it | |
| 1666 | \\%{f} takes up these regs: {any}, however this regs {any}, don't use it | |
| 1688 | 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 | } |
| 1695 | 1674 | |
| 1696 | 1675 | fn getValue(func: *Func, value: MCValue, inst: ?Air.Inst.Index) !void { |
| ... | ... | @@ -1713,7 +1692,7 @@ fn freeValue(func: *Func, value: MCValue) !void { |
| 1713 | 1692 | |
| 1714 | 1693 | fn feed(func: *Func, bt: *Air.Liveness.BigTomb, operand: Air.Inst.Ref) !void { |
| 1715 | 1694 | if (bt.feed()) if (operand.toIndex()) |inst| { |
| 1716 | log.debug("feed inst: %{}", .{inst}); | |
| 1695 | log.debug("feed inst: %{f}", .{inst}); | |
| 1717 | 1696 | try func.processDeath(inst); |
| 1718 | 1697 | }; |
| 1719 | 1698 | } |
| ... | ... | @@ -1843,7 +1822,7 @@ fn computeFrameLayout(func: *Func) !FrameLayout { |
| 1843 | 1822 | total_alloc_size + 64 + args_frame_size + spill_frame_size + call_frame_size, |
| 1844 | 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}); | |
| 1847 | 1826 | |
| 1848 | 1827 | // store the ra at total_size - 8, so it's the very first thing in the stack |
| 1849 | 1828 | // relative to the fp |
| ... | ... | @@ -1907,7 +1886,7 @@ fn splitType(func: *Func, ty: Type) ![2]Type { |
| 1907 | 1886 | else => return func.fail("TODO: splitType class {}", .{class}), |
| 1908 | 1887 | }; |
| 1909 | 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 | } |
| 1912 | 1891 | |
| 1913 | 1892 | /// Truncates the value in the register in place. |
| ... | ... | @@ -2020,7 +1999,7 @@ fn allocMemPtr(func: *Func, inst: Air.Inst.Index) !FrameIndex { |
| 2020 | 1999 | const val_ty = ptr_ty.childType(zcu); |
| 2021 | 2000 | return func.allocFrameIndex(FrameAlloc.init(.{ |
| 2022 | 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 | 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 | 2139 | /// allocated. A second call to `copyToTmpRegister` may return the same register. |
| 2161 | 2140 | /// This can have a side effect of spilling instructions to the stack to free up a register. |
| 2162 | 2141 | fn 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 | 2143 | const reg = try func.register_manager.allocReg(null, func.regTempClassForType(ty)); |
| 2165 | 2144 | try func.genSetReg(ty, reg, mcv); |
| 2166 | 2145 | return reg; |
| ... | ... | @@ -2245,7 +2224,7 @@ fn airIntCast(func: *Func, inst: Air.Inst.Index) !void { |
| 2245 | 2224 | break :result null; // TODO |
| 2246 | 2225 | |
| 2247 | 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 | 2228 | src_ty.fmt(pt), dst_ty.fmt(pt), |
| 2250 | 2229 | }); |
| 2251 | 2230 | |
| ... | ... | @@ -2633,7 +2612,7 @@ fn genBinOp( |
| 2633 | 2612 | .add_sat, |
| 2634 | 2613 | => { |
| 2635 | 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)}); | |
| 2637 | 2616 | |
| 2638 | 2617 | const tmp_reg = try func.copyToTmpRegister(rhs_ty, .{ .register = rhs_reg }); |
| 2639 | 2618 | const tmp_lock = func.register_manager.lockRegAssumeUnused(tmp_reg); |
| ... | ... | @@ -4065,7 +4044,7 @@ fn airGetUnionTag(func: *Func, inst: Air.Inst.Index) !void { |
| 4065 | 4044 | ); |
| 4066 | 4045 | } else { |
| 4067 | 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 | 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 | 4165 | |
| 4187 | 4166 | switch (scalar_ty.zigTypeTag(zcu)) { |
| 4188 | 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 | 4169 | } else { |
| 4191 | 4170 | const int_info = scalar_ty.intInfo(zcu); |
| 4192 | 4171 | const int_bits = int_info.bits; |
| ... | ... | @@ -4267,7 +4246,7 @@ fn airAbs(func: *Func, inst: Air.Inst.Index) !void { |
| 4267 | 4246 | |
| 4268 | 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 | } |
| 4272 | 4251 | |
| 4273 | 4252 | break :result .unreach; |
| ... | ... | @@ -4331,7 +4310,7 @@ fn airByteSwap(func: *Func, inst: Air.Inst.Index) !void { |
| 4331 | 4310 | |
| 4332 | 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 | 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 | 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 | } |
| 4402 | 4381 | |
| 4403 | 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 | 4476 | const zcu = pt.zcu; |
| 4498 | 4477 | const dst_ty = ptr_ty.childType(zcu); |
| 4499 | 4478 | |
| 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 }); | |
| 4501 | 4480 | |
| 4502 | 4481 | switch (ptr_mcv) { |
| 4503 | 4482 | .none, |
| ... | ... | @@ -4550,7 +4529,7 @@ fn airStore(func: *Func, inst: Air.Inst.Index, safety: bool) !void { |
| 4550 | 4529 | fn store(func: *Func, ptr_mcv: MCValue, src_mcv: MCValue, ptr_ty: Type) !void { |
| 4551 | 4530 | const zcu = func.pt.zcu; |
| 4552 | 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) }); | |
| 4554 | 4533 | |
| 4555 | 4534 | switch (ptr_mcv) { |
| 4556 | 4535 | .none => unreachable, |
| ... | ... | @@ -7305,7 +7284,7 @@ fn airBitCast(func: *Func, inst: Air.Inst.Index) !void { |
| 7305 | 7284 | const bit_size = dst_ty.bitSize(zcu); |
| 7306 | 7285 | if (abi_size * 8 <= bit_size) break :result dst_mcv; |
| 7307 | 7286 | |
| 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 | 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 | 8100 | ); |
| 8122 | 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 | }; |
| 8127 | 8106 | |
| ... | ... | @@ -8322,7 +8301,7 @@ fn resolveCallingConventionValues( |
| 8322 | 8301 | }; |
| 8323 | 8302 | |
| 8324 | 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 | 8305 | 1 => ret_tracking[0], |
| 8327 | 8306 | 2 => InstTracking.init(.{ .register_pair = .{ |
| 8328 | 8307 | ret_tracking[0].short.register, ret_tracking[1].short.register, |
| ... | ... | @@ -8377,7 +8356,7 @@ fn resolveCallingConventionValues( |
| 8377 | 8356 | else => return func.fail("TODO: C calling convention arg class {}", .{class}), |
| 8378 | 8357 | } else { |
| 8379 | 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 | 8360 | 1 => arg_mcv[0], |
| 8382 | 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 | 172 | |
| 173 | 173 | fn fixupRelocs(emit: *Emit) Error!void { |
| 174 | 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 | 176 | const target = emit.code_offset_mapping.get(reloc.target) orelse |
| 177 | 177 | return emit.fail("relocation target not found!", .{}); |
| 178 | 178 |
src/arch/riscv64/Lower.zig+1-1| ... | ... | @@ -61,7 +61,7 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index, options: struct { |
| 61 | 61 | defer lower.result_relocs_len = undefined; |
| 62 | 62 | |
| 63 | 63 | const inst = lower.mir.instructions.get(index); |
| 64 | log.debug("lowerMir {}", .{inst}); | |
| 64 | log.debug("lowerMir {f}", .{inst}); | |
| 65 | 65 | switch (inst.tag) { |
| 66 | 66 | else => try lower.generic(inst), |
| 67 | 67 | .pseudo_dbg_line_column, |
src/arch/riscv64/Mir.zig+1-7| ... | ... | @@ -92,13 +92,7 @@ pub const Inst = struct { |
| 92 | 92 | }, |
| 93 | 93 | }; |
| 94 | 94 | |
| 95 | pub fn format( | |
| 96 | inst: Inst, | |
| 97 | comptime fmt: []const u8, | |
| 98 | _: std.fmt.FormatOptions, | |
| 99 | writer: anytype, | |
| 100 | ) !void { | |
| 101 | assert(fmt.len == 0); | |
| 95 | pub fn format(inst: Inst, writer: *std.io.Writer) std.io.Writer.Error!void { | |
| 102 | 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 | 255 | pub fn isNamed(fi: FrameIndex) bool { |
| 256 | 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 | }; |
| 276 | 259 | |
| 277 | 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 | 723 | |
| 724 | 724 | if (std.debug.runtime_safety) { |
| 725 | 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 | 1001 | switch (self.args[arg_index]) { |
| 1002 | 1002 | .stack_offset => |off| { |
| 1003 | 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 | 1006 | const offset = off + abi_size; |
| 1007 | 1007 | break :blk .{ .stack_offset = offset }; |
| ... | ... | @@ -2748,7 +2748,7 @@ fn allocMemPtr(self: *Self, inst: Air.Inst.Index) !u32 { |
| 2748 | 2748 | } |
| 2749 | 2749 | |
| 2750 | 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 | 2753 | // TODO swap this for inst.ty.ptrAlign |
| 2754 | 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 | 2760 | const zcu = pt.zcu; |
| 2761 | 2761 | const elem_ty = self.typeOfIndex(inst); |
| 2762 | 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 | 2765 | const abi_align = elem_ty.abiAlignment(zcu); |
| 2766 | 2766 | self.stack_align = self.stack_align.max(abi_align); |
| ... | ... | @@ -4111,7 +4111,7 @@ fn getResolvedInstValue(self: *Self, inst: Air.Inst.Index) MCValue { |
| 4111 | 4111 | while (true) { |
| 4112 | 4112 | i -= 1; |
| 4113 | 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 | 4115 | assert(mcv != .dead); |
| 4116 | 4116 | return mcv; |
| 4117 | 4117 | } |
| ... | ... | @@ -4382,7 +4382,7 @@ fn processDeath(self: *Self, inst: Air.Inst.Index) void { |
| 4382 | 4382 | const prev_value = self.getResolvedInstValue(inst); |
| 4383 | 4383 | const branch = &self.branch_stack.items[self.branch_stack.items.len - 1]; |
| 4384 | 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 | 4386 | switch (prev_value) { |
| 4387 | 4387 | .register => |reg| { |
| 4388 | 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 | 1463 | } |
| 1464 | 1464 | |
| 1465 | 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 | 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 | 1497 | |
| 1498 | 1498 | const abi_alignment = ptr_ty.ptrAlignment(zcu); |
| 1499 | 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 | 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 | 1959 | .wasm_memory_size => cg.airWasmMemorySize(inst), |
| 1960 | 1960 | .wasm_memory_grow => cg.airWasmMemoryGrow(inst), |
| 1961 | 1961 | |
| 1962 | .memcpy => cg.airMemcpy(inst), | |
| 1962 | .memcpy, .memmove => cg.airMemcpy(inst), | |
| 1963 | 1963 | |
| 1964 | 1964 | .ret_addr => cg.airRetAddr(inst), |
| 1965 | 1965 | .tag_name => cg.airTagName(inst), |
| ... | ... | @@ -1983,7 +1983,6 @@ fn genInst(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 1983 | 1983 | .c_va_copy, |
| 1984 | 1984 | .c_va_end, |
| 1985 | 1985 | .c_va_start, |
| 1986 | .memmove, | |
| 1987 | 1986 | => |tag| return cg.fail("TODO: Implement wasm inst: {s}", .{@tagName(tag)}), |
| 1988 | 1987 | |
| 1989 | 1988 | .atomic_load => cg.airAtomicLoad(inst), |
| ... | ... | @@ -2046,7 +2045,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 2046 | 2045 | try cg.genInst(inst); |
| 2047 | 2046 | |
| 2048 | 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 | 2049 | inst, |
| 2051 | 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 | 2403 | try cg.memcpy(lhs, rhs, .{ .imm32 = @as(u32, @intCast(ty.abiSize(zcu))) }); |
| 2405 | 2404 | }, |
| 2406 | 2405 | else => if (abi_size > 8) { |
| 2407 | return cg.fail("TODO: `store` for type `{}` with abisize `{d}`", .{ | |
| 2408 | ty.fmt(pt), | |
| 2409 | abi_size, | |
| 2410 | }); | |
| 2406 | return cg.fail("TODO: `store` for type `{f}` with abisize `{d}`", .{ ty.fmt(pt), abi_size }); | |
| 2411 | 2407 | }, |
| 2412 | 2408 | } |
| 2413 | 2409 | try cg.emitWValue(lhs); |
| ... | ... | @@ -2596,10 +2592,7 @@ fn binOp(cg: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, op: Op) InnerError!WV |
| 2596 | 2592 | if (ty.zigTypeTag(zcu) == .int) { |
| 2597 | 2593 | return cg.binOpBigInt(lhs, rhs, ty, op); |
| 2598 | 2594 | } else { |
| 2599 | return cg.fail( | |
| 2600 | "TODO: Implement binary operation for type: {}", | |
| 2601 | .{ty.fmt(pt)}, | |
| 2602 | ); | |
| 2595 | return cg.fail("TODO: Implement binary operation for type: {f}", .{ty.fmt(pt)}); | |
| 2603 | 2596 | } |
| 2604 | 2597 | } |
| 2605 | 2598 | |
| ... | ... | @@ -2817,7 +2810,7 @@ fn airAbs(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 2817 | 2810 | |
| 2818 | 2811 | switch (scalar_ty.zigTypeTag(zcu)) { |
| 2819 | 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 | 2814 | } else { |
| 2822 | 2815 | const int_bits = ty.intInfo(zcu).bits; |
| 2823 | 2816 | const wasm_bits = toWasmBits(int_bits) orelse { |
| ... | ... | @@ -3244,7 +3237,7 @@ fn lowerConstant(cg: *CodeGen, val: Value, ty: Type) InnerError!WValue { |
| 3244 | 3237 | return .{ .imm32 = @intFromBool(!val.isNull(zcu)) }; |
| 3245 | 3238 | }, |
| 3246 | 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 | 3241 | .vector_type => { |
| 3249 | 3242 | assert(determineSimdStoreStrategy(ty, zcu, cg.target) == .direct); |
| 3250 | 3243 | var buf: [16]u8 = undefined; |
| ... | ... | @@ -3332,7 +3325,7 @@ fn emitUndefined(cg: *CodeGen, ty: Type) InnerError!WValue { |
| 3332 | 3325 | }, |
| 3333 | 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 | } |
| 3338 | 3331 | |
| ... | ... | @@ -3608,7 +3601,7 @@ fn airNot(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 3608 | 3601 | } else { |
| 3609 | 3602 | const int_info = operand_ty.intInfo(zcu); |
| 3610 | 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 | }; |
| 3613 | 3606 | |
| 3614 | 3607 | switch (wasm_bits) { |
| ... | ... | @@ -3874,7 +3867,7 @@ fn airStructFieldVal(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 3874 | 3867 | }, |
| 3875 | 3868 | else => result: { |
| 3876 | 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 | 3872 | if (isByRef(field_ty, zcu, cg.target)) { |
| 3880 | 3873 | switch (operand) { |
| ... | ... | @@ -4360,7 +4353,7 @@ fn isNull(cg: *CodeGen, operand: WValue, optional_ty: Type, opcode: std.wasm.Opc |
| 4360 | 4353 | // a pointer to the stack value |
| 4361 | 4354 | if (payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) { |
| 4362 | 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 | 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 | 4423 | } |
| 4431 | 4424 | |
| 4432 | 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 | }; |
| 4435 | 4428 | |
| 4436 | 4429 | try cg.emitWValue(operand); |
| ... | ... | @@ -4462,7 +4455,7 @@ fn airWrapOptional(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 4462 | 4455 | break :result cg.reuseOperand(ty_op.operand, operand); |
| 4463 | 4456 | } |
| 4464 | 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 | }; |
| 4467 | 4460 | |
| 4468 | 4461 | // 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 | 6189 | _ = try cg.load(overflow_ret, Type.i32, 0); |
| 6197 | 6190 | try cg.addLocal(.local_set, overflow_bit.local.value); |
| 6198 | 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 | 6193 | var bin_op_local = try mul.toLocal(cg, ty); |
| 6201 | 6194 | defer bin_op_local.free(cg); |
| 6202 | 6195 | |
| ... | ... | @@ -6749,7 +6742,7 @@ fn airMod(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 6749 | 6742 | const add = try cg.binOp(rem, rhs, ty, .add); |
| 6750 | 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 | }; |
| 6754 | 6747 | |
| 6755 | 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 | 6760 | const lhs = try cg.resolveInst(bin_op.lhs); |
| 6768 | 6761 | const rhs = try cg.resolveInst(bin_op.rhs); |
| 6769 | 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 | }; |
| 6772 | 6765 | |
| 6773 | 6766 | switch (wasm_bits) { |
| ... | ... | @@ -6804,7 +6797,7 @@ fn airSatMul(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 6804 | 6797 | }, |
| 6805 | 6798 | 64 => { |
| 6806 | 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 | 6802 | const overflow_ret = try cg.allocStack(Type.i32); |
| 6810 | 6803 | _ = try cg.callIntrinsic( |
| ... | ... | @@ -6822,7 +6815,7 @@ fn airSatMul(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 6822 | 6815 | }, |
| 6823 | 6816 | 128 => { |
| 6824 | 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 | 6820 | const overflow_ret = try cg.allocStack(Type.i32); |
| 6828 | 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 | const tracking_log = std.log.scoped(.tracking); |
| 7 | 7 | const verbose_tracking_log = std.log.scoped(.verbose_tracking); |
| 8 | 8 | const wip_mir_log = std.log.scoped(.wip_mir); |
| 9 | const Writer = std.io.Writer; | |
| 9 | 10 | |
| 10 | 11 | const Air = @import("../../Air.zig"); |
| 11 | 12 | const Allocator = std.mem.Allocator; |
| ... | ... | @@ -524,52 +525,47 @@ pub const MCValue = union(enum) { |
| 524 | 525 | }; |
| 525 | 526 | } |
| 526 | 527 | |
| 527 | pub fn format( | |
| 528 | mcv: MCValue, | |
| 529 | comptime _: []const u8, | |
| 530 | _: std.fmt.FormatOptions, | |
| 531 | writer: anytype, | |
| 532 | ) @TypeOf(writer).Error!void { | |
| 528 | pub fn format(mcv: MCValue, w: *Writer) Writer.Error!void { | |
| 533 | 529 | switch (mcv) { |
| 534 | .none, .unreach, .dead, .undef => try writer.print("({s})", .{@tagName(mcv)}), | |
| 535 | .immediate => |pl| try writer.print("0x{x}", .{pl}), | |
| 536 | .memory => |pl| try writer.print("[ds:0x{x}]", .{pl}), | |
| 537 | inline .eflags, .register => |pl| try writer.print("{s}", .{@tagName(pl)}), | |
| 538 | .register_pair => |pl| try writer.print("{s}:{s}", .{ @tagName(pl[1]), @tagName(pl[0]) }), | |
| 539 | .register_triple => |pl| try writer.print("{s}:{s}:{s}", .{ | |
| 530 | .none, .unreach, .dead, .undef => try w.print("({s})", .{@tagName(mcv)}), | |
| 531 | .immediate => |pl| try w.print("0x{x}", .{pl}), | |
| 532 | .memory => |pl| try w.print("[ds:0x{x}]", .{pl}), | |
| 533 | inline .eflags, .register => |pl| try w.print("{s}", .{@tagName(pl)}), | |
| 534 | .register_pair => |pl| try w.print("{s}:{s}", .{ @tagName(pl[1]), @tagName(pl[0]) }), | |
| 535 | .register_triple => |pl| try w.print("{s}:{s}:{s}", .{ | |
| 540 | 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 | 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 }), | |
| 546 | .register_overflow => |pl| try writer.print("{s}:{s}", .{ | |
| 541 | .register_offset => |pl| try w.print("{s} + 0x{x}", .{ @tagName(pl.reg), pl.off }), | |
| 542 | .register_overflow => |pl| try w.print("{s}:{s}", .{ | |
| 547 | 543 | @tagName(pl.eflags), |
| 548 | 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 | 547 | @tagName(pl.info.kind), |
| 552 | 548 | pl.info.scalar, |
| 553 | 549 | @as(u8, if (pl.info.inverted) '!' else ' '), |
| 554 | 550 | @tagName(pl.reg), |
| 555 | 551 | }), |
| 556 | .indirect => |pl| try writer.print("[{s} + 0x{x}]", .{ @tagName(pl.reg), pl.off }), | |
| 557 | .indirect_load_frame => |pl| try writer.print("[[{} + 0x{x}]]", .{ pl.index, pl.off }), | |
| 558 | .load_frame => |pl| try writer.print("[{} + 0x{x}]", .{ pl.index, pl.off }), | |
| 559 | .lea_frame => |pl| try writer.print("{} + 0x{x}", .{ pl.index, pl.off }), | |
| 560 | .load_nav => |pl| try writer.print("[nav:{d}]", .{@intFromEnum(pl)}), | |
| 561 | .lea_nav => |pl| try writer.print("nav:{d}", .{@intFromEnum(pl)}), | |
| 562 | .load_uav => |pl| try writer.print("[uav:{d}]", .{@intFromEnum(pl.val)}), | |
| 563 | .lea_uav => |pl| try writer.print("uav:{d}", .{@intFromEnum(pl.val)}), | |
| 564 | .load_lazy_sym => |pl| try writer.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) }), | |
| 566 | .load_extern_func => |pl| try writer.print("[extern:{d}]", .{@intFromEnum(pl)}), | |
| 567 | .lea_extern_func => |pl| try writer.print("extern:{d}", .{@intFromEnum(pl)}), | |
| 568 | .elementwise_args => |pl| try writer.print("elementwise:{d}:[{} + 0x{x}]", .{ | |
| 552 | .indirect => |pl| try w.print("[{s} + 0x{x}]", .{ @tagName(pl.reg), pl.off }), | |
| 553 | .indirect_load_frame => |pl| try w.print("[[{} + 0x{x}]]", .{ pl.index, pl.off }), | |
| 554 | .load_frame => |pl| try w.print("[{} + 0x{x}]", .{ pl.index, pl.off }), | |
| 555 | .lea_frame => |pl| try w.print("{} + 0x{x}", .{ pl.index, pl.off }), | |
| 556 | .load_nav => |pl| try w.print("[nav:{d}]", .{@intFromEnum(pl)}), | |
| 557 | .lea_nav => |pl| try w.print("nav:{d}", .{@intFromEnum(pl)}), | |
| 558 | .load_uav => |pl| try w.print("[uav:{d}]", .{@intFromEnum(pl.val)}), | |
| 559 | .lea_uav => |pl| try w.print("uav:{d}", .{@intFromEnum(pl.val)}), | |
| 560 | .load_lazy_sym => |pl| try w.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) }), | |
| 562 | .load_extern_func => |pl| try w.print("[extern:{d}]", .{@intFromEnum(pl)}), | |
| 563 | .lea_extern_func => |pl| try w.print("extern:{d}", .{@intFromEnum(pl)}), | |
| 564 | .elementwise_args => |pl| try w.print("elementwise:{d}:[{} + 0x{x}]", .{ | |
| 569 | 565 | pl.regs, pl.frame_index, pl.frame_off, |
| 570 | 566 | }), |
| 571 | .reserved_frame => |pl| try writer.print("(dead:{})", .{pl}), | |
| 572 | .air_ref => |pl| try writer.print("(air:0x{x})", .{@intFromEnum(pl)}), | |
| 567 | .reserved_frame => |pl| try w.print("(dead:{})", .{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 | 635 | .reserved_frame => |index| self.long = .{ .load_frame = .{ .index = index } }, |
| 640 | 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 | 639 | try cg.genCopy(cg.typeOfIndex(inst), self.long, self.short, .{}); |
| 644 | 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 | 668 | else => {}, // TODO process stack allocation death |
| 673 | 669 | } |
| 674 | 670 | self.reuseFrame(); |
| 675 | tracking_log.debug("{} => {} (spilled)", .{ inst, self.* }); | |
| 671 | tracking_log.debug("{f} => {f} (spilled)", .{ inst, self.* }); | |
| 676 | 672 | } |
| 677 | 673 | |
| 678 | 674 | fn verifyMaterialize(self: InstTracking, target: InstTracking) void { |
| ... | ... | @@ -749,7 +745,7 @@ const InstTracking = struct { |
| 749 | 745 | else => target.long, |
| 750 | 746 | } else target.long; |
| 751 | 747 | self.short = target.short; |
| 752 | tracking_log.debug("{} => {} (materialize)", .{ inst, self.* }); | |
| 748 | tracking_log.debug("{f} => {f} (materialize)", .{ inst, self.* }); | |
| 753 | 749 | } |
| 754 | 750 | |
| 755 | 751 | fn resurrect(self: *InstTracking, function: *CodeGen, inst: Air.Inst.Index, scope_generation: u32) !void { |
| ... | ... | @@ -757,7 +753,7 @@ const InstTracking = struct { |
| 757 | 753 | .dead => |die_generation| if (die_generation >= scope_generation) { |
| 758 | 754 | self.reuseFrame(); |
| 759 | 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 | 758 | else => {}, |
| 763 | 759 | } |
| ... | ... | @@ -768,7 +764,7 @@ const InstTracking = struct { |
| 768 | 764 | try function.freeValue(self.short, opts); |
| 769 | 765 | if (self.long == .none) self.long = self.short; |
| 770 | 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 | } |
| 773 | 769 | |
| 774 | 770 | fn reuse( |
| ... | ... | @@ -778,13 +774,13 @@ const InstTracking = struct { |
| 778 | 774 | old_inst: Air.Inst.Index, |
| 779 | 775 | ) void { |
| 780 | 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 | } |
| 783 | 779 | |
| 784 | 780 | fn liveOut(self: *InstTracking, function: *CodeGen, inst: Air.Inst.Index) void { |
| 785 | 781 | for (self.getRegs()) |reg| { |
| 786 | 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 | 784 | continue; |
| 789 | 785 | } |
| 790 | 786 | |
| ... | ... | @@ -812,18 +808,13 @@ const InstTracking = struct { |
| 812 | 808 | // Perform side-effects of freeValue manually. |
| 813 | 809 | function.register_manager.freeReg(reg); |
| 814 | 810 | |
| 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 | } |
| 818 | 814 | |
| 819 | pub fn format( | |
| 820 | tracking: InstTracking, | |
| 821 | comptime _: []const u8, | |
| 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}); | |
| 815 | pub fn format(tracking: InstTracking, bw: *Writer) Writer.Error!void { | |
| 816 | if (!std.meta.eql(tracking.long, tracking.short)) try bw.print("|{f}| ", .{tracking.long}); | |
| 817 | try bw.print("{f}", .{tracking.short}); | |
| 827 | 818 | } |
| 828 | 819 | }; |
| 829 | 820 | |
| ... | ... | @@ -939,7 +930,7 @@ pub fn generate( |
| 939 | 930 | function.inst_tracking.putAssumeCapacityNoClobber(temp.toIndex(), .init(.none)); |
| 940 | 931 | } |
| 941 | 932 | |
| 942 | wip_mir_log.debug("{}:", .{fmtNav(func.owner_nav, ip)}); | |
| 933 | wip_mir_log.debug("{f}:", .{fmtNav(func.owner_nav, ip)}); | |
| 943 | 934 | |
| 944 | 935 | try function.frame_allocs.resize(gpa, FrameIndex.named_count); |
| 945 | 936 | function.frame_allocs.set( |
| ... | ... | @@ -1097,15 +1088,10 @@ const FormatNavData = struct { |
| 1097 | 1088 | ip: *const InternPool, |
| 1098 | 1089 | nav_index: InternPool.Nav.Index, |
| 1099 | 1090 | }; |
| 1100 | fn formatNav( | |
| 1101 | data: FormatNavData, | |
| 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)}); | |
| 1091 | fn formatNav(data: FormatNavData, w: *Writer) Writer.Error!void { | |
| 1092 | try w.print("{f}", .{data.ip.getNav(data.nav_index).fqn.fmt(data.ip)}); | |
| 1107 | 1093 | } |
| 1108 | fn fmtNav(nav_index: InternPool.Nav.Index, ip: *const InternPool) std.fmt.Formatter(formatNav) { | |
| 1094 | fn fmtNav(nav_index: InternPool.Nav.Index, ip: *const InternPool) std.fmt.Formatter(FormatNavData, formatNav) { | |
| 1109 | 1095 | return .{ .data = .{ |
| 1110 | 1096 | .ip = ip, |
| 1111 | 1097 | .nav_index = nav_index, |
| ... | ... | @@ -1116,15 +1102,14 @@ const FormatAirData = struct { |
| 1116 | 1102 | self: *CodeGen, |
| 1117 | 1103 | inst: Air.Inst.Index, |
| 1118 | 1104 | }; |
| 1119 | fn formatAir( | |
| 1120 | data: FormatAirData, | |
| 1121 | comptime _: []const u8, | |
| 1122 | _: std.fmt.FormatOptions, | |
| 1123 | writer: anytype, | |
| 1124 | ) @TypeOf(writer).Error!void { | |
| 1125 | data.self.air.dumpInst(data.inst, data.self.pt, data.self.liveness); | |
| 1105 | fn formatAir(data: FormatAirData, w: *std.io.Writer) Writer.Error!void { | |
| 1106 | // not acceptable implementation because it ignores `w`: | |
| 1107 | //data.self.air.dumpInst(data.inst, data.self.pt, data.self.liveness); | |
| 1108 | _ = data; | |
| 1109 | _ = w; | |
| 1110 | @panic("TODO: unimplemented"); | |
| 1126 | 1111 | } |
| 1127 | fn fmtAir(self: *CodeGen, inst: Air.Inst.Index) std.fmt.Formatter(formatAir) { | |
| 1112 | fn fmtAir(self: *CodeGen, inst: Air.Inst.Index) std.fmt.Formatter(FormatAirData, formatAir) { | |
| 1128 | 1113 | return .{ .data = .{ .self = self, .inst = inst } }; |
| 1129 | 1114 | } |
| 1130 | 1115 | |
| ... | ... | @@ -1132,12 +1117,7 @@ const FormatWipMirData = struct { |
| 1132 | 1117 | self: *CodeGen, |
| 1133 | 1118 | inst: Mir.Inst.Index, |
| 1134 | 1119 | }; |
| 1135 | fn formatWipMir( | |
| 1136 | data: FormatWipMirData, | |
| 1137 | comptime _: []const u8, | |
| 1138 | _: std.fmt.FormatOptions, | |
| 1139 | writer: anytype, | |
| 1140 | ) @TypeOf(writer).Error!void { | |
| 1120 | fn formatWipMir(data: FormatWipMirData, w: *Writer) Writer.Error!void { | |
| 1141 | 1121 | var lower: Lower = .{ |
| 1142 | 1122 | .target = data.self.target, |
| 1143 | 1123 | .allocator = data.self.gpa, |
| ... | ... | @@ -1152,27 +1132,22 @@ fn formatWipMir( |
| 1152 | 1132 | lower.err_msg.?.deinit(data.self.gpa); |
| 1153 | 1133 | lower.err_msg = null; |
| 1154 | 1134 | } |
| 1155 | try writer.writeAll(lower.err_msg.?.msg); | |
| 1135 | try w.writeAll(lower.err_msg.?.msg); | |
| 1156 | 1136 | return; |
| 1157 | 1137 | }, |
| 1158 | error.OutOfMemory, error.InvalidInstruction, error.CannotEncode => |e| { | |
| 1159 | try writer.writeAll(switch (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 | }); | |
| 1138 | else => |e| { | |
| 1139 | try w.writeAll(@errorName(e)); | |
| 1164 | 1140 | return; |
| 1165 | 1141 | }, |
| 1166 | else => |e| return e, | |
| 1167 | 1142 | }).insts) |lowered_inst| { |
| 1168 | if (!first) try writer.writeAll("\ndebug(wip_mir): "); | |
| 1169 | try writer.print(" | {}", .{lowered_inst}); | |
| 1143 | if (!first) try w.writeAll("\ndebug(wip_mir): "); | |
| 1144 | try w.print(" | {f}", .{lowered_inst}); | |
| 1170 | 1145 | first = false; |
| 1171 | 1146 | } |
| 1172 | 1147 | if (first) { |
| 1173 | 1148 | const ip = &data.self.pt.zcu.intern_pool; |
| 1174 | 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 | 1151 | switch (mir_inst.ops) { |
| 1177 | 1152 | else => unreachable, |
| 1178 | 1153 | .pseudo_dbg_prologue_end_none, |
| ... | ... | @@ -1184,20 +1159,20 @@ fn formatWipMir( |
| 1184 | 1159 | .pseudo_dbg_var_none, |
| 1185 | 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 | 1163 | " {[line]d}, {[column]d}", |
| 1189 | 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 | 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 | 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 | 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 | 1176 | mir_inst.data.i64, |
| 1202 | 1177 | }), |
| 1203 | 1178 | .pseudo_dbg_arg_ro, .pseudo_dbg_var_ro => { |
| ... | ... | @@ -1205,44 +1180,39 @@ fn formatWipMir( |
| 1205 | 1180 | .base = .{ .reg = mir_inst.data.ro.reg }, |
| 1206 | 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 | 1185 | .pseudo_dbg_arg_fa, .pseudo_dbg_var_fa => { |
| 1211 | 1186 | const mem_op: encoder.Instruction.Operand = .{ .mem = .initSib(.qword, .{ |
| 1212 | 1187 | .base = .{ .frame = mir_inst.data.fa.index }, |
| 1213 | 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 | 1192 | .pseudo_dbg_arg_m, .pseudo_dbg_var_m => { |
| 1218 | 1193 | const mem_op: encoder.Instruction.Operand = .{ |
| 1219 | 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 | 1199 | Value.fromInterned(mir_inst.data.ip_index).fmtValue(data.self.pt), |
| 1225 | 1200 | }), |
| 1226 | 1201 | } |
| 1227 | 1202 | } |
| 1228 | 1203 | } |
| 1229 | fn fmtWipMir(self: *CodeGen, inst: Mir.Inst.Index) std.fmt.Formatter(formatWipMir) { | |
| 1204 | fn fmtWipMir(self: *CodeGen, inst: Mir.Inst.Index) std.fmt.Formatter(FormatWipMirData, formatWipMir) { | |
| 1230 | 1205 | return .{ .data = .{ .self = self, .inst = inst } }; |
| 1231 | 1206 | } |
| 1232 | 1207 | |
| 1233 | 1208 | const FormatTrackingData = struct { |
| 1234 | 1209 | self: *CodeGen, |
| 1235 | 1210 | }; |
| 1236 | fn formatTracking( | |
| 1237 | data: FormatTrackingData, | |
| 1238 | comptime _: []const u8, | |
| 1239 | _: std.fmt.FormatOptions, | |
| 1240 | writer: anytype, | |
| 1241 | ) @TypeOf(writer).Error!void { | |
| 1211 | fn formatTracking(data: FormatTrackingData, w: *Writer) Writer.Error!void { | |
| 1242 | 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 | } |
| 1245 | fn fmtTracking(self: *CodeGen) std.fmt.Formatter(formatTracking) { | |
| 1215 | fn fmtTracking(self: *CodeGen) std.fmt.Formatter(FormatTrackingData, formatTracking) { | |
| 1246 | 1216 | return .{ .data = .{ .self = self } }; |
| 1247 | 1217 | } |
| 1248 | 1218 | |
| ... | ... | @@ -1251,7 +1221,7 @@ fn addInst(self: *CodeGen, inst: Mir.Inst) error{OutOfMemory}!Mir.Inst.Index { |
| 1251 | 1221 | try self.mir_instructions.ensureUnusedCapacity(gpa, 1); |
| 1252 | 1222 | const result_index: Mir.Inst.Index = @intCast(self.mir_instructions.len); |
| 1253 | 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 | 1225 | return result_index; |
| 1256 | 1226 | } |
| 1257 | 1227 | |
| ... | ... | @@ -2056,7 +2026,7 @@ fn gen( |
| 2056 | 2026 | .{}, |
| 2057 | 2027 | ); |
| 2058 | 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 | 2031 | else => unreachable, |
| 2062 | 2032 | } |
| ... | ... | @@ -2334,8 +2304,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 2334 | 2304 | |
| 2335 | 2305 | for (body) |inst| { |
| 2336 | 2306 | if (cg.liveness.isUnused(inst) and !cg.air.mustLower(inst, ip)) continue; |
| 2337 | wip_mir_log.debug("{}", .{cg.fmtAir(inst)}); | |
| 2338 | verbose_tracking_log.debug("{}", .{cg.fmtTracking()}); | |
| 2307 | wip_mir_log.debug("{f}", .{cg.fmtAir(inst)}); | |
| 2308 | verbose_tracking_log.debug("{f}", .{cg.fmtTracking()}); | |
| 2339 | 2309 | |
| 2340 | 2310 | cg.reused_operands = .initEmpty(); |
| 2341 | 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 | 4309 | .{ ._, ._nc, .j, .@"0b", ._, ._, ._ }, |
| 4340 | 4310 | } }, |
| 4341 | 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 | 4313 | @tagName(air_tag), |
| 4344 | 4314 | cg.typeOf(bin_op.lhs).fmt(pt), |
| 4345 | 4315 | ops[0].tracking(cg), |
| ... | ... | @@ -4351,7 +4321,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 4351 | 4321 | else => unreachable, |
| 4352 | 4322 | .add, .add_optimized => {}, |
| 4353 | 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 | 4325 | @tagName(air_tag), |
| 4356 | 4326 | cg.typeOf(bin_op.lhs).fmt(pt), |
| 4357 | 4327 | res[0].tracking(cg), |
| ... | ... | @@ -12917,7 +12887,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 12917 | 12887 | .{ ._, ._nc, .j, .@"0b", ._, ._, ._ }, |
| 12918 | 12888 | } }, |
| 12919 | 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 | 12891 | @tagName(air_tag), |
| 12922 | 12892 | cg.typeOf(bin_op.lhs).fmt(pt), |
| 12923 | 12893 | ops[0].tracking(cg), |
| ... | ... | @@ -14947,7 +14917,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 14947 | 14917 | .{ ._, ._nc, .j, .@"0b", ._, ._, ._ }, |
| 14948 | 14918 | } }, |
| 14949 | 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 | 14921 | @tagName(air_tag), |
| 14952 | 14922 | cg.typeOf(bin_op.lhs).fmt(pt), |
| 14953 | 14923 | ops[0].tracking(cg), |
| ... | ... | @@ -14959,7 +14929,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 14959 | 14929 | else => unreachable, |
| 14960 | 14930 | .sub, .sub_optimized => {}, |
| 14961 | 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 | 14933 | @tagName(air_tag), |
| 14964 | 14934 | cg.typeOf(bin_op.lhs).fmt(pt), |
| 14965 | 14935 | res[0].tracking(cg), |
| ... | ... | @@ -21794,7 +21764,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 21794 | 21764 | .{ ._, ._nc, .j, .@"0b", ._, ._, ._ }, |
| 21795 | 21765 | } }, |
| 21796 | 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 | 21768 | @tagName(air_tag), |
| 21799 | 21769 | cg.typeOf(bin_op.lhs).fmt(pt), |
| 21800 | 21770 | ops[0].tracking(cg), |
| ... | ... | @@ -24587,7 +24557,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 24587 | 24557 | .{ ._, ._nc, .j, .@"0b", ._, ._, ._ }, |
| 24588 | 24558 | } }, |
| 24589 | 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 | 24561 | @tagName(air_tag), |
| 24592 | 24562 | ty.fmt(pt), |
| 24593 | 24563 | ops[0].tracking(cg), |
| ... | ... | @@ -27287,7 +27257,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 27287 | 27257 | .{ ._, ._nc, .j, .@"0b", ._, ._, ._ }, |
| 27288 | 27258 | } }, |
| 27289 | 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 | 27261 | @tagName(air_tag), |
| 27292 | 27262 | ty.fmt(pt), |
| 27293 | 27263 | ops[0].tracking(cg), |
| ... | ... | @@ -27296,7 +27266,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 27296 | 27266 | else => |e| return e, |
| 27297 | 27267 | }; |
| 27298 | 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 | 27270 | @tagName(air_tag), |
| 27301 | 27271 | cg.typeOf(bin_op.lhs).fmt(pt), |
| 27302 | 27272 | res[0].tracking(cg), |
| ... | ... | @@ -32512,7 +32482,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 32512 | 32482 | .{ .@"0:", ._, .mov, .memad(.dst0q, .add_size, -8), .tmp3q, ._, ._ }, |
| 32513 | 32483 | } }, |
| 32514 | 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 | 32486 | @tagName(air_tag), |
| 32517 | 32487 | cg.typeOf(bin_op.lhs).fmt(pt), |
| 32518 | 32488 | ops[0].tracking(cg), |
| ... | ... | @@ -33606,7 +33576,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 33606 | 33576 | assert(air_tag == .div_exact); |
| 33607 | 33577 | res[0] = ops[0].divTruncInts(&ops[1], cg) catch |err| break :err err; |
| 33608 | 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 | 33580 | @tagName(air_tag), |
| 33611 | 33581 | ty.fmt(pt), |
| 33612 | 33582 | ops[0].tracking(cg), |
| ... | ... | @@ -34837,7 +34807,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 34837 | 34807 | } }) else err: { |
| 34838 | 34808 | res[0] = ops[0].divTruncInts(&ops[1], cg) catch |err| break :err err; |
| 34839 | 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 | 34811 | @tagName(air_tag), |
| 34842 | 34812 | ty.fmt(pt), |
| 34843 | 34813 | ops[0].tracking(cg), |
| ... | ... | @@ -36148,7 +36118,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 36148 | 36118 | } }, |
| 36149 | 36119 | } }, |
| 36150 | 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 | 36122 | @tagName(air_tag), |
| 36153 | 36123 | cg.typeOf(bin_op.lhs).fmt(pt), |
| 36154 | 36124 | ops[0].tracking(cg), |
| ... | ... | @@ -37614,7 +37584,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 37614 | 37584 | .{ ._, ._nc, .j, .@"0b", ._, ._, ._ }, |
| 37615 | 37585 | } }, |
| 37616 | 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 | 37588 | @tagName(air_tag), |
| 37619 | 37589 | ty.fmt(pt), |
| 37620 | 37590 | ops[0].tracking(cg), |
| ... | ... | @@ -39248,7 +39218,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 39248 | 39218 | .{ ._, ._nc, .j, .@"0b", ._, ._, ._ }, |
| 39249 | 39219 | } }, |
| 39250 | 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 | 39222 | @tagName(air_tag), |
| 39253 | 39223 | cg.typeOf(bin_op.lhs).fmt(pt), |
| 39254 | 39224 | ops[0].tracking(cg), |
| ... | ... | @@ -42077,7 +42047,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 42077 | 42047 | .{ ._, ._nc, .j, .@"0b", ._, ._, ._ }, |
| 42078 | 42048 | } }, |
| 42079 | 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 | 42051 | @tagName(air_tag), |
| 42082 | 42052 | cg.typeOf(bin_op.lhs).fmt(pt), |
| 42083 | 42053 | ops[0].tracking(cg), |
| ... | ... | @@ -42191,7 +42161,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 42191 | 42161 | .{ ._, ._, .lea, .dst0p, .leai(.src0, .dst0), ._, ._ }, |
| 42192 | 42162 | } }, |
| 42193 | 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 | 42165 | @tagName(air_tag), |
| 42196 | 42166 | cg.typeOf(bin_op.lhs).fmt(pt), |
| 42197 | 42167 | ops[0].tracking(cg), |
| ... | ... | @@ -42320,7 +42290,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 42320 | 42290 | .{ ._, ._, .lea, .dst0p, .leai(.src0, .dst0), ._, ._ }, |
| 42321 | 42291 | } }, |
| 42322 | 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 | 42294 | @tagName(air_tag), |
| 42325 | 42295 | cg.typeOf(bin_op.lhs).fmt(pt), |
| 42326 | 42296 | ops[0].tracking(cg), |
| ... | ... | @@ -46485,7 +46455,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 46485 | 46455 | .{ ._, ._nc, .j, .@"0b", ._, ._, ._ }, |
| 46486 | 46456 | } }, |
| 46487 | 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 | 46459 | @tagName(air_tag), |
| 46490 | 46460 | cg.typeOf(bin_op.lhs).fmt(pt), |
| 46491 | 46461 | ops[0].tracking(cg), |
| ... | ... | @@ -50644,7 +50614,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 50644 | 50614 | .{ ._, ._nc, .j, .@"0b", ._, ._, ._ }, |
| 50645 | 50615 | } }, |
| 50646 | 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 | 50618 | @tagName(air_tag), |
| 50649 | 50619 | cg.typeOf(bin_op.lhs).fmt(pt), |
| 50650 | 50620 | ops[0].tracking(cg), |
| ... | ... | @@ -51493,7 +51463,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 51493 | 51463 | .{ ._, ._, .mov, .memad(.dst0q, .add_src0_size, -8), .tmp0q, ._, ._ }, |
| 51494 | 51464 | } }, |
| 51495 | 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 | 51467 | @tagName(air_tag), |
| 51498 | 51468 | ty_pl.ty.toType().fmt(pt), |
| 51499 | 51469 | ops[0].tracking(cg), |
| ... | ... | @@ -52398,7 +52368,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 52398 | 52368 | .{ ._, ._, .mov, .memad(.dst0q, .add_src0_size, -8), .tmp0q, ._, ._ }, |
| 52399 | 52369 | } }, |
| 52400 | 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 | 52372 | @tagName(air_tag), |
| 52403 | 52373 | ty_pl.ty.toType().fmt(pt), |
| 52404 | 52374 | ops[0].tracking(cg), |
| ... | ... | @@ -55995,7 +55965,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 55995 | 55965 | .{ ._, ._, .@"or", .tmp2q, .tmp1q, ._, ._ }, |
| 55996 | 55966 | } }, |
| 55997 | 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 | 55969 | @tagName(air_tag), |
| 56000 | 55970 | ty_pl.ty.toType().fmt(pt), |
| 56001 | 55971 | ops[0].tracking(cg), |
| ... | ... | @@ -59340,7 +59310,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 59340 | 59310 | .{ ._, ._, .@"or", .tmp4q, .tmp5q, ._, ._ }, |
| 59341 | 59311 | } }, |
| 59342 | 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 | 59314 | @tagName(air_tag), |
| 59345 | 59315 | ty_pl.ty.toType().fmt(pt), |
| 59346 | 59316 | ops[0].tracking(cg), |
| ... | ... | @@ -59735,7 +59705,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 59735 | 59705 | } }, |
| 59736 | 59706 | } }, |
| 59737 | 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 | 59709 | @tagName(air_tag), |
| 59740 | 59710 | cg.typeOf(bin_op.lhs).fmt(pt), |
| 59741 | 59711 | ops[0].tracking(cg), |
| ... | ... | @@ -60298,7 +60268,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 60298 | 60268 | .{ ._, ._nz, .j, .@"0b", ._, ._, ._ }, |
| 60299 | 60269 | } }, |
| 60300 | 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 | 60272 | @tagName(air_tag), |
| 60303 | 60273 | cg.typeOf(bin_op.lhs).fmt(pt), |
| 60304 | 60274 | cg.typeOf(bin_op.rhs).fmt(pt), |
| ... | ... | @@ -60660,7 +60630,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 60660 | 60630 | .{ ._, ._ns, .j, .@"0b", ._, ._, ._ }, |
| 60661 | 60631 | } }, |
| 60662 | 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 | 60634 | @tagName(air_tag), |
| 60665 | 60635 | cg.typeOf(bin_op.lhs).fmt(pt), |
| 60666 | 60636 | cg.typeOf(bin_op.rhs).fmt(pt), |
| ... | ... | @@ -60672,7 +60642,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 60672 | 60642 | switch (air_tag) { |
| 60673 | 60643 | else => unreachable, |
| 60674 | 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 | 60646 | @tagName(air_tag), |
| 60677 | 60647 | cg.typeOf(bin_op.lhs).fmt(pt), |
| 60678 | 60648 | res[0].tracking(cg), |
| ... | ... | @@ -60839,7 +60809,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 60839 | 60809 | .{ ._, ._, .@"or", .dst0d, .tmp0d, ._, ._ }, |
| 60840 | 60810 | } }, |
| 60841 | 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 | 60813 | @tagName(air_tag), |
| 60844 | 60814 | cg.typeOf(bin_op.rhs).fmt(pt), |
| 60845 | 60815 | ops[1].tracking(cg), |
| ... | ... | @@ -64096,7 +64066,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 64096 | 64066 | .{ .@"0:", ._, .mov, .memad(.dst0q, .add_size, -8), .tmp1q, ._, ._ }, |
| 64097 | 64067 | } }, |
| 64098 | 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 | 64070 | @tagName(air_tag), |
| 64101 | 64071 | lhs_ty.fmt(pt), |
| 64102 | 64072 | ops[0].tracking(cg), |
| ... | ... | @@ -65329,7 +65299,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 65329 | 65299 | .{ ._, ._b, .j, .@"0b", ._, ._, ._ }, |
| 65330 | 65300 | } }, |
| 65331 | 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 | 65303 | @tagName(air_tag), |
| 65334 | 65304 | ty_op.ty.toType().fmt(pt), |
| 65335 | 65305 | ops[0].tracking(cg), |
| ... | ... | @@ -68483,7 +68453,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 68483 | 68453 | .{ ._, ._nc, .j, .@"0b", ._, ._, ._ }, |
| 68484 | 68454 | } }, |
| 68485 | 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 | 68457 | @tagName(air_tag), |
| 68488 | 68458 | cg.typeOf(ty_op.operand).fmt(pt), |
| 68489 | 68459 | ops[0].tracking(cg), |
| ... | ... | @@ -68880,7 +68850,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 68880 | 68850 | .{ .@"0:", ._, .lea, .dst0d, .leasia(.dst0, .@"8", .tmp0, .add_8_src0_size), ._, ._ }, |
| 68881 | 68851 | } }, |
| 68882 | 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 | 68854 | @tagName(air_tag), |
| 68885 | 68855 | cg.typeOf(ty_op.operand).fmt(pt), |
| 68886 | 68856 | ops[0].tracking(cg), |
| ... | ... | @@ -69768,7 +69738,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 69768 | 69738 | .{ ._, ._ae, .j, .@"0b", ._, ._, ._ }, |
| 69769 | 69739 | } }, |
| 69770 | 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 | 69742 | @tagName(air_tag), |
| 69773 | 69743 | cg.typeOf(ty_op.operand).fmt(pt), |
| 69774 | 69744 | ops[0].tracking(cg), |
| ... | ... | @@ -70417,7 +70387,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 70417 | 70387 | .{ ._, ._ae, .j, .@"0b", ._, ._, ._ }, |
| 70418 | 70388 | } }, |
| 70419 | 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 | 70391 | @tagName(air_tag), |
| 70422 | 70392 | ty_op.ty.toType().fmt(pt), |
| 70423 | 70393 | ops[0].tracking(cg), |
| ... | ... | @@ -73519,7 +73489,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 73519 | 73489 | .{ ._, ._ae, .j, .@"0b", ._, ._, ._ }, |
| 73520 | 73490 | } }, |
| 73521 | 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 | 73493 | @tagName(air_tag), |
| 73524 | 73494 | ty_op.ty.toType().fmt(pt), |
| 73525 | 73495 | ops[0].tracking(cg), |
| ... | ... | @@ -74457,7 +74427,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 74457 | 74427 | .{ ._, ._nc, .j, .@"0b", ._, ._, ._ }, |
| 74458 | 74428 | } }, |
| 74459 | 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 | 74431 | @tagName(air_tag), |
| 74462 | 74432 | cg.typeOf(un_op).fmt(pt), |
| 74463 | 74433 | ops[0].tracking(cg), |
| ... | ... | @@ -75183,7 +75153,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 75183 | 75153 | } }, |
| 75184 | 75154 | } }, |
| 75185 | 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 | 75157 | @tagName(air_tag), |
| 75188 | 75158 | cg.typeOf(un_op).fmt(pt), |
| 75189 | 75159 | ops[0].tracking(cg), |
| ... | ... | @@ -76734,7 +76704,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 76734 | 76704 | .{ ._, ._nc, .j, .@"0b", ._, ._, ._ }, |
| 76735 | 76705 | } }, |
| 76736 | 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 | 76708 | @tagName(air_tag), |
| 76739 | 76709 | cg.typeOf(ty_op.operand).fmt(pt), |
| 76740 | 76710 | ops[0].tracking(cg), |
| ... | ... | @@ -77926,7 +77896,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 77926 | 77896 | } }, |
| 77927 | 77897 | } }, |
| 77928 | 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 | 77900 | @tagName(air_tag), |
| 77931 | 77901 | cg.typeOf(un_op).fmt(pt), |
| 77932 | 77902 | ops[0].tracking(cg), |
| ... | ... | @@ -78466,7 +78436,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 78466 | 78436 | .{ ._, ._nc, .j, .@"0b", ._, ._, ._ }, |
| 78467 | 78437 | } }, |
| 78468 | 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 | 78440 | @tagName(air_tag), |
| 78471 | 78441 | cg.typeOf(un_op).fmt(pt), |
| 78472 | 78442 | ops[0].tracking(cg), |
| ... | ... | @@ -78913,7 +78883,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 78913 | 78883 | } else err: { |
| 78914 | 78884 | res[0] = ops[0].cmpInts(cmp_op, &ops[1], cg) catch |err| break :err err; |
| 78915 | 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 | 78887 | @tagName(air_tag), |
| 78918 | 78888 | cg.typeOf(bin_op.lhs).fmt(pt), |
| 78919 | 78889 | ops[0].tracking(cg), |
| ... | ... | @@ -79458,7 +79428,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 79458 | 79428 | .@"struct", .@"union" => { |
| 79459 | 79429 | assert(ty.containerLayout(zcu) == .@"packed"); |
| 79460 | 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 | 79432 | @tagName(air_tag), |
| 79463 | 79433 | ty.fmt(pt), |
| 79464 | 79434 | op.tracking(cg), |
| ... | ... | @@ -79470,7 +79440,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 79470 | 79440 | res[0] = ops[0].cmpInts(cmp_op, &ops[1], cg) catch |err| break :err err; |
| 79471 | 79441 | }, |
| 79472 | 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 | 79444 | @tagName(air_tag), |
| 79475 | 79445 | ty.fmt(pt), |
| 79476 | 79446 | ops[0].tracking(cg), |
| ... | ... | @@ -86551,7 +86521,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 86551 | 86521 | } }, |
| 86552 | 86522 | }), |
| 86553 | 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 | 86525 | @tagName(air_tag), |
| 86556 | 86526 | @tagName(vector_cmp.compareOperator()), |
| 86557 | 86527 | cg.typeOf(vector_cmp.lhs).fmt(pt), |
| ... | ... | @@ -88546,7 +88516,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 88546 | 88516 | .{ ._, ._ae, .j, .@"0b", ._, ._, ._ }, |
| 88547 | 88517 | } }, |
| 88548 | 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 | 88520 | @tagName(air_tag), |
| 88551 | 88521 | ty_op.ty.toType().fmt(pt), |
| 88552 | 88522 | cg.typeOf(ty_op.operand).fmt(pt), |
| ... | ... | @@ -90221,7 +90191,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 90221 | 90191 | .{ ._, ._ae, .j, .@"0b", ._, ._, ._ }, |
| 90222 | 90192 | } }, |
| 90223 | 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 | 90195 | @tagName(air_tag), |
| 90226 | 90196 | ty_op.ty.toType().fmt(pt), |
| 90227 | 90197 | cg.typeOf(ty_op.operand).fmt(pt), |
| ... | ... | @@ -94899,7 +94869,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 94899 | 94869 | .{ ._, ._nz, .j, .@"0b", ._, ._, ._ }, |
| 94900 | 94870 | } }, |
| 94901 | 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 | 94873 | @tagName(air_tag), |
| 94904 | 94874 | dst_ty.fmt(pt), |
| 94905 | 94875 | src_ty.fmt(pt), |
| ... | ... | @@ -100565,7 +100535,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 100565 | 100535 | .{ ._, ._nz, .j, .@"0b", ._, ._, ._ }, |
| 100566 | 100536 | } }, |
| 100567 | 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 | 100539 | @tagName(air_tag), |
| 100570 | 100540 | ty_op.ty.toType().fmt(pt), |
| 100571 | 100541 | cg.typeOf(ty_op.operand).fmt(pt), |
| ... | ... | @@ -111427,7 +111397,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 111427 | 111397 | .{ ._, ._ae, .j, .@"0b", ._, ._, ._ }, |
| 111428 | 111398 | } }, |
| 111429 | 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 | 111401 | @tagName(air_tag), |
| 111432 | 111402 | ty_op.ty.toType().fmt(pt), |
| 111433 | 111403 | cg.typeOf(ty_op.operand).fmt(pt), |
| ... | ... | @@ -123446,7 +123416,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 123446 | 123416 | .{ ._, ._ae, .j, .@"0b", ._, ._, ._ }, |
| 123447 | 123417 | } }, |
| 123448 | 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 | 123420 | @tagName(air_tag), |
| 123451 | 123421 | ty_op.ty.toType().fmt(pt), |
| 123452 | 123422 | cg.typeOf(ty_op.operand).fmt(pt), |
| ... | ... | @@ -157216,7 +157186,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 157216 | 157186 | } }, |
| 157217 | 157187 | } }, |
| 157218 | 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 | 157190 | @tagName(air_tag), |
| 157221 | 157191 | @tagName(reduce.operation), |
| 157222 | 157192 | cg.typeOf(reduce.operand).fmt(pt), |
| ... | ... | @@ -157227,7 +157197,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 157227 | 157197 | switch (reduce.operation) { |
| 157228 | 157198 | .And, .Or, .Xor, .Min, .Max => {}, |
| 157229 | 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 | 157201 | @tagName(air_tag), |
| 157232 | 157202 | @tagName(reduce.operation), |
| 157233 | 157203 | res_ty.fmt(pt), |
| ... | ... | @@ -164510,7 +164480,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 164510 | 164480 | } }, |
| 164511 | 164481 | } }, |
| 164512 | 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 | 164484 | @tagName(air_tag), |
| 164515 | 164485 | @tagName(reduce.operation), |
| 164516 | 164486 | cg.typeOf(reduce.operand).fmt(pt), |
| ... | ... | @@ -166307,7 +166277,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 166307 | 166277 | .{ ._, ._nz, .j, .@"0b", ._, ._, ._ }, |
| 166308 | 166278 | } }, |
| 166309 | 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 | 166281 | @tagName(air_tag), |
| 166312 | 166282 | ty_op.ty.toType().fmt(pt), |
| 166313 | 166283 | ops[0].tracking(cg), |
| ... | ... | @@ -166323,7 +166293,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 166323 | 166293 | const bin_op = air_datas[@intFromEnum(inst)].bin_op; |
| 166324 | 166294 | var ops = try cg.tempsFromOperands(inst, .{ bin_op.lhs, bin_op.rhs }) ++ .{undefined}; |
| 166325 | 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 | 166297 | @tagName(air_tag), |
| 166328 | 166298 | cg.typeOf(bin_op.lhs).fmt(pt), |
| 166329 | 166299 | cg.typeOf(bin_op.rhs).fmt(pt), |
| ... | ... | @@ -166363,7 +166333,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 166363 | 166333 | } }, |
| 166364 | 166334 | }}, |
| 166365 | 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 | 166337 | @tagName(air_tag), |
| 166368 | 166338 | cg.typeOf(bin_op.lhs).fmt(pt), |
| 166369 | 166339 | cg.typeOf(bin_op.rhs).fmt(pt), |
| ... | ... | @@ -166464,7 +166434,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 166464 | 166434 | .{ ._, ._, .@"test", .src0p, .src0p, ._, ._ }, |
| 166465 | 166435 | } }, |
| 166466 | 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 | 166438 | @tagName(air_tag), |
| 166469 | 166439 | cg.typeOf(un_op).fmt(pt), |
| 166470 | 166440 | ops[0].tracking(cg), |
| ... | ... | @@ -166552,7 +166522,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 166552 | 166522 | .{ ._, ._, .call, .tmp0d, ._, ._, ._ }, |
| 166553 | 166523 | } }, |
| 166554 | 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 | 166526 | @tagName(air_tag), |
| 166557 | 166527 | cg.typeOf(un_op).fmt(pt), |
| 166558 | 166528 | ops[0].tracking(cg), |
| ... | ... | @@ -166654,7 +166624,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 166654 | 166624 | .{ ._, ._, .lea, .dst1d, .leai(.dst1, .tmp1), ._, ._ }, |
| 166655 | 166625 | } }, |
| 166656 | 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 | 166628 | @tagName(air_tag), |
| 166659 | 166629 | cg.typeOf(un_op).fmt(pt), |
| 166660 | 166630 | ops[0].tracking(cg), |
| ... | ... | @@ -166752,7 +166722,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 166752 | 166722 | .{ ._, ._, .@"test", .src0d, .src0d, ._, ._ }, |
| 166753 | 166723 | } }, |
| 166754 | 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 | 166726 | @tagName(air_tag), |
| 166757 | 166727 | ty_op.ty.toType().fmt(pt), |
| 166758 | 166728 | ops[0].tracking(cg), |
| ... | ... | @@ -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 | 166778 | @tagName(air_tag), |
| 166809 | 166779 | agg_ty.fmt(pt), |
| 166810 | 166780 | }), |
| ... | ... | @@ -166825,7 +166795,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 166825 | 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 | 166799 | @tagName(air_tag), |
| 166830 | 166800 | agg_ty.fmt(pt), |
| 166831 | 166801 | }), |
| ... | ... | @@ -168123,7 +168093,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 168123 | 168093 | .{ ._, ._ae, .j, .@"0b", ._, ._, ._ }, |
| 168124 | 168094 | } }, |
| 168125 | 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 | 168097 | @tagName(air_tag), |
| 168128 | 168098 | cg.typeOf(bin_op.lhs).fmt(pt), |
| 168129 | 168099 | ops[0].tracking(cg), |
| ... | ... | @@ -168223,7 +168193,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 168223 | 168193 | .{ ._, ._, .cmp, .src0d, .lea(.tmp1d), ._, ._ }, |
| 168224 | 168194 | } }, |
| 168225 | 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 | 168197 | @tagName(air_tag), |
| 168228 | 168198 | ops[0].tracking(cg), |
| 168229 | 168199 | }), |
| ... | ... | @@ -168242,12 +168212,12 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 168242 | 168212 | .ref => { |
| 168243 | 168213 | const result = try cg.allocRegOrMem(err_ret_trace_index, true); |
| 168244 | 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 | 168216 | cg.inst_tracking.putAssumeCapacityNoClobber(err_ret_trace_index, .init(result)); |
| 168247 | 168217 | }, |
| 168248 | 168218 | .temp => |temp_index| { |
| 168249 | 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 | 168221 | cg.inst_tracking.putAssumeCapacityNoClobber(err_ret_trace_index, temp_tracking.*); |
| 168252 | 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 | 168887 | try cg.resetTemps(@enumFromInt(0)); |
| 168918 | 168888 | cg.checkInvariantsAfterAirInst(); |
| 168919 | 168889 | } |
| 168920 | verbose_tracking_log.debug("{}", .{cg.fmtTracking()}); | |
| 168890 | verbose_tracking_log.debug("{f}", .{cg.fmtTracking()}); | |
| 168921 | 168891 | } |
| 168922 | 168892 | |
| 168923 | 168893 | 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 | 168897 | switch (ip.indexToKey(lazy_sym.ty)) { |
| 168928 | 168898 | .enum_type => { |
| 168929 | 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)}); | |
| 168931 | 168901 | |
| 168932 | 168902 | const param_regs = abi.getCAbiIntParamRegs(.auto); |
| 168933 | 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 | 168946 | }, |
| 168977 | 168947 | .error_set_type => |error_set_type| { |
| 168978 | 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)}); | |
| 168980 | 168950 | |
| 168981 | 168951 | const param_regs = abi.getCAbiIntParamRegs(.auto); |
| 168982 | 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 | 168986 | try cg.asmOpOnly(.{ ._, .ret }); |
| 169017 | 168987 | }, |
| 169018 | 168988 | else => return cg.fail( |
| 169019 | "TODO implement {s} for {}", | |
| 168989 | "TODO implement {s} for {f}", | |
| 169020 | 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 | 169046 | .none, .dead, .unreach => {}, |
| 169077 | 169047 | else => unreachable, // Why didn't the result die? |
| 169078 | 169048 | } else { |
| 169079 | tracking_log.debug("{} => {} (birth)", .{ inst, result }); | |
| 169049 | tracking_log.debug("{f} => {f} (birth)", .{ inst, result }); | |
| 169080 | 169050 | self.inst_tracking.putAssumeCapacityNoClobber(inst, .init(result)); |
| 169081 | 169051 | // In some cases, an operand may be reused as the result. |
| 169082 | 169052 | // 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 | 169196 | const val_ty = ptr_ty.childType(zcu); |
| 169227 | 169197 | return self.allocFrameIndex(.init(.{ |
| 169228 | 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 | 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 | 169214 | const pt = self.pt; |
| 169245 | 169215 | const zcu = pt.zcu; |
| 169246 | 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 | }; |
| 169249 | 169219 | |
| 169250 | 169220 | if (reg_ok) need_mem: { |
| ... | ... | @@ -169749,7 +169719,7 @@ fn airFpext(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 169749 | 169719 | ); |
| 169750 | 169720 | } |
| 169751 | 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 | 169723 | src_ty.fmt(pt), dst_ty.fmt(pt), |
| 169754 | 169724 | }); |
| 169755 | 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 | 169974 | ); |
| 170005 | 169975 | |
| 170006 | 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 | 169978 | src_ty.fmt(pt), dst_ty.fmt(pt), |
| 170009 | 169979 | }); |
| 170010 | 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 | 170046 | else => null, |
| 170077 | 170047 | }, |
| 170078 | 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)}); | |
| 170080 | 170050 | |
| 170081 | 170051 | const dst_info = dst_elem_ty.intInfo(zcu); |
| 170082 | 170052 | const src_info = src_elem_ty.intInfo(zcu); |
| ... | ... | @@ -170497,7 +170467,7 @@ fn airAddSat(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 170497 | 170467 | const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; |
| 170498 | 170468 | const ty = self.typeOf(bin_op.lhs); |
| 170499 | 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 | 170471 | .{ty.fmt(pt)}, |
| 170502 | 170472 | ); |
| 170503 | 170473 | |
| ... | ... | @@ -170575,7 +170545,7 @@ fn airSubSat(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 170575 | 170545 | const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; |
| 170576 | 170546 | const ty = self.typeOf(bin_op.lhs); |
| 170577 | 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 | 170549 | .{ty.fmt(pt)}, |
| 170580 | 170550 | ); |
| 170581 | 170551 | |
| ... | ... | @@ -170726,7 +170696,7 @@ fn airMulSat(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 170726 | 170696 | } |
| 170727 | 170697 | |
| 170728 | 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 | 170700 | .{ty.fmt(pt)}, |
| 170731 | 170701 | ); |
| 170732 | 170702 | |
| ... | ... | @@ -171020,7 +170990,7 @@ fn airMulWithOverflow(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 171020 | 170990 | const tuple_ty = self.typeOfIndex(inst); |
| 171021 | 170991 | const dst_ty = self.typeOf(bin_op.lhs); |
| 171022 | 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 | 170994 | .int => result: { |
| 171025 | 170995 | const dst_info = dst_ty.intInfo(zcu); |
| 171026 | 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 | 171343 | else => { |
| 171374 | 171344 | // For now, this is the only supported multiply that doesn't fit in a register. |
| 171375 | 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 | 171347 | src_ty.fmt(pt), dst_ty.fmt(pt), |
| 171378 | 171348 | }); |
| 171379 | 171349 | |
| ... | ... | @@ -171774,7 +171744,7 @@ fn airShlShrBinOp(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 171774 | 171744 | }, |
| 171775 | 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 | 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 | 172004 | .index = frame_addr.index, |
| 172035 | 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 | 172010 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); |
| ... | ... | @@ -172196,7 +172166,7 @@ fn genUnwrapErrUnionPayloadMir( |
| 172196 | 172166 | else |
| 172197 | 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 | }; |
| 172202 | 172172 | |
| ... | ... | @@ -172362,7 +172332,7 @@ fn airSliceLen(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 172362 | 172332 | .index = frame_addr.index, |
| 172363 | 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 | 172337 | if (self.reuseOperand(inst, ty_op.operand, 0, src_mcv)) { |
| 172368 | 172338 | switch (src_mcv) { |
| ... | ... | @@ -172645,7 +172615,7 @@ fn airArrayElemVal(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 172645 | 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 | 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 | 172658 | .load_extern_func, |
| 172689 | 172659 | .lea_extern_func, |
| 172690 | 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 | 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 | 172851 | } |
| 172882 | 172852 | |
| 172883 | 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 | 172855 | .{operand}, |
| 172886 | 172856 | ); |
| 172887 | 172857 | }, |
| ... | ... | @@ -172893,7 +172863,7 @@ fn airGetUnionTag(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 172893 | 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 | }; |
| 172899 | 172869 | |
| ... | ... | @@ -172909,7 +172879,7 @@ fn airClz(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 172909 | 172879 | |
| 172910 | 172880 | const dst_ty = self.typeOfIndex(inst); |
| 172911 | 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 | 172883 | src_ty.fmt(pt), |
| 172914 | 172884 | }); |
| 172915 | 172885 | |
| ... | ... | @@ -173105,7 +173075,7 @@ fn airCtz(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 173105 | 173075 | |
| 173106 | 173076 | const dst_ty = self.typeOfIndex(inst); |
| 173107 | 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 | 173079 | src_ty.fmt(pt), |
| 173110 | 173080 | }); |
| 173111 | 173081 | |
| ... | ... | @@ -173277,7 +173247,7 @@ fn airPopCount(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 173277 | 173247 | const src_ty = self.typeOf(ty_op.operand); |
| 173278 | 173248 | const src_abi_size: u32 = @intCast(src_ty.abiSize(zcu)); |
| 173279 | 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 | 173251 | const src_mcv = try self.resolveInst(ty_op.operand); |
| 173282 | 173252 | |
| 173283 | 173253 | const mat_src_mcv = switch (src_mcv) { |
| ... | ... | @@ -173430,7 +173400,7 @@ fn genByteSwap( |
| 173430 | 173400 | const has_movbe = self.hasFeature(.movbe); |
| 173431 | 173401 | |
| 173432 | 173402 | if (src_ty.zigTypeTag(zcu) == .vector) return self.fail( |
| 173433 | "TODO implement genByteSwap for {}", | |
| 173403 | "TODO implement genByteSwap for {f}", | |
| 173434 | 173404 | .{src_ty.fmt(pt)}, |
| 173435 | 173405 | ); |
| 173436 | 173406 | |
| ... | ... | @@ -173739,7 +173709,7 @@ fn floatSign(self: *CodeGen, inst: Air.Inst.Index, tag: Air.Inst.Tag, operand: A |
| 173739 | 173709 | const result = result: { |
| 173740 | 173710 | const scalar_bits = ty.scalarType(zcu).floatBits(self.target); |
| 173741 | 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 | 173713 | ty.fmt(pt), |
| 173744 | 173714 | }); |
| 173745 | 173715 | |
| ... | ... | @@ -173763,7 +173733,7 @@ fn floatSign(self: *CodeGen, inst: Air.Inst.Index, tag: Air.Inst.Tag, operand: A |
| 173763 | 173733 | const abi_size: u32 = switch (ty.abiSize(zcu)) { |
| 173764 | 173734 | 1...16 => 16, |
| 173765 | 173735 | 17...32 => 32, |
| 173766 | else => return self.fail("TODO implement floatSign for {}", .{ | |
| 173736 | else => return self.fail("TODO implement floatSign for {f}", .{ | |
| 173767 | 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 | 173792 | .abs => .{ .v_pd, .@"and" }, |
| 173823 | 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 | 173796 | else => unreachable, |
| 173827 | 173797 | }, |
| 173828 | 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 | 173818 | .abs => .{ ._pd, .@"and" }, |
| 173849 | 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 | 173822 | else => unreachable, |
| 173853 | 173823 | }, |
| 173854 | 173824 | registerAlias(dst_reg, abi_size), |
| ... | ... | @@ -173928,7 +173898,7 @@ fn genRoundLibcall(self: *CodeGen, ty: Type, src_mcv: MCValue, mode: bits.RoundM |
| 173928 | 173898 | if (self.getRoundTag(ty)) |_| return .none; |
| 173929 | 173899 | |
| 173930 | 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)}); | |
| 173932 | 173902 | |
| 173933 | 173903 | var sym_buf: ["__trunc?".len]u8 = undefined; |
| 173934 | 173904 | return try self.genCall(.{ .extern_func = .{ |
| ... | ... | @@ -174164,7 +174134,7 @@ fn airAbs(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 174164 | 174134 | }, |
| 174165 | 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)}); | |
| 174168 | 174138 | |
| 174169 | 174139 | const abi_size: u32 = @intCast(ty.abiSize(zcu)); |
| 174170 | 174140 | const src_mcv = try self.resolveInst(ty_op.operand); |
| ... | ... | @@ -174323,7 +174293,7 @@ fn airSqrt(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 174323 | 174293 | else => unreachable, |
| 174324 | 174294 | }, |
| 174325 | 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 | 174297 | switch (mir_tag[0]) { |
| 174328 | 174298 | .v_ss, .v_sd => if (src_mcv.isBase()) try self.asmRegisterRegisterMemory( |
| 174329 | 174299 | mir_tag, |
| ... | ... | @@ -174481,7 +174451,7 @@ fn packedLoad(self: *CodeGen, dst_mcv: MCValue, ptr_ty: Type, ptr_mcv: MCValue) |
| 174481 | 174451 | return; |
| 174482 | 174452 | } |
| 174483 | 174453 | |
| 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)}); | |
| 174485 | 174455 | |
| 174486 | 174456 | const limb_abi_size: u31 = @min(val_abi_size, 8); |
| 174487 | 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 | 174723 | limb_mem, |
| 174754 | 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 | } |
| 174759 | 174729 | |
| ... | ... | @@ -174856,7 +174826,7 @@ fn genUnOp(self: *CodeGen, maybe_inst: ?Air.Inst.Index, tag: Air.Inst.Tag, src_a |
| 174856 | 174826 | const zcu = pt.zcu; |
| 174857 | 174827 | const src_ty = self.typeOf(src_air); |
| 174858 | 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)}); | |
| 174860 | 174830 | |
| 174861 | 174831 | var src_mcv = try self.resolveInst(src_air); |
| 174862 | 174832 | switch (src_mcv) { |
| ... | ... | @@ -174943,7 +174913,7 @@ fn genUnOp(self: *CodeGen, maybe_inst: ?Air.Inst.Index, tag: Air.Inst.Tag, src_a |
| 174943 | 174913 | fn genUnOpMir(self: *CodeGen, mir_tag: Mir.Inst.FixedTag, dst_ty: Type, dst_mcv: MCValue) !void { |
| 174944 | 174914 | const pt = self.pt; |
| 174945 | 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 | 174917 | switch (dst_mcv) { |
| 174948 | 174918 | .none, |
| 174949 | 174919 | .unreach, |
| ... | ... | @@ -175672,7 +175642,7 @@ fn genBinOp( |
| 175672 | 175642 | }, |
| 175673 | 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 | 175646 | @tagName(air_tag), lhs_ty.fmt(pt), |
| 175677 | 175647 | }), |
| 175678 | 175648 | } catch unreachable; |
| ... | ... | @@ -175785,7 +175755,7 @@ fn genBinOp( |
| 175785 | 175755 | ); |
| 175786 | 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 | 175759 | @tagName(air_tag), lhs_ty.fmt(pt), |
| 175790 | 175760 | }), |
| 175791 | 175761 | else => unreachable, |
| ... | ... | @@ -175819,7 +175789,7 @@ fn genBinOp( |
| 175819 | 175789 | if (sse_op and ((lhs_ty.scalarType(zcu).isRuntimeFloat() and |
| 175820 | 175790 | lhs_ty.scalarType(zcu).floatBits(self.target) == 80) or |
| 175821 | 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) }); | |
| 175823 | 175793 | |
| 175824 | 175794 | const maybe_mask_reg = switch (air_tag) { |
| 175825 | 175795 | else => null, |
| ... | ... | @@ -176199,7 +176169,7 @@ fn genBinOp( |
| 176199 | 176169 | } |
| 176200 | 176170 | }, |
| 176201 | 176171 | |
| 176202 | else => return self.fail("TODO implement genBinOp for {s} {}", .{ | |
| 176172 | else => return self.fail("TODO implement genBinOp for {s} {f}", .{ | |
| 176203 | 176173 | @tagName(air_tag), lhs_ty.fmt(pt), |
| 176204 | 176174 | }), |
| 176205 | 176175 | } |
| ... | ... | @@ -176953,7 +176923,7 @@ fn genBinOp( |
| 176953 | 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 | 176927 | @tagName(air_tag), lhs_ty.fmt(pt), |
| 176958 | 176928 | }); |
| 176959 | 176929 | |
| ... | ... | @@ -177086,7 +177056,7 @@ fn genBinOp( |
| 177086 | 177056 | else => unreachable, |
| 177087 | 177057 | }, |
| 177088 | 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 | 177060 | @tagName(air_tag), lhs_ty.fmt(pt), |
| 177091 | 177061 | }), |
| 177092 | 177062 | mask_reg, |
| ... | ... | @@ -177118,7 +177088,7 @@ fn genBinOp( |
| 177118 | 177088 | else => unreachable, |
| 177119 | 177089 | }, |
| 177120 | 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 | 177092 | @tagName(air_tag), lhs_ty.fmt(pt), |
| 177123 | 177093 | }), |
| 177124 | 177094 | dst_reg, |
| ... | ... | @@ -177154,7 +177124,7 @@ fn genBinOp( |
| 177154 | 177124 | else => unreachable, |
| 177155 | 177125 | }, |
| 177156 | 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 | 177128 | @tagName(air_tag), lhs_ty.fmt(pt), |
| 177159 | 177129 | }), |
| 177160 | 177130 | mask_reg, |
| ... | ... | @@ -177185,7 +177155,7 @@ fn genBinOp( |
| 177185 | 177155 | else => unreachable, |
| 177186 | 177156 | }, |
| 177187 | 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 | 177159 | @tagName(air_tag), lhs_ty.fmt(pt), |
| 177190 | 177160 | }), |
| 177191 | 177161 | dst_reg, |
| ... | ... | @@ -177215,7 +177185,7 @@ fn genBinOp( |
| 177215 | 177185 | else => unreachable, |
| 177216 | 177186 | }, |
| 177217 | 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 | 177189 | @tagName(air_tag), lhs_ty.fmt(pt), |
| 177220 | 177190 | }); |
| 177221 | 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 | 177992 | |
| 178023 | 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 | 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 | 179049 | const reg = try self.copyToTmpRegister(ty, mcv); |
| 179080 | 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 | 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 | 179136 | } }, |
| 179167 | 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 | } |
| 179171 | 179141 | |
| 179172 | 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 | 180886 | }, |
| 180917 | 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 | } |
| 180921 | 180891 | |
| 180922 | 180892 | const CopyOptions = struct { |
| ... | ... | @@ -181048,7 +181018,7 @@ fn genCopy(self: *CodeGen, ty: Type, dst_mcv: MCValue, src_mcv: MCValue, opts: C |
| 181048 | 181018 | break :src_info .{ .addr_reg = src_addr_reg, .addr_lock = src_addr_lock }; |
| 181049 | 181019 | }, |
| 181050 | 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 | 181022 | @tagName(src_mcv), ty.fmt(pt), |
| 181053 | 181023 | }), |
| 181054 | 181024 | }; |
| ... | ... | @@ -181424,7 +181394,7 @@ fn genSetReg( |
| 181424 | 181394 | 80 => null, |
| 181425 | 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 | 181398 | dst_alias, |
| 181429 | 181399 | registerAlias(src_reg, abi_size), |
| 181430 | 181400 | ), |
| ... | ... | @@ -181532,7 +181502,7 @@ fn genSetReg( |
| 181532 | 181502 | assert(!ty.optionalReprIsPayload(zcu)); |
| 181533 | 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 | 181507 | const first_size: u31 = @intCast(first_ty.abiSize(zcu)); |
| 181538 | 181508 | const frame_size = std.math.ceilPowerOfTwoAssert(u32, abi_size); |
| ... | ... | @@ -181854,7 +181824,7 @@ fn genSetMem( |
| 181854 | 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 | 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 | 182137 | 32, 64 => src_size > 8, |
| 182168 | 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 | 182141 | src_ty.fmt(pt), dst_ty.fmt(pt), |
| 182172 | 182142 | }); |
| 182173 | 182143 | |
| ... | ... | @@ -182209,7 +182179,7 @@ fn airFloatFromInt(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 182209 | 182179 | else => unreachable, |
| 182210 | 182180 | }, |
| 182211 | 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 | 182183 | src_ty.fmt(pt), dst_ty.fmt(pt), |
| 182214 | 182184 | }); |
| 182215 | 182185 | const dst_alias = dst_reg.to128(); |
| ... | ... | @@ -182247,7 +182217,7 @@ fn airIntFromFloat(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 182247 | 182217 | 32, 64 => dst_size > 8, |
| 182248 | 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 | 182221 | src_ty.fmt(pt), dst_ty.fmt(pt), |
| 182252 | 182222 | }); |
| 182253 | 182223 | |
| ... | ... | @@ -182531,7 +182501,7 @@ fn atomicOp( |
| 182531 | 182501 | else => null, |
| 182532 | 182502 | }, |
| 182533 | 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 | 182505 | @tagName(op), val_ty.fmt(pt), |
| 182536 | 182506 | }); |
| 182537 | 182507 | try self.genSetReg(sse_reg, val_ty, .{ .register = .rax }, .{}); |
| ... | ... | @@ -183286,7 +183256,7 @@ fn airSplat(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 183286 | 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 | 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 | 183292 | else |
| 183323 | 183293 | try self.copyToTmpRegister(pred_ty, pred_mcv) |
| 183324 | 183294 | 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 | 183296 | else => unreachable, |
| 183327 | 183297 | }, |
| 183328 | 183298 | .register_mask => |pred_reg_mask| { |
| 183329 | 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)}); | |
| 183331 | 183301 | |
| 183332 | 183302 | const mask_reg: Register = if (need_xmm0 and pred_reg_mask.reg.id() != comptime Register.xmm0.id()) mask_reg: { |
| 183333 | 183303 | try self.register_manager.getKnownReg(.xmm0, null); |
| ... | ... | @@ -183401,7 +183371,7 @@ fn airSelect(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 183401 | 183371 | else |
| 183402 | 183372 | null |
| 183403 | 183373 | 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 | 183375 | if (has_avx) { |
| 183406 | 183376 | const rhs_alias = if (reuse_mcv.isRegister()) |
| 183407 | 183377 | registerAlias(reuse_mcv.getReg().?, abi_size) |
| ... | ... | @@ -183554,7 +183524,7 @@ fn airSelect(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 183554 | 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 | 183528 | const elem_bits: u16 = @intCast(elem_abi_size * 8); |
| 183559 | 183529 | if (!pred_fits_in_elem) if (self.hasFeature(.ssse3)) { |
| 183560 | 183530 | const mask_len = elem_abi_size * vec_len; |
| ... | ... | @@ -183583,7 +183553,7 @@ fn airSelect(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 183583 | 183553 | mask_alias, |
| 183584 | 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 | 183558 | const mask_elem_ty = try pt.intType(.unsigned, elem_bits); |
| 183589 | 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 | 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 | 183680 | if (has_avx) { |
| 183711 | 183681 | const rhs_alias = if (rhs_mcv.isRegister()) |
| 183712 | 183682 | registerAlias(rhs_mcv.getReg().?, abi_size) |
| ... | ... | @@ -184551,7 +184521,7 @@ fn airShuffle(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 184551 | 184521 | } |
| 184552 | 184522 | |
| 184553 | 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 | 184525 | lhs_ty.fmt(pt), |
| 184556 | 184526 | rhs_ty.fmt(pt), |
| 184557 | 184527 | dst_ty.fmt(pt), |
| ... | ... | @@ -184800,7 +184770,7 @@ fn airMulAdd(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 184800 | 184770 | 32, 64 => !self.hasFeature(.fma), |
| 184801 | 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 | 184774 | ty.fmt(pt), |
| 184805 | 184775 | }); |
| 184806 | 184776 | |
| ... | ... | @@ -184930,7 +184900,7 @@ fn airMulAdd(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 184930 | 184900 | else => unreachable, |
| 184931 | 184901 | } |
| 184932 | 184902 | 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)}); | |
| 184934 | 184904 | |
| 184935 | 184905 | var mops: [3]MCValue = undefined; |
| 184936 | 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 | 185100 | assert(classes.len == 1); |
| 185131 | 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 | } |
| 185135 | 185105 | |
| 185136 | 185106 | if (unused) break :result .unreach; |
| ... | ... | @@ -185779,7 +185749,7 @@ fn splitType(self: *CodeGen, comptime parts_len: usize, ty: Type) ![parts_len]Ty |
| 185779 | 185749 | for (parts) |part| part_sizes += part.abiSize(zcu); |
| 185780 | 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 | } |
| 185784 | 185754 | |
| 185785 | 185755 | /// Truncates the value in the register in place. |
| ... | ... | @@ -186153,7 +186123,7 @@ const Temp = struct { |
| 186153 | 186123 | cg.next_temp_index = @enumFromInt(@intFromEnum(new_temp_index) + 1); |
| 186154 | 186124 | const mcv = temp.tracking(cg).short; |
| 186155 | 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 | 186127 | .register => |reg| { |
| 186158 | 186128 | const new_reg = try cg.register_manager.allocReg(new_temp_index.toIndex(), abi.RegisterClass.gp); |
| 186159 | 186129 | new_temp_index.tracking(cg).* = .init(.{ .register = new_reg }); |
| ... | ... | @@ -186227,7 +186197,7 @@ const Temp = struct { |
| 186227 | 186197 | const new_temp_index = cg.next_temp_index; |
| 186228 | 186198 | cg.temp_type[@intFromEnum(new_temp_index)] = limb_ty; |
| 186229 | 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 | 186201 | .immediate => |imm| { |
| 186232 | 186202 | assert(limb_index == 0); |
| 186233 | 186203 | new_temp_index.tracking(cg).* = .init(.{ .immediate = imm }); |
| ... | ... | @@ -186568,7 +186538,7 @@ const Temp = struct { |
| 186568 | 186538 | }, |
| 186569 | 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 | } |
| 186573 | 186543 | |
| 186574 | 186544 | fn asMask(temp: Temp, info: MaskInfo, cg: *CodeGen) void { |
| ... | ... | @@ -186658,7 +186628,7 @@ const Temp = struct { |
| 186658 | 186628 | while (try ptr.toLea(cg)) {} |
| 186659 | 186629 | const val_mcv = val.tracking(cg).short; |
| 186660 | 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 | 186632 | .register => |val_reg| try ptr.loadReg(val_ty, registerAlias( |
| 186663 | 186633 | val_reg, |
| 186664 | 186634 | @intCast(val_ty.abiSize(cg.pt.zcu)), |
| ... | ... | @@ -186698,7 +186668,7 @@ const Temp = struct { |
| 186698 | 186668 | {}) { |
| 186699 | 186669 | const val_mcv = val.tracking(cg).short; |
| 186700 | 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 | 186672 | .undef => if (opts.safe) { |
| 186703 | 186673 | var pat = try cg.tempInit(.u8, .{ .immediate = 0xaa }); |
| 186704 | 186674 | var len = try cg.tempInit(.usize, .{ .immediate = val_ty.abiSize(cg.pt.zcu) }); |
| ... | ... | @@ -186772,7 +186742,7 @@ const Temp = struct { |
| 186772 | 186742 | assert(!val_ty.optionalReprIsPayload(cg.pt.zcu)); |
| 186773 | 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 | 186747 | const first_size: u31 = @intCast(first_ty.abiSize(cg.pt.zcu)); |
| 186778 | 186748 | try ptr.storeRegs(first_ty, &.{registerAlias(val_reg_ov.reg, first_size)}, cg); |
| ... | ... | @@ -186804,7 +186774,7 @@ const Temp = struct { |
| 186804 | 186774 | |
| 186805 | 186775 | fn readTo(src: *Temp, val_ty: Type, val_mcv: MCValue, opts: AccessOptions, cg: *CodeGen) InnerError!void { |
| 186806 | 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 | 186778 | .register => |val_reg| try src.readReg(opts.disp, val_ty, registerAlias( |
| 186809 | 186779 | val_reg, |
| 186810 | 186780 | @intCast(cg.unalignedSize(val_ty)), |
| ... | ... | @@ -186844,7 +186814,7 @@ const Temp = struct { |
| 186844 | 186814 | {}) { |
| 186845 | 186815 | const val_mcv = val.tracking(cg).short; |
| 186846 | 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 | 186818 | .none => {}, |
| 186849 | 186819 | .undef => if (opts.safe) { |
| 186850 | 186820 | var dst_ptr = try cg.tempInit(.usize, dst.tracking(cg).short.address().offset(opts.disp)); |
| ... | ... | @@ -186905,7 +186875,7 @@ const Temp = struct { |
| 186905 | 186875 | assert(!val_ty.optionalReprIsPayload(cg.pt.zcu)); |
| 186906 | 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 | 186880 | const first_size: u31 = @intCast(first_ty.abiSize(cg.pt.zcu)); |
| 186911 | 186881 | try dst.writeReg(opts.disp, first_ty, registerAlias(val_reg_ov.reg, first_size), cg); |
| ... | ... | @@ -186960,7 +186930,7 @@ const Temp = struct { |
| 186960 | 186930 | assert(src_regs.len == std.math.divCeil(u16, int_info.bits, 64) catch unreachable); |
| 186961 | 186931 | break :part_ty .u64; |
| 186962 | 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 | 186934 | .ptr_type => |ptr_info| { |
| 186965 | 186935 | assert(ptr_info.flags.size == .slice); |
| 186966 | 186936 | assert(src_regs.len == 2); |
| ... | ... | @@ -186971,7 +186941,7 @@ const Temp = struct { |
| 186971 | 186941 | break :part_ty try cg.pt.intType(.unsigned, @as(u16, 8) * @min(src_abi_size, 8)); |
| 186972 | 186942 | }, |
| 186973 | 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 | 186945 | .ptr_type => |ptr_info| { |
| 186976 | 186946 | assert(ptr_info.flags.size == .slice); |
| 186977 | 186947 | assert(src_regs.len == 2); |
| ... | ... | @@ -191677,12 +191647,12 @@ const Temp = struct { |
| 191677 | 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 | 191651 | cg.inst_tracking.putAssumeCapacityNoClobber(inst, .init(result)); |
| 191682 | 191652 | }, |
| 191683 | 191653 | .temp => |temp_index| { |
| 191684 | 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 | 191656 | cg.inst_tracking.putAssumeCapacityNoClobber(inst, .init(temp_tracking.short)); |
| 191687 | 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 | 191727 | const temp: Temp.Index = @enumFromInt(temp_index); |
| 191758 | 191728 | if (temp.isValid(cg)) { |
| 191759 | 191729 | any_valid = true; |
| 191760 | tracking_log.err("failed to kill {}: {}", .{ | |
| 191730 | tracking_log.err("failed to kill {f}: {f}", .{ | |
| 191761 | 191731 | temp.toIndex(), |
| 191762 | 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 | 707 | const comp = emit.bin_file.comp; |
| 708 | 708 | const gpa = comp.gpa; |
| 709 | 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 | 718 | const end_offset: u32 = @intCast(emit.code.items.len); |
| 712 | 719 | for (reloc_info) |reloc| switch (reloc.target.type) { |
| 713 | 720 | .inst => { |
src/arch/x86_64/Encoding.zig+16-15| ... | ... | @@ -158,15 +158,7 @@ pub fn modRmExt(encoding: Encoding) u3 { |
| 158 | 158 | }; |
| 159 | 159 | } |
| 160 | 160 | |
| 161 | pub fn format( | |
| 162 | encoding: Encoding, | |
| 163 | comptime fmt: []const u8, | |
| 164 | options: std.fmt.FormatOptions, | |
| 165 | writer: anytype, | |
| 166 | ) !void { | |
| 167 | _ = options; | |
| 168 | _ = fmt; | |
| 169 | ||
| 161 | pub fn format(encoding: Encoding, writer: *std.io.Writer) std.io.Writer.Error!void { | |
| 170 | 162 | var opc = encoding.opcode(); |
| 171 | 163 | if (encoding.data.mode.isVex()) { |
| 172 | 164 | try writer.writeAll("VEX."); |
| ... | ... | @@ -187,7 +179,7 @@ pub fn format( |
| 187 | 179 | }, |
| 188 | 180 | } |
| 189 | 181 | |
| 190 | try writer.print(".{}", .{std.fmt.fmtSliceHexUpper(opc[0 .. opc.len - 1])}); | |
| 182 | try writer.print(".{X}", .{opc[0 .. opc.len - 1]}); | |
| 191 | 183 | opc = opc[opc.len - 1 ..]; |
| 192 | 184 | |
| 193 | 185 | try writer.writeAll(".W"); |
| ... | ... | @@ -1014,19 +1006,28 @@ pub const Feature = enum { |
| 1014 | 1006 | }; |
| 1015 | 1007 | |
| 1016 | 1008 | fn estimateInstructionLength(prefix: Prefix, encoding: Encoding, ops: []const Operand) usize { |
| 1017 | var inst = Instruction{ | |
| 1009 | var inst: Instruction = .{ | |
| 1018 | 1010 | .prefix = prefix, |
| 1019 | 1011 | .encoding = encoding, |
| 1020 | 1012 | .ops = @splat(.none), |
| 1021 | 1013 | }; |
| 1022 | 1014 | @memcpy(inst.ops[0..ops.len], ops); |
| 1023 | 1015 | |
| 1024 | var cwriter = std.io.countingWriter(std.io.null_writer); | |
| 1025 | inst.encode(cwriter.writer(), .{ | |
| 1016 | // By using a buffer with maximum length of encoded instruction, we can use | |
| 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 | 1021 | .allow_frame_locs = true, |
| 1027 | 1022 | .allow_symbols = true, |
| 1028 | }) catch unreachable; // Not allowed to fail here unless OOM. | |
| 1029 | return @as(usize, @intCast(cwriter.bytes_written)); | |
| 1023 | }) catch { | |
| 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 | } |
| 1031 | 1032 | |
| 1032 | 1033 | const mnemonic_to_encodings_map = init: { |
src/arch/x86_64/bits.zig+2-29| ... | ... | @@ -727,23 +727,6 @@ pub const FrameIndex = enum(u32) { |
| 727 | 727 | pub fn isNamed(fi: FrameIndex) bool { |
| 728 | 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 | }; |
| 748 | 731 | |
| 749 | 732 | pub const FrameAddr = struct { index: FrameIndex, off: i32 = 0 }; |
| ... | ... | @@ -844,12 +827,7 @@ pub const Memory = struct { |
| 844 | 827 | }; |
| 845 | 828 | } |
| 846 | 829 | |
| 847 | pub fn format( | |
| 848 | s: Size, | |
| 849 | comptime _: []const u8, | |
| 850 | _: std.fmt.FormatOptions, | |
| 851 | writer: anytype, | |
| 852 | ) @TypeOf(writer).Error!void { | |
| 830 | pub fn format(s: Size, writer: *std.io.Writer) std.io.Writer.Error!void { | |
| 853 | 831 | if (s == .none) return; |
| 854 | 832 | try writer.writeAll(@tagName(s)); |
| 855 | 833 | switch (s) { |
| ... | ... | @@ -914,12 +892,7 @@ pub const Immediate = union(enum) { |
| 914 | 892 | return .{ .signed = x }; |
| 915 | 893 | } |
| 916 | 894 | |
| 917 | pub fn format( | |
| 918 | imm: Immediate, | |
| 919 | comptime _: []const u8, | |
| 920 | _: std.fmt.FormatOptions, | |
| 921 | writer: anytype, | |
| 922 | ) @TypeOf(writer).Error!void { | |
| 895 | pub fn format(imm: Immediate, writer: *std.io.Writer) std.io.Writer.Error!void { | |
| 923 | 896 | switch (imm) { |
| 924 | 897 | inline else => |int| try writer.print("{d}", .{int}), |
| 925 | 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 | 3 | const log = std.log.scoped(.x86_64_encoder); |
| 4 | 4 | const math = std.math; |
| 5 | 5 | const testing = std.testing; |
| 6 | const Writer = std.io.Writer; | |
| 6 | 7 | |
| 7 | 8 | const bits = @import("bits.zig"); |
| 8 | 9 | const Encoding = @import("Encoding.zig"); |
| ... | ... | @@ -226,101 +227,81 @@ pub const Instruction = struct { |
| 226 | 227 | }; |
| 227 | 228 | } |
| 228 | 229 | |
| 229 | fn format( | |
| 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 { | |
| 230 | const Format = struct { | |
| 243 | 231 | op: Operand, |
| 244 | 232 | enc_op: Encoding.Op, |
| 245 | }; | |
| 246 | 233 | |
| 247 | fn fmtContext( | |
| 248 | ctx: FormatContext, | |
| 249 | comptime unused_format_string: []const u8, | |
| 250 | options: std.fmt.FormatOptions, | |
| 251 | writer: anytype, | |
| 252 | ) @TypeOf(writer).Error!void { | |
| 253 | _ = unused_format_string; | |
| 254 | _ = options; | |
| 255 | const op = ctx.op; | |
| 256 | const enc_op = ctx.enc_op; | |
| 257 | switch (op) { | |
| 258 | .none => {}, | |
| 259 | .reg => |reg| try writer.writeAll(@tagName(reg)), | |
| 260 | .mem => |mem| switch (mem) { | |
| 261 | .rip => |rip| { | |
| 262 | try writer.print("{} [rip", .{rip.ptr_size}); | |
| 263 | if (rip.disp != 0) try writer.print(" {c} 0x{x}", .{ | |
| 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}); | |
| 234 | fn default(f: Format, w: *Writer) Writer.Error!void { | |
| 235 | const op = f.op; | |
| 236 | const enc_op = f.enc_op; | |
| 237 | switch (op) { | |
| 238 | .none => {}, | |
| 239 | .reg => |reg| try w.writeAll(@tagName(reg)), | |
| 240 | .mem => |mem| switch (mem) { | |
| 241 | .rip => |rip| { | |
| 242 | try w.print("{f} [rip", .{rip.ptr_size}); | |
| 243 | if (rip.disp != 0) try w.print(" {c} 0x{x}", .{ | |
| 244 | @as(u8, if (rip.disp < 0) '-' else '+'), | |
| 245 | @abs(rip.disp), | |
| 246 | }); | |
| 247 | try w.writeByte(']'); | |
| 248 | }, | |
| 249 | .sib => |sib| { | |
| 250 | try w.print("{f} ", .{sib.ptr_size}); | |
| 271 | 251 | |
| 272 | if (mem.isSegmentRegister()) { | |
| 273 | return writer.print("{s}:0x{x}", .{ @tagName(sib.base.reg), sib.disp }); | |
| 274 | } | |
| 252 | if (mem.isSegmentRegister()) { | |
| 253 | return w.print("{s}:0x{x}", .{ @tagName(sib.base.reg), sib.disp }); | |
| 254 | } | |
| 275 | 255 | |
| 276 | try writer.writeByte('['); | |
| 277 | ||
| 278 | var any = true; | |
| 279 | switch (sib.base) { | |
| 280 | .none => any = false, | |
| 281 | .reg => |reg| try writer.print("{s}", .{@tagName(reg)}), | |
| 282 | .frame => |frame_index| try writer.print("{}", .{frame_index}), | |
| 283 | .table => try writer.print("Table", .{}), | |
| 284 | .rip_inst => |inst_index| try writer.print("RipInst({d})", .{inst_index}), | |
| 285 | .nav => |nav| try writer.print("Nav({d})", .{@intFromEnum(nav)}), | |
| 286 | .uav => |uav| try writer.print("Uav({d})", .{@intFromEnum(uav.val)}), | |
| 287 | .lazy_sym => |lazy_sym| try writer.print("LazySym({s}, {d})", .{ | |
| 288 | @tagName(lazy_sym.kind), | |
| 289 | @intFromEnum(lazy_sym.ty), | |
| 290 | }), | |
| 291 | .extern_func => |extern_func| try writer.print("ExternFunc({d})", .{@intFromEnum(extern_func)}), | |
| 292 | } | |
| 293 | if (mem.scaleIndex()) |si| { | |
| 294 | if (any) try writer.writeAll(" + "); | |
| 295 | try writer.print("{s} * {d}", .{ @tagName(si.index), si.scale }); | |
| 296 | any = true; | |
| 297 | } | |
| 298 | if (sib.disp != 0 or !any) { | |
| 299 | if (any) | |
| 300 | try writer.print(" {c} ", .{@as(u8, if (sib.disp < 0) '-' else '+')}) | |
| 301 | else if (sib.disp < 0) | |
| 302 | try writer.writeByte('-'); | |
| 303 | try writer.print("0x{x}", .{@abs(sib.disp)}); | |
| 304 | any = true; | |
| 305 | } | |
| 256 | try w.writeByte('['); | |
| 257 | ||
| 258 | var any = true; | |
| 259 | switch (sib.base) { | |
| 260 | .none => any = false, | |
| 261 | .reg => |reg| try w.print("{s}", .{@tagName(reg)}), | |
| 262 | .frame => |frame_index| try w.print("{}", .{frame_index}), | |
| 263 | .table => try w.print("Table", .{}), | |
| 264 | .rip_inst => |inst_index| try w.print("RipInst({d})", .{inst_index}), | |
| 265 | .nav => |nav| try w.print("Nav({d})", .{@intFromEnum(nav)}), | |
| 266 | .uav => |uav| try w.print("Uav({d})", .{@intFromEnum(uav.val)}), | |
| 267 | .lazy_sym => |lazy_sym| try w.print("LazySym({s}, {d})", .{ | |
| 268 | @tagName(lazy_sym.kind), | |
| 269 | @intFromEnum(lazy_sym.ty), | |
| 270 | }), | |
| 271 | .extern_func => |extern_func| try w.print("ExternFunc({d})", .{@intFromEnum(extern_func)}), | |
| 272 | } | |
| 273 | if (mem.scaleIndex()) |si| { | |
| 274 | if (any) try w.writeAll(" + "); | |
| 275 | try w.print("{s} * {d}", .{ @tagName(si.index), si.scale }); | |
| 276 | any = true; | |
| 277 | } | |
| 278 | if (sib.disp != 0 or !any) { | |
| 279 | if (any) | |
| 280 | try w.print(" {c} ", .{@as(u8, if (sib.disp < 0) '-' else '+')}) | |
| 281 | else if (sib.disp < 0) | |
| 282 | try w.writeByte('-'); | |
| 283 | try w.print("0x{x}", .{@abs(sib.disp)}); | |
| 284 | any = true; | |
| 285 | } | |
| 306 | 286 | |
| 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}", .{ | |
| 310 | @tagName(moffs.seg), | |
| 311 | moffs.offset, | |
| 312 | }), | |
| 313 | }, | |
| 314 | .imm => |imm| if (enc_op.isSigned()) { | |
| 315 | const imms = imm.asSigned(enc_op.immBitSize()); | |
| 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, | |
| 294 | .imm => |imm| if (enc_op.isSigned()) { | |
| 295 | const imms = imm.asSigned(enc_op.immBitSize()); | |
| 296 | if (imms < 0) try w.writeByte('-'); | |
| 297 | try w.print("0x{x}", .{@abs(imms)}); | |
| 298 | } else try w.print("0x{x}", .{imm.asUnsigned(enc_op.immBitSize())}), | |
| 299 | .bytes => unreachable, | |
| 300 | } | |
| 320 | 301 | } |
| 321 | } | |
| 302 | }; | |
| 322 | 303 | |
| 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 | 305 | return .{ .data = .{ .op = op, .enc_op = enc_op } }; |
| 325 | 306 | } |
| 326 | 307 | }; |
| ... | ... | @@ -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}); | |
| 365 | 346 | |
| 366 | 347 | var inst: Instruction = .{ |
| 367 | 348 | .prefix = prefix, |
| ... | ... | @@ -372,30 +353,22 @@ pub const Instruction = struct { |
| 372 | 353 | return inst; |
| 373 | 354 | } |
| 374 | 355 | |
| 375 | pub fn format( | |
| 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; | |
| 356 | pub fn format(inst: Instruction, w: *Writer) Writer.Error!void { | |
| 383 | 357 | switch (inst.prefix) { |
| 384 | 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 | 362 | for (inst.ops, inst.encoding.data.ops, 0..) |op, enc, i| { |
| 389 | 363 | if (op == .none) break; |
| 390 | if (i > 0) try writer.writeByte(','); | |
| 391 | try writer.writeByte(' '); | |
| 392 | try writer.print("{}", .{op.fmt(enc)}); | |
| 364 | if (i > 0) try w.writeByte(','); | |
| 365 | try w.print(" {f}", .{op.fmt(enc)}); | |
| 393 | 366 | } |
| 394 | 367 | } |
| 395 | 368 | |
| 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 | 370 | assert(inst.prefix != .directive); |
| 398 | const encoder = Encoder(@TypeOf(writer), opts){ .writer = writer }; | |
| 371 | const encoder: Encoder(opts) = .{ .w = w }; | |
| 399 | 372 | const enc = inst.encoding; |
| 400 | 373 | const data = enc.data; |
| 401 | 374 | |
| ... | ... | @@ -801,9 +774,9 @@ pub const LegacyPrefixes = packed struct { |
| 801 | 774 | |
| 802 | 775 | pub const Options = struct { allow_frame_locs: bool = false, allow_symbols: bool = false }; |
| 803 | 776 | |
| 804 | fn Encoder(comptime T: type, comptime opts: Options) type { | |
| 777 | fn Encoder(comptime opts: Options) type { | |
| 805 | 778 | return struct { |
| 806 | writer: T, | |
| 779 | w: *Writer, | |
| 807 | 780 | |
| 808 | 781 | const Self = @This(); |
| 809 | 782 | pub const options = opts; |
| ... | ... | @@ -818,31 +791,31 @@ fn Encoder(comptime T: type, comptime opts: Options) type { |
| 818 | 791 | // Hopefully this path isn't taken very often, so we'll do it the slow way for now |
| 819 | 792 | |
| 820 | 793 | // LOCK |
| 821 | if (prefixes.prefix_f0) try self.writer.writeByte(0xf0); | |
| 794 | if (prefixes.prefix_f0) try self.w.writeByte(0xf0); | |
| 822 | 795 | // 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 | 797 | // 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); | |
| 826 | 799 | |
| 827 | 800 | // 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 | 802 | // DS segment override |
| 830 | if (prefixes.prefix_36) try self.writer.writeByte(0x36); | |
| 803 | if (prefixes.prefix_36) try self.w.writeByte(0x36); | |
| 831 | 804 | // ES segment override |
| 832 | if (prefixes.prefix_26) try self.writer.writeByte(0x26); | |
| 805 | if (prefixes.prefix_26) try self.w.writeByte(0x26); | |
| 833 | 806 | // FS segment override |
| 834 | if (prefixes.prefix_64) try self.writer.writeByte(0x64); | |
| 807 | if (prefixes.prefix_64) try self.w.writeByte(0x64); | |
| 835 | 808 | // GS segment override |
| 836 | if (prefixes.prefix_65) try self.writer.writeByte(0x65); | |
| 809 | if (prefixes.prefix_65) try self.w.writeByte(0x65); | |
| 837 | 810 | |
| 838 | 811 | // Branch taken |
| 839 | if (prefixes.prefix_3e) try self.writer.writeByte(0x3e); | |
| 812 | if (prefixes.prefix_3e) try self.w.writeByte(0x3e); | |
| 840 | 813 | |
| 841 | 814 | // Operand size override |
| 842 | if (prefixes.prefix_66) try self.writer.writeByte(0x66); | |
| 815 | if (prefixes.prefix_66) try self.w.writeByte(0x66); | |
| 843 | 816 | |
| 844 | 817 | // 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 | } |
| 848 | 821 | |
| ... | ... | @@ -850,7 +823,7 @@ fn Encoder(comptime T: type, comptime opts: Options) type { |
| 850 | 823 | /// |
| 851 | 824 | /// Note that this flag is overridden by REX.W, if both are present. |
| 852 | 825 | pub fn prefix16BitMode(self: Self) !void { |
| 853 | try self.writer.writeByte(0x66); | |
| 826 | try self.w.writeByte(0x66); | |
| 854 | 827 | } |
| 855 | 828 | |
| 856 | 829 | /// Encodes a REX prefix byte given all the fields |
| ... | ... | @@ -869,7 +842,7 @@ fn Encoder(comptime T: type, comptime opts: Options) type { |
| 869 | 842 | if (fields.x) byte |= 0b0010; |
| 870 | 843 | if (fields.b) byte |= 0b0001; |
| 871 | 844 | |
| 872 | try self.writer.writeByte(byte); | |
| 845 | try self.w.writeByte(byte); | |
| 873 | 846 | } |
| 874 | 847 | |
| 875 | 848 | /// Encodes a VEX prefix given all the fields |
| ... | ... | @@ -877,24 +850,24 @@ fn Encoder(comptime T: type, comptime opts: Options) type { |
| 877 | 850 | /// See struct `Vex` for a description of each field. |
| 878 | 851 | pub fn vex(self: Self, fields: Vex) !void { |
| 879 | 852 | if (fields.is3Byte()) { |
| 880 | try self.writer.writeByte(0b1100_0100); | |
| 853 | try self.w.writeByte(0b1100_0100); | |
| 881 | 854 | |
| 882 | try self.writer.writeByte( | |
| 855 | try self.w.writeByte( | |
| 883 | 856 | @as(u8, ~@intFromBool(fields.r)) << 7 | |
| 884 | 857 | @as(u8, ~@intFromBool(fields.x)) << 6 | |
| 885 | 858 | @as(u8, ~@intFromBool(fields.b)) << 5 | |
| 886 | 859 | @as(u8, @intFromEnum(fields.m)) << 0, |
| 887 | 860 | ); |
| 888 | 861 | |
| 889 | try self.writer.writeByte( | |
| 862 | try self.w.writeByte( | |
| 890 | 863 | @as(u8, @intFromBool(fields.w)) << 7 | |
| 891 | 864 | @as(u8, ~@as(u4, @intCast(fields.v.enc()))) << 3 | |
| 892 | 865 | @as(u8, @intFromBool(fields.l)) << 2 | |
| 893 | 866 | @as(u8, @intFromEnum(fields.p)) << 0, |
| 894 | 867 | ); |
| 895 | 868 | } else { |
| 896 | try self.writer.writeByte(0b1100_0101); | |
| 897 | try self.writer.writeByte( | |
| 869 | try self.w.writeByte(0b1100_0101); | |
| 870 | try self.w.writeByte( | |
| 898 | 871 | @as(u8, ~@intFromBool(fields.r)) << 7 | |
| 899 | 872 | @as(u8, ~@as(u4, @intCast(fields.v.enc()))) << 3 | |
| 900 | 873 | @as(u8, @intFromBool(fields.l)) << 2 | |
| ... | ... | @@ -909,7 +882,7 @@ fn Encoder(comptime T: type, comptime opts: Options) type { |
| 909 | 882 | |
| 910 | 883 | /// Encodes a 1 byte opcode |
| 911 | 884 | pub fn opcode_1byte(self: Self, opcode: u8) !void { |
| 912 | try self.writer.writeByte(opcode); | |
| 885 | try self.w.writeByte(opcode); | |
| 913 | 886 | } |
| 914 | 887 | |
| 915 | 888 | /// Encodes a 2 byte opcode |
| ... | ... | @@ -918,7 +891,7 @@ fn Encoder(comptime T: type, comptime opts: Options) type { |
| 918 | 891 | /// |
| 919 | 892 | /// encoder.opcode_2byte(0x0f, 0xaf); |
| 920 | 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 | } |
| 923 | 896 | |
| 924 | 897 | /// Encodes a 3 byte opcode |
| ... | ... | @@ -927,7 +900,7 @@ fn Encoder(comptime T: type, comptime opts: Options) type { |
| 927 | 900 | /// |
| 928 | 901 | /// encoder.opcode_3byte(0xf2, 0x0f, 0x10); |
| 929 | 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 | } |
| 932 | 905 | |
| 933 | 906 | /// Encodes a 1 byte opcode with a reg field |
| ... | ... | @@ -935,7 +908,7 @@ fn Encoder(comptime T: type, comptime opts: Options) type { |
| 935 | 908 | /// Remember to add a REX prefix byte if reg is extended! |
| 936 | 909 | pub fn opcode_withReg(self: Self, opcode: u8, reg: u3) !void { |
| 937 | 910 | assert(opcode & 0b111 == 0); |
| 938 | try self.writer.writeByte(opcode | reg); | |
| 911 | try self.w.writeByte(opcode | reg); | |
| 939 | 912 | } |
| 940 | 913 | |
| 941 | 914 | // ------ |
| ... | ... | @@ -946,7 +919,7 @@ fn Encoder(comptime T: type, comptime opts: Options) type { |
| 946 | 919 | /// |
| 947 | 920 | /// Remember to add a REX prefix byte if reg or rm are extended! |
| 948 | 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 | } |
| 951 | 924 | |
| 952 | 925 | /// Construct a ModR/M byte using direct r/m addressing |
| ... | ... | @@ -1032,7 +1005,7 @@ fn Encoder(comptime T: type, comptime opts: Options) type { |
| 1032 | 1005 | /// |
| 1033 | 1006 | /// Remember to add a REX prefix byte if index or base are extended! |
| 1034 | 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 | } |
| 1037 | 1010 | |
| 1038 | 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 | 1097 | /// |
| 1125 | 1098 | /// It is sign-extended to 64 bits by the cpu. |
| 1126 | 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 | } |
| 1129 | 1102 | |
| 1130 | 1103 | /// Encode an 32 bit displacement |
| 1131 | 1104 | /// |
| 1132 | 1105 | /// It is sign-extended to 64 bits by the cpu. |
| 1133 | 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 | } |
| 1136 | 1109 | |
| 1137 | 1110 | /// Encode an 8 bit immediate |
| 1138 | 1111 | /// |
| 1139 | 1112 | /// It is sign-extended to 64 bits by the cpu. |
| 1140 | 1113 | pub fn imm8(self: Self, imm: u8) !void { |
| 1141 | try self.writer.writeByte(imm); | |
| 1114 | try self.w.writeByte(imm); | |
| 1142 | 1115 | } |
| 1143 | 1116 | |
| 1144 | 1117 | /// Encode an 16 bit immediate |
| 1145 | 1118 | /// |
| 1146 | 1119 | /// It is sign-extended to 64 bits by the cpu. |
| 1147 | 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 | } |
| 1150 | 1123 | |
| 1151 | 1124 | /// Encode an 32 bit immediate |
| 1152 | 1125 | /// |
| 1153 | 1126 | /// It is sign-extended to 64 bits by the cpu. |
| 1154 | 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 | } |
| 1157 | 1130 | |
| 1158 | 1131 | /// Encode an 64 bit immediate |
| 1159 | 1132 | /// |
| 1160 | 1133 | /// It is sign-extended to 64 bits by the cpu. |
| 1161 | 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 | 1178 | fn expectEqualHexStrings(expected: []const u8, given: []const u8, assembly: []const u8) !void { |
| 1206 | 1179 | assert(expected.len > 0); |
| 1207 | 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 | 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 | 1184 | defer testing.allocator.free(given_fmt); |
| 1212 | 1185 | const idx = std.mem.indexOfDiff(u8, expected_fmt, given_fmt).?; |
| 1213 | 1186 | const padding = try testing.allocator.alloc(u8, idx + 5); |
| ... | ... | @@ -2217,10 +2190,10 @@ const Assembler = struct { |
| 2217 | 2190 | }; |
| 2218 | 2191 | } |
| 2219 | 2192 | |
| 2220 | pub fn assemble(as: *Assembler, writer: anytype) !void { | |
| 2193 | pub fn assemble(as: *Assembler, w: *Writer) !void { | |
| 2221 | 2194 | while (try as.next()) |parsed_inst| { |
| 2222 | 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 | } |
| 2226 | 2199 |
src/codegen.zig+6-6| ... | ... | @@ -237,7 +237,7 @@ pub fn generateLazySymbol( |
| 237 | 237 | const target = &comp.root_mod.resolved_target.result; |
| 238 | 238 | const endian = target.cpu.arch.endian(); |
| 239 | 239 | |
| 240 | log.debug("generateLazySymbol: kind = {s}, ty = {}", .{ | |
| 240 | log.debug("generateLazySymbol: kind = {s}, ty = {f}", .{ | |
| 241 | 241 | @tagName(lazy_sym.kind), |
| 242 | 242 | Type.fromInterned(lazy_sym.ty).fmt(pt), |
| 243 | 243 | }); |
| ... | ... | @@ -277,7 +277,7 @@ pub fn generateLazySymbol( |
| 277 | 277 | code.appendAssumeCapacity(0); |
| 278 | 278 | } |
| 279 | 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 | 281 | @tagName(lazy_sym.kind), Type.fromInterned(lazy_sym.ty).fmt(pt), |
| 282 | 282 | }); |
| 283 | 283 | } |
| ... | ... | @@ -310,7 +310,7 @@ pub fn generateSymbol( |
| 310 | 310 | const target = zcu.getTarget(); |
| 311 | 311 | const endian = target.cpu.arch.endian(); |
| 312 | 312 | |
| 313 | log.debug("generateSymbol: val = {}", .{val.fmtValue(pt)}); | |
| 313 | log.debug("generateSymbol: val = {f}", .{val.fmtValue(pt)}); | |
| 314 | 314 | |
| 315 | 315 | if (val.isUndefDeep(zcu)) { |
| 316 | 316 | const abi_size = math.cast(usize, ty.abiSize(zcu)) orelse return error.Overflow; |
| ... | ... | @@ -767,7 +767,7 @@ fn lowerUavRef( |
| 767 | 767 | const uav_ty = Type.fromInterned(ip.typeOf(uav_val)); |
| 768 | 768 | const is_fn_body = uav_ty.zigTypeTag(zcu) == .@"fn"; |
| 769 | 769 | |
| 770 | log.debug("lowerUavRef: ty = {}", .{uav_ty.fmt(pt)}); | |
| 770 | log.debug("lowerUavRef: ty = {f}", .{uav_ty.fmt(pt)}); | |
| 771 | 771 | try code.ensureUnusedCapacity(gpa, ptr_width_bytes); |
| 772 | 772 | |
| 773 | 773 | if (!is_fn_body and !uav_ty.hasRuntimeBits(zcu)) { |
| ... | ... | @@ -913,7 +913,7 @@ pub fn genNavRef( |
| 913 | 913 | const zcu = pt.zcu; |
| 914 | 914 | const ip = &zcu.intern_pool; |
| 915 | 915 | const nav = ip.getNav(nav_index); |
| 916 | log.debug("genNavRef({})", .{nav.fqn.fmt(ip)}); | |
| 916 | log.debug("genNavRef({f})", .{nav.fqn.fmt(ip)}); | |
| 917 | 917 | |
| 918 | 918 | const lib_name, const linkage, const is_threadlocal = if (nav.getExtern(ip)) |e| |
| 919 | 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 | 1065 | const ip = &zcu.intern_pool; |
| 1066 | 1066 | const ty = val.typeOf(zcu); |
| 1067 | 1067 | |
| 1068 | log.debug("lowerValue(@as({}, {}))", .{ ty.fmt(pt), val.fmtValue(pt) }); | |
| 1068 | log.debug("lowerValue(@as({f}, {f}))", .{ ty.fmt(pt), val.fmtValue(pt) }); | |
| 1069 | 1069 | |
| 1070 | 1070 | if (val.isUndef(zcu)) return .undef; |
| 1071 | 1071 |
src/codegen/c.zig+2215-2164| ... | ... | @@ -4,6 +4,7 @@ const assert = std.debug.assert; |
| 4 | 4 | const mem = std.mem; |
| 5 | 5 | const log = std.log.scoped(.c); |
| 6 | 6 | const Allocator = mem.Allocator; |
| 7 | const Writer = std.io.Writer; | |
| 7 | 8 | |
| 8 | 9 | const dev = @import("../dev.zig"); |
| 9 | 10 | const link = @import("../link.zig"); |
| ... | ... | @@ -55,6 +56,7 @@ pub const Mir = struct { |
| 55 | 56 | /// less than the natural alignment. |
| 56 | 57 | uavs: std.AutoArrayHashMapUnmanaged(InternPool.Index, Alignment), |
| 57 | 58 | // These remaining fields are essentially just an owned version of `link.C.AvBlock`. |
| 59 | code_header: []u8, | |
| 58 | 60 | code: []u8, |
| 59 | 61 | fwd_decl: []u8, |
| 60 | 62 | ctype_pool: CType.Pool, |
| ... | ... | @@ -62,6 +64,7 @@ pub const Mir = struct { |
| 62 | 64 | |
| 63 | 65 | pub fn deinit(mir: *Mir, gpa: Allocator) void { |
| 64 | 66 | mir.uavs.deinit(gpa); |
| 67 | gpa.free(mir.code_header); | |
| 65 | 68 | gpa.free(mir.code); |
| 66 | 69 | gpa.free(mir.fwd_decl); |
| 67 | 70 | mir.ctype_pool.deinit(gpa); |
| ... | ... | @@ -69,6 +72,8 @@ pub const Mir = struct { |
| 69 | 72 | } |
| 70 | 73 | }; |
| 71 | 74 | |
| 75 | pub const Error = Writer.Error || std.mem.Allocator.Error || error{AnalysisFail}; | |
| 76 | ||
| 72 | 77 | pub const CType = @import("c/Type.zig"); |
| 73 | 78 | |
| 74 | 79 | pub const CValue = union(enum) { |
| ... | ... | @@ -340,53 +345,61 @@ fn isReservedIdent(ident: []const u8) bool { |
| 340 | 345 | } else return reserved_idents.has(ident); |
| 341 | 346 | } |
| 342 | 347 | |
| 343 | fn formatIdent( | |
| 344 | ident: []const u8, | |
| 345 | comptime fmt_str: []const u8, | |
| 346 | _: std.fmt.FormatOptions, | |
| 347 | writer: anytype, | |
| 348 | ) @TypeOf(writer).Error!void { | |
| 349 | const solo = fmt_str.len != 0 and fmt_str[0] == ' '; // space means solo; not part of a bigger ident. | |
| 348 | fn formatIdentSolo(ident: []const u8, w: *std.io.Writer) std.io.Writer.Error!void { | |
| 349 | return formatIdentOptions(ident, w, true); | |
| 350 | } | |
| 351 | ||
| 352 | fn formatIdentUnsolo(ident: []const u8, w: *std.io.Writer) std.io.Writer.Error!void { | |
| 353 | return formatIdentOptions(ident, w, false); | |
| 354 | } | |
| 355 | ||
| 356 | fn formatIdentOptions(ident: []const u8, w: *std.io.Writer, solo: bool) std.io.Writer.Error!void { | |
| 350 | 357 | if (solo and isReservedIdent(ident)) { |
| 351 | try writer.writeAll("zig_e_"); | |
| 358 | try w.writeAll("zig_e_"); | |
| 352 | 359 | } |
| 353 | 360 | for (ident, 0..) |c, i| { |
| 354 | 361 | switch (c) { |
| 355 | 'a'...'z', 'A'...'Z', '_' => try writer.writeByte(c), | |
| 356 | '.' => try writer.writeByte('_'), | |
| 362 | 'a'...'z', 'A'...'Z', '_' => try w.writeByte(c), | |
| 363 | '.' => try w.writeByte('_'), | |
| 357 | 364 | '0'...'9' => if (i == 0) { |
| 358 | try writer.print("_{x:2}", .{c}); | |
| 365 | try w.print("_{x:2}", .{c}); | |
| 359 | 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 | } |
| 366 | pub fn fmtIdent(ident: []const u8) std.fmt.Formatter(formatIdent) { | |
| 373 | ||
| 374 | pub fn fmtIdentSolo(ident: []const u8) std.fmt.Formatter([]const u8, formatIdentSolo) { | |
| 375 | return .{ .data = ident }; | |
| 376 | } | |
| 377 | ||
| 378 | pub fn fmtIdentUnsolo(ident: []const u8) std.fmt.Formatter([]const u8, formatIdentUnsolo) { | |
| 367 | 379 | return .{ .data = ident }; |
| 368 | 380 | } |
| 369 | 381 | |
| 370 | 382 | const CTypePoolStringFormatData = struct { |
| 371 | 383 | ctype_pool_string: CType.Pool.String, |
| 372 | 384 | ctype_pool: *const CType.Pool, |
| 385 | solo: bool, | |
| 373 | 386 | }; |
| 374 | fn formatCTypePoolString( | |
| 375 | data: CTypePoolStringFormatData, | |
| 376 | comptime fmt_str: []const u8, | |
| 377 | fmt_opts: std.fmt.FormatOptions, | |
| 378 | writer: anytype, | |
| 379 | ) @TypeOf(writer).Error!void { | |
| 387 | fn formatCTypePoolString(data: CTypePoolStringFormatData, w: *std.io.Writer) std.io.Writer.Error!void { | |
| 380 | 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 | 390 | 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 | } |
| 385 | 393 | pub fn fmtCTypePoolString( |
| 386 | 394 | ctype_pool_string: CType.Pool.String, |
| 387 | 395 | ctype_pool: *const CType.Pool, |
| 388 | ) std.fmt.Formatter(formatCTypePoolString) { | |
| 389 | return .{ .data = .{ .ctype_pool_string = ctype_pool_string, .ctype_pool = ctype_pool } }; | |
| 396 | solo: bool, | |
| 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 | } |
| 391 | 404 | |
| 392 | 405 | // Returns true if `formatIdent` would make any edits to ident. |
| ... | ... | @@ -440,18 +453,18 @@ pub const Function = struct { |
| 440 | 453 | const ty = f.typeOf(ref); |
| 441 | 454 | |
| 442 | 455 | const result: CValue = if (lowersToArray(ty, pt)) result: { |
| 443 | const writer = f.object.codeHeaderWriter(); | |
| 456 | const ch = &f.object.code_header.writer; | |
| 444 | 457 | const decl_c_value = try f.allocLocalValue(.{ |
| 445 | 458 | .ctype = try f.ctypeFromType(ty, .complete), |
| 446 | 459 | .alignas = CType.AlignAs.fromAbiAlignment(ty.abiAlignment(pt.zcu)), |
| 447 | 460 | }); |
| 448 | 461 | const gpa = f.object.dg.gpa; |
| 449 | 462 | try f.allocs.put(gpa, decl_c_value.new_local, false); |
| 450 | try writer.writeAll("static "); | |
| 451 | try f.object.dg.renderTypeAndName(writer, ty, decl_c_value, Const, .none, .complete); | |
| 452 | try writer.writeAll(" = "); | |
| 453 | try f.object.dg.renderValue(writer, val, .StaticInitializer); | |
| 454 | try writer.writeAll(";\n "); | |
| 463 | try ch.writeAll("static "); | |
| 464 | try f.object.dg.renderTypeAndName(ch, ty, decl_c_value, Const, .none, .complete); | |
| 465 | try ch.writeAll(" = "); | |
| 466 | try f.object.dg.renderValue(ch, val, .StaticInitializer); | |
| 467 | try ch.writeAll(";\n "); | |
| 455 | 468 | break :result .{ .local = decl_c_value.new_local }; |
| 456 | 469 | } else .{ .constant = val }; |
| 457 | 470 | |
| ... | ... | @@ -504,7 +517,7 @@ pub const Function = struct { |
| 504 | 517 | return result; |
| 505 | 518 | } |
| 506 | 519 | |
| 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 | 521 | switch (c_value) { |
| 509 | 522 | .none => unreachable, |
| 510 | 523 | .new_local, .local => |i| try w.print("t{d}", .{i}), |
| ... | ... | @@ -517,7 +530,7 @@ pub const Function = struct { |
| 517 | 530 | } |
| 518 | 531 | } |
| 519 | 532 | |
| 520 | fn writeCValueDeref(f: *Function, w: anytype, c_value: CValue) !void { | |
| 533 | fn writeCValueDeref(f: *Function, w: *Writer, c_value: CValue) !void { | |
| 521 | 534 | switch (c_value) { |
| 522 | 535 | .none => unreachable, |
| 523 | 536 | .new_local, .local, .constant => { |
| ... | ... | @@ -538,41 +551,41 @@ pub const Function = struct { |
| 538 | 551 | |
| 539 | 552 | fn writeCValueMember( |
| 540 | 553 | f: *Function, |
| 541 | writer: anytype, | |
| 554 | w: *Writer, | |
| 542 | 555 | c_value: CValue, |
| 543 | 556 | member: CValue, |
| 544 | ) error{ OutOfMemory, AnalysisFail }!void { | |
| 557 | ) Error!void { | |
| 545 | 558 | switch (c_value) { |
| 546 | 559 | .new_local, .local, .local_ref, .constant, .arg, .arg_array => { |
| 547 | try f.writeCValue(writer, c_value, .Other); | |
| 548 | try writer.writeByte('.'); | |
| 549 | try f.writeCValue(writer, member, .Other); | |
| 560 | try f.writeCValue(w, c_value, .Other); | |
| 561 | try w.writeByte('.'); | |
| 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 | } |
| 554 | 567 | |
| 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 | 569 | switch (c_value) { |
| 557 | 570 | .new_local, .local, .arg, .arg_array => { |
| 558 | try f.writeCValue(writer, c_value, .Other); | |
| 559 | try writer.writeAll("->"); | |
| 571 | try f.writeCValue(w, c_value, .Other); | |
| 572 | try w.writeAll("->"); | |
| 560 | 573 | }, |
| 561 | 574 | .constant => { |
| 562 | try writer.writeByte('('); | |
| 563 | try f.writeCValue(writer, c_value, .Other); | |
| 564 | try writer.writeAll(")->"); | |
| 575 | try w.writeByte('('); | |
| 576 | try f.writeCValue(w, c_value, .Other); | |
| 577 | try w.writeAll(")->"); | |
| 565 | 578 | }, |
| 566 | 579 | .local_ref => { |
| 567 | try f.writeCValueDeref(writer, c_value); | |
| 568 | try writer.writeByte('.'); | |
| 580 | try f.writeCValueDeref(w, c_value); | |
| 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 | } |
| 574 | 587 | |
| 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 | 589 | return f.object.dg.fail(format, args); |
| 577 | 590 | } |
| 578 | 591 | |
| ... | ... | @@ -584,20 +597,24 @@ pub const Function = struct { |
| 584 | 597 | return f.object.dg.byteSize(ctype); |
| 585 | 598 | } |
| 586 | 599 | |
| 587 | fn renderType(f: *Function, w: anytype, ctype: Type) !void { | |
| 600 | fn renderType(f: *Function, w: *Writer, ctype: Type) !void { | |
| 588 | 601 | return f.object.dg.renderType(w, ctype); |
| 589 | 602 | } |
| 590 | 603 | |
| 591 | fn renderCType(f: *Function, w: anytype, ctype: CType) !void { | |
| 604 | fn renderCType(f: *Function, w: *Writer, ctype: CType) !void { | |
| 592 | 605 | return f.object.dg.renderCType(w, ctype); |
| 593 | 606 | } |
| 594 | 607 | |
| 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 | 609 | return f.object.dg.renderIntCast(w, dest_ty, .{ .c_value = .{ .f = f, .value = src, .v = v } }, src_ty, location); |
| 597 | 610 | } |
| 598 | 611 | |
| 599 | fn fmtIntLiteral(f: *Function, val: Value) !std.fmt.Formatter(formatIntLiteral) { | |
| 600 | return f.object.dg.fmtIntLiteral(val, .Other); | |
| 612 | fn fmtIntLiteralDec(f: *Function, val: Value) !std.fmt.Formatter(FormatIntLiteralContext, formatIntLiteral) { | |
| 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 | } |
| 602 | 619 | |
| 603 | 620 | fn getLazyFnName(f: *Function, key: LazyFnKey) ![]const u8 { |
| ... | ... | @@ -614,16 +631,16 @@ pub const Function = struct { |
| 614 | 631 | gop.value_ptr.* = .{ |
| 615 | 632 | .fn_name = switch (key) { |
| 616 | 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 | 635 | @tagName(key), |
| 619 | fmtIdent(ip.loadEnumType(enum_ty).name.toSlice(ip)), | |
| 636 | fmtIdentUnsolo(ip.loadEnumType(enum_ty).name.toSlice(ip)), | |
| 620 | 637 | @intFromEnum(enum_ty), |
| 621 | 638 | }), |
| 622 | 639 | .never_tail, |
| 623 | 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 | 642 | @tagName(key), |
| 626 | fmtIdent(ip.getNav(owner_nav).name.toSlice(ip)), | |
| 643 | fmtIdentUnsolo(ip.getNav(owner_nav).name.toSlice(ip)), | |
| 627 | 644 | @intFromEnum(owner_nav), |
| 628 | 645 | }), |
| 629 | 646 | }, |
| ... | ... | @@ -659,12 +676,12 @@ pub const Function = struct { |
| 659 | 676 | }, |
| 660 | 677 | else => {}, |
| 661 | 678 | } |
| 662 | const writer = f.object.writer(); | |
| 663 | const a = try Assignment.start(f, writer, ctype); | |
| 664 | try f.writeCValue(writer, dst, .Other); | |
| 665 | try a.assign(f, writer); | |
| 666 | try f.writeCValue(writer, src, .Other); | |
| 667 | try a.end(f, writer); | |
| 679 | const w = &f.object.code.writer; | |
| 680 | const a = try Assignment.start(f, w, ctype); | |
| 681 | try f.writeCValue(w, dst, .Other); | |
| 682 | try a.assign(f, w); | |
| 683 | try f.writeCValue(w, src, .Other); | |
| 684 | try a.end(f, w); | |
| 668 | 685 | } |
| 669 | 686 | |
| 670 | 687 | fn moveCValue(f: *Function, inst: Air.Inst.Index, ty: Type, src: CValue) !CValue { |
| ... | ... | @@ -693,18 +710,32 @@ pub const Function = struct { |
| 693 | 710 | /// It is not available when generating .h file. |
| 694 | 711 | pub const Object = struct { |
| 695 | 712 | dg: DeclGen, |
| 696 | /// This is a borrowed reference from `link.C`. | |
| 697 | code: std.ArrayList(u8), | |
| 698 | /// Goes before code. Initialized and deinitialized in `genFunc`. | |
| 699 | code_header: std.ArrayList(u8) = undefined, | |
| 700 | indent_writer: IndentWriter(std.ArrayList(u8).Writer), | |
| 701 | ||
| 702 | fn writer(o: *Object) IndentWriter(std.ArrayList(u8).Writer).Writer { | |
| 703 | return o.indent_writer.writer(); | |
| 704 | } | |
| 705 | ||
| 706 | fn codeHeaderWriter(o: *Object) ArrayListWriter { | |
| 707 | return arrayListWriter(&o.code_header); | |
| 713 | code_header: std.io.Writer.Allocating, | |
| 714 | code: std.io.Writer.Allocating, | |
| 715 | indent_counter: usize, | |
| 716 | ||
| 717 | const indent_width = 1; | |
| 718 | const indent_char = ' '; | |
| 719 | ||
| 720 | fn newline(o: *Object) !void { | |
| 721 | const w = &o.code.writer; | |
| 722 | try w.writeByte('\n'); | |
| 723 | try w.splatByteAll(indent_char, o.indent_counter); | |
| 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 | }; |
| 710 | 741 | |
| ... | ... | @@ -716,8 +747,7 @@ pub const DeclGen = struct { |
| 716 | 747 | pass: Pass, |
| 717 | 748 | is_naked_fn: bool, |
| 718 | 749 | expected_block: ?u32, |
| 719 | /// This is a borrowed reference from `link.C`. | |
| 720 | fwd_decl: std.ArrayList(u8), | |
| 750 | fwd_decl: std.io.Writer.Allocating, | |
| 721 | 751 | error_msg: ?*Zcu.ErrorMsg, |
| 722 | 752 | ctype_pool: CType.Pool, |
| 723 | 753 | scratch: std.ArrayListUnmanaged(u32), |
| ... | ... | @@ -734,11 +764,7 @@ pub const DeclGen = struct { |
| 734 | 764 | flush, |
| 735 | 765 | }; |
| 736 | 766 | |
| 737 | fn fwdDeclWriter(dg: *DeclGen) ArrayListWriter { | |
| 738 | return arrayListWriter(&dg.fwd_decl); | |
| 739 | } | |
| 740 | ||
| 741 | fn fail(dg: *DeclGen, comptime format: []const u8, args: anytype) error{ AnalysisFail, OutOfMemory } { | |
| 767 | fn fail(dg: *DeclGen, comptime format: []const u8, args: anytype) Error { | |
| 742 | 768 | @branchHint(.cold); |
| 743 | 769 | const zcu = dg.pt.zcu; |
| 744 | 770 | const src_loc = zcu.navSrcLoc(dg.pass.nav); |
| ... | ... | @@ -748,10 +774,10 @@ pub const DeclGen = struct { |
| 748 | 774 | |
| 749 | 775 | fn renderUav( |
| 750 | 776 | dg: *DeclGen, |
| 751 | writer: anytype, | |
| 777 | w: *Writer, | |
| 752 | 778 | uav: InternPool.Key.Ptr.BaseAddr.Uav, |
| 753 | 779 | location: ValueRenderLocation, |
| 754 | ) error{ OutOfMemory, AnalysisFail }!void { | |
| 780 | ) Error!void { | |
| 755 | 781 | const pt = dg.pt; |
| 756 | 782 | const zcu = pt.zcu; |
| 757 | 783 | const ip = &zcu.intern_pool; |
| ... | ... | @@ -762,14 +788,14 @@ pub const DeclGen = struct { |
| 762 | 788 | // Render an undefined pointer if we have a pointer to a zero-bit or comptime type. |
| 763 | 789 | const ptr_ty: Type = .fromInterned(uav.orig_ty); |
| 764 | 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 | } |
| 767 | 793 | |
| 768 | 794 | // Chase function values in order to be able to reference the original function. |
| 769 | 795 | switch (ip.indexToKey(uav.val)) { |
| 770 | 796 | .variable => unreachable, |
| 771 | .func => |func| return dg.renderNav(writer, func.owner_nav, location), | |
| 772 | .@"extern" => |@"extern"| return dg.renderNav(writer, @"extern".owner_nav, location), | |
| 797 | .func => |func| return dg.renderNav(w, func.owner_nav, location), | |
| 798 | .@"extern" => |@"extern"| return dg.renderNav(w, @"extern".owner_nav, location), | |
| 773 | 799 | else => {}, |
| 774 | 800 | } |
| 775 | 801 | |
| ... | ... | @@ -783,13 +809,13 @@ pub const DeclGen = struct { |
| 783 | 809 | const need_cast = !elem_ctype.eql(uav_ctype) and |
| 784 | 810 | (elem_ctype.info(ctype_pool) != .function or uav_ctype.info(ctype_pool) != .function); |
| 785 | 811 | if (need_cast) { |
| 786 | try writer.writeAll("(("); | |
| 787 | try dg.renderCType(writer, ptr_ctype); | |
| 788 | try writer.writeByte(')'); | |
| 812 | try w.writeAll("(("); | |
| 813 | try dg.renderCType(w, ptr_ctype); | |
| 814 | try w.writeByte(')'); | |
| 789 | 815 | } |
| 790 | try writer.writeByte('&'); | |
| 791 | try renderUavName(writer, uav_val); | |
| 792 | if (need_cast) try writer.writeByte(')'); | |
| 816 | try w.writeByte('&'); | |
| 817 | try renderUavName(w, uav_val); | |
| 818 | if (need_cast) try w.writeByte(')'); | |
| 793 | 819 | |
| 794 | 820 | // Indicate that the anon decl should be rendered to the output so that |
| 795 | 821 | // our reference above is not undefined. |
| ... | ... | @@ -810,10 +836,10 @@ pub const DeclGen = struct { |
| 810 | 836 | |
| 811 | 837 | fn renderNav( |
| 812 | 838 | dg: *DeclGen, |
| 813 | writer: anytype, | |
| 839 | w: *Writer, | |
| 814 | 840 | nav_index: InternPool.Nav.Index, |
| 815 | 841 | location: ValueRenderLocation, |
| 816 | ) error{ OutOfMemory, AnalysisFail }!void { | |
| 842 | ) Error!void { | |
| 817 | 843 | _ = location; |
| 818 | 844 | const pt = dg.pt; |
| 819 | 845 | const zcu = pt.zcu; |
| ... | ... | @@ -835,7 +861,7 @@ pub const DeclGen = struct { |
| 835 | 861 | const nav_ty: Type = .fromInterned(ip.getNav(owner_nav).typeOf(ip)); |
| 836 | 862 | const ptr_ty = try pt.navPtrType(owner_nav); |
| 837 | 863 | if (!nav_ty.isFnOrHasRuntimeBits(zcu)) { |
| 838 | return dg.writeCValue(writer, .{ .undef = ptr_ty }); | |
| 864 | return dg.writeCValue(w, .{ .undef = ptr_ty }); | |
| 839 | 865 | } |
| 840 | 866 | |
| 841 | 867 | // We shouldn't cast C function pointers as this is UB (when you call |
| ... | ... | @@ -848,21 +874,21 @@ pub const DeclGen = struct { |
| 848 | 874 | const need_cast = !elem_ctype.eql(nav_ctype) and |
| 849 | 875 | (elem_ctype.info(ctype_pool) != .function or nav_ctype.info(ctype_pool) != .function); |
| 850 | 876 | if (need_cast) { |
| 851 | try writer.writeAll("(("); | |
| 852 | try dg.renderCType(writer, ctype); | |
| 853 | try writer.writeByte(')'); | |
| 877 | try w.writeAll("(("); | |
| 878 | try dg.renderCType(w, ctype); | |
| 879 | try w.writeByte(')'); | |
| 854 | 880 | } |
| 855 | try writer.writeByte('&'); | |
| 856 | try dg.renderNavName(writer, owner_nav); | |
| 857 | if (need_cast) try writer.writeByte(')'); | |
| 881 | try w.writeByte('&'); | |
| 882 | try dg.renderNavName(w, owner_nav); | |
| 883 | if (need_cast) try w.writeByte(')'); | |
| 858 | 884 | } |
| 859 | 885 | |
| 860 | 886 | fn renderPointer( |
| 861 | 887 | dg: *DeclGen, |
| 862 | writer: anytype, | |
| 888 | w: *Writer, | |
| 863 | 889 | derivation: Value.PointerDeriveStep, |
| 864 | 890 | location: ValueRenderLocation, |
| 865 | ) error{ OutOfMemory, AnalysisFail }!void { | |
| 891 | ) Error!void { | |
| 866 | 892 | const pt = dg.pt; |
| 867 | 893 | const zcu = pt.zcu; |
| 868 | 894 | switch (derivation) { |
| ... | ... | @@ -870,18 +896,18 @@ pub const DeclGen = struct { |
| 870 | 896 | .int => |int| { |
| 871 | 897 | const ptr_ctype = try dg.ctypeFromType(int.ptr_ty, .complete); |
| 872 | 898 | const addr_val = try pt.intValue(.usize, int.addr); |
| 873 | try writer.writeByte('('); | |
| 874 | try dg.renderCType(writer, ptr_ctype); | |
| 875 | try writer.print("){x}", .{try dg.fmtIntLiteral(addr_val, .Other)}); | |
| 899 | try w.writeByte('('); | |
| 900 | try dg.renderCType(w, ptr_ctype); | |
| 901 | try w.print("){f}", .{try dg.fmtIntLiteralHex(addr_val, .Other)}); | |
| 876 | 902 | }, |
| 877 | 903 | |
| 878 | .nav_ptr => |nav| try dg.renderNav(writer, nav, location), | |
| 879 | .uav_ptr => |uav| try dg.renderUav(writer, uav, location), | |
| 904 | .nav_ptr => |nav| try dg.renderNav(w, nav, location), | |
| 905 | .uav_ptr => |uav| try dg.renderUav(w, uav, location), | |
| 880 | 906 | |
| 881 | 907 | inline .eu_payload_ptr, .opt_payload_ptr => |info| { |
| 882 | try writer.writeAll("&("); | |
| 883 | try dg.renderPointer(writer, info.parent.*, location); | |
| 884 | try writer.writeAll(")->payload"); | |
| 908 | try w.writeAll("&("); | |
| 909 | try dg.renderPointer(w, info.parent.*, location); | |
| 910 | try w.writeAll(")->payload"); | |
| 885 | 911 | }, |
| 886 | 912 | |
| 887 | 913 | .field_ptr => |field| { |
| ... | ... | @@ -893,26 +919,26 @@ pub const DeclGen = struct { |
| 893 | 919 | switch (fieldLocation(parent_ptr_ty, field.result_ptr_ty, field.field_idx, pt)) { |
| 894 | 920 | .begin => { |
| 895 | 921 | const ptr_ctype = try dg.ctypeFromType(field.result_ptr_ty, .complete); |
| 896 | try writer.writeByte('('); | |
| 897 | try dg.renderCType(writer, ptr_ctype); | |
| 898 | try writer.writeByte(')'); | |
| 899 | try dg.renderPointer(writer, field.parent.*, location); | |
| 922 | try w.writeByte('('); | |
| 923 | try dg.renderCType(w, ptr_ctype); | |
| 924 | try w.writeByte(')'); | |
| 925 | try dg.renderPointer(w, field.parent.*, location); | |
| 900 | 926 | }, |
| 901 | 927 | .field => |name| { |
| 902 | try writer.writeAll("&("); | |
| 903 | try dg.renderPointer(writer, field.parent.*, location); | |
| 904 | try writer.writeAll(")->"); | |
| 905 | try dg.writeCValue(writer, name); | |
| 928 | try w.writeAll("&("); | |
| 929 | try dg.renderPointer(w, field.parent.*, location); | |
| 930 | try w.writeAll(")->"); | |
| 931 | try dg.writeCValue(w, name); | |
| 906 | 932 | }, |
| 907 | 933 | .byte_offset => |byte_offset| { |
| 908 | 934 | const ptr_ctype = try dg.ctypeFromType(field.result_ptr_ty, .complete); |
| 909 | try writer.writeByte('('); | |
| 910 | try dg.renderCType(writer, ptr_ctype); | |
| 911 | try writer.writeByte(')'); | |
| 935 | try w.writeByte('('); | |
| 936 | try dg.renderCType(w, ptr_ctype); | |
| 937 | try w.writeByte(')'); | |
| 912 | 938 | const offset_val = try pt.intValue(.usize, byte_offset); |
| 913 | try writer.writeAll("((char *)"); | |
| 914 | try dg.renderPointer(writer, field.parent.*, location); | |
| 915 | try writer.print(" + {})", .{try dg.fmtIntLiteral(offset_val, .Other)}); | |
| 939 | try w.writeAll("((char *)"); | |
| 940 | try dg.renderPointer(w, field.parent.*, location); | |
| 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 | 946 | .elem_ptr => |elem| if (!(try elem.parent.ptrType(pt)).childType(zcu).hasRuntimeBits(zcu)) { |
| 921 | 947 | // Element type is zero-bit, so lowers to `void`. The index is irrelevant; just cast the pointer. |
| 922 | 948 | const ptr_ctype = try dg.ctypeFromType(elem.result_ptr_ty, .complete); |
| 923 | try writer.writeByte('('); | |
| 924 | try dg.renderCType(writer, ptr_ctype); | |
| 925 | try writer.writeByte(')'); | |
| 926 | try dg.renderPointer(writer, elem.parent.*, location); | |
| 949 | try w.writeByte('('); | |
| 950 | try dg.renderCType(w, ptr_ctype); | |
| 951 | try w.writeByte(')'); | |
| 952 | try dg.renderPointer(w, elem.parent.*, location); | |
| 927 | 953 | } else { |
| 928 | 954 | const index_val = try pt.intValue(.usize, elem.elem_idx); |
| 929 | 955 | // We want to do pointer arithmetic on a pointer to the element type. |
| ... | ... | @@ -932,48 +958,47 @@ pub const DeclGen = struct { |
| 932 | 958 | const parent_ctype = try dg.ctypeFromType(try elem.parent.ptrType(pt), .complete); |
| 933 | 959 | if (result_ctype.eql(parent_ctype)) { |
| 934 | 960 | // The pointer already has an appropriate type - just do the arithmetic. |
| 935 | try writer.writeByte('('); | |
| 936 | try dg.renderPointer(writer, elem.parent.*, location); | |
| 937 | try writer.print(" + {})", .{try dg.fmtIntLiteral(index_val, .Other)}); | |
| 961 | try w.writeByte('('); | |
| 962 | try dg.renderPointer(w, elem.parent.*, location); | |
| 963 | try w.print(" + {f})", .{try dg.fmtIntLiteralDec(index_val, .Other)}); | |
| 938 | 964 | } else { |
| 939 | 965 | // We probably have an array pointer `T (*)[n]`. Cast to an element pointer, |
| 940 | 966 | // and *then* apply the index. |
| 941 | try writer.writeAll("(("); | |
| 942 | try dg.renderCType(writer, result_ctype); | |
| 943 | try writer.writeByte(')'); | |
| 944 | try dg.renderPointer(writer, elem.parent.*, location); | |
| 945 | try writer.print(" + {})", .{try dg.fmtIntLiteral(index_val, .Other)}); | |
| 967 | try w.writeAll("(("); | |
| 968 | try dg.renderCType(w, result_ctype); | |
| 969 | try w.writeByte(')'); | |
| 970 | try dg.renderPointer(w, elem.parent.*, location); | |
| 971 | try w.print(" + {f})", .{try dg.fmtIntLiteralDec(index_val, .Other)}); | |
| 946 | 972 | } |
| 947 | 973 | }, |
| 948 | 974 | |
| 949 | 975 | .offset_and_cast => |oac| { |
| 950 | 976 | const ptr_ctype = try dg.ctypeFromType(oac.new_ptr_ty, .complete); |
| 951 | try writer.writeByte('('); | |
| 952 | try dg.renderCType(writer, ptr_ctype); | |
| 953 | try writer.writeByte(')'); | |
| 977 | try w.writeByte('('); | |
| 978 | try dg.renderCType(w, ptr_ctype); | |
| 979 | try w.writeByte(')'); | |
| 954 | 980 | if (oac.byte_offset == 0) { |
| 955 | try dg.renderPointer(writer, oac.parent.*, location); | |
| 981 | try dg.renderPointer(w, oac.parent.*, location); | |
| 956 | 982 | } else { |
| 957 | 983 | const offset_val = try pt.intValue(.usize, oac.byte_offset); |
| 958 | try writer.writeAll("((char *)"); | |
| 959 | try dg.renderPointer(writer, oac.parent.*, location); | |
| 960 | try writer.print(" + {})", .{try dg.fmtIntLiteral(offset_val, .Other)}); | |
| 984 | try w.writeAll("((char *)"); | |
| 985 | try dg.renderPointer(w, oac.parent.*, location); | |
| 986 | try w.print(" + {f})", .{try dg.fmtIntLiteralDec(offset_val, .Other)}); | |
| 961 | 987 | } |
| 962 | 988 | }, |
| 963 | 989 | } |
| 964 | 990 | } |
| 965 | 991 | |
| 966 | fn renderErrorName(dg: *DeclGen, writer: anytype, err_name: InternPool.NullTerminatedString) !void { | |
| 967 | const ip = &dg.pt.zcu.intern_pool; | |
| 968 | try writer.print("zig_error_{}", .{fmtIdent(err_name.toSlice(ip))}); | |
| 992 | fn renderErrorName(dg: *DeclGen, w: *Writer, err_name: InternPool.NullTerminatedString) !void { | |
| 993 | try w.print("zig_error_{f}", .{fmtIdentUnsolo(err_name.toSlice(&dg.pt.zcu.intern_pool))}); | |
| 969 | 994 | } |
| 970 | 995 | |
| 971 | 996 | fn renderValue( |
| 972 | 997 | dg: *DeclGen, |
| 973 | writer: anytype, | |
| 998 | w: *Writer, | |
| 974 | 999 | val: Value, |
| 975 | 1000 | location: ValueRenderLocation, |
| 976 | ) error{ OutOfMemory, AnalysisFail }!void { | |
| 1001 | ) Error!void { | |
| 977 | 1002 | const pt = dg.pt; |
| 978 | 1003 | const zcu = pt.zcu; |
| 979 | 1004 | const ip = &zcu.intern_pool; |
| ... | ... | @@ -986,7 +1011,7 @@ pub const DeclGen = struct { |
| 986 | 1011 | }; |
| 987 | 1012 | |
| 988 | 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 | 1015 | const ctype = try dg.ctypeFromType(ty, location.toCTypeKind()); |
| 991 | 1016 | switch (ip.indexToKey(val.toIntern())) { |
| 992 | 1017 | // types, not values |
| ... | ... | @@ -1019,8 +1044,8 @@ pub const DeclGen = struct { |
| 1019 | 1044 | .empty_tuple => unreachable, |
| 1020 | 1045 | .@"unreachable" => unreachable, |
| 1021 | 1046 | |
| 1022 | .false => try writer.writeAll("false"), | |
| 1023 | .true => try writer.writeAll("true"), | |
| 1047 | .false => try w.writeAll("false"), | |
| 1048 | .true => try w.writeAll("true"), | |
| 1024 | 1049 | }, |
| 1025 | 1050 | .variable, |
| 1026 | 1051 | .@"extern", |
| ... | ... | @@ -1029,45 +1054,45 @@ pub const DeclGen = struct { |
| 1029 | 1054 | .empty_enum_value, |
| 1030 | 1055 | => unreachable, // non-runtime values |
| 1031 | 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 | 1058 | .lazy_align, .lazy_size => { |
| 1034 | try writer.writeAll("(("); | |
| 1035 | try dg.renderCType(writer, ctype); | |
| 1036 | try writer.print("){x})", .{try dg.fmtIntLiteral( | |
| 1059 | try w.writeAll("(("); | |
| 1060 | try dg.renderCType(w, ctype); | |
| 1061 | try w.print("){f})", .{try dg.fmtIntLiteralHex( | |
| 1037 | 1062 | try pt.intValue(.usize, val.toUnsignedInt(zcu)), |
| 1038 | 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 | 1068 | .error_union => |error_union| switch (ctype.info(ctype_pool)) { |
| 1044 | 1069 | .basic => switch (error_union.val) { |
| 1045 | .err_name => |err_name| try dg.renderErrorName(writer, err_name), | |
| 1046 | .payload => try writer.writeAll("0"), | |
| 1070 | .err_name => |err_name| try dg.renderErrorName(w, err_name), | |
| 1071 | .payload => try w.writeByte('0'), | |
| 1047 | 1072 | }, |
| 1048 | 1073 | .pointer, .aligned, .array, .vector, .fwd_decl, .function => unreachable, |
| 1049 | 1074 | .aggregate => |aggregate| { |
| 1050 | 1075 | if (!location.isInitializer()) { |
| 1051 | try writer.writeByte('('); | |
| 1052 | try dg.renderCType(writer, ctype); | |
| 1053 | try writer.writeByte(')'); | |
| 1076 | try w.writeByte('('); | |
| 1077 | try dg.renderCType(w, ctype); | |
| 1078 | try w.writeByte(')'); | |
| 1054 | 1079 | } |
| 1055 | try writer.writeByte('{'); | |
| 1080 | try w.writeByte('{'); | |
| 1056 | 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 | 1083 | switch (aggregate.fields.at(field_index, ctype_pool).name.index) { |
| 1059 | 1084 | .@"error" => switch (error_union.val) { |
| 1060 | .err_name => |err_name| try dg.renderErrorName(writer, err_name), | |
| 1061 | .payload => try writer.writeByte('0'), | |
| 1085 | .err_name => |err_name| try dg.renderErrorName(w, err_name), | |
| 1086 | .payload => try w.writeByte('0'), | |
| 1062 | 1087 | }, |
| 1063 | 1088 | .payload => switch (error_union.val) { |
| 1064 | 1089 | .err_name => try dg.renderUndefValue( |
| 1065 | writer, | |
| 1090 | w, | |
| 1066 | 1091 | ty.errorUnionPayload(zcu), |
| 1067 | 1092 | initializer_type, |
| 1068 | 1093 | ), |
| 1069 | 1094 | .payload => |payload| try dg.renderValue( |
| 1070 | writer, | |
| 1095 | w, | |
| 1071 | 1096 | Value.fromInterned(payload), |
| 1072 | 1097 | initializer_type, |
| 1073 | 1098 | ), |
| ... | ... | @@ -1075,10 +1100,10 @@ pub const DeclGen = struct { |
| 1075 | 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 | 1107 | .float => { |
| 1083 | 1108 | const bits = ty.floatBits(target); |
| 1084 | 1109 | const f128_val = val.toFloat(f128, zcu); |
| ... | ... | @@ -1105,18 +1130,18 @@ pub const DeclGen = struct { |
| 1105 | 1130 | |
| 1106 | 1131 | var empty = true; |
| 1107 | 1132 | if (std.math.isFinite(f128_val)) { |
| 1108 | try writer.writeAll("zig_make_"); | |
| 1109 | try dg.renderTypeForBuiltinFnName(writer, ty); | |
| 1110 | try writer.writeByte('('); | |
| 1133 | try w.writeAll("zig_make_"); | |
| 1134 | try dg.renderTypeForBuiltinFnName(w, ty); | |
| 1135 | try w.writeByte('('); | |
| 1111 | 1136 | switch (bits) { |
| 1112 | 16 => try writer.print("{x}", .{val.toFloat(f16, zcu)}), | |
| 1113 | 32 => try writer.print("{x}", .{val.toFloat(f32, zcu)}), | |
| 1114 | 64 => try writer.print("{x}", .{val.toFloat(f64, zcu)}), | |
| 1115 | 80 => try writer.print("{x}", .{val.toFloat(f80, zcu)}), | |
| 1116 | 128 => try writer.print("{x}", .{f128_val}), | |
| 1137 | 16 => try w.print("{x}", .{val.toFloat(f16, zcu)}), | |
| 1138 | 32 => try w.print("{x}", .{val.toFloat(f32, zcu)}), | |
| 1139 | 64 => try w.print("{x}", .{val.toFloat(f64, zcu)}), | |
| 1140 | 80 => try w.print("{x}", .{val.toFloat(f80, zcu)}), | |
| 1141 | 128 => try w.print("{x}", .{f128_val}), | |
| 1117 | 1142 | else => unreachable, |
| 1118 | 1143 | } |
| 1119 | try writer.writeAll(", "); | |
| 1144 | try w.writeAll(", "); | |
| 1120 | 1145 | empty = false; |
| 1121 | 1146 | } else { |
| 1122 | 1147 | // isSignalNan is equivalent to isNan currently, and MSVC doesn't have nans, so prefer nan |
| ... | ... | @@ -1140,45 +1165,45 @@ pub const DeclGen = struct { |
| 1140 | 1165 | // return dg.fail("Only quiet nans are supported in global variable initializers", .{}); |
| 1141 | 1166 | } |
| 1142 | 1167 | |
| 1143 | try writer.writeAll("zig_"); | |
| 1144 | try writer.writeAll(if (location == .StaticInitializer) "init" else "make"); | |
| 1145 | try writer.writeAll("_special_"); | |
| 1146 | try dg.renderTypeForBuiltinFnName(writer, ty); | |
| 1147 | try writer.writeByte('('); | |
| 1148 | if (std.math.signbit(f128_val)) try writer.writeByte('-'); | |
| 1149 | try writer.writeAll(", "); | |
| 1150 | try writer.writeAll(operation); | |
| 1151 | try writer.writeAll(", "); | |
| 1168 | try w.writeAll("zig_"); | |
| 1169 | try w.writeAll(if (location == .StaticInitializer) "init" else "make"); | |
| 1170 | try w.writeAll("_special_"); | |
| 1171 | try dg.renderTypeForBuiltinFnName(w, ty); | |
| 1172 | try w.writeByte('('); | |
| 1173 | if (std.math.signbit(f128_val)) try w.writeByte('-'); | |
| 1174 | try w.writeAll(", "); | |
| 1175 | try w.writeAll(operation); | |
| 1176 | try w.writeAll(", "); | |
| 1152 | 1177 | if (std.math.isNan(f128_val)) switch (bits) { |
| 1153 | 1178 | // We only actually need to pass the significand, but it will get |
| 1154 | 1179 | // properly masked anyway, so just pass the whole value. |
| 1155 | 16 => try writer.print("\"0x{x}\"", .{@as(u16, @bitCast(val.toFloat(f16, zcu)))}), | |
| 1156 | 32 => try writer.print("\"0x{x}\"", .{@as(u32, @bitCast(val.toFloat(f32, zcu)))}), | |
| 1157 | 64 => try writer.print("\"0x{x}\"", .{@as(u64, @bitCast(val.toFloat(f64, zcu)))}), | |
| 1158 | 80 => try writer.print("\"0x{x}\"", .{@as(u80, @bitCast(val.toFloat(f80, zcu)))}), | |
| 1159 | 128 => try writer.print("\"0x{x}\"", .{@as(u128, @bitCast(f128_val))}), | |
| 1180 | 16 => try w.print("\"0x{x}\"", .{@as(u16, @bitCast(val.toFloat(f16, zcu)))}), | |
| 1181 | 32 => try w.print("\"0x{x}\"", .{@as(u32, @bitCast(val.toFloat(f32, zcu)))}), | |
| 1182 | 64 => try w.print("\"0x{x}\"", .{@as(u64, @bitCast(val.toFloat(f64, zcu)))}), | |
| 1183 | 80 => try w.print("\"0x{x}\"", .{@as(u80, @bitCast(val.toFloat(f80, zcu)))}), | |
| 1184 | 128 => try w.print("\"0x{x}\"", .{@as(u128, @bitCast(f128_val))}), | |
| 1160 | 1185 | else => unreachable, |
| 1161 | 1186 | }; |
| 1162 | try writer.writeAll(", "); | |
| 1187 | try w.writeAll(", "); | |
| 1163 | 1188 | empty = false; |
| 1164 | 1189 | } |
| 1165 | try writer.print("{x}", .{try dg.fmtIntLiteral( | |
| 1190 | try w.print("{f}", .{try dg.fmtIntLiteralHex( | |
| 1166 | 1191 | try pt.intValue_big(repr_ty, repr_val_big.toConst()), |
| 1167 | 1192 | location, |
| 1168 | 1193 | )}); |
| 1169 | if (!empty) try writer.writeByte(')'); | |
| 1194 | if (!empty) try w.writeByte(')'); | |
| 1170 | 1195 | }, |
| 1171 | 1196 | .slice => |slice| { |
| 1172 | 1197 | const aggregate = ctype.info(ctype_pool).aggregate; |
| 1173 | 1198 | if (!location.isInitializer()) { |
| 1174 | try writer.writeByte('('); | |
| 1175 | try dg.renderCType(writer, ctype); | |
| 1176 | try writer.writeByte(')'); | |
| 1199 | try w.writeByte('('); | |
| 1200 | try dg.renderCType(w, ctype); | |
| 1201 | try w.writeByte(')'); | |
| 1177 | 1202 | } |
| 1178 | try writer.writeByte('{'); | |
| 1203 | try w.writeByte('{'); | |
| 1179 | 1204 | for (0..aggregate.fields.len) |field_index| { |
| 1180 | if (field_index > 0) try writer.writeByte(','); | |
| 1181 | try dg.renderValue(writer, Value.fromInterned( | |
| 1205 | if (field_index > 0) try w.writeByte(','); | |
| 1206 | try dg.renderValue(w, Value.fromInterned( | |
| 1182 | 1207 | switch (aggregate.fields.at(field_index, ctype_pool).name.index) { |
| 1183 | 1208 | .ptr => slice.ptr, |
| 1184 | 1209 | .len => slice.len, |
| ... | ... | @@ -1186,33 +1211,33 @@ pub const DeclGen = struct { |
| 1186 | 1211 | }, |
| 1187 | 1212 | ), initializer_type); |
| 1188 | 1213 | } |
| 1189 | try writer.writeByte('}'); | |
| 1214 | try w.writeByte('}'); | |
| 1190 | 1215 | }, |
| 1191 | 1216 | .ptr => { |
| 1192 | 1217 | var arena = std.heap.ArenaAllocator.init(zcu.gpa); |
| 1193 | 1218 | defer arena.deinit(); |
| 1194 | 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 | 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 | 1224 | .none => "true", |
| 1200 | 1225 | else => "false", |
| 1201 | 1226 | }) else switch (opt.val) { |
| 1202 | .none => try writer.writeAll("0"), | |
| 1227 | .none => try w.writeByte('0'), | |
| 1203 | 1228 | else => |payload| switch (ip.indexToKey(payload)) { |
| 1204 | 1229 | .undef => |err_ty| try dg.renderUndefValue( |
| 1205 | writer, | |
| 1230 | w, | |
| 1206 | 1231 | .fromInterned(err_ty), |
| 1207 | 1232 | location, |
| 1208 | 1233 | ), |
| 1209 | .err => |err| try dg.renderErrorName(writer, err.name), | |
| 1234 | .err => |err| try dg.renderErrorName(w, err.name), | |
| 1210 | 1235 | else => unreachable, |
| 1211 | 1236 | }, |
| 1212 | 1237 | }, |
| 1213 | 1238 | .pointer => switch (opt.val) { |
| 1214 | .none => try writer.writeAll("NULL"), | |
| 1215 | else => |payload| try dg.renderValue(writer, Value.fromInterned(payload), location), | |
| 1239 | .none => try w.writeAll("NULL"), | |
| 1240 | else => |payload| try dg.renderValue(w, Value.fromInterned(payload), location), | |
| 1216 | 1241 | }, |
| 1217 | 1242 | .aligned, .array, .vector, .fwd_decl, .function => unreachable, |
| 1218 | 1243 | .aggregate => |aggregate| { |
| ... | ... | @@ -1221,7 +1246,7 @@ pub const DeclGen = struct { |
| 1221 | 1246 | else => |payload| switch (aggregate.fields.at(0, ctype_pool).name.index) { |
| 1222 | 1247 | .is_null, .payload => {}, |
| 1223 | 1248 | .ptr, .len => return dg.renderValue( |
| 1224 | writer, | |
| 1249 | w, | |
| 1225 | 1250 | Value.fromInterned(payload), |
| 1226 | 1251 | location, |
| 1227 | 1252 | ), |
| ... | ... | @@ -1229,48 +1254,48 @@ pub const DeclGen = struct { |
| 1229 | 1254 | }, |
| 1230 | 1255 | } |
| 1231 | 1256 | if (!location.isInitializer()) { |
| 1232 | try writer.writeByte('('); | |
| 1233 | try dg.renderCType(writer, ctype); | |
| 1234 | try writer.writeByte(')'); | |
| 1257 | try w.writeByte('('); | |
| 1258 | try dg.renderCType(w, ctype); | |
| 1259 | try w.writeByte(')'); | |
| 1235 | 1260 | } |
| 1236 | try writer.writeByte('{'); | |
| 1261 | try w.writeByte('{'); | |
| 1237 | 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 | 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 | 1266 | .none => "true", |
| 1242 | 1267 | else => "false", |
| 1243 | 1268 | }), |
| 1244 | 1269 | .payload => switch (opt.val) { |
| 1245 | 1270 | .none => try dg.renderUndefValue( |
| 1246 | writer, | |
| 1271 | w, | |
| 1247 | 1272 | ty.optionalChild(zcu), |
| 1248 | 1273 | initializer_type, |
| 1249 | 1274 | ), |
| 1250 | 1275 | else => |payload| try dg.renderValue( |
| 1251 | writer, | |
| 1276 | w, | |
| 1252 | 1277 | Value.fromInterned(payload), |
| 1253 | 1278 | initializer_type, |
| 1254 | 1279 | ), |
| 1255 | 1280 | }, |
| 1256 | .ptr => try writer.writeAll("NULL"), | |
| 1257 | .len => try dg.renderUndefValue(writer, .usize, initializer_type), | |
| 1281 | .ptr => try w.writeAll("NULL"), | |
| 1282 | .len => try dg.renderUndefValue(w, .usize, initializer_type), | |
| 1258 | 1283 | else => unreachable, |
| 1259 | 1284 | } |
| 1260 | 1285 | } |
| 1261 | try writer.writeByte('}'); | |
| 1286 | try w.writeByte('}'); | |
| 1262 | 1287 | }, |
| 1263 | 1288 | }, |
| 1264 | 1289 | .aggregate => switch (ip.indexToKey(ty.toIntern())) { |
| 1265 | 1290 | .array_type, .vector_type => { |
| 1266 | 1291 | if (location == .FunctionArgument) { |
| 1267 | try writer.writeByte('('); | |
| 1268 | try dg.renderCType(writer, ctype); | |
| 1269 | try writer.writeByte(')'); | |
| 1292 | try w.writeByte('('); | |
| 1293 | try dg.renderCType(w, ctype); | |
| 1294 | try w.writeByte(')'); | |
| 1270 | 1295 | } |
| 1271 | 1296 | const ai = ty.arrayInfo(zcu); |
| 1272 | 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 | 1299 | try literal.start(); |
| 1275 | 1300 | var index: usize = 0; |
| 1276 | 1301 | while (index < ai.len) : (index += 1) { |
| ... | ... | @@ -1287,28 +1312,28 @@ pub const DeclGen = struct { |
| 1287 | 1312 | } |
| 1288 | 1313 | try literal.end(); |
| 1289 | 1314 | } else { |
| 1290 | try writer.writeByte('{'); | |
| 1315 | try w.writeByte('{'); | |
| 1291 | 1316 | var index: usize = 0; |
| 1292 | 1317 | while (index < ai.len) : (index += 1) { |
| 1293 | if (index != 0) try writer.writeByte(','); | |
| 1318 | if (index != 0) try w.writeByte(','); | |
| 1294 | 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 | 1322 | if (ai.sentinel) |s| { |
| 1298 | if (index != 0) try writer.writeByte(','); | |
| 1299 | try dg.renderValue(writer, s, initializer_type); | |
| 1323 | if (index != 0) try w.writeByte(','); | |
| 1324 | try dg.renderValue(w, s, initializer_type); | |
| 1300 | 1325 | } |
| 1301 | try writer.writeByte('}'); | |
| 1326 | try w.writeByte('}'); | |
| 1302 | 1327 | } |
| 1303 | 1328 | }, |
| 1304 | 1329 | .tuple_type => |tuple| { |
| 1305 | 1330 | if (!location.isInitializer()) { |
| 1306 | try writer.writeByte('('); | |
| 1307 | try dg.renderCType(writer, ctype); | |
| 1308 | try writer.writeByte(')'); | |
| 1331 | try w.writeByte('('); | |
| 1332 | try dg.renderCType(w, ctype); | |
| 1333 | try w.writeByte(')'); | |
| 1309 | 1334 | } |
| 1310 | 1335 | |
| 1311 | try writer.writeByte('{'); | |
| 1336 | try w.writeByte('{'); | |
| 1312 | 1337 | var empty = true; |
| 1313 | 1338 | for (0..tuple.types.len) |field_index| { |
| 1314 | 1339 | const comptime_val = tuple.values.get(ip)[field_index]; |
| ... | ... | @@ -1316,7 +1341,7 @@ pub const DeclGen = struct { |
| 1316 | 1341 | const field_ty: Type = .fromInterned(tuple.types.get(ip)[field_index]); |
| 1317 | 1342 | if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue; |
| 1318 | 1343 | |
| 1319 | if (!empty) try writer.writeByte(','); | |
| 1344 | if (!empty) try w.writeByte(','); | |
| 1320 | 1345 | |
| 1321 | 1346 | const field_val = Value.fromInterned( |
| 1322 | 1347 | switch (ip.indexToKey(val.toIntern()).aggregate.storage) { |
| ... | ... | @@ -1328,30 +1353,30 @@ pub const DeclGen = struct { |
| 1328 | 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); | |
| 1332 | 1357 | |
| 1333 | 1358 | empty = false; |
| 1334 | 1359 | } |
| 1335 | try writer.writeByte('}'); | |
| 1360 | try w.writeByte('}'); | |
| 1336 | 1361 | }, |
| 1337 | 1362 | .struct_type => { |
| 1338 | 1363 | const loaded_struct = ip.loadStructType(ty.toIntern()); |
| 1339 | 1364 | switch (loaded_struct.layout) { |
| 1340 | 1365 | .auto, .@"extern" => { |
| 1341 | 1366 | if (!location.isInitializer()) { |
| 1342 | try writer.writeByte('('); | |
| 1343 | try dg.renderCType(writer, ctype); | |
| 1344 | try writer.writeByte(')'); | |
| 1367 | try w.writeByte('('); | |
| 1368 | try dg.renderCType(w, ctype); | |
| 1369 | try w.writeByte(')'); | |
| 1345 | 1370 | } |
| 1346 | 1371 | |
| 1347 | try writer.writeByte('{'); | |
| 1372 | try w.writeByte('{'); | |
| 1348 | 1373 | var field_it = loaded_struct.iterateRuntimeOrder(ip); |
| 1349 | 1374 | var need_comma = false; |
| 1350 | 1375 | while (field_it.next()) |field_index| { |
| 1351 | 1376 | const field_ty: Type = .fromInterned(loaded_struct.field_types.get(ip)[field_index]); |
| 1352 | 1377 | if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue; |
| 1353 | 1378 | |
| 1354 | if (need_comma) try writer.writeByte(','); | |
| 1379 | if (need_comma) try w.writeByte(','); | |
| 1355 | 1380 | need_comma = true; |
| 1356 | 1381 | const field_val = switch (ip.indexToKey(val.toIntern()).aggregate.storage) { |
| 1357 | 1382 | .bytes => |bytes| try pt.intern(.{ .int = .{ |
| ... | ... | @@ -1361,9 +1386,9 @@ pub const DeclGen = struct { |
| 1361 | 1386 | .elems => |elems| elems[field_index], |
| 1362 | 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 | 1393 | .@"packed" => { |
| 1369 | 1394 | const int_info = ty.intInfo(zcu); |
| ... | ... | @@ -1381,16 +1406,16 @@ pub const DeclGen = struct { |
| 1381 | 1406 | } |
| 1382 | 1407 | |
| 1383 | 1408 | if (eff_num_fields == 0) { |
| 1384 | try writer.writeByte('('); | |
| 1385 | try dg.renderUndefValue(writer, ty, location); | |
| 1386 | try writer.writeByte(')'); | |
| 1409 | try w.writeByte('('); | |
| 1410 | try dg.renderUndefValue(w, ty, location); | |
| 1411 | try w.writeByte(')'); | |
| 1387 | 1412 | } else if (ty.bitSize(zcu) > 64) { |
| 1388 | 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 | 1414 | var num_or = eff_num_fields - 1; |
| 1390 | 1415 | while (num_or > 0) : (num_or -= 1) { |
| 1391 | try writer.writeAll("zig_or_"); | |
| 1392 | try dg.renderTypeForBuiltinFnName(writer, ty); | |
| 1393 | try writer.writeByte('('); | |
| 1416 | try w.writeAll("zig_or_"); | |
| 1417 | try dg.renderTypeForBuiltinFnName(w, ty); | |
| 1418 | try w.writeByte('('); | |
| 1394 | 1419 | } |
| 1395 | 1420 | |
| 1396 | 1421 | var eff_index: usize = 0; |
| ... | ... | @@ -1409,36 +1434,36 @@ pub const DeclGen = struct { |
| 1409 | 1434 | }; |
| 1410 | 1435 | const cast_context = IntCastContext{ .value = .{ .value = Value.fromInterned(field_val) } }; |
| 1411 | 1436 | if (bit_offset != 0) { |
| 1412 | try writer.writeAll("zig_shl_"); | |
| 1413 | try dg.renderTypeForBuiltinFnName(writer, ty); | |
| 1414 | try writer.writeByte('('); | |
| 1415 | try dg.renderIntCast(writer, ty, cast_context, field_ty, .FunctionArgument); | |
| 1416 | try writer.writeAll(", "); | |
| 1417 | try dg.renderValue(writer, try pt.intValue(bit_offset_ty, bit_offset), .FunctionArgument); | |
| 1418 | try writer.writeByte(')'); | |
| 1437 | try w.writeAll("zig_shl_"); | |
| 1438 | try dg.renderTypeForBuiltinFnName(w, ty); | |
| 1439 | try w.writeByte('('); | |
| 1440 | try dg.renderIntCast(w, ty, cast_context, field_ty, .FunctionArgument); | |
| 1441 | try w.writeAll(", "); | |
| 1442 | try dg.renderValue(w, try pt.intValue(bit_offset_ty, bit_offset), .FunctionArgument); | |
| 1443 | try w.writeByte(')'); | |
| 1419 | 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 | } |
| 1422 | 1447 | |
| 1423 | if (needs_closing_paren) try writer.writeByte(')'); | |
| 1424 | if (eff_index != eff_num_fields - 1) try writer.writeAll(", "); | |
| 1448 | if (needs_closing_paren) try w.writeByte(')'); | |
| 1449 | if (eff_index != eff_num_fields - 1) try w.writeAll(", "); | |
| 1425 | 1450 | |
| 1426 | 1451 | bit_offset += field_ty.bitSize(zcu); |
| 1427 | 1452 | needs_closing_paren = true; |
| 1428 | 1453 | eff_index += 1; |
| 1429 | 1454 | } |
| 1430 | 1455 | } else { |
| 1431 | try writer.writeByte('('); | |
| 1456 | try w.writeByte('('); | |
| 1432 | 1457 | // a << a_off | b << b_off | c << c_off |
| 1433 | 1458 | var empty = true; |
| 1434 | 1459 | for (0..loaded_struct.field_types.len) |field_index| { |
| 1435 | 1460 | const field_ty: Type = .fromInterned(loaded_struct.field_types.get(ip)[field_index]); |
| 1436 | 1461 | if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue; |
| 1437 | 1462 | |
| 1438 | if (!empty) try writer.writeAll(" | "); | |
| 1439 | try writer.writeByte('('); | |
| 1440 | try dg.renderCType(writer, ctype); | |
| 1441 | try writer.writeByte(')'); | |
| 1463 | if (!empty) try w.writeAll(" | "); | |
| 1464 | try w.writeByte('('); | |
| 1465 | try dg.renderCType(w, ctype); | |
| 1466 | try w.writeByte(')'); | |
| 1442 | 1467 | |
| 1443 | 1468 | const field_val = switch (ip.indexToKey(val.toIntern()).aggregate.storage) { |
| 1444 | 1469 | .bytes => |bytes| try pt.intern(.{ .int = .{ |
| ... | ... | @@ -1455,24 +1480,24 @@ pub const DeclGen = struct { |
| 1455 | 1480 | .{ .signedness = .unsigned, .bits = undefined }; |
| 1456 | 1481 | switch (field_int_info.signedness) { |
| 1457 | 1482 | .signed => { |
| 1458 | try writer.writeByte('('); | |
| 1459 | try dg.renderValue(writer, Value.fromInterned(field_val), .Other); | |
| 1460 | try writer.writeAll(" & "); | |
| 1483 | try w.writeByte('('); | |
| 1484 | try dg.renderValue(w, Value.fromInterned(field_val), .Other); | |
| 1485 | try w.writeAll(" & "); | |
| 1461 | 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); | |
| 1463 | try writer.writeByte(')'); | |
| 1487 | try dg.renderValue(w, try field_uint_ty.maxIntScalar(pt, field_uint_ty), .Other); | |
| 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 | 1492 | if (bit_offset != 0) { |
| 1468 | try writer.writeAll(" << "); | |
| 1469 | try dg.renderValue(writer, try pt.intValue(bit_offset_ty, bit_offset), .FunctionArgument); | |
| 1493 | try w.writeAll(" << "); | |
| 1494 | try dg.renderValue(w, try pt.intValue(bit_offset_ty, bit_offset), .FunctionArgument); | |
| 1470 | 1495 | } |
| 1471 | 1496 | |
| 1472 | 1497 | bit_offset += field_ty.bitSize(zcu); |
| 1473 | 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 | 1511 | switch (loaded_union.flagsUnordered(ip).layout) { |
| 1487 | 1512 | .@"packed" => { |
| 1488 | 1513 | if (!location.isInitializer()) { |
| 1489 | try writer.writeByte('('); | |
| 1490 | try dg.renderType(writer, backing_ty); | |
| 1491 | try writer.writeByte(')'); | |
| 1514 | try w.writeByte('('); | |
| 1515 | try dg.renderType(w, backing_ty); | |
| 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 | 1520 | .@"extern" => { |
| 1496 | 1521 | if (location == .StaticInitializer) { |
| ... | ... | @@ -1498,21 +1523,21 @@ pub const DeclGen = struct { |
| 1498 | 1523 | } |
| 1499 | 1524 | |
| 1500 | 1525 | const ptr_ty = try pt.singleConstPtrType(ty); |
| 1501 | try writer.writeAll("*(("); | |
| 1502 | try dg.renderType(writer, ptr_ty); | |
| 1503 | try writer.writeAll(")("); | |
| 1504 | try dg.renderType(writer, backing_ty); | |
| 1505 | try writer.writeAll("){"); | |
| 1506 | try dg.renderValue(writer, Value.fromInterned(un.val), location); | |
| 1507 | try writer.writeAll("})"); | |
| 1526 | try w.writeAll("*(("); | |
| 1527 | try dg.renderType(w, ptr_ty); | |
| 1528 | try w.writeAll(")("); | |
| 1529 | try dg.renderType(w, backing_ty); | |
| 1530 | try w.writeAll("){"); | |
| 1531 | try dg.renderValue(w, Value.fromInterned(un.val), location); | |
| 1532 | try w.writeAll("})"); | |
| 1508 | 1533 | }, |
| 1509 | 1534 | else => unreachable, |
| 1510 | 1535 | } |
| 1511 | 1536 | } else { |
| 1512 | 1537 | if (!location.isInitializer()) { |
| 1513 | try writer.writeByte('('); | |
| 1514 | try dg.renderCType(writer, ctype); | |
| 1515 | try writer.writeByte(')'); | |
| 1538 | try w.writeByte('('); | |
| 1539 | try dg.renderCType(w, ctype); | |
| 1540 | try w.writeByte(')'); | |
| 1516 | 1541 | } |
| 1517 | 1542 | |
| 1518 | 1543 | const field_index = zcu.unionTagFieldIndex(loaded_union, Value.fromInterned(un.tag)).?; |
| ... | ... | @@ -1521,57 +1546,57 @@ pub const DeclGen = struct { |
| 1521 | 1546 | if (loaded_union.flagsUnordered(ip).layout == .@"packed") { |
| 1522 | 1547 | if (field_ty.hasRuntimeBits(zcu)) { |
| 1523 | 1548 | if (field_ty.isPtrAtRuntime(zcu)) { |
| 1524 | try writer.writeByte('('); | |
| 1525 | try dg.renderCType(writer, ctype); | |
| 1526 | try writer.writeByte(')'); | |
| 1549 | try w.writeByte('('); | |
| 1550 | try dg.renderCType(w, ctype); | |
| 1551 | try w.writeByte(')'); | |
| 1527 | 1552 | } else if (field_ty.zigTypeTag(zcu) == .float) { |
| 1528 | try writer.writeByte('('); | |
| 1529 | try dg.renderCType(writer, ctype); | |
| 1530 | try writer.writeByte(')'); | |
| 1553 | try w.writeByte('('); | |
| 1554 | try dg.renderCType(w, ctype); | |
| 1555 | try w.writeByte(')'); | |
| 1531 | 1556 | } |
| 1532 | try dg.renderValue(writer, Value.fromInterned(un.val), location); | |
| 1533 | } else try writer.writeAll("0"); | |
| 1557 | try dg.renderValue(w, Value.fromInterned(un.val), location); | |
| 1558 | } else try w.writeByte('0'); | |
| 1534 | 1559 | return; |
| 1535 | 1560 | } |
| 1536 | 1561 | |
| 1537 | 1562 | const has_tag = loaded_union.hasTag(ip); |
| 1538 | if (has_tag) try writer.writeByte('{'); | |
| 1563 | if (has_tag) try w.writeByte('{'); | |
| 1539 | 1564 | const aggregate = ctype.info(ctype_pool).aggregate; |
| 1540 | 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 | 1567 | switch (if (has_tag) |
| 1543 | 1568 | aggregate.fields.at(outer_field_index, ctype_pool).name.index |
| 1544 | 1569 | else |
| 1545 | 1570 | .payload) { |
| 1546 | 1571 | .tag => try dg.renderValue( |
| 1547 | writer, | |
| 1572 | w, | |
| 1548 | 1573 | Value.fromInterned(un.tag), |
| 1549 | 1574 | initializer_type, |
| 1550 | 1575 | ), |
| 1551 | 1576 | .payload => { |
| 1552 | try writer.writeByte('{'); | |
| 1577 | try w.writeByte('{'); | |
| 1553 | 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 | 1580 | try dg.renderValue( |
| 1556 | writer, | |
| 1581 | w, | |
| 1557 | 1582 | Value.fromInterned(un.val), |
| 1558 | 1583 | initializer_type, |
| 1559 | 1584 | ); |
| 1560 | try writer.writeByte(' '); | |
| 1585 | try w.writeByte(' '); | |
| 1561 | 1586 | } else for (0..loaded_union.field_types.len) |inner_field_index| { |
| 1562 | 1587 | const inner_field_ty: Type = .fromInterned( |
| 1563 | 1588 | loaded_union.field_types.get(ip)[inner_field_index], |
| 1564 | 1589 | ); |
| 1565 | 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 | 1592 | break; |
| 1568 | 1593 | } |
| 1569 | try writer.writeByte('}'); | |
| 1594 | try w.writeByte('}'); | |
| 1570 | 1595 | }, |
| 1571 | 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 | 1604 | |
| 1580 | 1605 | fn renderUndefValue( |
| 1581 | 1606 | dg: *DeclGen, |
| 1582 | writer: anytype, | |
| 1607 | w: *Writer, | |
| 1583 | 1608 | ty: Type, |
| 1584 | 1609 | location: ValueRenderLocation, |
| 1585 | ) error{ OutOfMemory, AnalysisFail }!void { | |
| 1610 | ) Error!void { | |
| 1586 | 1611 | const pt = dg.pt; |
| 1587 | 1612 | const zcu = pt.zcu; |
| 1588 | 1613 | const ip = &zcu.intern_pool; |
| ... | ... | @@ -1612,57 +1637,57 @@ pub const DeclGen = struct { |
| 1612 | 1637 | // All unsigned ints matching float types are pre-allocated. |
| 1613 | 1638 | const repr_ty = dg.pt.intType(.unsigned, bits) catch unreachable; |
| 1614 | 1639 | |
| 1615 | try writer.writeAll("zig_make_"); | |
| 1616 | try dg.renderTypeForBuiltinFnName(writer, ty); | |
| 1617 | try writer.writeByte('('); | |
| 1640 | try w.writeAll("zig_make_"); | |
| 1641 | try dg.renderTypeForBuiltinFnName(w, ty); | |
| 1642 | try w.writeByte('('); | |
| 1618 | 1643 | switch (bits) { |
| 1619 | 16 => try writer.print("{x}", .{@as(f16, @bitCast(undefPattern(i16)))}), | |
| 1620 | 32 => try writer.print("{x}", .{@as(f32, @bitCast(undefPattern(i32)))}), | |
| 1621 | 64 => try writer.print("{x}", .{@as(f64, @bitCast(undefPattern(i64)))}), | |
| 1622 | 80 => try writer.print("{x}", .{@as(f80, @bitCast(undefPattern(i80)))}), | |
| 1623 | 128 => try writer.print("{x}", .{@as(f128, @bitCast(undefPattern(i128)))}), | |
| 1644 | 16 => try w.print("{x}", .{@as(f16, @bitCast(undefPattern(i16)))}), | |
| 1645 | 32 => try w.print("{x}", .{@as(f32, @bitCast(undefPattern(i32)))}), | |
| 1646 | 64 => try w.print("{x}", .{@as(f64, @bitCast(undefPattern(i64)))}), | |
| 1647 | 80 => try w.print("{x}", .{@as(f80, @bitCast(undefPattern(i80)))}), | |
| 1648 | 128 => try w.print("{x}", .{@as(f128, @bitCast(undefPattern(i128)))}), | |
| 1624 | 1649 | else => unreachable, |
| 1625 | 1650 | } |
| 1626 | try writer.writeAll(", "); | |
| 1627 | try dg.renderUndefValue(writer, repr_ty, .FunctionArgument); | |
| 1628 | return writer.writeByte(')'); | |
| 1651 | try w.writeAll(", "); | |
| 1652 | try dg.renderUndefValue(w, repr_ty, .FunctionArgument); | |
| 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 | 1656 | else => switch (ip.indexToKey(ty.toIntern())) { |
| 1632 | 1657 | .simple_type, |
| 1633 | 1658 | .int_type, |
| 1634 | 1659 | .enum_type, |
| 1635 | 1660 | .error_set_type, |
| 1636 | 1661 | .inferred_error_set_type, |
| 1637 | => return writer.print("{x}", .{ | |
| 1638 | try dg.fmtIntLiteral(try pt.undefValue(ty), location), | |
| 1662 | => return w.print("{f}", .{ | |
| 1663 | try dg.fmtIntLiteralHex(try pt.undefValue(ty), location), | |
| 1639 | 1664 | }), |
| 1640 | 1665 | .ptr_type => |ptr_type| switch (ptr_type.flags.size) { |
| 1641 | 1666 | .one, .many, .c => { |
| 1642 | try writer.writeAll("(("); | |
| 1643 | try dg.renderCType(writer, ctype); | |
| 1644 | return writer.print("){x})", .{ | |
| 1645 | try dg.fmtIntLiteral(.undef_usize, .Other), | |
| 1667 | try w.writeAll("(("); | |
| 1668 | try dg.renderCType(w, ctype); | |
| 1669 | return w.print("){f})", .{ | |
| 1670 | try dg.fmtIntLiteralHex(.undef_usize, .Other), | |
| 1646 | 1671 | }); |
| 1647 | 1672 | }, |
| 1648 | 1673 | .slice => { |
| 1649 | 1674 | if (!location.isInitializer()) { |
| 1650 | try writer.writeByte('('); | |
| 1651 | try dg.renderCType(writer, ctype); | |
| 1652 | try writer.writeByte(')'); | |
| 1675 | try w.writeByte('('); | |
| 1676 | try dg.renderCType(w, ctype); | |
| 1677 | try w.writeByte(')'); | |
| 1653 | 1678 | } |
| 1654 | 1679 | |
| 1655 | try writer.writeAll("{("); | |
| 1680 | try w.writeAll("{("); | |
| 1656 | 1681 | const ptr_ty = ty.slicePtrFieldType(zcu); |
| 1657 | try dg.renderType(writer, ptr_ty); | |
| 1658 | return writer.print("){x}, {0x}}}", .{ | |
| 1659 | try dg.fmtIntLiteral(.undef_usize, .Other), | |
| 1682 | try dg.renderType(w, ptr_ty); | |
| 1683 | return w.print("){f}, {0f}}}", .{ | |
| 1684 | try dg.fmtIntLiteralHex(.undef_usize, .Other), | |
| 1660 | 1685 | }); |
| 1661 | 1686 | }, |
| 1662 | 1687 | }, |
| 1663 | 1688 | .opt_type => |child_type| switch (ctype.info(ctype_pool)) { |
| 1664 | 1689 | .basic, .pointer => try dg.renderUndefValue( |
| 1665 | writer, | |
| 1690 | w, | |
| 1666 | 1691 | .fromInterned(if (ctype.isBool()) .bool_type else child_type), |
| 1667 | 1692 | location, |
| 1668 | 1693 | ), |
| ... | ... | @@ -1671,21 +1696,21 @@ pub const DeclGen = struct { |
| 1671 | 1696 | switch (aggregate.fields.at(0, ctype_pool).name.index) { |
| 1672 | 1697 | .is_null, .payload => {}, |
| 1673 | 1698 | .ptr, .len => return dg.renderUndefValue( |
| 1674 | writer, | |
| 1699 | w, | |
| 1675 | 1700 | .fromInterned(child_type), |
| 1676 | 1701 | location, |
| 1677 | 1702 | ), |
| 1678 | 1703 | else => unreachable, |
| 1679 | 1704 | } |
| 1680 | 1705 | if (!location.isInitializer()) { |
| 1681 | try writer.writeByte('('); | |
| 1682 | try dg.renderCType(writer, ctype); | |
| 1683 | try writer.writeByte(')'); | |
| 1706 | try w.writeByte('('); | |
| 1707 | try dg.renderCType(w, ctype); | |
| 1708 | try w.writeByte(')'); | |
| 1684 | 1709 | } |
| 1685 | try writer.writeByte('{'); | |
| 1710 | try w.writeByte('{'); | |
| 1686 | 1711 | for (0..aggregate.fields.len) |field_index| { |
| 1687 | if (field_index > 0) try writer.writeByte(','); | |
| 1688 | try dg.renderUndefValue(writer, .fromInterned( | |
| 1712 | if (field_index > 0) try w.writeByte(','); | |
| 1713 | try dg.renderUndefValue(w, .fromInterned( | |
| 1689 | 1714 | switch (aggregate.fields.at(field_index, ctype_pool).name.index) { |
| 1690 | 1715 | .is_null => .bool_type, |
| 1691 | 1716 | .payload => child_type, |
| ... | ... | @@ -1693,7 +1718,7 @@ pub const DeclGen = struct { |
| 1693 | 1718 | }, |
| 1694 | 1719 | ), initializer_type); |
| 1695 | 1720 | } |
| 1696 | try writer.writeByte('}'); | |
| 1721 | try w.writeByte('}'); | |
| 1697 | 1722 | }, |
| 1698 | 1723 | }, |
| 1699 | 1724 | .struct_type => { |
| ... | ... | @@ -1701,117 +1726,117 @@ pub const DeclGen = struct { |
| 1701 | 1726 | switch (loaded_struct.layout) { |
| 1702 | 1727 | .auto, .@"extern" => { |
| 1703 | 1728 | if (!location.isInitializer()) { |
| 1704 | try writer.writeByte('('); | |
| 1705 | try dg.renderCType(writer, ctype); | |
| 1706 | try writer.writeByte(')'); | |
| 1729 | try w.writeByte('('); | |
| 1730 | try dg.renderCType(w, ctype); | |
| 1731 | try w.writeByte(')'); | |
| 1707 | 1732 | } |
| 1708 | 1733 | |
| 1709 | try writer.writeByte('{'); | |
| 1734 | try w.writeByte('{'); | |
| 1710 | 1735 | var field_it = loaded_struct.iterateRuntimeOrder(ip); |
| 1711 | 1736 | var need_comma = false; |
| 1712 | 1737 | while (field_it.next()) |field_index| { |
| 1713 | 1738 | const field_ty: Type = .fromInterned(loaded_struct.field_types.get(ip)[field_index]); |
| 1714 | 1739 | if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue; |
| 1715 | 1740 | |
| 1716 | if (need_comma) try writer.writeByte(','); | |
| 1741 | if (need_comma) try w.writeByte(','); | |
| 1717 | 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}", .{ | |
| 1723 | try dg.fmtIntLiteral(try pt.undefValue(ty), .Other), | |
| 1747 | .@"packed" => return w.print("{f}", .{ | |
| 1748 | try dg.fmtIntLiteralHex(try pt.undefValue(ty), .Other), | |
| 1724 | 1749 | }), |
| 1725 | 1750 | } |
| 1726 | 1751 | }, |
| 1727 | 1752 | .tuple_type => |tuple_info| { |
| 1728 | 1753 | if (!location.isInitializer()) { |
| 1729 | try writer.writeByte('('); | |
| 1730 | try dg.renderCType(writer, ctype); | |
| 1731 | try writer.writeByte(')'); | |
| 1754 | try w.writeByte('('); | |
| 1755 | try dg.renderCType(w, ctype); | |
| 1756 | try w.writeByte(')'); | |
| 1732 | 1757 | } |
| 1733 | 1758 | |
| 1734 | try writer.writeByte('{'); | |
| 1759 | try w.writeByte('{'); | |
| 1735 | 1760 | var need_comma = false; |
| 1736 | 1761 | for (0..tuple_info.types.len) |field_index| { |
| 1737 | 1762 | if (tuple_info.values.get(ip)[field_index] != .none) continue; |
| 1738 | 1763 | const field_ty: Type = .fromInterned(tuple_info.types.get(ip)[field_index]); |
| 1739 | 1764 | if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue; |
| 1740 | 1765 | |
| 1741 | if (need_comma) try writer.writeByte(','); | |
| 1766 | if (need_comma) try w.writeByte(','); | |
| 1742 | 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 | 1772 | .union_type => { |
| 1748 | 1773 | const loaded_union = ip.loadUnionType(ty.toIntern()); |
| 1749 | 1774 | switch (loaded_union.flagsUnordered(ip).layout) { |
| 1750 | 1775 | .auto, .@"extern" => { |
| 1751 | 1776 | if (!location.isInitializer()) { |
| 1752 | try writer.writeByte('('); | |
| 1753 | try dg.renderCType(writer, ctype); | |
| 1754 | try writer.writeByte(')'); | |
| 1777 | try w.writeByte('('); | |
| 1778 | try dg.renderCType(w, ctype); | |
| 1779 | try w.writeByte(')'); | |
| 1755 | 1780 | } |
| 1756 | 1781 | |
| 1757 | 1782 | const has_tag = loaded_union.hasTag(ip); |
| 1758 | if (has_tag) try writer.writeByte('{'); | |
| 1783 | if (has_tag) try w.writeByte('{'); | |
| 1759 | 1784 | const aggregate = ctype.info(ctype_pool).aggregate; |
| 1760 | 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 | 1787 | switch (if (has_tag) |
| 1763 | 1788 | aggregate.fields.at(outer_field_index, ctype_pool).name.index |
| 1764 | 1789 | else |
| 1765 | 1790 | .payload) { |
| 1766 | 1791 | .tag => try dg.renderUndefValue( |
| 1767 | writer, | |
| 1792 | w, | |
| 1768 | 1793 | .fromInterned(loaded_union.enum_tag_ty), |
| 1769 | 1794 | initializer_type, |
| 1770 | 1795 | ), |
| 1771 | 1796 | .payload => { |
| 1772 | try writer.writeByte('{'); | |
| 1797 | try w.writeByte('{'); | |
| 1773 | 1798 | for (0..loaded_union.field_types.len) |inner_field_index| { |
| 1774 | 1799 | const inner_field_ty: Type = .fromInterned( |
| 1775 | 1800 | loaded_union.field_types.get(ip)[inner_field_index], |
| 1776 | 1801 | ); |
| 1777 | 1802 | if (!inner_field_ty.hasRuntimeBits(pt.zcu)) continue; |
| 1778 | 1803 | try dg.renderUndefValue( |
| 1779 | writer, | |
| 1804 | w, | |
| 1780 | 1805 | inner_field_ty, |
| 1781 | 1806 | initializer_type, |
| 1782 | 1807 | ); |
| 1783 | 1808 | break; |
| 1784 | 1809 | } |
| 1785 | try writer.writeByte('}'); | |
| 1810 | try w.writeByte('}'); | |
| 1786 | 1811 | }, |
| 1787 | 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}", .{ | |
| 1793 | try dg.fmtIntLiteral(try pt.undefValue(ty), .Other), | |
| 1817 | .@"packed" => return w.print("{f}", .{ | |
| 1818 | try dg.fmtIntLiteralHex(try pt.undefValue(ty), .Other), | |
| 1794 | 1819 | }), |
| 1795 | 1820 | } |
| 1796 | 1821 | }, |
| 1797 | 1822 | .error_union_type => |error_union_type| switch (ctype.info(ctype_pool)) { |
| 1798 | 1823 | .basic => try dg.renderUndefValue( |
| 1799 | writer, | |
| 1824 | w, | |
| 1800 | 1825 | .fromInterned(error_union_type.error_set_type), |
| 1801 | 1826 | location, |
| 1802 | 1827 | ), |
| 1803 | 1828 | .pointer, .aligned, .array, .vector, .fwd_decl, .function => unreachable, |
| 1804 | 1829 | .aggregate => |aggregate| { |
| 1805 | 1830 | if (!location.isInitializer()) { |
| 1806 | try writer.writeByte('('); | |
| 1807 | try dg.renderCType(writer, ctype); | |
| 1808 | try writer.writeByte(')'); | |
| 1831 | try w.writeByte('('); | |
| 1832 | try dg.renderCType(w, ctype); | |
| 1833 | try w.writeByte(')'); | |
| 1809 | 1834 | } |
| 1810 | try writer.writeByte('{'); | |
| 1835 | try w.writeByte('{'); | |
| 1811 | 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 | 1838 | try dg.renderUndefValue( |
| 1814 | writer, | |
| 1839 | w, | |
| 1815 | 1840 | .fromInterned( |
| 1816 | 1841 | switch (aggregate.fields.at(field_index, ctype_pool).name.index) { |
| 1817 | 1842 | .@"error" => error_union_type.error_set_type, |
| ... | ... | @@ -1822,14 +1847,14 @@ pub const DeclGen = struct { |
| 1822 | 1847 | initializer_type, |
| 1823 | 1848 | ); |
| 1824 | 1849 | } |
| 1825 | try writer.writeByte('}'); | |
| 1850 | try w.writeByte('}'); | |
| 1826 | 1851 | }, |
| 1827 | 1852 | }, |
| 1828 | 1853 | .array_type, .vector_type => { |
| 1829 | 1854 | const ai = ty.arrayInfo(zcu); |
| 1830 | 1855 | if (ai.elem_type.eql(.u8, zcu)) { |
| 1831 | 1856 | const c_len = ty.arrayLenIncludingSentinel(zcu); |
| 1832 | var literal = stringLiteral(writer, c_len); | |
| 1857 | var literal: StringLiteral = .init(w, @intCast(c_len)); | |
| 1833 | 1858 | try literal.start(); |
| 1834 | 1859 | var index: u64 = 0; |
| 1835 | 1860 | while (index < c_len) : (index += 1) |
| ... | ... | @@ -1837,19 +1862,19 @@ pub const DeclGen = struct { |
| 1837 | 1862 | return literal.end(); |
| 1838 | 1863 | } else { |
| 1839 | 1864 | if (!location.isInitializer()) { |
| 1840 | try writer.writeByte('('); | |
| 1841 | try dg.renderCType(writer, ctype); | |
| 1842 | try writer.writeByte(')'); | |
| 1865 | try w.writeByte('('); | |
| 1866 | try dg.renderCType(w, ctype); | |
| 1867 | try w.writeByte(')'); | |
| 1843 | 1868 | } |
| 1844 | 1869 | |
| 1845 | try writer.writeByte('{'); | |
| 1870 | try w.writeByte('{'); | |
| 1846 | 1871 | const c_len = ty.arrayLenIncludingSentinel(zcu); |
| 1847 | 1872 | var index: u64 = 0; |
| 1848 | 1873 | while (index < c_len) : (index += 1) { |
| 1849 | if (index > 0) try writer.writeAll(", "); | |
| 1850 | try dg.renderUndefValue(writer, ty.childType(zcu), initializer_type); | |
| 1874 | if (index > 0) try w.writeAll(", "); | |
| 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 | 1880 | .anyframe_type, |
| ... | ... | @@ -1882,13 +1907,13 @@ pub const DeclGen = struct { |
| 1882 | 1907 | |
| 1883 | 1908 | fn renderFunctionSignature( |
| 1884 | 1909 | dg: *DeclGen, |
| 1885 | w: anytype, | |
| 1910 | w: *Writer, | |
| 1886 | 1911 | fn_val: Value, |
| 1887 | 1912 | fn_align: InternPool.Alignment, |
| 1888 | 1913 | kind: CType.Kind, |
| 1889 | 1914 | name: union(enum) { |
| 1890 | 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 | 1917 | @"export": struct { |
| 1893 | 1918 | main_name: InternPool.NullTerminatedString, |
| 1894 | 1919 | extern_name: InternPool.NullTerminatedString, |
| ... | ... | @@ -1925,15 +1950,15 @@ pub const DeclGen = struct { |
| 1925 | 1950 | var trailing = try renderTypePrefix(dg.pass, &dg.ctype_pool, zcu, w, fn_ctype, .suffix, .{}); |
| 1926 | 1951 | |
| 1927 | 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 | 1954 | trailing = .maybe_space; |
| 1930 | 1955 | } |
| 1931 | 1956 | |
| 1932 | try w.print("{}", .{trailing}); | |
| 1957 | try w.print("{f}", .{trailing}); | |
| 1933 | 1958 | switch (name) { |
| 1934 | 1959 | .nav => |nav| try dg.renderNavName(w, nav), |
| 1935 | .fmt_ctype_pool_string => |fmt| try w.print("{ }", .{fmt}), | |
| 1936 | .@"export" => |@"export"| try w.print("{ }", .{fmtIdent(@"export".extern_name.toSlice(ip))}), | |
| 1960 | .fmt_ctype_pool_string => |fmt| try w.print("{f}", .{fmt}), | |
| 1961 | .@"export" => |@"export"| try w.print("{f}", .{fmtIdentSolo(@"export".extern_name.toSlice(ip))}), | |
| 1937 | 1962 | } |
| 1938 | 1963 | |
| 1939 | 1964 | try renderTypeSuffix( |
| ... | ... | @@ -1960,17 +1985,17 @@ pub const DeclGen = struct { |
| 1960 | 1985 | const is_mangled = isMangledIdent(extern_name, true); |
| 1961 | 1986 | const is_export = @"export".extern_name != @"export".main_name; |
| 1962 | 1987 | if (is_mangled and is_export) { |
| 1963 | try w.print(" zig_mangled_export({ }, {s}, {s})", .{ | |
| 1964 | fmtIdent(extern_name), | |
| 1988 | try w.print(" zig_mangled_export({f}, {f}, {f})", .{ | |
| 1989 | fmtIdentSolo(extern_name), | |
| 1965 | 1990 | fmtStringLiteral(extern_name, null), |
| 1966 | 1991 | fmtStringLiteral(@"export".main_name.toSlice(ip), null), |
| 1967 | 1992 | }); |
| 1968 | 1993 | } else if (is_mangled) { |
| 1969 | try w.print(" zig_mangled({ }, {s})", .{ | |
| 1970 | fmtIdent(extern_name), fmtStringLiteral(extern_name, null), | |
| 1994 | try w.print(" zig_mangled({f}, {f})", .{ | |
| 1995 | fmtIdentSolo(extern_name), fmtStringLiteral(extern_name, null), | |
| 1971 | 1996 | }); |
| 1972 | 1997 | } else if (is_export) { |
| 1973 | try w.print(" zig_export({s}, {s})", .{ | |
| 1998 | try w.print(" zig_export({f}, {f})", .{ | |
| 1974 | 1999 | fmtStringLiteral(@"export".main_name.toSlice(ip), null), |
| 1975 | 2000 | fmtStringLiteral(extern_name, null), |
| 1976 | 2001 | }); |
| ... | ... | @@ -2003,11 +2028,11 @@ pub const DeclGen = struct { |
| 2003 | 2028 | /// | `renderTypeAndName` | "uint8_t *name" | "uint8_t *name[10]" | |
| 2004 | 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 | 2032 | try dg.renderCType(w, try dg.ctypeFromType(t, .complete)); |
| 2008 | 2033 | } |
| 2009 | 2034 | |
| 2010 | fn renderCType(dg: *DeclGen, w: anytype, ctype: CType) error{OutOfMemory}!void { | |
| 2035 | fn renderCType(dg: *DeclGen, w: *Writer, ctype: CType) Error!void { | |
| 2011 | 2036 | _ = try renderTypePrefix(dg.pass, &dg.ctype_pool, dg.pt.zcu, w, ctype, .suffix, .{}); |
| 2012 | 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 | 2047 | value: Value, |
| 2023 | 2048 | }, |
| 2024 | 2049 | |
| 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 | 2051 | switch (self.*) { |
| 2027 | 2052 | .c_value => |v| { |
| 2028 | 2053 | try v.f.writeCValue(w, v.value, location); |
| ... | ... | @@ -2068,7 +2093,7 @@ pub const DeclGen = struct { |
| 2068 | 2093 | /// | > 64 bit integer | > 64 bit integer | zig_make_<dest_ty>(zig_hi_<src_ty>(src), zig_lo_<src_ty>(src)) |
| 2069 | 2094 | fn renderIntCast( |
| 2070 | 2095 | dg: *DeclGen, |
| 2071 | w: anytype, | |
| 2096 | w: *Writer, | |
| 2072 | 2097 | dest_ty: Type, |
| 2073 | 2098 | context: IntCastContext, |
| 2074 | 2099 | src_ty: Type, |
| ... | ... | @@ -2118,7 +2143,7 @@ pub const DeclGen = struct { |
| 2118 | 2143 | } else if (dest_bits > 64 and src_bits <= 64) { |
| 2119 | 2144 | try w.writeAll("zig_make_"); |
| 2120 | 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 | 2147 | if (src_is_ptr) { |
| 2123 | 2148 | try w.writeByte('('); |
| 2124 | 2149 | try dg.renderType(w, src_eff_ty); |
| ... | ... | @@ -2152,13 +2177,13 @@ pub const DeclGen = struct { |
| 2152 | 2177 | /// |
| 2153 | 2178 | fn renderTypeAndName( |
| 2154 | 2179 | dg: *DeclGen, |
| 2155 | w: anytype, | |
| 2180 | w: *Writer, | |
| 2156 | 2181 | ty: Type, |
| 2157 | 2182 | name: CValue, |
| 2158 | 2183 | qualifiers: CQualifiers, |
| 2159 | 2184 | alignment: Alignment, |
| 2160 | 2185 | kind: CType.Kind, |
| 2161 | ) error{ OutOfMemory, AnalysisFail }!void { | |
| 2186 | ) !void { | |
| 2162 | 2187 | try dg.renderCTypeAndName( |
| 2163 | 2188 | w, |
| 2164 | 2189 | try dg.ctypeFromType(ty, kind), |
| ... | ... | @@ -2173,12 +2198,12 @@ pub const DeclGen = struct { |
| 2173 | 2198 | |
| 2174 | 2199 | fn renderCTypeAndName( |
| 2175 | 2200 | dg: *DeclGen, |
| 2176 | w: anytype, | |
| 2201 | w: *Writer, | |
| 2177 | 2202 | ctype: CType, |
| 2178 | 2203 | name: CValue, |
| 2179 | 2204 | qualifiers: CQualifiers, |
| 2180 | 2205 | alignas: CType.AlignAs, |
| 2181 | ) error{ OutOfMemory, AnalysisFail }!void { | |
| 2206 | ) !void { | |
| 2182 | 2207 | const zcu = dg.pt.zcu; |
| 2183 | 2208 | switch (alignas.abiOrder()) { |
| 2184 | 2209 | .lt => try w.print("zig_under_align({}) ", .{alignas.toByteUnits()}), |
| ... | ... | @@ -2186,24 +2211,24 @@ pub const DeclGen = struct { |
| 2186 | 2211 | .gt => try w.print("zig_align({}) ", .{alignas.toByteUnits()}), |
| 2187 | 2212 | } |
| 2188 | 2213 | |
| 2189 | try w.print("{}", .{ | |
| 2214 | try w.print("{f}", .{ | |
| 2190 | 2215 | try renderTypePrefix(dg.pass, &dg.ctype_pool, zcu, w, ctype, .suffix, qualifiers), |
| 2191 | 2216 | }); |
| 2192 | 2217 | try dg.writeName(w, name); |
| 2193 | 2218 | try renderTypeSuffix(dg.pass, &dg.ctype_pool, zcu, w, ctype, .suffix, .{}); |
| 2194 | 2219 | } |
| 2195 | 2220 | |
| 2196 | fn writeName(dg: *DeclGen, w: anytype, c_value: CValue) !void { | |
| 2221 | fn writeName(dg: *DeclGen, w: *Writer, c_value: CValue) !void { | |
| 2197 | 2222 | switch (c_value) { |
| 2198 | 2223 | .new_local, .local => |i| try w.print("t{d}", .{i}), |
| 2199 | 2224 | .constant => |uav| try renderUavName(w, uav), |
| 2200 | 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 | 2227 | else => unreachable, |
| 2203 | 2228 | } |
| 2204 | 2229 | } |
| 2205 | 2230 | |
| 2206 | fn writeCValue(dg: *DeclGen, w: anytype, c_value: CValue) !void { | |
| 2231 | fn writeCValue(dg: *DeclGen, w: *Writer, c_value: CValue) Error!void { | |
| 2207 | 2232 | switch (c_value) { |
| 2208 | 2233 | .none, .new_local, .local, .local_ref => unreachable, |
| 2209 | 2234 | .constant => |uav| try renderUavName(w, uav), |
| ... | ... | @@ -2215,18 +2240,18 @@ pub const DeclGen = struct { |
| 2215 | 2240 | try dg.renderNavName(w, nav); |
| 2216 | 2241 | }, |
| 2217 | 2242 | .undef => |ty| try dg.renderUndefValue(w, ty, .Other), |
| 2218 | .identifier => |ident| try w.print("{ }", .{fmtIdent(ident)}), | |
| 2219 | .payload_identifier => |ident| try w.print("{ }.{ }", .{ | |
| 2220 | fmtIdent("payload"), | |
| 2221 | fmtIdent(ident), | |
| 2243 | .identifier => |ident| try w.print("{f}", .{fmtIdentSolo(ident)}), | |
| 2244 | .payload_identifier => |ident| try w.print("{f}.{f}", .{ | |
| 2245 | fmtIdentSolo("payload"), | |
| 2246 | fmtIdentSolo(ident), | |
| 2222 | 2247 | }), |
| 2223 | .ctype_pool_string => |string| try w.print("{ }", .{ | |
| 2224 | fmtCTypePoolString(string, &dg.ctype_pool), | |
| 2248 | .ctype_pool_string => |string| try w.print("{f}", .{ | |
| 2249 | fmtCTypePoolString(string, &dg.ctype_pool, true), | |
| 2225 | 2250 | }), |
| 2226 | 2251 | } |
| 2227 | 2252 | } |
| 2228 | 2253 | |
| 2229 | fn writeCValueDeref(dg: *DeclGen, w: anytype, c_value: CValue) !void { | |
| 2254 | fn writeCValueDeref(dg: *DeclGen, w: *Writer, c_value: CValue) !void { | |
| 2230 | 2255 | switch (c_value) { |
| 2231 | 2256 | .none, |
| 2232 | 2257 | .new_local, |
| ... | ... | @@ -2245,26 +2270,31 @@ pub const DeclGen = struct { |
| 2245 | 2270 | }, |
| 2246 | 2271 | .nav_ref => |nav| try dg.renderNavName(w, nav), |
| 2247 | 2272 | .undef => unreachable, |
| 2248 | .identifier => |ident| try w.print("(*{ })", .{fmtIdent(ident)}), | |
| 2249 | .payload_identifier => |ident| try w.print("(*{ }.{ })", .{ | |
| 2250 | fmtIdent("payload"), | |
| 2251 | fmtIdent(ident), | |
| 2273 | .identifier => |ident| try w.print("(*{f})", .{fmtIdentSolo(ident)}), | |
| 2274 | .payload_identifier => |ident| try w.print("(*{f}.{f})", .{ | |
| 2275 | fmtIdentSolo("payload"), | |
| 2276 | fmtIdentSolo(ident), | |
| 2252 | 2277 | }), |
| 2253 | 2278 | } |
| 2254 | 2279 | } |
| 2255 | 2280 | |
| 2256 | 2281 | fn writeCValueMember( |
| 2257 | 2282 | dg: *DeclGen, |
| 2258 | writer: anytype, | |
| 2283 | w: *Writer, | |
| 2259 | 2284 | c_value: CValue, |
| 2260 | 2285 | member: CValue, |
| 2261 | ) error{ OutOfMemory, AnalysisFail }!void { | |
| 2262 | try dg.writeCValue(writer, c_value); | |
| 2263 | try writer.writeByte('.'); | |
| 2264 | try dg.writeCValue(writer, member); | |
| 2286 | ) Error!void { | |
| 2287 | try dg.writeCValue(w, c_value); | |
| 2288 | try w.writeByte('.'); | |
| 2289 | try dg.writeCValue(w, member); | |
| 2265 | 2290 | } |
| 2266 | 2291 | |
| 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 | 2298 | switch (c_value) { |
| 2269 | 2299 | .none, |
| 2270 | 2300 | .new_local, |
| ... | ... | @@ -2278,15 +2308,15 @@ pub const DeclGen = struct { |
| 2278 | 2308 | .ctype_pool_string, |
| 2279 | 2309 | => unreachable, |
| 2280 | 2310 | .nav, .identifier, .payload_identifier => { |
| 2281 | try dg.writeCValue(writer, c_value); | |
| 2282 | try writer.writeAll("->"); | |
| 2311 | try dg.writeCValue(w, c_value); | |
| 2312 | try w.writeAll("->"); | |
| 2283 | 2313 | }, |
| 2284 | 2314 | .nav_ref => { |
| 2285 | try dg.writeCValueDeref(writer, c_value); | |
| 2286 | try writer.writeByte('.'); | |
| 2315 | try dg.writeCValueDeref(w, c_value); | |
| 2316 | try w.writeByte('.'); | |
| 2287 | 2317 | }, |
| 2288 | 2318 | } |
| 2289 | try dg.writeCValue(writer, member); | |
| 2319 | try dg.writeCValue(w, member); | |
| 2290 | 2320 | } |
| 2291 | 2321 | |
| 2292 | 2322 | fn renderFwdDecl( |
| ... | ... | @@ -2302,7 +2332,7 @@ pub const DeclGen = struct { |
| 2302 | 2332 | const zcu = dg.pt.zcu; |
| 2303 | 2333 | const ip = &zcu.intern_pool; |
| 2304 | 2334 | const nav = ip.getNav(nav_index); |
| 2305 | const fwd = dg.fwdDeclWriter(); | |
| 2335 | const fwd = &dg.fwd_decl.writer; | |
| 2306 | 2336 | try fwd.writeAll(switch (flags.linkage) { |
| 2307 | 2337 | .internal => "static ", |
| 2308 | 2338 | .strong, .weak, .link_once => "zig_extern ", |
| ... | ... | @@ -2328,36 +2358,36 @@ pub const DeclGen = struct { |
| 2328 | 2358 | try fwd.writeAll(";\n"); |
| 2329 | 2359 | } |
| 2330 | 2360 | |
| 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 | 2362 | const zcu = dg.pt.zcu; |
| 2333 | 2363 | const ip = &zcu.intern_pool; |
| 2334 | 2364 | const nav = ip.getNav(nav_index); |
| 2335 | 2365 | if (nav.getExtern(ip)) |@"extern"| { |
| 2336 | try writer.print("{ }", .{ | |
| 2337 | fmtIdent(ip.getNav(@"extern".owner_nav).name.toSlice(ip)), | |
| 2366 | try w.print("{f}", .{ | |
| 2367 | fmtIdentSolo(ip.getNav(@"extern".owner_nav).name.toSlice(ip)), | |
| 2338 | 2368 | }); |
| 2339 | 2369 | } else { |
| 2340 | 2370 | // MSVC has a limit of 4095 character token length limit, and fmtIdent can (worst case), |
| 2341 | 2371 | // expand to 3x the length of its input, but let's cut it off at a much shorter limit. |
| 2342 | 2372 | const fqn_slice = ip.getNav(nav_index).fqn.toSlice(ip); |
| 2343 | try writer.print("{}__{d}", .{ | |
| 2344 | fmtIdent(fqn_slice[0..@min(fqn_slice.len, 100)]), | |
| 2373 | try w.print("{f}__{d}", .{ | |
| 2374 | fmtIdentUnsolo(fqn_slice[0..@min(fqn_slice.len, 100)]), | |
| 2345 | 2375 | @intFromEnum(nav_index), |
| 2346 | 2376 | }); |
| 2347 | 2377 | } |
| 2348 | 2378 | } |
| 2349 | 2379 | |
| 2350 | fn renderUavName(writer: anytype, uav: Value) !void { | |
| 2351 | try writer.print("__anon_{d}", .{@intFromEnum(uav.toIntern())}); | |
| 2380 | fn renderUavName(w: *Writer, uav: Value) !void { | |
| 2381 | try w.print("__anon_{d}", .{@intFromEnum(uav.toIntern())}); | |
| 2352 | 2382 | } |
| 2353 | 2383 | |
| 2354 | fn renderTypeForBuiltinFnName(dg: *DeclGen, writer: anytype, ty: Type) !void { | |
| 2355 | try dg.renderCTypeForBuiltinFnName(writer, try dg.ctypeFromType(ty, .complete)); | |
| 2384 | fn renderTypeForBuiltinFnName(dg: *DeclGen, w: *Writer, ty: Type) !void { | |
| 2385 | try dg.renderCTypeForBuiltinFnName(w, try dg.ctypeFromType(ty, .complete)); | |
| 2356 | 2386 | } |
| 2357 | 2387 | |
| 2358 | fn renderCTypeForBuiltinFnName(dg: *DeclGen, writer: anytype, ctype: CType) !void { | |
| 2388 | fn renderCTypeForBuiltinFnName(dg: *DeclGen, w: *Writer, ctype: CType) !void { | |
| 2359 | 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 | 2391 | if (ctype.isBool()) |
| 2362 | 2392 | signAbbrev(.unsigned) |
| 2363 | 2393 | else if (ctype.isInteger()) |
| ... | ... | @@ -2370,11 +2400,11 @@ pub const DeclGen = struct { |
| 2370 | 2400 | return dg.fail("TODO: CBE: implement renderTypeForBuiltinFnName for {s} type", .{@tagName(ctype_info)}), |
| 2371 | 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 | } |
| 2376 | 2406 | |
| 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 | 2408 | const ctype = try dg.ctypeFromType(ty, .complete); |
| 2379 | 2409 | const is_big = ctype.info(&dg.ctype_pool) == .array; |
| 2380 | 2410 | switch (info) { |
| ... | ... | @@ -2389,8 +2419,8 @@ pub const DeclGen = struct { |
| 2389 | 2419 | .bits = @intCast(ty.bitSize(zcu)), |
| 2390 | 2420 | }; |
| 2391 | 2421 | |
| 2392 | if (is_big) try writer.print(", {}", .{int_info.signedness == .signed}); | |
| 2393 | try writer.print(", {}", .{try dg.fmtIntLiteral( | |
| 2422 | if (is_big) try w.print(", {}", .{int_info.signedness == .signed}); | |
| 2423 | try w.print(", {f}", .{try dg.fmtIntLiteralDec( | |
| 2394 | 2424 | try pt.intValue(if (is_big) .u16 else .u8, int_info.bits), |
| 2395 | 2425 | .FunctionArgument, |
| 2396 | 2426 | )}); |
| ... | ... | @@ -2400,18 +2430,38 @@ pub const DeclGen = struct { |
| 2400 | 2430 | dg: *DeclGen, |
| 2401 | 2431 | val: Value, |
| 2402 | 2432 | loc: ValueRenderLocation, |
| 2403 | ) !std.fmt.Formatter(formatIntLiteral) { | |
| 2433 | base: u8, | |
| 2434 | case: std.fmt.Case, | |
| 2435 | ) !std.fmt.Formatter(FormatIntLiteralContext, formatIntLiteral) { | |
| 2404 | 2436 | const zcu = dg.pt.zcu; |
| 2405 | 2437 | const kind = loc.toCTypeKind(); |
| 2406 | 2438 | const ty = val.typeOf(zcu); |
| 2407 | return std.fmt.Formatter(formatIntLiteral){ .data = .{ | |
| 2439 | return .{ .data = .{ | |
| 2408 | 2440 | .dg = dg, |
| 2409 | 2441 | .int_info = ty.intInfo(zcu), |
| 2410 | 2442 | .kind = kind, |
| 2411 | 2443 | .ctype = try dg.ctypeFromType(ty, kind), |
| 2412 | 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 | }; |
| 2416 | 2466 | |
| 2417 | 2467 | const CTypeFix = enum { prefix, suffix }; |
| ... | ... | @@ -2421,28 +2471,19 @@ const RenderCTypeTrailing = enum { |
| 2421 | 2471 | no_space, |
| 2422 | 2472 | maybe_space, |
| 2423 | 2473 | |
| 2424 | pub fn format( | |
| 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); | |
| 2474 | pub fn format(self: @This(), w: *Writer) Writer.Error!void { | |
| 2434 | 2475 | switch (self) { |
| 2435 | 2476 | .no_space => {}, |
| 2436 | 2477 | .maybe_space => try w.writeByte(' '), |
| 2437 | 2478 | } |
| 2438 | 2479 | } |
| 2439 | 2480 | }; |
| 2440 | fn renderAlignedTypeName(w: anytype, ctype: CType) !void { | |
| 2481 | fn renderAlignedTypeName(w: *Writer, ctype: CType) !void { | |
| 2441 | 2482 | try w.print("anon__aligned_{d}", .{@intFromEnum(ctype.index)}); |
| 2442 | 2483 | } |
| 2443 | 2484 | fn renderFwdDeclTypeName( |
| 2444 | 2485 | zcu: *Zcu, |
| 2445 | w: anytype, | |
| 2486 | w: *Writer, | |
| 2446 | 2487 | ctype: CType, |
| 2447 | 2488 | fwd_decl: CType.Info.FwdDecl, |
| 2448 | 2489 | attributes: []const u8, |
| ... | ... | @@ -2451,8 +2492,8 @@ fn renderFwdDeclTypeName( |
| 2451 | 2492 | try w.print("{s} {s}", .{ @tagName(fwd_decl.tag), attributes }); |
| 2452 | 2493 | switch (fwd_decl.name) { |
| 2453 | 2494 | .anon => try w.print("anon__lazy_{d}", .{@intFromEnum(ctype.index)}), |
| 2454 | .index => |index| try w.print("{}__{d}", .{ | |
| 2455 | fmtIdent(Type.fromInterned(index).containerTypeName(ip).toSlice(&zcu.intern_pool)), | |
| 2495 | .index => |index| try w.print("{f}__{d}", .{ | |
| 2496 | fmtIdentUnsolo(Type.fromInterned(index).containerTypeName(ip).toSlice(&zcu.intern_pool)), | |
| 2456 | 2497 | @intFromEnum(index), |
| 2457 | 2498 | }), |
| 2458 | 2499 | } |
| ... | ... | @@ -2461,17 +2502,17 @@ fn renderTypePrefix( |
| 2461 | 2502 | pass: DeclGen.Pass, |
| 2462 | 2503 | ctype_pool: *const CType.Pool, |
| 2463 | 2504 | zcu: *Zcu, |
| 2464 | w: anytype, | |
| 2505 | w: *Writer, | |
| 2465 | 2506 | ctype: CType, |
| 2466 | 2507 | parent_fix: CTypeFix, |
| 2467 | 2508 | qualifiers: CQualifiers, |
| 2468 | ) @TypeOf(w).Error!RenderCTypeTrailing { | |
| 2509 | ) Writer.Error!RenderCTypeTrailing { | |
| 2469 | 2510 | var trailing = RenderCTypeTrailing.maybe_space; |
| 2470 | 2511 | switch (ctype.info(ctype_pool)) { |
| 2471 | 2512 | .basic => |basic_info| try w.writeAll(@tagName(basic_info)), |
| 2472 | 2513 | |
| 2473 | 2514 | .pointer => |pointer_info| { |
| 2474 | try w.print("{}*", .{try renderTypePrefix( | |
| 2515 | try w.print("{f}*", .{try renderTypePrefix( | |
| 2475 | 2516 | pass, |
| 2476 | 2517 | ctype_pool, |
| 2477 | 2518 | zcu, |
| ... | ... | @@ -2508,7 +2549,7 @@ fn renderTypePrefix( |
| 2508 | 2549 | ); |
| 2509 | 2550 | switch (parent_fix) { |
| 2510 | 2551 | .prefix => { |
| 2511 | try w.print("{}(", .{child_trailing}); | |
| 2552 | try w.print("{f}(", .{child_trailing}); | |
| 2512 | 2553 | return .no_space; |
| 2513 | 2554 | }, |
| 2514 | 2555 | .suffix => return child_trailing, |
| ... | ... | @@ -2560,7 +2601,7 @@ fn renderTypePrefix( |
| 2560 | 2601 | ); |
| 2561 | 2602 | switch (parent_fix) { |
| 2562 | 2603 | .prefix => { |
| 2563 | try w.print("{}(", .{child_trailing}); | |
| 2604 | try w.print("{f}(", .{child_trailing}); | |
| 2564 | 2605 | return .no_space; |
| 2565 | 2606 | }, |
| 2566 | 2607 | .suffix => return child_trailing, |
| ... | ... | @@ -2569,7 +2610,7 @@ fn renderTypePrefix( |
| 2569 | 2610 | } |
| 2570 | 2611 | var qualifier_it = qualifiers.iterator(); |
| 2571 | 2612 | while (qualifier_it.next()) |qualifier| { |
| 2572 | try w.print("{}{s}", .{ trailing, @tagName(qualifier) }); | |
| 2613 | try w.print("{f}{s}", .{ trailing, @tagName(qualifier) }); | |
| 2573 | 2614 | trailing = .maybe_space; |
| 2574 | 2615 | } |
| 2575 | 2616 | return trailing; |
| ... | ... | @@ -2578,11 +2619,11 @@ fn renderTypeSuffix( |
| 2578 | 2619 | pass: DeclGen.Pass, |
| 2579 | 2620 | ctype_pool: *const CType.Pool, |
| 2580 | 2621 | zcu: *Zcu, |
| 2581 | w: anytype, | |
| 2622 | w: *Writer, | |
| 2582 | 2623 | ctype: CType, |
| 2583 | 2624 | parent_fix: CTypeFix, |
| 2584 | 2625 | qualifiers: CQualifiers, |
| 2585 | ) @TypeOf(w).Error!void { | |
| 2626 | ) Writer.Error!void { | |
| 2586 | 2627 | switch (ctype.info(ctype_pool)) { |
| 2587 | 2628 | .basic, .aligned, .fwd_decl, .aggregate => {}, |
| 2588 | 2629 | .pointer => |pointer_info| try renderTypeSuffix( |
| ... | ... | @@ -2617,7 +2658,7 @@ fn renderTypeSuffix( |
| 2617 | 2658 | need_comma = true; |
| 2618 | 2659 | const trailing = |
| 2619 | 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 | 2662 | try renderTypeSuffix(pass, ctype_pool, zcu, w, param_type, .suffix, .{}); |
| 2622 | 2663 | } |
| 2623 | 2664 | if (function_info.varargs) { |
| ... | ... | @@ -2634,49 +2675,49 @@ fn renderTypeSuffix( |
| 2634 | 2675 | } |
| 2635 | 2676 | fn renderFields( |
| 2636 | 2677 | zcu: *Zcu, |
| 2637 | writer: anytype, | |
| 2678 | w: *Writer, | |
| 2638 | 2679 | ctype_pool: *const CType.Pool, |
| 2639 | 2680 | aggregate_info: CType.Info.Aggregate, |
| 2640 | 2681 | indent: usize, |
| 2641 | 2682 | ) !void { |
| 2642 | try writer.writeAll("{\n"); | |
| 2683 | try w.writeAll("{\n"); | |
| 2643 | 2684 | for (0..aggregate_info.fields.len) |field_index| { |
| 2644 | 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 | 2687 | switch (field_info.alignas.abiOrder()) { |
| 2647 | 2688 | .lt => { |
| 2648 | 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 | 2691 | field_info.alignas.toByteUnits(), |
| 2651 | 2692 | }); |
| 2652 | 2693 | }, |
| 2653 | 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 | 2696 | .gt => { |
| 2656 | 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 | 2701 | const trailing = try renderTypePrefix( |
| 2661 | 2702 | .flush, |
| 2662 | 2703 | ctype_pool, |
| 2663 | 2704 | zcu, |
| 2664 | writer, | |
| 2705 | w, | |
| 2665 | 2706 | field_info.ctype, |
| 2666 | 2707 | .suffix, |
| 2667 | 2708 | .{}, |
| 2668 | 2709 | ); |
| 2669 | try writer.print("{}{ }", .{ trailing, fmtCTypePoolString(field_info.name, ctype_pool) }); | |
| 2670 | try renderTypeSuffix(.flush, ctype_pool, zcu, writer, field_info.ctype, .suffix, .{}); | |
| 2671 | try writer.writeAll(";\n"); | |
| 2710 | try w.print("{f}{f}", .{ trailing, fmtCTypePoolString(field_info.name, ctype_pool, true) }); | |
| 2711 | try renderTypeSuffix(.flush, ctype_pool, zcu, w, field_info.ctype, .suffix, .{}); | |
| 2712 | try w.writeAll(";\n"); | |
| 2672 | 2713 | } |
| 2673 | try writer.writeByteNTimes(' ', indent); | |
| 2674 | try writer.writeByte('}'); | |
| 2714 | try w.splatByteAll(' ', indent); | |
| 2715 | try w.writeByte('}'); | |
| 2675 | 2716 | } |
| 2676 | 2717 | |
| 2677 | 2718 | pub fn genTypeDecl( |
| 2678 | 2719 | zcu: *Zcu, |
| 2679 | writer: anytype, | |
| 2720 | w: *Writer, | |
| 2680 | 2721 | global_ctype_pool: *const CType.Pool, |
| 2681 | 2722 | global_ctype: CType, |
| 2682 | 2723 | pass: DeclGen.Pass, |
| ... | ... | @@ -2689,27 +2730,27 @@ pub fn genTypeDecl( |
| 2689 | 2730 | .aligned => |aligned_info| { |
| 2690 | 2731 | if (!found_existing) { |
| 2691 | 2732 | std.debug.assert(aligned_info.alignas.abiOrder().compare(.lt)); |
| 2692 | try writer.print("typedef zig_under_align({d}) ", .{aligned_info.alignas.toByteUnits()}); | |
| 2693 | try writer.print("{}", .{try renderTypePrefix( | |
| 2733 | try w.print("typedef zig_under_align({d}) ", .{aligned_info.alignas.toByteUnits()}); | |
| 2734 | try w.print("{f}", .{try renderTypePrefix( | |
| 2694 | 2735 | .flush, |
| 2695 | 2736 | global_ctype_pool, |
| 2696 | 2737 | zcu, |
| 2697 | writer, | |
| 2738 | w, | |
| 2698 | 2739 | aligned_info.ctype, |
| 2699 | 2740 | .suffix, |
| 2700 | 2741 | .{}, |
| 2701 | 2742 | )}); |
| 2702 | try renderAlignedTypeName(writer, global_ctype); | |
| 2703 | try renderTypeSuffix(.flush, global_ctype_pool, zcu, writer, aligned_info.ctype, .suffix, .{}); | |
| 2704 | try writer.writeAll(";\n"); | |
| 2743 | try renderAlignedTypeName(w, global_ctype); | |
| 2744 | try renderTypeSuffix(.flush, global_ctype_pool, zcu, w, aligned_info.ctype, .suffix, .{}); | |
| 2745 | try w.writeAll(";\n"); | |
| 2705 | 2746 | } |
| 2706 | 2747 | switch (pass) { |
| 2707 | 2748 | .nav, .uav => { |
| 2708 | try writer.writeAll("typedef "); | |
| 2709 | _ = try renderTypePrefix(.flush, global_ctype_pool, zcu, writer, global_ctype, .suffix, .{}); | |
| 2710 | try writer.writeByte(' '); | |
| 2711 | _ = try renderTypePrefix(pass, decl_ctype_pool, zcu, writer, decl_ctype, .suffix, .{}); | |
| 2712 | try writer.writeAll(";\n"); | |
| 2749 | try w.writeAll("typedef "); | |
| 2750 | _ = try renderTypePrefix(.flush, global_ctype_pool, zcu, w, global_ctype, .suffix, .{}); | |
| 2751 | try w.writeByte(' '); | |
| 2752 | _ = try renderTypePrefix(pass, decl_ctype_pool, zcu, w, decl_ctype, .suffix, .{}); | |
| 2753 | try w.writeAll(";\n"); | |
| 2713 | 2754 | }, |
| 2714 | 2755 | .flush => {}, |
| 2715 | 2756 | } |
| ... | ... | @@ -2717,24 +2758,24 @@ pub fn genTypeDecl( |
| 2717 | 2758 | .fwd_decl => |fwd_decl_info| switch (fwd_decl_info.name) { |
| 2718 | 2759 | .anon => switch (pass) { |
| 2719 | 2760 | .nav, .uav => { |
| 2720 | try writer.writeAll("typedef "); | |
| 2721 | _ = try renderTypePrefix(.flush, global_ctype_pool, zcu, writer, global_ctype, .suffix, .{}); | |
| 2722 | try writer.writeByte(' '); | |
| 2723 | _ = try renderTypePrefix(pass, decl_ctype_pool, zcu, writer, decl_ctype, .suffix, .{}); | |
| 2724 | try writer.writeAll(";\n"); | |
| 2761 | try w.writeAll("typedef "); | |
| 2762 | _ = try renderTypePrefix(.flush, global_ctype_pool, zcu, w, global_ctype, .suffix, .{}); | |
| 2763 | try w.writeByte(' '); | |
| 2764 | _ = try renderTypePrefix(pass, decl_ctype_pool, zcu, w, decl_ctype, .suffix, .{}); | |
| 2765 | try w.writeAll(";\n"); | |
| 2725 | 2766 | }, |
| 2726 | 2767 | .flush => {}, |
| 2727 | 2768 | }, |
| 2728 | 2769 | .index => |index| if (!found_existing) { |
| 2729 | 2770 | const ip = &zcu.intern_pool; |
| 2730 | 2771 | const ty: Type = .fromInterned(index); |
| 2731 | _ = try renderTypePrefix(.flush, global_ctype_pool, zcu, writer, global_ctype, .suffix, .{}); | |
| 2732 | try writer.writeByte(';'); | |
| 2772 | _ = try renderTypePrefix(.flush, global_ctype_pool, zcu, w, global_ctype, .suffix, .{}); | |
| 2773 | try w.writeByte(';'); | |
| 2733 | 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 | 2776 | ty.containerTypeName(ip).fmt(ip), |
| 2736 | 2777 | }); |
| 2737 | try writer.writeByte('\n'); | |
| 2778 | try w.writeByte('\n'); | |
| 2738 | 2779 | }, |
| 2739 | 2780 | }, |
| 2740 | 2781 | .aggregate => |aggregate_info| switch (aggregate_info.name) { |
| ... | ... | @@ -2742,38 +2783,39 @@ pub fn genTypeDecl( |
| 2742 | 2783 | .fwd_decl => |fwd_decl| if (!found_existing) { |
| 2743 | 2784 | try renderFwdDeclTypeName( |
| 2744 | 2785 | zcu, |
| 2745 | writer, | |
| 2786 | w, | |
| 2746 | 2787 | fwd_decl, |
| 2747 | 2788 | fwd_decl.info(global_ctype_pool).fwd_decl, |
| 2748 | 2789 | if (aggregate_info.@"packed") "zig_packed(" else "", |
| 2749 | 2790 | ); |
| 2750 | try writer.writeByte(' '); | |
| 2751 | try renderFields(zcu, writer, global_ctype_pool, aggregate_info, 0); | |
| 2752 | if (aggregate_info.@"packed") try writer.writeByte(')'); | |
| 2753 | try writer.writeAll(";\n"); | |
| 2791 | try w.writeByte(' '); | |
| 2792 | try renderFields(zcu, w, global_ctype_pool, aggregate_info, 0); | |
| 2793 | if (aggregate_info.@"packed") try w.writeByte(')'); | |
| 2794 | try w.writeAll(";\n"); | |
| 2754 | 2795 | }, |
| 2755 | 2796 | }, |
| 2756 | 2797 | } |
| 2757 | 2798 | } |
| 2758 | 2799 | |
| 2759 | pub fn genGlobalAsm(zcu: *Zcu, writer: anytype) !void { | |
| 2800 | pub fn genGlobalAsm(zcu: *Zcu, w: *Writer) !void { | |
| 2760 | 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 | } |
| 2764 | 2805 | |
| 2765 | pub fn genErrDecls(o: *Object) !void { | |
| 2806 | pub fn genErrDecls(o: *Object) Error!void { | |
| 2766 | 2807 | const pt = o.dg.pt; |
| 2767 | 2808 | const zcu = pt.zcu; |
| 2768 | 2809 | const ip = &zcu.intern_pool; |
| 2769 | const writer = o.writer(); | |
| 2810 | const w = &o.code.writer; | |
| 2770 | 2811 | |
| 2771 | 2812 | var max_name_len: usize = 0; |
| 2772 | 2813 | // do not generate an invalid empty enum when the global error set is empty |
| 2773 | 2814 | const names = ip.global_error_set.getNamesFromMainThread(); |
| 2774 | 2815 | if (names.len > 0) { |
| 2775 | try writer.writeAll("enum {\n"); | |
| 2776 | o.indent_writer.pushIndent(); | |
| 2816 | try w.writeAll("enum {"); | |
| 2817 | o.indent(); | |
| 2818 | try o.newline(); | |
| 2777 | 2819 | for (names, 1..) |name_nts, value| { |
| 2778 | 2820 | const name = name_nts.toSlice(ip); |
| 2779 | 2821 | max_name_len = @max(name.len, max_name_len); |
| ... | ... | @@ -2781,11 +2823,13 @@ pub fn genErrDecls(o: *Object) !void { |
| 2781 | 2823 | .ty = .anyerror_type, |
| 2782 | 2824 | .name = name_nts, |
| 2783 | 2825 | } }); |
| 2784 | try o.dg.renderValue(writer, Value.fromInterned(err_val), .Other); | |
| 2785 | try writer.print(" = {d}u,\n", .{value}); | |
| 2826 | try o.dg.renderValue(w, Value.fromInterned(err_val), .Other); | |
| 2827 | try w.print(" = {d}u,", .{value}); | |
| 2828 | try o.newline(); | |
| 2786 | 2829 | } |
| 2787 | o.indent_writer.popIndent(); | |
| 2788 | try writer.writeAll("};\n"); | |
| 2830 | try o.outdent(); | |
| 2831 | try w.writeAll("};"); | |
| 2832 | try o.newline(); | |
| 2789 | 2833 | } |
| 2790 | 2834 | const array_identifier = "zig_errorName"; |
| 2791 | 2835 | const name_prefix = array_identifier ++ "_"; |
| ... | ... | @@ -2808,18 +2852,19 @@ pub fn genErrDecls(o: *Object) !void { |
| 2808 | 2852 | .storage = .{ .bytes = name.toString() }, |
| 2809 | 2853 | } }); |
| 2810 | 2854 | |
| 2811 | try writer.writeAll("static "); | |
| 2855 | try w.writeAll("static "); | |
| 2812 | 2856 | try o.dg.renderTypeAndName( |
| 2813 | writer, | |
| 2857 | w, | |
| 2814 | 2858 | name_ty, |
| 2815 | 2859 | .{ .identifier = identifier }, |
| 2816 | 2860 | Const, |
| 2817 | 2861 | .none, |
| 2818 | 2862 | .complete, |
| 2819 | 2863 | ); |
| 2820 | try writer.writeAll(" = "); | |
| 2821 | try o.dg.renderValue(writer, Value.fromInterned(name_val), .StaticInitializer); | |
| 2822 | try writer.writeAll(";\n"); | |
| 2864 | try w.writeAll(" = "); | |
| 2865 | try o.dg.renderValue(w, Value.fromInterned(name_val), .StaticInitializer); | |
| 2866 | try w.writeByte(';'); | |
| 2867 | try o.newline(); | |
| 2823 | 2868 | } |
| 2824 | 2869 | |
| 2825 | 2870 | const name_array_ty = try pt.arrayType(.{ |
| ... | ... | @@ -2827,33 +2872,34 @@ pub fn genErrDecls(o: *Object) !void { |
| 2827 | 2872 | .child = .slice_const_u8_sentinel_0_type, |
| 2828 | 2873 | }); |
| 2829 | 2874 | |
| 2830 | try writer.writeAll("static "); | |
| 2875 | try w.writeAll("static "); | |
| 2831 | 2876 | try o.dg.renderTypeAndName( |
| 2832 | writer, | |
| 2877 | w, | |
| 2833 | 2878 | name_array_ty, |
| 2834 | 2879 | .{ .identifier = array_identifier }, |
| 2835 | 2880 | Const, |
| 2836 | 2881 | .none, |
| 2837 | 2882 | .complete, |
| 2838 | 2883 | ); |
| 2839 | try writer.writeAll(" = {"); | |
| 2884 | try w.writeAll(" = {"); | |
| 2840 | 2885 | for (names, 1..) |name_nts, val| { |
| 2841 | 2886 | const name = name_nts.toSlice(ip); |
| 2842 | if (val > 1) try writer.writeAll(", "); | |
| 2843 | try writer.print("{{" ++ name_prefix ++ "{}, {}}}", .{ | |
| 2844 | fmtIdent(name), | |
| 2845 | try o.dg.fmtIntLiteral(try pt.intValue(.usize, name.len), .StaticInitializer), | |
| 2887 | if (val > 1) try w.writeAll(", "); | |
| 2888 | try w.print("{{" ++ name_prefix ++ "{f}, {f}}}", .{ | |
| 2889 | fmtIdentUnsolo(name), | |
| 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 | } |
| 2850 | 2896 | |
| 2851 | pub fn genLazyFn(o: *Object, lazy_ctype_pool: *const CType.Pool, lazy_fn: LazyFnMap.Entry) !void { | |
| 2897 | pub fn genLazyFn(o: *Object, lazy_ctype_pool: *const CType.Pool, lazy_fn: LazyFnMap.Entry) Error!void { | |
| 2852 | 2898 | const pt = o.dg.pt; |
| 2853 | 2899 | const zcu = pt.zcu; |
| 2854 | 2900 | const ip = &zcu.intern_pool; |
| 2855 | 2901 | const ctype_pool = &o.dg.ctype_pool; |
| 2856 | const w = o.writer(); | |
| 2902 | const w = &o.code.writer; | |
| 2857 | 2903 | const key = lazy_fn.key_ptr.*; |
| 2858 | 2904 | const val = lazy_fn.value_ptr; |
| 2859 | 2905 | switch (key) { |
| ... | ... | @@ -2863,9 +2909,14 @@ pub fn genLazyFn(o: *Object, lazy_ctype_pool: *const CType.Pool, lazy_fn: LazyFn |
| 2863 | 2909 | |
| 2864 | 2910 | try w.writeAll("static "); |
| 2865 | 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 | 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 | 2920 | const tag_names = enum_ty.enumFields(zcu); |
| 2870 | 2921 | for (0..tag_names.len) |tag_index| { |
| 2871 | 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 | 2933 | .storage = .{ .bytes = tag_name.toString() }, |
| 2883 | 2934 | } }); |
| 2884 | 2935 | |
| 2885 | try w.print(" case {}: {{\n static ", .{ | |
| 2886 | try o.dg.fmtIntLiteral(try tag_val.intFromEnum(enum_ty, pt), .Other), | |
| 2936 | try w.print("case {f}: {{", .{ | |
| 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 | 2942 | try o.dg.renderTypeAndName(w, name_ty, .{ .identifier = "name" }, Const, .none, .complete); |
| 2889 | 2943 | try w.writeAll(" = "); |
| 2890 | 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 | 2948 | try o.dg.renderType(w, name_slice_ty); |
| 2893 | try w.print("){{{}, {}}};\n", .{ | |
| 2894 | fmtIdent("name"), | |
| 2895 | try o.dg.fmtIntLiteral(try pt.intValue(.usize, tag_name_len), .Other), | |
| 2949 | try w.print("){{{f}, {f}}};", .{ | |
| 2950 | fmtIdentUnsolo("name"), | |
| 2951 | try o.dg.fmtIntLiteralDec(try pt.intValue(.usize, tag_name_len), .Other), | |
| 2896 | 2952 | }); |
| 2897 | ||
| 2898 | try w.writeAll(" }\n"); | |
| 2953 | try o.newline(); | |
| 2954 | try o.outdent(); | |
| 2955 | try w.writeByte('}'); | |
| 2956 | try o.newline(); | |
| 2899 | 2957 | } |
| 2900 | try w.writeAll(" }\n while ("); | |
| 2901 | try o.dg.renderValue(w, Value.true, .Other); | |
| 2902 | try w.writeAll(") "); | |
| 2903 | _ = try airBreakpoint(w); | |
| 2904 | try w.writeAll("}\n"); | |
| 2958 | try o.outdent(); | |
| 2959 | try w.writeByte('}'); | |
| 2960 | try o.newline(); | |
| 2961 | try airUnreach(o); | |
| 2962 | try o.outdent(); | |
| 2963 | try w.writeByte('}'); | |
| 2964 | try o.newline(); | |
| 2905 | 2965 | }, |
| 2906 | 2966 | .never_tail, .never_inline => |fn_nav_index| { |
| 2907 | 2967 | const fn_val = zcu.navValue(fn_nav_index); |
| 2908 | 2968 | const fn_ctype = try o.dg.ctypeFromType(fn_val.typeOf(zcu), .complete); |
| 2909 | 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); | |
| 2911 | 2971 | |
| 2912 | const fwd = o.dg.fwdDeclWriter(); | |
| 2972 | const fwd = &o.dg.fwd_decl.writer; | |
| 2913 | 2973 | try fwd.print("static zig_{s} ", .{@tagName(key)}); |
| 2914 | 2974 | try o.dg.renderFunctionSignature(fwd, fn_val, ip.getNav(fn_nav_index).getAlignment(), .forward, .{ |
| 2915 | 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 | 2980 | try o.dg.renderFunctionSignature(w, fn_val, .none, .complete, .{ |
| 2921 | 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 | 2987 | try o.dg.renderNavName(w, fn_nav_index); |
| 2925 | 2988 | try w.writeByte('('); |
| 2926 | 2989 | for (0..fn_info.param_ctypes.len) |arg| { |
| 2927 | 2990 | if (arg > 0) try w.writeAll(", "); |
| 2928 | 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 | 3034 | .scratch = .empty, |
| 2968 | 3035 | .uavs = .empty, |
| 2969 | 3036 | }, |
| 3037 | .code_header = .init(gpa), | |
| 2970 | 3038 | .code = .init(gpa), |
| 2971 | .indent_writer = undefined, // set later so we can get a pointer to object.code | |
| 3039 | .indent_counter = 0, | |
| 2972 | 3040 | }, |
| 2973 | 3041 | .lazy_fns = .empty, |
| 2974 | 3042 | }; |
| 2975 | 3043 | defer { |
| 3044 | function.object.code_header.deinit(); | |
| 2976 | 3045 | function.object.code.deinit(); |
| 2977 | 3046 | function.object.dg.fwd_decl.deinit(); |
| 2978 | 3047 | function.object.dg.ctype_pool.deinit(gpa); |
| ... | ... | @@ -2981,22 +3050,24 @@ pub fn generate( |
| 2981 | 3050 | function.deinit(); |
| 2982 | 3051 | } |
| 2983 | 3052 | try function.object.dg.ctype_pool.init(gpa); |
| 2984 | function.object.indent_writer = .{ .underlying_writer = function.object.code.writer() }; | |
| 2985 | 3053 | |
| 2986 | 3054 | genFunc(&function) catch |err| switch (err) { |
| 2987 | 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 | }; |
| 2990 | 3059 | |
| 2991 | 3060 | var mir: Mir = .{ |
| 2992 | 3061 | .uavs = .empty, |
| 2993 | 3062 | .code = &.{}, |
| 3063 | .code_header = &.{}, | |
| 2994 | 3064 | .fwd_decl = &.{}, |
| 2995 | 3065 | .ctype_pool = .empty, |
| 2996 | 3066 | .lazy_fns = .empty, |
| 2997 | 3067 | }; |
| 2998 | 3068 | errdefer mir.deinit(gpa); |
| 2999 | 3069 | mir.uavs = function.object.dg.uavs.move(); |
| 3070 | mir.code_header = try function.object.code_header.toOwnedSlice(); | |
| 3000 | 3071 | mir.code = try function.object.code.toOwnedSlice(); |
| 3001 | 3072 | mir.fwd_decl = try function.object.dg.fwd_decl.toOwnedSlice(); |
| 3002 | 3073 | mir.ctype_pool = function.object.dg.ctype_pool.move(); |
| ... | ... | @@ -3004,7 +3075,7 @@ pub fn generate( |
| 3004 | 3075 | return mir; |
| 3005 | 3076 | } |
| 3006 | 3077 | |
| 3007 | fn genFunc(f: *Function) !void { | |
| 3078 | pub fn genFunc(f: *Function) Error!void { | |
| 3008 | 3079 | const tracy = trace(@src()); |
| 3009 | 3080 | defer tracy.end(); |
| 3010 | 3081 | |
| ... | ... | @@ -3016,10 +3087,7 @@ fn genFunc(f: *Function) !void { |
| 3016 | 3087 | const nav_val = zcu.navValue(nav_index); |
| 3017 | 3088 | const nav = ip.getNav(nav_index); |
| 3018 | 3089 | |
| 3019 | o.code_header = std.ArrayList(u8).init(gpa); | |
| 3020 | defer o.code_header.deinit(); | |
| 3021 | ||
| 3022 | const fwd = o.dg.fwdDeclWriter(); | |
| 3090 | const fwd = &o.dg.fwd_decl.writer; | |
| 3023 | 3091 | try fwd.writeAll("static "); |
| 3024 | 3092 | try o.dg.renderFunctionSignature( |
| 3025 | 3093 | fwd, |
| ... | ... | @@ -3030,29 +3098,26 @@ fn genFunc(f: *Function) !void { |
| 3030 | 3098 | ); |
| 3031 | 3099 | try fwd.writeAll(";\n"); |
| 3032 | 3100 | |
| 3101 | const ch = &o.code_header.writer; | |
| 3033 | 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 | 3104 | try o.dg.renderFunctionSignature( |
| 3036 | o.writer(), | |
| 3105 | ch, | |
| 3037 | 3106 | nav_val, |
| 3038 | 3107 | .none, |
| 3039 | 3108 | .complete, |
| 3040 | 3109 | .{ .nav = nav_index }, |
| 3041 | 3110 | ); |
| 3042 | try o.writer().writeByte(' '); | |
| 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; | |
| 3111 | try ch.writeAll(" {\n "); | |
| 3050 | 3112 | |
| 3051 | 3113 | f.free_locals_map.clearRetainingCapacity(); |
| 3052 | 3114 | |
| 3053 | 3115 | const main_body = f.air.getMainBody(); |
| 3054 | try genBodyResolveState(f, undefined, &.{}, main_body, false); | |
| 3055 | try o.indent_writer.insertNewline(); | |
| 3116 | o.indent(); | |
| 3117 | try genBodyResolveState(f, undefined, &.{}, main_body, true); | |
| 3118 | try o.outdent(); | |
| 3119 | try o.code.writer.writeByte('}'); | |
| 3120 | try o.newline(); | |
| 3056 | 3121 | if (o.dg.expected_block) |_| |
| 3057 | 3122 | return f.fail("runtime code not allowed in naked function", .{}); |
| 3058 | 3123 | |
| ... | ... | @@ -3083,24 +3148,16 @@ fn genFunc(f: *Function) !void { |
| 3083 | 3148 | }; |
| 3084 | 3149 | free_locals.sort(SortContext{ .keys = free_locals.keys() }); |
| 3085 | 3150 | |
| 3086 | const w = o.codeHeaderWriter(); | |
| 3087 | 3151 | for (free_locals.values()) |list| { |
| 3088 | 3152 | for (list.keys()) |local_index| { |
| 3089 | 3153 | const local = f.locals.items[local_index]; |
| 3090 | try o.dg.renderCTypeAndName(w, local.ctype, .{ .local = local_index }, .{}, local.flags.alignas); | |
| 3091 | try w.writeAll(";\n "); | |
| 3154 | try o.dg.renderCTypeAndName(ch, local.ctype, .{ .local = local_index }, .{}, local.flags.alignas); | |
| 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 | } |
| 3102 | 3159 | |
| 3103 | pub fn genDecl(o: *Object) !void { | |
| 3160 | pub fn genDecl(o: *Object) Error!void { | |
| 3104 | 3161 | const tracy = trace(@src()); |
| 3105 | 3162 | defer tracy.end(); |
| 3106 | 3163 | |
| ... | ... | @@ -3120,7 +3177,7 @@ pub fn genDecl(o: *Object) !void { |
| 3120 | 3177 | .visibility = @"extern".visibility, |
| 3121 | 3178 | }); |
| 3122 | 3179 | |
| 3123 | const fwd = o.dg.fwdDeclWriter(); | |
| 3180 | const fwd = &o.dg.fwd_decl.writer; | |
| 3124 | 3181 | try fwd.writeAll("zig_extern "); |
| 3125 | 3182 | try o.dg.renderFunctionSignature( |
| 3126 | 3183 | fwd, |
| ... | ... | @@ -3141,10 +3198,10 @@ pub fn genDecl(o: *Object) !void { |
| 3141 | 3198 | .linkage = .internal, |
| 3142 | 3199 | .visibility = .default, |
| 3143 | 3200 | }); |
| 3144 | const w = o.writer(); | |
| 3201 | const w = &o.code.writer; | |
| 3145 | 3202 | if (variable.is_threadlocal and !o.dg.mod.single_threaded) try w.writeAll("zig_threadlocal "); |
| 3146 | 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 | 3205 | try o.dg.renderTypeAndName( |
| 3149 | 3206 | w, |
| 3150 | 3207 | nav_ty, |
| ... | ... | @@ -3156,7 +3213,7 @@ pub fn genDecl(o: *Object) !void { |
| 3156 | 3213 | try w.writeAll(" = "); |
| 3157 | 3214 | try o.dg.renderValue(w, Value.fromInterned(variable.init), .StaticInitializer); |
| 3158 | 3215 | try w.writeByte(';'); |
| 3159 | try o.indent_writer.insertNewline(); | |
| 3216 | try o.newline(); | |
| 3160 | 3217 | }, |
| 3161 | 3218 | else => try genDeclValue( |
| 3162 | 3219 | o, |
| ... | ... | @@ -3174,28 +3231,29 @@ pub fn genDeclValue( |
| 3174 | 3231 | decl_c_value: CValue, |
| 3175 | 3232 | alignment: Alignment, |
| 3176 | 3233 | @"linksection": InternPool.OptionalNullTerminatedString, |
| 3177 | ) !void { | |
| 3234 | ) Error!void { | |
| 3178 | 3235 | const zcu = o.dg.pt.zcu; |
| 3179 | 3236 | const ty = val.typeOf(zcu); |
| 3180 | 3237 | |
| 3181 | const fwd = o.dg.fwdDeclWriter(); | |
| 3238 | const fwd = &o.dg.fwd_decl.writer; | |
| 3182 | 3239 | try fwd.writeAll("static "); |
| 3183 | 3240 | try o.dg.renderTypeAndName(fwd, ty, decl_c_value, Const, alignment, .complete); |
| 3184 | 3241 | try fwd.writeAll(";\n"); |
| 3185 | 3242 | |
| 3186 | const w = o.writer(); | |
| 3243 | const w = &o.code.writer; | |
| 3187 | 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 | 3246 | try o.dg.renderTypeAndName(w, ty, decl_c_value, Const, alignment, .complete); |
| 3190 | 3247 | try w.writeAll(" = "); |
| 3191 | 3248 | try o.dg.renderValue(w, val, .StaticInitializer); |
| 3192 | try w.writeAll(";\n"); | |
| 3249 | try w.writeByte(';'); | |
| 3250 | try o.newline(); | |
| 3193 | 3251 | } |
| 3194 | 3252 | |
| 3195 | 3253 | pub fn genExports(dg: *DeclGen, exported: Zcu.Exported, export_indices: []const Zcu.Export.Index) !void { |
| 3196 | 3254 | const zcu = dg.pt.zcu; |
| 3197 | 3255 | const ip = &zcu.intern_pool; |
| 3198 | const fwd = dg.fwdDeclWriter(); | |
| 3256 | const fwd = &dg.fwd_decl.writer; | |
| 3199 | 3257 | |
| 3200 | 3258 | const main_name = export_indices[0].ptr(zcu).opts.name; |
| 3201 | 3259 | try fwd.writeAll("#define "); |
| ... | ... | @@ -3204,7 +3262,7 @@ pub fn genExports(dg: *DeclGen, exported: Zcu.Exported, export_indices: []const |
| 3204 | 3262 | .uav => |uav| try DeclGen.renderUavName(fwd, Value.fromInterned(uav)), |
| 3205 | 3263 | } |
| 3206 | 3264 | try fwd.writeByte(' '); |
| 3207 | try fwd.print("{ }", .{fmtIdent(main_name.toSlice(ip))}); | |
| 3265 | try fwd.print("{f}", .{fmtIdentSolo(main_name.toSlice(ip))}); | |
| 3208 | 3266 | try fwd.writeByte('\n'); |
| 3209 | 3267 | |
| 3210 | 3268 | const exported_val = exported.getValue(zcu); |
| ... | ... | @@ -3234,7 +3292,7 @@ pub fn genExports(dg: *DeclGen, exported: Zcu.Exported, export_indices: []const |
| 3234 | 3292 | const @"export" = export_index.ptr(zcu); |
| 3235 | 3293 | try fwd.writeAll("zig_extern "); |
| 3236 | 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 | 3296 | fmtStringLiteral(s, null), |
| 3239 | 3297 | }); |
| 3240 | 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 | 3307 | .complete, |
| 3250 | 3308 | ); |
| 3251 | 3309 | if (is_mangled and is_export) { |
| 3252 | try fwd.print(" zig_mangled_export({ }, {s}, {s})", .{ | |
| 3253 | fmtIdent(extern_name), | |
| 3310 | try fwd.print(" zig_mangled_export({f}, {f}, {f})", .{ | |
| 3311 | fmtIdentSolo(extern_name), | |
| 3254 | 3312 | fmtStringLiteral(extern_name, null), |
| 3255 | 3313 | fmtStringLiteral(main_name.toSlice(ip), null), |
| 3256 | 3314 | }); |
| 3257 | 3315 | } else if (is_mangled) { |
| 3258 | try fwd.print(" zig_mangled({ }, {s})", .{ | |
| 3259 | fmtIdent(extern_name), fmtStringLiteral(extern_name, null), | |
| 3316 | try fwd.print(" zig_mangled({f}, {f})", .{ | |
| 3317 | fmtIdentSolo(extern_name), fmtStringLiteral(extern_name, null), | |
| 3260 | 3318 | }); |
| 3261 | 3319 | } else if (is_export) { |
| 3262 | try fwd.print(" zig_export({s}, {s})", .{ | |
| 3320 | try fwd.print(" zig_export({f}, {f})", .{ | |
| 3263 | 3321 | fmtStringLiteral(main_name.toSlice(ip), null), |
| 3264 | 3322 | fmtStringLiteral(extern_name, null), |
| 3265 | 3323 | }); |
| ... | ... | @@ -3272,16 +3330,17 @@ pub fn genExports(dg: *DeclGen, exported: Zcu.Exported, export_indices: []const |
| 3272 | 3330 | /// `value_map` and `free_locals_map` are undefined after the generation, and new locals may not |
| 3273 | 3331 | /// have been added to `free_locals_map`. For a version of this function that restores this state, |
| 3274 | 3332 | /// see `genBodyResolveState`. |
| 3275 | fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutOfMemory }!void { | |
| 3276 | const writer = f.object.writer(); | |
| 3333 | fn genBody(f: *Function, body: []const Air.Inst.Index) Error!void { | |
| 3334 | const w = &f.object.code.writer; | |
| 3277 | 3335 | if (body.len == 0) { |
| 3278 | try writer.writeAll("{}"); | |
| 3336 | try w.writeAll("{}"); | |
| 3279 | 3337 | } else { |
| 3280 | try writer.writeAll("{\n"); | |
| 3281 | f.object.indent_writer.pushIndent(); | |
| 3338 | try w.writeByte('{'); | |
| 3339 | f.object.indent(); | |
| 3340 | try f.object.newline(); | |
| 3282 | 3341 | try genBodyInner(f, body); |
| 3283 | f.object.indent_writer.popIndent(); | |
| 3284 | try writer.writeByte('}'); | |
| 3342 | try f.object.outdent(); | |
| 3343 | try w.writeByte('}'); | |
| 3285 | 3344 | } |
| 3286 | 3345 | } |
| 3287 | 3346 | |
| ... | ... | @@ -3291,10 +3350,10 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO |
| 3291 | 3350 | /// `leading_deaths` have their deaths processed before the body is generated. |
| 3292 | 3351 | /// A scope is introduced (using braces) only if `inner` is `false`. |
| 3293 | 3352 | /// If `leading_deaths` is empty, `inst` may be `undefined`. |
| 3294 | fn genBodyResolveState(f: *Function, inst: Air.Inst.Index, leading_deaths: []const Air.Inst.Index, body: []const Air.Inst.Index, inner: bool) error{ AnalysisFail, OutOfMemory }!void { | |
| 3353 | fn genBodyResolveState(f: *Function, inst: Air.Inst.Index, leading_deaths: []const Air.Inst.Index, body: []const Air.Inst.Index, inner: bool) Error!void { | |
| 3295 | 3354 | if (body.len == 0) { |
| 3296 | 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 | 3357 | return; |
| 3299 | 3358 | } |
| 3300 | 3359 | |
| ... | ... | @@ -3340,7 +3399,7 @@ fn genBodyResolveState(f: *Function, inst: Air.Inst.Index, leading_deaths: []con |
| 3340 | 3399 | } |
| 3341 | 3400 | } |
| 3342 | 3401 | |
| 3343 | fn genBodyInner(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutOfMemory }!void { | |
| 3402 | fn genBodyInner(f: *Function, body: []const Air.Inst.Index) Error!void { | |
| 3344 | 3403 | const zcu = f.object.dg.pt.zcu; |
| 3345 | 3404 | const ip = &zcu.intern_pool; |
| 3346 | 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 | 3417 | |
| 3359 | 3418 | .arg => try airArg(f, inst), |
| 3360 | 3419 | |
| 3361 | .breakpoint => try airBreakpoint(f.object.writer()), | |
| 3420 | .breakpoint => try airBreakpoint(f), | |
| 3362 | 3421 | .ret_addr => try airRetAddr(f, inst), |
| 3363 | 3422 | .frame_addr => try airFrameAddress(f, inst), |
| 3364 | 3423 | |
| ... | ... | @@ -3611,8 +3670,8 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, |
| 3611 | 3670 | .ret => return airRet(f, inst, false), |
| 3612 | 3671 | .ret_safe => return airRet(f, inst, false), // TODO |
| 3613 | 3672 | .ret_load => return airRet(f, inst, true), |
| 3614 | .trap => return airTrap(f, f.object.writer()), | |
| 3615 | .unreach => return airUnreach(f), | |
| 3673 | .trap => return airTrap(f, &f.object.code.writer), | |
| 3674 | .unreach => return airUnreach(&f.object), | |
| 3616 | 3675 | |
| 3617 | 3676 | // Instructions which may be `noreturn`. |
| 3618 | 3677 | .block => res: { |
| ... | ... | @@ -3655,16 +3714,16 @@ fn airSliceField(f: *Function, inst: Air.Inst.Index, is_ptr: bool, field_name: [ |
| 3655 | 3714 | const operand = try f.resolveInst(ty_op.operand); |
| 3656 | 3715 | try reap(f, inst, &.{ty_op.operand}); |
| 3657 | 3716 | |
| 3658 | const writer = f.object.writer(); | |
| 3717 | const w = &f.object.code.writer; | |
| 3659 | 3718 | const local = try f.allocLocal(inst, inst_ty); |
| 3660 | const a = try Assignment.start(f, writer, try f.ctypeFromType(inst_ty, .complete)); | |
| 3661 | try f.writeCValue(writer, local, .Other); | |
| 3662 | try a.assign(f, writer); | |
| 3719 | const a = try Assignment.start(f, w, try f.ctypeFromType(inst_ty, .complete)); | |
| 3720 | try f.writeCValue(w, local, .Other); | |
| 3721 | try a.assign(f, w); | |
| 3663 | 3722 | if (is_ptr) { |
| 3664 | try writer.writeByte('&'); | |
| 3665 | try f.writeCValueDerefMember(writer, operand, .{ .identifier = field_name }); | |
| 3666 | } else try f.writeCValueMember(writer, operand, .{ .identifier = field_name }); | |
| 3667 | try a.end(f, writer); | |
| 3723 | try w.writeByte('&'); | |
| 3724 | try f.writeCValueDerefMember(w, operand, .{ .identifier = field_name }); | |
| 3725 | } else try f.writeCValueMember(w, operand, .{ .identifier = field_name }); | |
| 3726 | try a.end(f, w); | |
| 3668 | 3727 | return local; |
| 3669 | 3728 | } |
| 3670 | 3729 | |
| ... | ... | @@ -3681,16 +3740,16 @@ fn airPtrElemVal(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3681 | 3740 | const index = try f.resolveInst(bin_op.rhs); |
| 3682 | 3741 | try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); |
| 3683 | 3742 | |
| 3684 | const writer = f.object.writer(); | |
| 3743 | const w = &f.object.code.writer; | |
| 3685 | 3744 | const local = try f.allocLocal(inst, inst_ty); |
| 3686 | const a = try Assignment.start(f, writer, try f.ctypeFromType(inst_ty, .complete)); | |
| 3687 | try f.writeCValue(writer, local, .Other); | |
| 3688 | try a.assign(f, writer); | |
| 3689 | try f.writeCValue(writer, ptr, .Other); | |
| 3690 | try writer.writeByte('['); | |
| 3691 | try f.writeCValue(writer, index, .Other); | |
| 3692 | try writer.writeByte(']'); | |
| 3693 | try a.end(f, writer); | |
| 3745 | const a = try Assignment.start(f, w, try f.ctypeFromType(inst_ty, .complete)); | |
| 3746 | try f.writeCValue(w, local, .Other); | |
| 3747 | try a.assign(f, w); | |
| 3748 | try f.writeCValue(w, ptr, .Other); | |
| 3749 | try w.writeByte('['); | |
| 3750 | try f.writeCValue(w, index, .Other); | |
| 3751 | try w.writeByte(']'); | |
| 3752 | try a.end(f, w); | |
| 3694 | 3753 | return local; |
| 3695 | 3754 | } |
| 3696 | 3755 | |
| ... | ... | @@ -3708,25 +3767,25 @@ fn airPtrElemPtr(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3708 | 3767 | const index = try f.resolveInst(bin_op.rhs); |
| 3709 | 3768 | try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); |
| 3710 | 3769 | |
| 3711 | const writer = f.object.writer(); | |
| 3770 | const w = &f.object.code.writer; | |
| 3712 | 3771 | const local = try f.allocLocal(inst, inst_ty); |
| 3713 | const a = try Assignment.start(f, writer, try f.ctypeFromType(inst_ty, .complete)); | |
| 3714 | try f.writeCValue(writer, local, .Other); | |
| 3715 | try a.assign(f, writer); | |
| 3716 | try writer.writeByte('('); | |
| 3717 | try f.renderType(writer, inst_ty); | |
| 3718 | try writer.writeByte(')'); | |
| 3719 | if (elem_has_bits) try writer.writeByte('&'); | |
| 3772 | const a = try Assignment.start(f, w, try f.ctypeFromType(inst_ty, .complete)); | |
| 3773 | try f.writeCValue(w, local, .Other); | |
| 3774 | try a.assign(f, w); | |
| 3775 | try w.writeByte('('); | |
| 3776 | try f.renderType(w, inst_ty); | |
| 3777 | try w.writeByte(')'); | |
| 3778 | if (elem_has_bits) try w.writeByte('&'); | |
| 3720 | 3779 | if (elem_has_bits and ptr_ty.ptrSize(zcu) == .one) { |
| 3721 | 3780 | // It's a pointer to an array, so we need to de-reference. |
| 3722 | try f.writeCValueDeref(writer, ptr); | |
| 3723 | } else try f.writeCValue(writer, ptr, .Other); | |
| 3781 | try f.writeCValueDeref(w, ptr); | |
| 3782 | } else try f.writeCValue(w, ptr, .Other); | |
| 3724 | 3783 | if (elem_has_bits) { |
| 3725 | try writer.writeByte('['); | |
| 3726 | try f.writeCValue(writer, index, .Other); | |
| 3727 | try writer.writeByte(']'); | |
| 3784 | try w.writeByte('['); | |
| 3785 | try f.writeCValue(w, index, .Other); | |
| 3786 | try w.writeByte(']'); | |
| 3728 | 3787 | } |
| 3729 | try a.end(f, writer); | |
| 3788 | try a.end(f, w); | |
| 3730 | 3789 | return local; |
| 3731 | 3790 | } |
| 3732 | 3791 | |
| ... | ... | @@ -3743,16 +3802,16 @@ fn airSliceElemVal(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3743 | 3802 | const index = try f.resolveInst(bin_op.rhs); |
| 3744 | 3803 | try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); |
| 3745 | 3804 | |
| 3746 | const writer = f.object.writer(); | |
| 3805 | const w = &f.object.code.writer; | |
| 3747 | 3806 | const local = try f.allocLocal(inst, inst_ty); |
| 3748 | const a = try Assignment.start(f, writer, try f.ctypeFromType(inst_ty, .complete)); | |
| 3749 | try f.writeCValue(writer, local, .Other); | |
| 3750 | try a.assign(f, writer); | |
| 3751 | try f.writeCValueMember(writer, slice, .{ .identifier = "ptr" }); | |
| 3752 | try writer.writeByte('['); | |
| 3753 | try f.writeCValue(writer, index, .Other); | |
| 3754 | try writer.writeByte(']'); | |
| 3755 | try a.end(f, writer); | |
| 3807 | const a = try Assignment.start(f, w, try f.ctypeFromType(inst_ty, .complete)); | |
| 3808 | try f.writeCValue(w, local, .Other); | |
| 3809 | try a.assign(f, w); | |
| 3810 | try f.writeCValueMember(w, slice, .{ .identifier = "ptr" }); | |
| 3811 | try w.writeByte('['); | |
| 3812 | try f.writeCValue(w, index, .Other); | |
| 3813 | try w.writeByte(']'); | |
| 3814 | try a.end(f, w); | |
| 3756 | 3815 | return local; |
| 3757 | 3816 | } |
| 3758 | 3817 | |
| ... | ... | @@ -3771,19 +3830,19 @@ fn airSliceElemPtr(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3771 | 3830 | const index = try f.resolveInst(bin_op.rhs); |
| 3772 | 3831 | try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); |
| 3773 | 3832 | |
| 3774 | const writer = f.object.writer(); | |
| 3833 | const w = &f.object.code.writer; | |
| 3775 | 3834 | const local = try f.allocLocal(inst, inst_ty); |
| 3776 | const a = try Assignment.start(f, writer, try f.ctypeFromType(inst_ty, .complete)); | |
| 3777 | try f.writeCValue(writer, local, .Other); | |
| 3778 | try a.assign(f, writer); | |
| 3779 | if (elem_has_bits) try writer.writeByte('&'); | |
| 3780 | try f.writeCValueMember(writer, slice, .{ .identifier = "ptr" }); | |
| 3835 | const a = try Assignment.start(f, w, try f.ctypeFromType(inst_ty, .complete)); | |
| 3836 | try f.writeCValue(w, local, .Other); | |
| 3837 | try a.assign(f, w); | |
| 3838 | if (elem_has_bits) try w.writeByte('&'); | |
| 3839 | try f.writeCValueMember(w, slice, .{ .identifier = "ptr" }); | |
| 3781 | 3840 | if (elem_has_bits) { |
| 3782 | try writer.writeByte('['); | |
| 3783 | try f.writeCValue(writer, index, .Other); | |
| 3784 | try writer.writeByte(']'); | |
| 3841 | try w.writeByte('['); | |
| 3842 | try f.writeCValue(w, index, .Other); | |
| 3843 | try w.writeByte(']'); | |
| 3785 | 3844 | } |
| 3786 | try a.end(f, writer); | |
| 3845 | try a.end(f, w); | |
| 3787 | 3846 | return local; |
| 3788 | 3847 | } |
| 3789 | 3848 | |
| ... | ... | @@ -3800,16 +3859,16 @@ fn airArrayElemVal(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3800 | 3859 | const index = try f.resolveInst(bin_op.rhs); |
| 3801 | 3860 | try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); |
| 3802 | 3861 | |
| 3803 | const writer = f.object.writer(); | |
| 3862 | const w = &f.object.code.writer; | |
| 3804 | 3863 | const local = try f.allocLocal(inst, inst_ty); |
| 3805 | const a = try Assignment.start(f, writer, try f.ctypeFromType(inst_ty, .complete)); | |
| 3806 | try f.writeCValue(writer, local, .Other); | |
| 3807 | try a.assign(f, writer); | |
| 3808 | try f.writeCValue(writer, array, .Other); | |
| 3809 | try writer.writeByte('['); | |
| 3810 | try f.writeCValue(writer, index, .Other); | |
| 3811 | try writer.writeByte(']'); | |
| 3812 | try a.end(f, writer); | |
| 3864 | const a = try Assignment.start(f, w, try f.ctypeFromType(inst_ty, .complete)); | |
| 3865 | try f.writeCValue(w, local, .Other); | |
| 3866 | try a.assign(f, w); | |
| 3867 | try f.writeCValue(w, array, .Other); | |
| 3868 | try w.writeByte('['); | |
| 3869 | try f.writeCValue(w, index, .Other); | |
| 3870 | try w.writeByte(']'); | |
| 3871 | try a.end(f, w); | |
| 3813 | 3872 | return local; |
| 3814 | 3873 | } |
| 3815 | 3874 | |
| ... | ... | @@ -3863,12 +3922,13 @@ fn airArg(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3863 | 3922 | .{ .arg_array = i }; |
| 3864 | 3923 | |
| 3865 | 3924 | if (f.liveness.isUnused(inst)) { |
| 3866 | const writer = f.object.writer(); | |
| 3867 | try writer.writeByte('('); | |
| 3868 | try f.renderType(writer, .void); | |
| 3869 | try writer.writeByte(')'); | |
| 3870 | try f.writeCValue(writer, result, .Other); | |
| 3871 | try writer.writeAll(";\n"); | |
| 3925 | const w = &f.object.code.writer; | |
| 3926 | try w.writeByte('('); | |
| 3927 | try f.renderType(w, .void); | |
| 3928 | try w.writeByte(')'); | |
| 3929 | try f.writeCValue(w, result, .Other); | |
| 3930 | try w.writeByte(';'); | |
| 3931 | try f.object.newline(); | |
| 3872 | 3932 | return .none; |
| 3873 | 3933 | } |
| 3874 | 3934 | |
| ... | ... | @@ -3901,21 +3961,21 @@ fn airLoad(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3901 | 3961 | const is_array = lowersToArray(src_ty, pt); |
| 3902 | 3962 | const need_memcpy = !is_aligned or is_array; |
| 3903 | 3963 | |
| 3904 | const writer = f.object.writer(); | |
| 3964 | const w = &f.object.code.writer; | |
| 3905 | 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); | |
| 3907 | 3967 | |
| 3908 | 3968 | if (need_memcpy) { |
| 3909 | try writer.writeAll("memcpy("); | |
| 3910 | if (!is_array) try writer.writeByte('&'); | |
| 3911 | try f.writeCValue(writer, local, .Other); | |
| 3912 | try v.elem(f, writer); | |
| 3913 | try writer.writeAll(", (const char *)"); | |
| 3914 | try f.writeCValue(writer, operand, .Other); | |
| 3915 | try v.elem(f, writer); | |
| 3916 | try writer.writeAll(", sizeof("); | |
| 3917 | try f.renderType(writer, src_ty); | |
| 3918 | try writer.writeAll("))"); | |
| 3969 | try w.writeAll("memcpy("); | |
| 3970 | if (!is_array) try w.writeByte('&'); | |
| 3971 | try f.writeCValue(w, local, .Other); | |
| 3972 | try v.elem(f, w); | |
| 3973 | try w.writeAll(", (const char *)"); | |
| 3974 | try f.writeCValue(w, operand, .Other); | |
| 3975 | try v.elem(f, w); | |
| 3976 | try w.writeAll(", sizeof("); | |
| 3977 | try f.renderType(w, src_ty); | |
| 3978 | try w.writeAll("))"); | |
| 3919 | 3979 | } else if (ptr_info.packed_offset.host_size > 0 and ptr_info.flags.vector_index == .none) { |
| 3920 | 3980 | const host_bits: u16 = ptr_info.packed_offset.host_size * 8; |
| 3921 | 3981 | const host_ty = try pt.intType(.unsigned, host_bits); |
| ... | ... | @@ -3925,40 +3985,41 @@ fn airLoad(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3925 | 3985 | |
| 3926 | 3986 | const field_ty = try pt.intType(.unsigned, @as(u16, @intCast(src_ty.bitSize(zcu)))); |
| 3927 | 3987 | |
| 3928 | try f.writeCValue(writer, local, .Other); | |
| 3929 | try v.elem(f, writer); | |
| 3930 | try writer.writeAll(" = ("); | |
| 3931 | try f.renderType(writer, src_ty); | |
| 3932 | try writer.writeAll(")zig_wrap_"); | |
| 3933 | try f.object.dg.renderTypeForBuiltinFnName(writer, field_ty); | |
| 3934 | try writer.writeAll("(("); | |
| 3935 | try f.renderType(writer, field_ty); | |
| 3936 | try writer.writeByte(')'); | |
| 3988 | try f.writeCValue(w, local, .Other); | |
| 3989 | try v.elem(f, w); | |
| 3990 | try w.writeAll(" = ("); | |
| 3991 | try f.renderType(w, src_ty); | |
| 3992 | try w.writeAll(")zig_wrap_"); | |
| 3993 | try f.object.dg.renderTypeForBuiltinFnName(w, field_ty); | |
| 3994 | try w.writeAll("(("); | |
| 3995 | try f.renderType(w, field_ty); | |
| 3996 | try w.writeByte(')'); | |
| 3937 | 3997 | const cant_cast = host_ty.isInt(zcu) and host_ty.bitSize(zcu) > 64; |
| 3938 | 3998 | if (cant_cast) { |
| 3939 | 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_"); | |
| 3941 | try f.object.dg.renderTypeForBuiltinFnName(writer, host_ty); | |
| 3942 | try writer.writeByte('('); | |
| 4000 | try w.writeAll("zig_lo_"); | |
| 4001 | try f.object.dg.renderTypeForBuiltinFnName(w, host_ty); | |
| 4002 | try w.writeByte('('); | |
| 3943 | 4003 | } |
| 3944 | try writer.writeAll("zig_shr_"); | |
| 3945 | try f.object.dg.renderTypeForBuiltinFnName(writer, host_ty); | |
| 3946 | try writer.writeByte('('); | |
| 3947 | try f.writeCValueDeref(writer, operand); | |
| 3948 | try v.elem(f, writer); | |
| 3949 | try writer.print(", {})", .{try f.fmtIntLiteral(bit_offset_val)}); | |
| 3950 | if (cant_cast) try writer.writeByte(')'); | |
| 3951 | try f.object.dg.renderBuiltinInfo(writer, field_ty, .bits); | |
| 3952 | try writer.writeByte(')'); | |
| 4004 | try w.writeAll("zig_shr_"); | |
| 4005 | try f.object.dg.renderTypeForBuiltinFnName(w, host_ty); | |
| 4006 | try w.writeByte('('); | |
| 4007 | try f.writeCValueDeref(w, operand); | |
| 4008 | try v.elem(f, w); | |
| 4009 | try w.print(", {f})", .{try f.fmtIntLiteralDec(bit_offset_val)}); | |
| 4010 | if (cant_cast) try w.writeByte(')'); | |
| 4011 | try f.object.dg.renderBuiltinInfo(w, field_ty, .bits); | |
| 4012 | try w.writeByte(')'); | |
| 3953 | 4013 | } else { |
| 3954 | try f.writeCValue(writer, local, .Other); | |
| 3955 | try v.elem(f, writer); | |
| 3956 | try writer.writeAll(" = "); | |
| 3957 | try f.writeCValueDeref(writer, operand); | |
| 3958 | try v.elem(f, writer); | |
| 3959 | } | |
| 3960 | try writer.writeAll(";\n"); | |
| 3961 | try v.end(f, inst, writer); | |
| 4014 | try f.writeCValue(w, local, .Other); | |
| 4015 | try v.elem(f, w); | |
| 4016 | try w.writeAll(" = "); | |
| 4017 | try f.writeCValueDeref(w, operand); | |
| 4018 | try v.elem(f, w); | |
| 4019 | } | |
| 4020 | try w.writeByte(';'); | |
| 4021 | try f.object.newline(); | |
| 4022 | try v.end(f, inst, w); | |
| 3962 | 4023 | |
| 3963 | 4024 | return local; |
| 3964 | 4025 | } |
| ... | ... | @@ -3967,7 +4028,7 @@ fn airRet(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !void { |
| 3967 | 4028 | const pt = f.object.dg.pt; |
| 3968 | 4029 | const zcu = pt.zcu; |
| 3969 | 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 | 4032 | const op_inst = un_op.toIndex(); |
| 3972 | 4033 | const op_ty = f.typeOf(un_op); |
| 3973 | 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 | 4047 | .ctype = ret_ctype, |
| 3987 | 4048 | .alignas = CType.AlignAs.fromAbiAlignment(ret_ty.abiAlignment(zcu)), |
| 3988 | 4049 | }); |
| 3989 | try writer.writeAll("memcpy("); | |
| 3990 | try f.writeCValueMember(writer, array_local, .{ .identifier = "array" }); | |
| 3991 | try writer.writeAll(", "); | |
| 4050 | try w.writeAll("memcpy("); | |
| 4051 | try f.writeCValueMember(w, array_local, .{ .identifier = "array" }); | |
| 4052 | try w.writeAll(", "); | |
| 3992 | 4053 | if (deref) |
| 3993 | try f.writeCValueDeref(writer, operand) | |
| 4054 | try f.writeCValueDeref(w, operand) | |
| 3994 | 4055 | else |
| 3995 | try f.writeCValue(writer, operand, .FunctionArgument); | |
| 4056 | try f.writeCValue(w, operand, .FunctionArgument); | |
| 3996 | 4057 | deref = false; |
| 3997 | try writer.writeAll(", sizeof("); | |
| 3998 | try f.renderType(writer, ret_ty); | |
| 3999 | try writer.writeAll("));\n"); | |
| 4058 | try w.writeAll(", sizeof("); | |
| 4059 | try f.renderType(w, ret_ty); | |
| 4060 | try w.writeAll("));"); | |
| 4061 | try f.object.newline(); | |
| 4000 | 4062 | break :ret_val array_local; |
| 4001 | 4063 | } else operand; |
| 4002 | 4064 | |
| 4003 | try writer.writeAll("return "); | |
| 4065 | try w.writeAll("return "); | |
| 4004 | 4066 | if (deref) |
| 4005 | try f.writeCValueDeref(writer, ret_val) | |
| 4067 | try f.writeCValueDeref(w, ret_val) | |
| 4006 | 4068 | else |
| 4007 | try f.writeCValue(writer, ret_val, .Other); | |
| 4008 | try writer.writeAll(";\n"); | |
| 4069 | try f.writeCValue(w, ret_val, .Other); | |
| 4070 | try w.writeAll(";\n"); | |
| 4009 | 4071 | if (is_array) { |
| 4010 | 4072 | try freeLocal(f, inst, ret_val.new_local, null); |
| 4011 | 4073 | } |
| 4012 | 4074 | } else { |
| 4013 | 4075 | try reap(f, inst, &.{un_op}); |
| 4014 | 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 | } |
| 4018 | 4080 | |
| ... | ... | @@ -4031,16 +4093,16 @@ fn airIntCast(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4031 | 4093 | |
| 4032 | 4094 | if (f.object.dg.intCastIsNoop(inst_scalar_ty, scalar_ty)) return f.moveCValue(inst, inst_ty, operand); |
| 4033 | 4095 | |
| 4034 | const writer = f.object.writer(); | |
| 4096 | const w = &f.object.code.writer; | |
| 4035 | 4097 | const local = try f.allocLocal(inst, inst_ty); |
| 4036 | const v = try Vectorize.start(f, inst, writer, operand_ty); | |
| 4037 | const a = try Assignment.start(f, writer, try f.ctypeFromType(scalar_ty, .complete)); | |
| 4038 | try f.writeCValue(writer, local, .Other); | |
| 4039 | try v.elem(f, writer); | |
| 4040 | try a.assign(f, writer); | |
| 4041 | try f.renderIntCast(writer, inst_scalar_ty, operand, v, scalar_ty, .Other); | |
| 4042 | try a.end(f, writer); | |
| 4043 | try v.end(f, inst, writer); | |
| 4098 | const v = try Vectorize.start(f, inst, w, operand_ty); | |
| 4099 | const a = try Assignment.start(f, w, try f.ctypeFromType(scalar_ty, .complete)); | |
| 4100 | try f.writeCValue(w, local, .Other); | |
| 4101 | try v.elem(f, w); | |
| 4102 | try a.assign(f, w); | |
| 4103 | try f.renderIntCast(w, inst_scalar_ty, operand, v, scalar_ty, .Other); | |
| 4104 | try a.end(f, w); | |
| 4105 | try v.end(f, inst, w); | |
| 4044 | 4106 | return local; |
| 4045 | 4107 | } |
| 4046 | 4108 | |
| ... | ... | @@ -4067,35 +4129,35 @@ fn airTrunc(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4067 | 4129 | const need_mask = dest_bits < 8 or !std.math.isPowerOfTwo(dest_bits); |
| 4068 | 4130 | if (!need_cast and !need_lo and !need_mask) return f.moveCValue(inst, inst_ty, operand); |
| 4069 | 4131 | |
| 4070 | const writer = f.object.writer(); | |
| 4132 | const w = &f.object.code.writer; | |
| 4071 | 4133 | const local = try f.allocLocal(inst, inst_ty); |
| 4072 | const v = try Vectorize.start(f, inst, writer, operand_ty); | |
| 4073 | const a = try Assignment.start(f, writer, try f.ctypeFromType(inst_scalar_ty, .complete)); | |
| 4074 | try f.writeCValue(writer, local, .Other); | |
| 4075 | try v.elem(f, writer); | |
| 4076 | try a.assign(f, writer); | |
| 4134 | const v = try Vectorize.start(f, inst, w, operand_ty); | |
| 4135 | const a = try Assignment.start(f, w, try f.ctypeFromType(inst_scalar_ty, .complete)); | |
| 4136 | try f.writeCValue(w, local, .Other); | |
| 4137 | try v.elem(f, w); | |
| 4138 | try a.assign(f, w); | |
| 4077 | 4139 | if (need_cast) { |
| 4078 | try writer.writeByte('('); | |
| 4079 | try f.renderType(writer, inst_scalar_ty); | |
| 4080 | try writer.writeByte(')'); | |
| 4140 | try w.writeByte('('); | |
| 4141 | try f.renderType(w, inst_scalar_ty); | |
| 4142 | try w.writeByte(')'); | |
| 4081 | 4143 | } |
| 4082 | 4144 | if (need_lo) { |
| 4083 | try writer.writeAll("zig_lo_"); | |
| 4084 | try f.object.dg.renderTypeForBuiltinFnName(writer, scalar_ty); | |
| 4085 | try writer.writeByte('('); | |
| 4145 | try w.writeAll("zig_lo_"); | |
| 4146 | try f.object.dg.renderTypeForBuiltinFnName(w, scalar_ty); | |
| 4147 | try w.writeByte('('); | |
| 4086 | 4148 | } |
| 4087 | 4149 | if (!need_mask) { |
| 4088 | try f.writeCValue(writer, operand, .Other); | |
| 4089 | try v.elem(f, writer); | |
| 4150 | try f.writeCValue(w, operand, .Other); | |
| 4151 | try v.elem(f, w); | |
| 4090 | 4152 | } else switch (dest_int_info.signedness) { |
| 4091 | 4153 | .unsigned => { |
| 4092 | try writer.writeAll("zig_and_"); | |
| 4093 | try f.object.dg.renderTypeForBuiltinFnName(writer, scalar_ty); | |
| 4094 | try writer.writeByte('('); | |
| 4095 | try f.writeCValue(writer, operand, .FunctionArgument); | |
| 4096 | try v.elem(f, writer); | |
| 4097 | try writer.print(", {x})", .{ | |
| 4098 | try f.fmtIntLiteral(try inst_scalar_ty.maxIntScalar(pt, scalar_ty)), | |
| 4154 | try w.writeAll("zig_and_"); | |
| 4155 | try f.object.dg.renderTypeForBuiltinFnName(w, scalar_ty); | |
| 4156 | try w.writeByte('('); | |
| 4157 | try f.writeCValue(w, operand, .FunctionArgument); | |
| 4158 | try v.elem(f, w); | |
| 4159 | try w.print(", {f})", .{ | |
| 4160 | try f.fmtIntLiteralHex(try inst_scalar_ty.maxIntScalar(pt, scalar_ty)), | |
| 4099 | 4161 | }); |
| 4100 | 4162 | }, |
| 4101 | 4163 | .signed => { |
| ... | ... | @@ -4103,30 +4165,30 @@ fn airTrunc(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4103 | 4165 | return f.fail("TODO: C backend: implement integer types larger than 128 bits", .{}); |
| 4104 | 4166 | const shift_val = try pt.intValue(.u8, c_bits - dest_bits); |
| 4105 | 4167 | |
| 4106 | try writer.writeAll("zig_shr_"); | |
| 4107 | try f.object.dg.renderTypeForBuiltinFnName(writer, scalar_ty); | |
| 4168 | try w.writeAll("zig_shr_"); | |
| 4169 | try f.object.dg.renderTypeForBuiltinFnName(w, scalar_ty); | |
| 4108 | 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 | 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 | 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 | 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); | |
| 4120 | try v.elem(f, writer); | |
| 4121 | if (c_bits == 128) try writer.writeByte(')'); | |
| 4122 | try writer.print(", {})", .{try f.fmtIntLiteral(shift_val)}); | |
| 4123 | if (c_bits == 128) try writer.writeByte(')'); | |
| 4124 | try writer.print(", {})", .{try f.fmtIntLiteral(shift_val)}); | |
| 4181 | try f.writeCValue(w, operand, .FunctionArgument); | |
| 4182 | try v.elem(f, w); | |
| 4183 | if (c_bits == 128) try w.writeByte(')'); | |
| 4184 | try w.print(", {f})", .{try f.fmtIntLiteralDec(shift_val)}); | |
| 4185 | if (c_bits == 128) try w.writeByte(')'); | |
| 4186 | try w.print(", {f})", .{try f.fmtIntLiteralDec(shift_val)}); | |
| 4125 | 4187 | }, |
| 4126 | 4188 | } |
| 4127 | if (need_lo) try writer.writeByte(')'); | |
| 4128 | try a.end(f, writer); | |
| 4129 | try v.end(f, inst, writer); | |
| 4189 | if (need_lo) try w.writeByte(')'); | |
| 4190 | try a.end(f, w); | |
| 4191 | try v.end(f, inst, w); | |
| 4130 | 4192 | return local; |
| 4131 | 4193 | } |
| 4132 | 4194 | |
| ... | ... | @@ -4145,15 +4207,16 @@ fn airStore(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue { |
| 4145 | 4207 | |
| 4146 | 4208 | const val_is_undef = if (try f.air.value(bin_op.rhs, pt)) |v| v.isUndefDeep(zcu) else false; |
| 4147 | 4209 | |
| 4210 | const w = &f.object.code.writer; | |
| 4148 | 4211 | if (val_is_undef) { |
| 4149 | 4212 | try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); |
| 4150 | 4213 | if (safety and ptr_info.packed_offset.host_size == 0) { |
| 4151 | const writer = f.object.writer(); | |
| 4152 | try writer.writeAll("memset("); | |
| 4153 | try f.writeCValue(writer, ptr_val, .FunctionArgument); | |
| 4154 | try writer.writeAll(", 0xaa, sizeof("); | |
| 4155 | try f.renderType(writer, .fromInterned(ptr_info.child)); | |
| 4156 | try writer.writeAll("));\n"); | |
| 4214 | try w.writeAll("memset("); | |
| 4215 | try f.writeCValue(w, ptr_val, .FunctionArgument); | |
| 4216 | try w.writeAll(", 0xaa, sizeof("); | |
| 4217 | try f.renderType(w, .fromInterned(ptr_info.child)); | |
| 4218 | try w.writeAll("));"); | |
| 4219 | try f.object.newline(); | |
| 4157 | 4220 | } |
| 4158 | 4221 | return .none; |
| 4159 | 4222 | } |
| ... | ... | @@ -4169,7 +4232,6 @@ fn airStore(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue { |
| 4169 | 4232 | try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); |
| 4170 | 4233 | |
| 4171 | 4234 | const src_scalar_ctype = try f.ctypeFromType(src_ty.scalarType(zcu), .complete); |
| 4172 | const writer = f.object.writer(); | |
| 4173 | 4235 | if (need_memcpy) { |
| 4174 | 4236 | // For this memcpy to safely work we need the rhs to have the same |
| 4175 | 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 | 4242 | // TODO this should be done by manually initializing elements of the dest array |
| 4181 | 4243 | const array_src = if (src_val == .constant) blk: { |
| 4182 | 4244 | const new_local = try f.allocLocal(inst, src_ty); |
| 4183 | try f.writeCValue(writer, new_local, .Other); | |
| 4184 | try writer.writeAll(" = "); | |
| 4185 | try f.writeCValue(writer, src_val, .Other); | |
| 4186 | try writer.writeAll(";\n"); | |
| 4245 | try f.writeCValue(w, new_local, .Other); | |
| 4246 | try w.writeAll(" = "); | |
| 4247 | try f.writeCValue(w, src_val, .Other); | |
| 4248 | try w.writeByte(';'); | |
| 4249 | try f.object.newline(); | |
| 4187 | 4250 | |
| 4188 | 4251 | break :blk new_local; |
| 4189 | 4252 | } else src_val; |
| 4190 | 4253 | |
| 4191 | const v = try Vectorize.start(f, inst, writer, ptr_ty); | |
| 4192 | try writer.writeAll("memcpy((char *)"); | |
| 4193 | try f.writeCValue(writer, ptr_val, .FunctionArgument); | |
| 4194 | try v.elem(f, writer); | |
| 4195 | try writer.writeAll(", "); | |
| 4196 | if (!is_array) try writer.writeByte('&'); | |
| 4197 | try f.writeCValue(writer, array_src, .FunctionArgument); | |
| 4198 | try v.elem(f, writer); | |
| 4199 | try writer.writeAll(", sizeof("); | |
| 4200 | try f.renderType(writer, src_ty); | |
| 4201 | try writer.writeAll("))"); | |
| 4254 | const v = try Vectorize.start(f, inst, w, ptr_ty); | |
| 4255 | try w.writeAll("memcpy((char *)"); | |
| 4256 | try f.writeCValue(w, ptr_val, .FunctionArgument); | |
| 4257 | try v.elem(f, w); | |
| 4258 | try w.writeAll(", "); | |
| 4259 | if (!is_array) try w.writeByte('&'); | |
| 4260 | try f.writeCValue(w, array_src, .FunctionArgument); | |
| 4261 | try v.elem(f, w); | |
| 4262 | try w.writeAll(", sizeof("); | |
| 4263 | try f.renderType(w, src_ty); | |
| 4264 | try w.writeAll("))"); | |
| 4202 | 4265 | try f.freeCValue(inst, array_src); |
| 4203 | try writer.writeAll(";\n"); | |
| 4204 | try v.end(f, inst, writer); | |
| 4266 | try w.writeByte(';'); | |
| 4267 | try f.object.newline(); | |
| 4268 | try v.end(f, inst, w); | |
| 4205 | 4269 | } else if (ptr_info.packed_offset.host_size > 0 and ptr_info.flags.vector_index == .none) { |
| 4206 | 4270 | const host_bits = ptr_info.packed_offset.host_size * 8; |
| 4207 | 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 | 4282 | var mask = try BigInt.Managed.initCapacity(stack.get(), BigInt.calcTwosCompLimbCount(host_bits)); |
| 4219 | 4283 | defer mask.deinit(); |
| 4220 | 4284 | |
| 4221 | try mask.setTwosCompIntLimit(.max, .unsigned, @as(usize, @intCast(src_bits))); | |
| 4285 | try mask.setTwosCompIntLimit(.max, .unsigned, @intCast(src_bits)); | |
| 4222 | 4286 | try mask.shiftLeft(&mask, ptr_info.packed_offset.bit_offset); |
| 4223 | 4287 | try mask.bitNotWrap(&mask, .unsigned, host_bits); |
| 4224 | 4288 | |
| 4225 | 4289 | const mask_val = try pt.intValue_big(host_ty, mask.toConst()); |
| 4226 | 4290 | |
| 4227 | const v = try Vectorize.start(f, inst, writer, ptr_ty); | |
| 4228 | const a = try Assignment.start(f, writer, src_scalar_ctype); | |
| 4229 | try f.writeCValueDeref(writer, ptr_val); | |
| 4230 | try v.elem(f, writer); | |
| 4231 | try a.assign(f, writer); | |
| 4232 | try writer.writeAll("zig_or_"); | |
| 4233 | try f.object.dg.renderTypeForBuiltinFnName(writer, host_ty); | |
| 4234 | try writer.writeAll("(zig_and_"); | |
| 4235 | try f.object.dg.renderTypeForBuiltinFnName(writer, host_ty); | |
| 4236 | try writer.writeByte('('); | |
| 4237 | try f.writeCValueDeref(writer, ptr_val); | |
| 4238 | try v.elem(f, writer); | |
| 4239 | try writer.print(", {x}), zig_shl_", .{try f.fmtIntLiteral(mask_val)}); | |
| 4240 | try f.object.dg.renderTypeForBuiltinFnName(writer, host_ty); | |
| 4241 | try writer.writeByte('('); | |
| 4291 | const v = try Vectorize.start(f, inst, w, ptr_ty); | |
| 4292 | const a = try Assignment.start(f, w, src_scalar_ctype); | |
| 4293 | try f.writeCValueDeref(w, ptr_val); | |
| 4294 | try v.elem(f, w); | |
| 4295 | try a.assign(f, w); | |
| 4296 | try w.writeAll("zig_or_"); | |
| 4297 | try f.object.dg.renderTypeForBuiltinFnName(w, host_ty); | |
| 4298 | try w.writeAll("(zig_and_"); | |
| 4299 | try f.object.dg.renderTypeForBuiltinFnName(w, host_ty); | |
| 4300 | try w.writeByte('('); | |
| 4301 | try f.writeCValueDeref(w, ptr_val); | |
| 4302 | try v.elem(f, w); | |
| 4303 | try w.print(", {f}), zig_shl_", .{try f.fmtIntLiteralHex(mask_val)}); | |
| 4304 | try f.object.dg.renderTypeForBuiltinFnName(w, host_ty); | |
| 4305 | try w.writeByte('('); | |
| 4242 | 4306 | const cant_cast = host_ty.isInt(zcu) and host_ty.bitSize(zcu) > 64; |
| 4243 | 4307 | if (cant_cast) { |
| 4244 | 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_"); | |
| 4246 | try f.object.dg.renderTypeForBuiltinFnName(writer, host_ty); | |
| 4247 | try writer.writeAll("(0, "); | |
| 4309 | try w.writeAll("zig_make_"); | |
| 4310 | try f.object.dg.renderTypeForBuiltinFnName(w, host_ty); | |
| 4311 | try w.writeAll("(0, "); | |
| 4248 | 4312 | } else { |
| 4249 | try writer.writeByte('('); | |
| 4250 | try f.renderType(writer, host_ty); | |
| 4251 | try writer.writeByte(')'); | |
| 4313 | try w.writeByte('('); | |
| 4314 | try f.renderType(w, host_ty); | |
| 4315 | try w.writeByte(')'); | |
| 4252 | 4316 | } |
| 4253 | 4317 | |
| 4254 | 4318 | if (src_ty.isPtrAtRuntime(zcu)) { |
| 4255 | try writer.writeByte('('); | |
| 4256 | try f.renderType(writer, .usize); | |
| 4257 | try writer.writeByte(')'); | |
| 4319 | try w.writeByte('('); | |
| 4320 | try f.renderType(w, .usize); | |
| 4321 | try w.writeByte(')'); | |
| 4258 | 4322 | } |
| 4259 | try f.writeCValue(writer, src_val, .Other); | |
| 4260 | try v.elem(f, writer); | |
| 4261 | if (cant_cast) try writer.writeByte(')'); | |
| 4262 | try writer.print(", {}))", .{try f.fmtIntLiteral(bit_offset_val)}); | |
| 4263 | try a.end(f, writer); | |
| 4264 | try v.end(f, inst, writer); | |
| 4323 | try f.writeCValue(w, src_val, .Other); | |
| 4324 | try v.elem(f, w); | |
| 4325 | if (cant_cast) try w.writeByte(')'); | |
| 4326 | try w.print(", {f}))", .{try f.fmtIntLiteralDec(bit_offset_val)}); | |
| 4327 | try a.end(f, w); | |
| 4328 | try v.end(f, inst, w); | |
| 4265 | 4329 | } else { |
| 4266 | 4330 | switch (ptr_val) { |
| 4267 | 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 | 4335 | }, |
| 4272 | 4336 | else => {}, |
| 4273 | 4337 | } |
| 4274 | const v = try Vectorize.start(f, inst, writer, ptr_ty); | |
| 4275 | const a = try Assignment.start(f, writer, src_scalar_ctype); | |
| 4276 | try f.writeCValueDeref(writer, ptr_val); | |
| 4277 | try v.elem(f, writer); | |
| 4278 | try a.assign(f, writer); | |
| 4279 | try f.writeCValue(writer, src_val, .Other); | |
| 4280 | try v.elem(f, writer); | |
| 4281 | try a.end(f, writer); | |
| 4282 | try v.end(f, inst, writer); | |
| 4338 | const v = try Vectorize.start(f, inst, w, ptr_ty); | |
| 4339 | const a = try Assignment.start(f, w, src_scalar_ctype); | |
| 4340 | try f.writeCValueDeref(w, ptr_val); | |
| 4341 | try v.elem(f, w); | |
| 4342 | try a.assign(f, w); | |
| 4343 | try f.writeCValue(w, src_val, .Other); | |
| 4344 | try v.elem(f, w); | |
| 4345 | try a.end(f, w); | |
| 4346 | try v.end(f, inst, w); | |
| 4283 | 4347 | } |
| 4284 | 4348 | return .none; |
| 4285 | 4349 | } |
| ... | ... | @@ -4298,7 +4362,7 @@ fn airOverflow(f: *Function, inst: Air.Inst.Index, operation: []const u8, info: |
| 4298 | 4362 | const operand_ty = f.typeOf(bin_op.lhs); |
| 4299 | 4363 | const scalar_ty = operand_ty.scalarType(zcu); |
| 4300 | 4364 | |
| 4301 | const w = f.object.writer(); | |
| 4365 | const w = &f.object.code.writer; | |
| 4302 | 4366 | const local = try f.allocLocal(inst, inst_ty); |
| 4303 | 4367 | const v = try Vectorize.start(f, inst, w, operand_ty); |
| 4304 | 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 | 4381 | try f.writeCValue(w, rhs, .FunctionArgument); |
| 4318 | 4382 | if (f.typeOf(bin_op.rhs).isVector(zcu)) try v.elem(f, w); |
| 4319 | 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 | 4386 | try v.end(f, inst, w); |
| 4322 | 4387 | |
| 4323 | 4388 | return local; |
| ... | ... | @@ -4336,17 +4401,18 @@ fn airNot(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4336 | 4401 | |
| 4337 | 4402 | const inst_ty = f.typeOfIndex(inst); |
| 4338 | 4403 | |
| 4339 | const writer = f.object.writer(); | |
| 4404 | const w = &f.object.code.writer; | |
| 4340 | 4405 | const local = try f.allocLocal(inst, inst_ty); |
| 4341 | const v = try Vectorize.start(f, inst, writer, operand_ty); | |
| 4342 | try f.writeCValue(writer, local, .Other); | |
| 4343 | try v.elem(f, writer); | |
| 4344 | try writer.writeAll(" = "); | |
| 4345 | try writer.writeByte('!'); | |
| 4346 | try f.writeCValue(writer, op, .Other); | |
| 4347 | try v.elem(f, writer); | |
| 4348 | try writer.writeAll(";\n"); | |
| 4349 | try v.end(f, inst, writer); | |
| 4406 | const v = try Vectorize.start(f, inst, w, operand_ty); | |
| 4407 | try f.writeCValue(w, local, .Other); | |
| 4408 | try v.elem(f, w); | |
| 4409 | try w.writeAll(" = "); | |
| 4410 | try w.writeByte('!'); | |
| 4411 | try f.writeCValue(w, op, .Other); | |
| 4412 | try v.elem(f, w); | |
| 4413 | try w.writeByte(';'); | |
| 4414 | try f.object.newline(); | |
| 4415 | try v.end(f, inst, w); | |
| 4350 | 4416 | |
| 4351 | 4417 | return local; |
| 4352 | 4418 | } |
| ... | ... | @@ -4372,21 +4438,22 @@ fn airBinOp( |
| 4372 | 4438 | |
| 4373 | 4439 | const inst_ty = f.typeOfIndex(inst); |
| 4374 | 4440 | |
| 4375 | const writer = f.object.writer(); | |
| 4441 | const w = &f.object.code.writer; | |
| 4376 | 4442 | const local = try f.allocLocal(inst, inst_ty); |
| 4377 | const v = try Vectorize.start(f, inst, writer, operand_ty); | |
| 4378 | try f.writeCValue(writer, local, .Other); | |
| 4379 | try v.elem(f, writer); | |
| 4380 | try writer.writeAll(" = "); | |
| 4381 | try f.writeCValue(writer, lhs, .Other); | |
| 4382 | try v.elem(f, writer); | |
| 4383 | try writer.writeByte(' '); | |
| 4384 | try writer.writeAll(operator); | |
| 4385 | try writer.writeByte(' '); | |
| 4386 | try f.writeCValue(writer, rhs, .Other); | |
| 4387 | try v.elem(f, writer); | |
| 4388 | try writer.writeAll(";\n"); | |
| 4389 | try v.end(f, inst, writer); | |
| 4443 | const v = try Vectorize.start(f, inst, w, operand_ty); | |
| 4444 | try f.writeCValue(w, local, .Other); | |
| 4445 | try v.elem(f, w); | |
| 4446 | try w.writeAll(" = "); | |
| 4447 | try f.writeCValue(w, lhs, .Other); | |
| 4448 | try v.elem(f, w); | |
| 4449 | try w.writeByte(' '); | |
| 4450 | try w.writeAll(operator); | |
| 4451 | try w.writeByte(' '); | |
| 4452 | try f.writeCValue(w, rhs, .Other); | |
| 4453 | try v.elem(f, w); | |
| 4454 | try w.writeByte(';'); | |
| 4455 | try f.object.newline(); | |
| 4456 | try v.end(f, inst, w); | |
| 4390 | 4457 | |
| 4391 | 4458 | return local; |
| 4392 | 4459 | } |
| ... | ... | @@ -4422,27 +4489,27 @@ fn airCmpOp( |
| 4422 | 4489 | |
| 4423 | 4490 | const rhs_ty = f.typeOf(data.rhs); |
| 4424 | 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 | 4493 | const local = try f.allocLocal(inst, inst_ty); |
| 4427 | const v = try Vectorize.start(f, inst, writer, lhs_ty); | |
| 4428 | const a = try Assignment.start(f, writer, try f.ctypeFromType(scalar_ty, .complete)); | |
| 4429 | try f.writeCValue(writer, local, .Other); | |
| 4430 | try v.elem(f, writer); | |
| 4431 | try a.assign(f, writer); | |
| 4432 | if (lhs != .undef and lhs.eql(rhs)) try writer.writeAll(switch (operator) { | |
| 4494 | const v = try Vectorize.start(f, inst, w, lhs_ty); | |
| 4495 | const a = try Assignment.start(f, w, try f.ctypeFromType(scalar_ty, .complete)); | |
| 4496 | try f.writeCValue(w, local, .Other); | |
| 4497 | try v.elem(f, w); | |
| 4498 | try a.assign(f, w); | |
| 4499 | if (lhs != .undef and lhs.eql(rhs)) try w.writeAll(switch (operator) { | |
| 4433 | 4500 | .lt, .neq, .gt => "false", |
| 4434 | 4501 | .lte, .eq, .gte => "true", |
| 4435 | 4502 | }) else { |
| 4436 | if (need_cast) try writer.writeAll("(void*)"); | |
| 4437 | try f.writeCValue(writer, lhs, .Other); | |
| 4438 | try v.elem(f, writer); | |
| 4439 | try writer.writeAll(compareOperatorC(operator)); | |
| 4440 | if (need_cast) try writer.writeAll("(void*)"); | |
| 4441 | try f.writeCValue(writer, rhs, .Other); | |
| 4442 | try v.elem(f, writer); | |
| 4443 | } | |
| 4444 | try a.end(f, writer); | |
| 4445 | try v.end(f, inst, writer); | |
| 4503 | if (need_cast) try w.writeAll("(void*)"); | |
| 4504 | try f.writeCValue(w, lhs, .Other); | |
| 4505 | try v.elem(f, w); | |
| 4506 | try w.writeAll(compareOperatorC(operator)); | |
| 4507 | if (need_cast) try w.writeAll("(void*)"); | |
| 4508 | try f.writeCValue(w, rhs, .Other); | |
| 4509 | try v.elem(f, w); | |
| 4510 | } | |
| 4511 | try a.end(f, w); | |
| 4512 | try v.end(f, inst, w); | |
| 4446 | 4513 | |
| 4447 | 4514 | return local; |
| 4448 | 4515 | } |
| ... | ... | @@ -4475,41 +4542,41 @@ fn airEquality( |
| 4475 | 4542 | const rhs = try f.resolveInst(bin_op.rhs); |
| 4476 | 4543 | try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); |
| 4477 | 4544 | |
| 4478 | const writer = f.object.writer(); | |
| 4545 | const w = &f.object.code.writer; | |
| 4479 | 4546 | const local = try f.allocLocal(inst, .bool); |
| 4480 | const a = try Assignment.start(f, writer, .bool); | |
| 4481 | try f.writeCValue(writer, local, .Other); | |
| 4482 | try a.assign(f, writer); | |
| 4547 | const a = try Assignment.start(f, w, .bool); | |
| 4548 | try f.writeCValue(w, local, .Other); | |
| 4549 | try a.assign(f, w); | |
| 4483 | 4550 | |
| 4484 | 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 | 4553 | .lt, .lte, .gte, .gt => unreachable, |
| 4487 | 4554 | .neq => "false", |
| 4488 | 4555 | .eq => "true", |
| 4489 | 4556 | }) else switch (operand_ctype.info(ctype_pool)) { |
| 4490 | 4557 | .basic, .pointer => { |
| 4491 | try f.writeCValue(writer, lhs, .Other); | |
| 4492 | try writer.writeAll(compareOperatorC(operator)); | |
| 4493 | try f.writeCValue(writer, rhs, .Other); | |
| 4558 | try f.writeCValue(w, lhs, .Other); | |
| 4559 | try w.writeAll(compareOperatorC(operator)); | |
| 4560 | try f.writeCValue(w, rhs, .Other); | |
| 4494 | 4561 | }, |
| 4495 | 4562 | .aligned, .array, .vector, .fwd_decl, .function => unreachable, |
| 4496 | 4563 | .aggregate => |aggregate| if (aggregate.fields.len == 2 and |
| 4497 | 4564 | (aggregate.fields.at(0, ctype_pool).name.index == .is_null or |
| 4498 | 4565 | aggregate.fields.at(1, ctype_pool).name.index == .is_null)) |
| 4499 | 4566 | { |
| 4500 | try f.writeCValueMember(writer, lhs, .{ .identifier = "is_null" }); | |
| 4501 | try writer.writeAll(" || "); | |
| 4502 | try f.writeCValueMember(writer, rhs, .{ .identifier = "is_null" }); | |
| 4503 | try writer.writeAll(" ? "); | |
| 4504 | try f.writeCValueMember(writer, lhs, .{ .identifier = "is_null" }); | |
| 4505 | try writer.writeAll(compareOperatorC(operator)); | |
| 4506 | try f.writeCValueMember(writer, rhs, .{ .identifier = "is_null" }); | |
| 4507 | try writer.writeAll(" : "); | |
| 4508 | try f.writeCValueMember(writer, lhs, .{ .identifier = "payload" }); | |
| 4509 | try writer.writeAll(compareOperatorC(operator)); | |
| 4510 | try f.writeCValueMember(writer, rhs, .{ .identifier = "payload" }); | |
| 4567 | try f.writeCValueMember(w, lhs, .{ .identifier = "is_null" }); | |
| 4568 | try w.writeAll(" || "); | |
| 4569 | try f.writeCValueMember(w, rhs, .{ .identifier = "is_null" }); | |
| 4570 | try w.writeAll(" ? "); | |
| 4571 | try f.writeCValueMember(w, lhs, .{ .identifier = "is_null" }); | |
| 4572 | try w.writeAll(compareOperatorC(operator)); | |
| 4573 | try f.writeCValueMember(w, rhs, .{ .identifier = "is_null" }); | |
| 4574 | try w.writeAll(" : "); | |
| 4575 | try f.writeCValueMember(w, lhs, .{ .identifier = "payload" }); | |
| 4576 | try w.writeAll(compareOperatorC(operator)); | |
| 4577 | try f.writeCValueMember(w, rhs, .{ .identifier = "payload" }); | |
| 4511 | 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 | 4580 | .lt, .lte, .gte, .gt => unreachable, |
| 4514 | 4581 | .eq => " && ", |
| 4515 | 4582 | .neq => " || ", |
| ... | ... | @@ -4517,12 +4584,12 @@ fn airEquality( |
| 4517 | 4584 | const field_name: CValue = .{ |
| 4518 | 4585 | .ctype_pool_string = aggregate.fields.at(field_index, ctype_pool).name, |
| 4519 | 4586 | }; |
| 4520 | try f.writeCValueMember(writer, lhs, field_name); | |
| 4521 | try writer.writeAll(compareOperatorC(operator)); | |
| 4522 | try f.writeCValueMember(writer, rhs, field_name); | |
| 4587 | try f.writeCValueMember(w, lhs, field_name); | |
| 4588 | try w.writeAll(compareOperatorC(operator)); | |
| 4589 | try f.writeCValueMember(w, rhs, field_name); | |
| 4523 | 4590 | }, |
| 4524 | 4591 | } |
| 4525 | try a.end(f, writer); | |
| 4592 | try a.end(f, w); | |
| 4526 | 4593 | |
| 4527 | 4594 | return local; |
| 4528 | 4595 | } |
| ... | ... | @@ -4533,12 +4600,13 @@ fn airCmpLtErrorsLen(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4533 | 4600 | const operand = try f.resolveInst(un_op); |
| 4534 | 4601 | try reap(f, inst, &.{un_op}); |
| 4535 | 4602 | |
| 4536 | const writer = f.object.writer(); | |
| 4603 | const w = &f.object.code.writer; | |
| 4537 | 4604 | const local = try f.allocLocal(inst, .bool); |
| 4538 | try f.writeCValue(writer, local, .Other); | |
| 4539 | try writer.writeAll(" = "); | |
| 4540 | try f.writeCValue(writer, operand, .Other); | |
| 4541 | try writer.print(" < sizeof({ }) / sizeof(*{0 });\n", .{fmtIdent("zig_errorName")}); | |
| 4605 | try f.writeCValue(w, local, .Other); | |
| 4606 | try w.writeAll(" = "); | |
| 4607 | try f.writeCValue(w, operand, .Other); | |
| 4608 | try w.print(" < sizeof({f}) / sizeof(*{0f});", .{fmtIdentSolo("zig_errorName")}); | |
| 4609 | try f.object.newline(); | |
| 4542 | 4610 | return local; |
| 4543 | 4611 | } |
| 4544 | 4612 | |
| ... | ... | @@ -4559,30 +4627,30 @@ fn airPtrAddSub(f: *Function, inst: Air.Inst.Index, operator: u8) !CValue { |
| 4559 | 4627 | const inst_scalar_ctype = try f.ctypeFromType(inst_scalar_ty, .complete); |
| 4560 | 4628 | |
| 4561 | 4629 | const local = try f.allocLocal(inst, inst_ty); |
| 4562 | const writer = f.object.writer(); | |
| 4563 | const v = try Vectorize.start(f, inst, writer, inst_ty); | |
| 4564 | const a = try Assignment.start(f, writer, inst_scalar_ctype); | |
| 4565 | try f.writeCValue(writer, local, .Other); | |
| 4566 | try v.elem(f, writer); | |
| 4567 | try a.assign(f, writer); | |
| 4630 | const w = &f.object.code.writer; | |
| 4631 | const v = try Vectorize.start(f, inst, w, inst_ty); | |
| 4632 | const a = try Assignment.start(f, w, inst_scalar_ctype); | |
| 4633 | try f.writeCValue(w, local, .Other); | |
| 4634 | try v.elem(f, w); | |
| 4635 | try a.assign(f, w); | |
| 4568 | 4636 | // We must convert to and from integer types to prevent UB if the operation |
| 4569 | 4637 | // results in a NULL pointer, or if LHS is NULL. The operation is only UB |
| 4570 | 4638 | // if the result is NULL and then dereferenced. |
| 4571 | try writer.writeByte('('); | |
| 4572 | try f.renderCType(writer, inst_scalar_ctype); | |
| 4573 | try writer.writeAll(")(((uintptr_t)"); | |
| 4574 | try f.writeCValue(writer, lhs, .Other); | |
| 4575 | try v.elem(f, writer); | |
| 4576 | try writer.writeAll(") "); | |
| 4577 | try writer.writeByte(operator); | |
| 4578 | try writer.writeAll(" ("); | |
| 4579 | try f.writeCValue(writer, rhs, .Other); | |
| 4580 | try v.elem(f, writer); | |
| 4581 | try writer.writeAll("*sizeof("); | |
| 4582 | try f.renderType(writer, elem_ty); | |
| 4583 | try writer.writeAll(")))"); | |
| 4584 | try a.end(f, writer); | |
| 4585 | try v.end(f, inst, writer); | |
| 4639 | try w.writeByte('('); | |
| 4640 | try f.renderCType(w, inst_scalar_ctype); | |
| 4641 | try w.writeAll(")(((uintptr_t)"); | |
| 4642 | try f.writeCValue(w, lhs, .Other); | |
| 4643 | try v.elem(f, w); | |
| 4644 | try w.writeAll(") "); | |
| 4645 | try w.writeByte(operator); | |
| 4646 | try w.writeAll(" ("); | |
| 4647 | try f.writeCValue(w, rhs, .Other); | |
| 4648 | try v.elem(f, w); | |
| 4649 | try w.writeAll("*sizeof("); | |
| 4650 | try f.renderType(w, elem_ty); | |
| 4651 | try w.writeAll(")))"); | |
| 4652 | try a.end(f, w); | |
| 4653 | try v.end(f, inst, w); | |
| 4586 | 4654 | return local; |
| 4587 | 4655 | } |
| 4588 | 4656 | |
| ... | ... | @@ -4601,28 +4669,29 @@ fn airMinMax(f: *Function, inst: Air.Inst.Index, operator: u8, operation: []cons |
| 4601 | 4669 | const rhs = try f.resolveInst(bin_op.rhs); |
| 4602 | 4670 | try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); |
| 4603 | 4671 | |
| 4604 | const writer = f.object.writer(); | |
| 4672 | const w = &f.object.code.writer; | |
| 4605 | 4673 | const local = try f.allocLocal(inst, inst_ty); |
| 4606 | const v = try Vectorize.start(f, inst, writer, inst_ty); | |
| 4607 | try f.writeCValue(writer, local, .Other); | |
| 4608 | try v.elem(f, writer); | |
| 4674 | const v = try Vectorize.start(f, inst, w, inst_ty); | |
| 4675 | try f.writeCValue(w, local, .Other); | |
| 4676 | try v.elem(f, w); | |
| 4609 | 4677 | // (lhs <> rhs) ? lhs : rhs |
| 4610 | try writer.writeAll(" = ("); | |
| 4611 | try f.writeCValue(writer, lhs, .Other); | |
| 4612 | try v.elem(f, writer); | |
| 4613 | try writer.writeByte(' '); | |
| 4614 | try writer.writeByte(operator); | |
| 4615 | try writer.writeByte(' '); | |
| 4616 | try f.writeCValue(writer, rhs, .Other); | |
| 4617 | try v.elem(f, writer); | |
| 4618 | try writer.writeAll(") ? "); | |
| 4619 | try f.writeCValue(writer, lhs, .Other); | |
| 4620 | try v.elem(f, writer); | |
| 4621 | try writer.writeAll(" : "); | |
| 4622 | try f.writeCValue(writer, rhs, .Other); | |
| 4623 | try v.elem(f, writer); | |
| 4624 | try writer.writeAll(";\n"); | |
| 4625 | try v.end(f, inst, writer); | |
| 4678 | try w.writeAll(" = ("); | |
| 4679 | try f.writeCValue(w, lhs, .Other); | |
| 4680 | try v.elem(f, w); | |
| 4681 | try w.writeByte(' '); | |
| 4682 | try w.writeByte(operator); | |
| 4683 | try w.writeByte(' '); | |
| 4684 | try f.writeCValue(w, rhs, .Other); | |
| 4685 | try v.elem(f, w); | |
| 4686 | try w.writeAll(") ? "); | |
| 4687 | try f.writeCValue(w, lhs, .Other); | |
| 4688 | try v.elem(f, w); | |
| 4689 | try w.writeAll(" : "); | |
| 4690 | try f.writeCValue(w, rhs, .Other); | |
| 4691 | try v.elem(f, w); | |
| 4692 | try w.writeByte(';'); | |
| 4693 | try f.object.newline(); | |
| 4694 | try v.end(f, inst, w); | |
| 4626 | 4695 | |
| 4627 | 4696 | return local; |
| 4628 | 4697 | } |
| ... | ... | @@ -4640,21 +4709,21 @@ fn airSlice(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4640 | 4709 | const inst_ty = f.typeOfIndex(inst); |
| 4641 | 4710 | const ptr_ty = inst_ty.slicePtrFieldType(zcu); |
| 4642 | 4711 | |
| 4643 | const writer = f.object.writer(); | |
| 4712 | const w = &f.object.code.writer; | |
| 4644 | 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)); | |
| 4647 | try f.writeCValueMember(writer, local, .{ .identifier = "ptr" }); | |
| 4648 | try a.assign(f, writer); | |
| 4649 | try f.writeCValue(writer, ptr, .Other); | |
| 4650 | try a.end(f, writer); | |
| 4715 | const a = try Assignment.start(f, w, try f.ctypeFromType(ptr_ty, .complete)); | |
| 4716 | try f.writeCValueMember(w, local, .{ .identifier = "ptr" }); | |
| 4717 | try a.assign(f, w); | |
| 4718 | try f.writeCValue(w, ptr, .Other); | |
| 4719 | try a.end(f, w); | |
| 4651 | 4720 | } |
| 4652 | 4721 | { |
| 4653 | const a = try Assignment.start(f, writer, .usize); | |
| 4654 | try f.writeCValueMember(writer, local, .{ .identifier = "len" }); | |
| 4655 | try a.assign(f, writer); | |
| 4656 | try f.writeCValue(writer, len, .Other); | |
| 4657 | try a.end(f, writer); | |
| 4722 | const a = try Assignment.start(f, w, .usize); | |
| 4723 | try f.writeCValueMember(w, local, .{ .identifier = "len" }); | |
| 4724 | try a.assign(f, w); | |
| 4725 | try f.writeCValue(w, len, .Other); | |
| 4726 | try a.end(f, w); | |
| 4658 | 4727 | } |
| 4659 | 4728 | return local; |
| 4660 | 4729 | } |
| ... | ... | @@ -4671,7 +4740,7 @@ fn airCall( |
| 4671 | 4740 | if (f.object.dg.is_naked_fn) return .none; |
| 4672 | 4741 | |
| 4673 | 4742 | const gpa = f.object.dg.gpa; |
| 4674 | const writer = f.object.writer(); | |
| 4743 | const w = &f.object.code.writer; | |
| 4675 | 4744 | |
| 4676 | 4745 | const pl_op = f.air.instructions.items(.data)[@intFromEnum(inst)].pl_op; |
| 4677 | 4746 | const extra = f.air.extraData(Air.Call, pl_op.payload); |
| ... | ... | @@ -4692,13 +4761,14 @@ fn airCall( |
| 4692 | 4761 | .ctype = arg_ctype, |
| 4693 | 4762 | .alignas = CType.AlignAs.fromAbiAlignment(arg_ty.abiAlignment(zcu)), |
| 4694 | 4763 | }); |
| 4695 | try writer.writeAll("memcpy("); | |
| 4696 | try f.writeCValueMember(writer, array_local, .{ .identifier = "array" }); | |
| 4697 | try writer.writeAll(", "); | |
| 4698 | try f.writeCValue(writer, resolved_arg.*, .FunctionArgument); | |
| 4699 | try writer.writeAll(", sizeof("); | |
| 4700 | try f.renderCType(writer, arg_ctype); | |
| 4701 | try writer.writeAll("));\n"); | |
| 4764 | try w.writeAll("memcpy("); | |
| 4765 | try f.writeCValueMember(w, array_local, .{ .identifier = "array" }); | |
| 4766 | try w.writeAll(", "); | |
| 4767 | try f.writeCValue(w, resolved_arg.*, .FunctionArgument); | |
| 4768 | try w.writeAll(", sizeof("); | |
| 4769 | try f.renderCType(w, arg_ctype); | |
| 4770 | try w.writeAll("));"); | |
| 4771 | try f.object.newline(); | |
| 4702 | 4772 | resolved_arg.* = array_local; |
| 4703 | 4773 | } |
| 4704 | 4774 | } |
| ... | ... | @@ -4726,22 +4796,22 @@ fn airCall( |
| 4726 | 4796 | |
| 4727 | 4797 | const result_local = result: { |
| 4728 | 4798 | if (modifier == .always_tail) { |
| 4729 | try writer.writeAll("zig_always_tail return "); | |
| 4799 | try w.writeAll("zig_always_tail return "); | |
| 4730 | 4800 | break :result .none; |
| 4731 | 4801 | } else if (ret_ctype.index == .void) { |
| 4732 | 4802 | break :result .none; |
| 4733 | 4803 | } else if (f.liveness.isUnused(inst)) { |
| 4734 | try writer.writeByte('('); | |
| 4735 | try f.renderCType(writer, .void); | |
| 4736 | try writer.writeByte(')'); | |
| 4804 | try w.writeByte('('); | |
| 4805 | try f.renderCType(w, .void); | |
| 4806 | try w.writeByte(')'); | |
| 4737 | 4807 | break :result .none; |
| 4738 | 4808 | } else { |
| 4739 | 4809 | const local = try f.allocAlignedLocal(inst, .{ |
| 4740 | 4810 | .ctype = ret_ctype, |
| 4741 | 4811 | .alignas = CType.AlignAs.fromAbiAlignment(ret_ty.abiAlignment(zcu)), |
| 4742 | 4812 | }); |
| 4743 | try f.writeCValue(writer, local, .Other); | |
| 4744 | try writer.writeAll(" = "); | |
| 4813 | try f.writeCValue(w, local, .Other); | |
| 4814 | try w.writeAll(" = "); | |
| 4745 | 4815 | break :result local; |
| 4746 | 4816 | } |
| 4747 | 4817 | }; |
| ... | ... | @@ -4761,17 +4831,17 @@ fn airCall( |
| 4761 | 4831 | else => break :known, |
| 4762 | 4832 | }; |
| 4763 | 4833 | if (need_cast) { |
| 4764 | try writer.writeAll("(("); | |
| 4765 | try f.renderType(writer, if (callee_is_ptr) callee_ty else try pt.singleConstPtrType(callee_ty)); | |
| 4766 | try writer.writeByte(')'); | |
| 4767 | if (!callee_is_ptr) try writer.writeByte('&'); | |
| 4834 | try w.writeAll("(("); | |
| 4835 | try f.renderType(w, if (callee_is_ptr) callee_ty else try pt.singleConstPtrType(callee_ty)); | |
| 4836 | try w.writeByte(')'); | |
| 4837 | if (!callee_is_ptr) try w.writeByte('&'); | |
| 4768 | 4838 | } |
| 4769 | 4839 | switch (modifier) { |
| 4770 | .auto, .always_tail => try f.object.dg.renderNavName(writer, fn_nav), | |
| 4771 | inline .never_tail, .never_inline => |m| try writer.writeAll(try f.getLazyFnName(@unionInit(LazyFnKey, @tagName(m), fn_nav))), | |
| 4840 | .auto, .always_tail => try f.object.dg.renderNavName(w, fn_nav), | |
| 4841 | inline .never_tail, .never_inline => |m| try w.writeAll(try f.getLazyFnName(@unionInit(LazyFnKey, @tagName(m), fn_nav))), | |
| 4772 | 4842 | else => unreachable, |
| 4773 | 4843 | } |
| 4774 | if (need_cast) try writer.writeByte(')'); | |
| 4844 | if (need_cast) try w.writeByte(')'); | |
| 4775 | 4845 | break :callee; |
| 4776 | 4846 | } |
| 4777 | 4847 | switch (modifier) { |
| ... | ... | @@ -4781,32 +4851,37 @@ fn airCall( |
| 4781 | 4851 | else => unreachable, |
| 4782 | 4852 | } |
| 4783 | 4853 | // Fall back to function pointer call. |
| 4784 | try f.writeCValue(writer, callee, .Other); | |
| 4854 | try f.writeCValue(w, callee, .Other); | |
| 4785 | 4855 | } |
| 4786 | 4856 | |
| 4787 | try writer.writeByte('('); | |
| 4857 | try w.writeByte('('); | |
| 4788 | 4858 | var need_comma = false; |
| 4789 | 4859 | for (resolved_args) |resolved_arg| { |
| 4790 | 4860 | if (resolved_arg == .none) continue; |
| 4791 | if (need_comma) try writer.writeAll(", "); | |
| 4861 | if (need_comma) try w.writeAll(", "); | |
| 4792 | 4862 | need_comma = true; |
| 4793 | try f.writeCValue(writer, resolved_arg, .FunctionArgument); | |
| 4863 | try f.writeCValue(w, resolved_arg, .FunctionArgument); | |
| 4794 | 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 | } | |
| 4797 | 4871 | |
| 4798 | 4872 | const result = result: { |
| 4799 | 4873 | if (result_local == .none or !lowersToArray(ret_ty, pt)) |
| 4800 | 4874 | break :result result_local; |
| 4801 | 4875 | |
| 4802 | 4876 | const array_local = try f.allocLocal(inst, ret_ty); |
| 4803 | try writer.writeAll("memcpy("); | |
| 4804 | try f.writeCValue(writer, array_local, .FunctionArgument); | |
| 4805 | try writer.writeAll(", "); | |
| 4806 | try f.writeCValueMember(writer, result_local, .{ .identifier = "array" }); | |
| 4807 | try writer.writeAll(", sizeof("); | |
| 4808 | try f.renderType(writer, ret_ty); | |
| 4809 | try writer.writeAll("));\n"); | |
| 4877 | try w.writeAll("memcpy("); | |
| 4878 | try f.writeCValue(w, array_local, .FunctionArgument); | |
| 4879 | try w.writeAll(", "); | |
| 4880 | try f.writeCValueMember(w, result_local, .{ .identifier = "array" }); | |
| 4881 | try w.writeAll(", sizeof("); | |
| 4882 | try f.renderType(w, ret_ty); | |
| 4883 | try w.writeAll("));"); | |
| 4884 | try f.object.newline(); | |
| 4810 | 4885 | try freeLocal(f, inst, result_local.new_local, null); |
| 4811 | 4886 | break :result array_local; |
| 4812 | 4887 | }; |
| ... | ... | @@ -4816,7 +4891,7 @@ fn airCall( |
| 4816 | 4891 | |
| 4817 | 4892 | fn airDbgStmt(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4818 | 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 | 4895 | // TODO re-evaluate whether to emit these or not. If we naively emit |
| 4821 | 4896 | // these directives, the output file will report bogus line numbers because |
| 4822 | 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 | 4899 | // If we wanted to go this route, we would need to go all the way and not output |
| 4825 | 4900 | // newlines until the next dbg_stmt occurs. |
| 4826 | 4901 | // Perhaps an additional compilation option is in order? |
| 4827 | //try writer.print("#line {d}\n", .{dbg_stmt.line + 1}); | |
| 4828 | try writer.print("/* file:{d}:{d} */\n", .{ dbg_stmt.line + 1, dbg_stmt.column + 1 }); | |
| 4902 | //try w.print("#line {d}", .{dbg_stmt.line + 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 | 4906 | return .none; |
| 4830 | 4907 | } |
| 4831 | 4908 | |
| 4832 | 4909 | fn 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 | 4912 | return .none; |
| 4835 | 4913 | } |
| 4836 | 4914 | |
| ... | ... | @@ -4841,8 +4919,9 @@ fn airDbgInlineBlock(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4841 | 4919 | const ty_pl = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; |
| 4842 | 4920 | const extra = f.air.extraData(Air.DbgInlineBlock, ty_pl.payload); |
| 4843 | 4921 | const owner_nav = ip.getNav(zcu.funcInfo(extra.data.func).owner_nav); |
| 4844 | const writer = f.object.writer(); | |
| 4845 | try writer.print("/* inline:{} */\n", .{owner_nav.fqn.fmt(&zcu.intern_pool)}); | |
| 4922 | const w = &f.object.code.writer; | |
| 4923 | try w.print("/* inline:{f} */", .{owner_nav.fqn.fmt(&zcu.intern_pool)}); | |
| 4924 | try f.object.newline(); | |
| 4846 | 4925 | return lowerBlock(f, inst, @ptrCast(f.air.extra.items[extra.end..][0..extra.data.body_len])); |
| 4847 | 4926 | } |
| 4848 | 4927 | |
| ... | ... | @@ -4856,8 +4935,9 @@ fn airDbgVar(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4856 | 4935 | if (!operand_is_undef) _ = try f.resolveInst(pl_op.operand); |
| 4857 | 4936 | |
| 4858 | 4937 | try reap(f, inst, &.{pl_op.operand}); |
| 4859 | const writer = f.object.writer(); | |
| 4860 | try writer.print("/* {s}:{s} */\n", .{ @tagName(tag), name.toSlice(f.air) }); | |
| 4938 | const w = &f.object.code.writer; | |
| 4939 | try w.print("/* {s}:{s} */", .{ @tagName(tag), name.toSlice(f.air) }); | |
| 4940 | try f.object.newline(); | |
| 4861 | 4941 | return .none; |
| 4862 | 4942 | } |
| 4863 | 4943 | |
| ... | ... | @@ -4874,7 +4954,7 @@ fn lowerBlock(f: *Function, inst: Air.Inst.Index, body: []const Air.Inst.Index) |
| 4874 | 4954 | |
| 4875 | 4955 | const block_id = f.next_block_index; |
| 4876 | 4956 | f.next_block_index += 1; |
| 4877 | const writer = f.object.writer(); | |
| 4957 | const w = &f.object.code.writer; | |
| 4878 | 4958 | |
| 4879 | 4959 | const inst_ty = f.typeOfIndex(inst); |
| 4880 | 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 | 4976 | try die(f, inst, death.toRef()); |
| 4897 | 4977 | } |
| 4898 | 4978 | |
| 4899 | try f.object.indent_writer.insertNewline(); | |
| 4900 | ||
| 4901 | 4979 | // noreturn blocks have no `br` instructions reaching them, so we don't want a label |
| 4902 | 4980 | if (f.object.dg.is_naked_fn) { |
| 4903 | 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 | 4985 | } |
| 4908 | 4986 | } else if (!f.typeOfIndex(inst).isNoReturn(zcu)) { |
| 4909 | 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 | } |
| 4912 | 4991 | |
| 4913 | 4992 | return result; |
| ... | ... | @@ -4944,31 +5023,31 @@ fn lowerTry( |
| 4944 | 5023 | const err_union = try f.resolveInst(operand); |
| 4945 | 5024 | const inst_ty = f.typeOfIndex(inst); |
| 4946 | 5025 | const liveness_condbr = f.liveness.getCondBr(inst); |
| 4947 | const writer = f.object.writer(); | |
| 5026 | const w = &f.object.code.writer; | |
| 4948 | 5027 | const payload_ty = err_union_ty.errorUnionPayload(zcu); |
| 4949 | 5028 | const payload_has_bits = payload_ty.hasRuntimeBitsIgnoreComptime(zcu); |
| 4950 | 5029 | |
| 4951 | 5030 | if (!err_union_ty.errorUnionSet(zcu).errorSetIsEmpty(zcu)) { |
| 4952 | try writer.writeAll("if ("); | |
| 5031 | try w.writeAll("if ("); | |
| 4953 | 5032 | if (!payload_has_bits) { |
| 4954 | 5033 | if (is_ptr) |
| 4955 | try f.writeCValueDeref(writer, err_union) | |
| 5034 | try f.writeCValueDeref(w, err_union) | |
| 4956 | 5035 | else |
| 4957 | try f.writeCValue(writer, err_union, .Other); | |
| 5036 | try f.writeCValue(w, err_union, .Other); | |
| 4958 | 5037 | } else { |
| 4959 | 5038 | // Reap the operand so that it can be reused inside genBody. |
| 4960 | 5039 | // Remember we must avoid calling reap() twice for the same operand |
| 4961 | 5040 | // in this function. |
| 4962 | 5041 | try reap(f, inst, &.{operand}); |
| 4963 | 5042 | if (is_ptr) |
| 4964 | try f.writeCValueDerefMember(writer, err_union, .{ .identifier = "error" }) | |
| 5043 | try f.writeCValueDerefMember(w, err_union, .{ .identifier = "error" }) | |
| 4965 | 5044 | 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(") "); | |
| 4969 | 5048 | |
| 4970 | 5049 | try genBodyResolveState(f, inst, liveness_condbr.else_deaths, body, false); |
| 4971 | try f.object.indent_writer.insertNewline(); | |
| 5050 | try f.object.newline(); | |
| 4972 | 5051 | if (f.object.dg.expected_block) |_| |
| 4973 | 5052 | return f.fail("runtime code not allowed in naked function", .{}); |
| 4974 | 5053 | } |
| ... | ... | @@ -4991,14 +5070,14 @@ fn lowerTry( |
| 4991 | 5070 | if (f.liveness.isUnused(inst)) return .none; |
| 4992 | 5071 | |
| 4993 | 5072 | const local = try f.allocLocal(inst, inst_ty); |
| 4994 | const a = try Assignment.start(f, writer, try f.ctypeFromType(inst_ty, .complete)); | |
| 4995 | try f.writeCValue(writer, local, .Other); | |
| 4996 | try a.assign(f, writer); | |
| 5073 | const a = try Assignment.start(f, w, try f.ctypeFromType(inst_ty, .complete)); | |
| 5074 | try f.writeCValue(w, local, .Other); | |
| 5075 | try a.assign(f, w); | |
| 4997 | 5076 | if (is_ptr) { |
| 4998 | try writer.writeByte('&'); | |
| 4999 | try f.writeCValueDerefMember(writer, err_union, .{ .identifier = "payload" }); | |
| 5000 | } else try f.writeCValueMember(writer, err_union, .{ .identifier = "payload" }); | |
| 5001 | try a.end(f, writer); | |
| 5077 | try w.writeByte('&'); | |
| 5078 | try f.writeCValueDerefMember(w, err_union, .{ .identifier = "payload" }); | |
| 5079 | } else try f.writeCValueMember(w, err_union, .{ .identifier = "payload" }); | |
| 5080 | try a.end(f, w); | |
| 5002 | 5081 | return local; |
| 5003 | 5082 | } |
| 5004 | 5083 | |
| ... | ... | @@ -5006,7 +5085,7 @@ fn airBr(f: *Function, inst: Air.Inst.Index) !void { |
| 5006 | 5085 | const branch = f.air.instructions.items(.data)[@intFromEnum(inst)].br; |
| 5007 | 5086 | const block = f.blocks.get(branch.block_inst).?; |
| 5008 | 5087 | const result = block.result; |
| 5009 | const writer = f.object.writer(); | |
| 5088 | const w = &f.object.code.writer; | |
| 5010 | 5089 | |
| 5011 | 5090 | if (f.object.dg.is_naked_fn) { |
| 5012 | 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 | 5099 | const operand = try f.resolveInst(branch.operand); |
| 5021 | 5100 | try reap(f, inst, &.{branch.operand}); |
| 5022 | 5101 | |
| 5023 | const a = try Assignment.start(f, writer, try f.ctypeFromType(operand_ty, .complete)); | |
| 5024 | try f.writeCValue(writer, result, .Other); | |
| 5025 | try a.assign(f, writer); | |
| 5026 | try f.writeCValue(writer, operand, .Other); | |
| 5027 | try a.end(f, writer); | |
| 5102 | const a = try Assignment.start(f, w, try f.ctypeFromType(operand_ty, .complete)); | |
| 5103 | try f.writeCValue(w, result, .Other); | |
| 5104 | try a.assign(f, w); | |
| 5105 | try f.writeCValue(w, operand, .Other); | |
| 5106 | try a.end(f, w); | |
| 5028 | 5107 | } |
| 5029 | 5108 | |
| 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 | } |
| 5032 | 5111 | |
| 5033 | 5112 | fn airRepeat(f: *Function, inst: Air.Inst.Index) !void { |
| 5034 | 5113 | const repeat = f.air.instructions.items(.data)[@intFromEnum(inst)].repeat; |
| 5035 | const writer = f.object.writer(); | |
| 5036 | try writer.print("goto zig_loop_{d};\n", .{@intFromEnum(repeat.loop_inst)}); | |
| 5114 | try f.object.code.writer.print("goto zig_loop_{d};\n", .{@intFromEnum(repeat.loop_inst)}); | |
| 5037 | 5115 | } |
| 5038 | 5116 | |
| 5039 | 5117 | fn airSwitchDispatch(f: *Function, inst: Air.Inst.Index) !void { |
| 5040 | 5118 | const pt = f.object.dg.pt; |
| 5041 | 5119 | const zcu = pt.zcu; |
| 5042 | 5120 | const br = f.air.instructions.items(.data)[@intFromEnum(inst)].br; |
| 5043 | const writer = f.object.writer(); | |
| 5121 | const w = &f.object.code.writer; | |
| 5044 | 5122 | |
| 5045 | 5123 | if (try f.air.value(br.operand, pt)) |cond_val| { |
| 5046 | 5124 | // Comptime-known dispatch. Iterate the cases to find the correct |
| ... | ... | @@ -5062,18 +5140,19 @@ fn airSwitchDispatch(f: *Function, inst: Air.Inst.Index) !void { |
| 5062 | 5140 | } |
| 5063 | 5141 | } |
| 5064 | 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 | 5144 | return; |
| 5067 | 5145 | } |
| 5068 | 5146 | |
| 5069 | 5147 | // Runtime-known dispatch. Set the switch condition, and branch back. |
| 5070 | 5148 | const cond = try f.resolveInst(br.operand); |
| 5071 | 5149 | const cond_local = f.loop_switch_conds.get(br.block_inst).?; |
| 5072 | try f.writeCValue(writer, .{ .local = cond_local }, .Other); | |
| 5073 | try writer.writeAll(" = "); | |
| 5074 | try f.writeCValue(writer, cond, .Other); | |
| 5075 | try writer.writeAll(";\n"); | |
| 5076 | try writer.print("goto zig_switch_{d}_loop;", .{@intFromEnum(br.block_inst)}); | |
| 5150 | try f.writeCValue(w, .{ .local = cond_local }, .Other); | |
| 5151 | try w.writeAll(" = "); | |
| 5152 | try f.writeCValue(w, cond, .Other); | |
| 5153 | try w.writeByte(';'); | |
| 5154 | try f.object.newline(); | |
| 5155 | try w.print("goto zig_switch_{d}_loop;\n", .{@intFromEnum(br.block_inst)}); | |
| 5077 | 5156 | } |
| 5078 | 5157 | |
| 5079 | 5158 | fn 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 | 5172 | const zcu = pt.zcu; |
| 5094 | 5173 | const target = &f.object.dg.mod.resolved_target.result; |
| 5095 | 5174 | const ctype_pool = &f.object.dg.ctype_pool; |
| 5096 | const writer = f.object.writer(); | |
| 5175 | const w = &f.object.code.writer; | |
| 5097 | 5176 | |
| 5098 | 5177 | if (operand_ty.isAbiInt(zcu) and dest_ty.isAbiInt(zcu)) { |
| 5099 | 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 | 5183 | |
| 5105 | 5184 | if (dest_ty.isPtrAtRuntime(zcu) or operand_ty.isPtrAtRuntime(zcu)) { |
| 5106 | 5185 | const local = try f.allocLocal(null, dest_ty); |
| 5107 | try f.writeCValue(writer, local, .Other); | |
| 5108 | try writer.writeAll(" = ("); | |
| 5109 | try f.renderType(writer, dest_ty); | |
| 5110 | try writer.writeByte(')'); | |
| 5111 | try f.writeCValue(writer, operand, .Other); | |
| 5112 | try writer.writeAll(";\n"); | |
| 5186 | try f.writeCValue(w, local, .Other); | |
| 5187 | try w.writeAll(" = ("); | |
| 5188 | try f.renderType(w, dest_ty); | |
| 5189 | try w.writeByte(')'); | |
| 5190 | try f.writeCValue(w, operand, .Other); | |
| 5191 | try w.writeByte(';'); | |
| 5192 | try f.object.newline(); | |
| 5113 | 5193 | return local; |
| 5114 | 5194 | } |
| 5115 | 5195 | |
| 5116 | 5196 | const operand_lval = if (operand == .constant) blk: { |
| 5117 | 5197 | const operand_local = try f.allocLocal(null, operand_ty); |
| 5118 | try f.writeCValue(writer, operand_local, .Other); | |
| 5119 | try writer.writeAll(" = "); | |
| 5120 | try f.writeCValue(writer, operand, .Other); | |
| 5121 | try writer.writeAll(";\n"); | |
| 5198 | try f.writeCValue(w, operand_local, .Other); | |
| 5199 | try w.writeAll(" = "); | |
| 5200 | try f.writeCValue(w, operand, .Other); | |
| 5201 | try w.writeByte(';'); | |
| 5202 | try f.object.newline(); | |
| 5122 | 5203 | break :blk operand_local; |
| 5123 | 5204 | } else operand; |
| 5124 | 5205 | |
| 5125 | 5206 | const local = try f.allocLocal(null, dest_ty); |
| 5126 | try writer.writeAll("memcpy(&"); | |
| 5127 | try f.writeCValue(writer, local, .Other); | |
| 5128 | try writer.writeAll(", &"); | |
| 5129 | try f.writeCValue(writer, operand_lval, .Other); | |
| 5130 | try writer.writeAll(", sizeof("); | |
| 5207 | try w.writeAll("memcpy(&"); | |
| 5208 | try f.writeCValue(w, local, .Other); | |
| 5209 | try w.writeAll(", &"); | |
| 5210 | try f.writeCValue(w, operand_lval, .Other); | |
| 5211 | try w.writeAll(", sizeof("); | |
| 5131 | 5212 | try f.renderType( |
| 5132 | writer, | |
| 5213 | w, | |
| 5133 | 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(); | |
| 5136 | 5218 | |
| 5137 | 5219 | // Ensure padding bits have the expected value. |
| 5138 | 5220 | if (dest_ty.isAbiInt(zcu)) { |
| ... | ... | @@ -5142,11 +5224,11 @@ fn bitcast(f: *Function, dest_ty: Type, operand: CValue, operand_ty: Type) !CVal |
| 5142 | 5224 | var wrap_ctype: ?CType = null; |
| 5143 | 5225 | var need_bitcasts = false; |
| 5144 | 5226 | |
| 5145 | try f.writeCValue(writer, local, .Other); | |
| 5227 | try f.writeCValue(w, local, .Other); | |
| 5146 | 5228 | switch (dest_ctype.info(ctype_pool)) { |
| 5147 | 5229 | else => {}, |
| 5148 | 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 | 5232 | .little => array_info.len - 1, |
| 5151 | 5233 | .big => 0, |
| 5152 | 5234 | }}); |
| ... | ... | @@ -5157,92 +5239,98 @@ fn bitcast(f: *Function, dest_ty: Type, operand: CValue, operand_ty: Type) !CVal |
| 5157 | 5239 | bits += 1; |
| 5158 | 5240 | }, |
| 5159 | 5241 | } |
| 5160 | try writer.writeAll(" = "); | |
| 5242 | try w.writeAll(" = "); | |
| 5161 | 5243 | if (need_bitcasts) { |
| 5162 | try writer.writeAll("zig_bitCast_"); | |
| 5163 | try f.object.dg.renderCTypeForBuiltinFnName(writer, wrap_ctype.?.toUnsigned()); | |
| 5164 | try writer.writeByte('('); | |
| 5244 | try w.writeAll("zig_bitCast_"); | |
| 5245 | try f.object.dg.renderCTypeForBuiltinFnName(w, wrap_ctype.?.toUnsigned()); | |
| 5246 | try w.writeByte('('); | |
| 5165 | 5247 | } |
| 5166 | try writer.writeAll("zig_wrap_"); | |
| 5248 | try w.writeAll("zig_wrap_"); | |
| 5167 | 5249 | const info_ty = try pt.intType(dest_info.signedness, bits); |
| 5168 | 5250 | if (wrap_ctype) |ctype| |
| 5169 | try f.object.dg.renderCTypeForBuiltinFnName(writer, ctype) | |
| 5251 | try f.object.dg.renderCTypeForBuiltinFnName(w, ctype) | |
| 5170 | 5252 | else |
| 5171 | try f.object.dg.renderTypeForBuiltinFnName(writer, info_ty); | |
| 5172 | try writer.writeByte('('); | |
| 5253 | try f.object.dg.renderTypeForBuiltinFnName(w, info_ty); | |
| 5254 | try w.writeByte('('); | |
| 5173 | 5255 | if (need_bitcasts) { |
| 5174 | try writer.writeAll("zig_bitCast_"); | |
| 5175 | try f.object.dg.renderCTypeForBuiltinFnName(writer, wrap_ctype.?); | |
| 5176 | try writer.writeByte('('); | |
| 5256 | try w.writeAll("zig_bitCast_"); | |
| 5257 | try f.object.dg.renderCTypeForBuiltinFnName(w, wrap_ctype.?); | |
| 5258 | try w.writeByte('('); | |
| 5177 | 5259 | } |
| 5178 | try f.writeCValue(writer, local, .Other); | |
| 5260 | try f.writeCValue(w, local, .Other); | |
| 5179 | 5261 | switch (dest_ctype.info(ctype_pool)) { |
| 5180 | 5262 | else => {}, |
| 5181 | .array => |array_info| try writer.print("[{d}]", .{ | |
| 5263 | .array => |array_info| try w.print("[{d}]", .{ | |
| 5182 | 5264 | switch (target.cpu.arch.endian()) { |
| 5183 | 5265 | .little => array_info.len - 1, |
| 5184 | 5266 | .big => 0, |
| 5185 | 5267 | }, |
| 5186 | 5268 | }), |
| 5187 | 5269 | } |
| 5188 | if (need_bitcasts) try writer.writeByte(')'); | |
| 5189 | try f.object.dg.renderBuiltinInfo(writer, info_ty, .bits); | |
| 5190 | if (need_bitcasts) try writer.writeByte(')'); | |
| 5191 | try writer.writeAll(");\n"); | |
| 5270 | if (need_bitcasts) try w.writeByte(')'); | |
| 5271 | try f.object.dg.renderBuiltinInfo(w, info_ty, .bits); | |
| 5272 | if (need_bitcasts) try w.writeByte(')'); | |
| 5273 | try w.writeAll(");"); | |
| 5274 | try f.object.newline(); | |
| 5192 | 5275 | } |
| 5193 | 5276 | |
| 5194 | 5277 | try f.freeCValue(null, operand_lval); |
| 5195 | 5278 | return local; |
| 5196 | 5279 | } |
| 5197 | 5280 | |
| 5198 | fn airTrap(f: *Function, writer: anytype) !void { | |
| 5281 | fn airTrap(f: *Function, w: *Writer) !void { | |
| 5199 | 5282 | // Not even allowed to call trap in a naked function. |
| 5200 | 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 | } |
| 5203 | 5286 | |
| 5204 | fn airBreakpoint(writer: anytype) !CValue { | |
| 5205 | try writer.writeAll("zig_breakpoint();\n"); | |
| 5287 | fn airBreakpoint(f: *Function) !CValue { | |
| 5288 | const w = &f.object.code.writer; | |
| 5289 | try w.writeAll("zig_breakpoint();"); | |
| 5290 | try f.object.newline(); | |
| 5206 | 5291 | return .none; |
| 5207 | 5292 | } |
| 5208 | 5293 | |
| 5209 | 5294 | fn airRetAddr(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5210 | const writer = f.object.writer(); | |
| 5295 | const w = &f.object.code.writer; | |
| 5211 | 5296 | const local = try f.allocLocal(inst, .usize); |
| 5212 | try f.writeCValue(writer, local, .Other); | |
| 5213 | try writer.writeAll(" = ("); | |
| 5214 | try f.renderType(writer, .usize); | |
| 5215 | try writer.writeAll(")zig_return_address();\n"); | |
| 5297 | try f.writeCValue(w, local, .Other); | |
| 5298 | try w.writeAll(" = ("); | |
| 5299 | try f.renderType(w, .usize); | |
| 5300 | try w.writeAll(")zig_return_address();"); | |
| 5301 | try f.object.newline(); | |
| 5216 | 5302 | return local; |
| 5217 | 5303 | } |
| 5218 | 5304 | |
| 5219 | 5305 | fn airFrameAddress(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5220 | const writer = f.object.writer(); | |
| 5306 | const w = &f.object.code.writer; | |
| 5221 | 5307 | const local = try f.allocLocal(inst, .usize); |
| 5222 | try f.writeCValue(writer, local, .Other); | |
| 5223 | try writer.writeAll(" = ("); | |
| 5224 | try f.renderType(writer, .usize); | |
| 5225 | try writer.writeAll(")zig_frame_address();\n"); | |
| 5308 | try f.writeCValue(w, local, .Other); | |
| 5309 | try w.writeAll(" = ("); | |
| 5310 | try f.renderType(w, .usize); | |
| 5311 | try w.writeAll(")zig_frame_address();"); | |
| 5312 | try f.object.newline(); | |
| 5226 | 5313 | return local; |
| 5227 | 5314 | } |
| 5228 | 5315 | |
| 5229 | fn airUnreach(f: *Function) !void { | |
| 5316 | fn airUnreach(o: *Object) !void { | |
| 5230 | 5317 | // Not even allowed to call unreachable in a naked function. |
| 5231 | if (f.object.dg.is_naked_fn) return; | |
| 5232 | try f.object.writer().writeAll("zig_unreachable();\n"); | |
| 5318 | if (o.dg.is_naked_fn) return; | |
| 5319 | try o.code.writer.writeAll("zig_unreachable();\n"); | |
| 5233 | 5320 | } |
| 5234 | 5321 | |
| 5235 | 5322 | fn airLoop(f: *Function, inst: Air.Inst.Index) !void { |
| 5236 | 5323 | const ty_pl = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; |
| 5237 | 5324 | const loop = f.air.extraData(Air.Block, ty_pl.payload); |
| 5238 | 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; | |
| 5240 | 5327 | |
| 5241 | 5328 | // `repeat` instructions matching this loop will branch to |
| 5242 | 5329 | // this label. Since we need a label for arbitrary `repeat` |
| 5243 | 5330 | // anyway, there's actually no need to use a "real" looping |
| 5244 | 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 | 5334 | try genBodyInner(f, body); // no need to restore state, we're noreturn |
| 5247 | 5335 | } |
| 5248 | 5336 | |
| ... | ... | @@ -5254,14 +5342,14 @@ fn airCondBr(f: *Function, inst: Air.Inst.Index) !void { |
| 5254 | 5342 | const then_body: []const Air.Inst.Index = @ptrCast(f.air.extra.items[extra.end..][0..extra.data.then_body_len]); |
| 5255 | 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 | 5344 | const liveness_condbr = f.liveness.getCondBr(inst); |
| 5257 | const writer = f.object.writer(); | |
| 5345 | const w = &f.object.code.writer; | |
| 5258 | 5346 | |
| 5259 | try writer.writeAll("if ("); | |
| 5260 | try f.writeCValue(writer, cond, .Other); | |
| 5261 | try writer.writeAll(") "); | |
| 5347 | try w.writeAll("if ("); | |
| 5348 | try f.writeCValue(w, cond, .Other); | |
| 5349 | try w.writeAll(") "); | |
| 5262 | 5350 | |
| 5263 | 5351 | try genBodyResolveState(f, inst, liveness_condbr.then_deaths, then_body, false); |
| 5264 | try writer.writeByte('\n'); | |
| 5352 | try f.object.newline(); | |
| 5265 | 5353 | if (else_body.len > 0) if (f.object.dg.expected_block) |_| |
| 5266 | 5354 | return f.fail("runtime code not allowed in naked function", .{}); |
| 5267 | 5355 | |
| ... | ... | @@ -5287,7 +5375,7 @@ fn airSwitchBr(f: *Function, inst: Air.Inst.Index, is_dispatch_loop: bool) !void |
| 5287 | 5375 | const init_condition = try f.resolveInst(switch_br.operand); |
| 5288 | 5376 | try reap(f, inst, &.{switch_br.operand}); |
| 5289 | 5377 | const condition_ty = f.typeOf(switch_br.operand); |
| 5290 | const writer = f.object.writer(); | |
| 5378 | const w = &f.object.code.writer; | |
| 5291 | 5379 | |
| 5292 | 5380 | // For dispatches, we will create a local alloc to contain the condition value. |
| 5293 | 5381 | // 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 | 5383 | const condition = if (is_dispatch_loop) cond: { |
| 5296 | 5384 | const new_local = try f.allocLocal(inst, condition_ty); |
| 5297 | 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 | 5388 | try f.loop_switch_conds.put(gpa, inst, new_local.new_local); |
| 5300 | 5389 | break :cond new_local; |
| 5301 | 5390 | } else init_condition; |
| ... | ... | @@ -5304,7 +5393,7 @@ fn airSwitchBr(f: *Function, inst: Air.Inst.Index, is_dispatch_loop: bool) !void |
| 5304 | 5393 | assert(f.loop_switch_conds.remove(inst)); |
| 5305 | 5394 | }; |
| 5306 | 5395 | |
| 5307 | try writer.writeAll("switch ("); | |
| 5396 | try w.writeAll("switch ("); | |
| 5308 | 5397 | |
| 5309 | 5398 | const lowered_condition_ty: Type = if (condition_ty.toIntern() == .bool_type) |
| 5310 | 5399 | .u1 |
| ... | ... | @@ -5313,13 +5402,13 @@ fn airSwitchBr(f: *Function, inst: Air.Inst.Index, is_dispatch_loop: bool) !void |
| 5313 | 5402 | else |
| 5314 | 5403 | condition_ty; |
| 5315 | 5404 | if (condition_ty.toIntern() != lowered_condition_ty.toIntern()) { |
| 5316 | try writer.writeByte('('); | |
| 5317 | try f.renderType(writer, lowered_condition_ty); | |
| 5318 | try writer.writeByte(')'); | |
| 5405 | try w.writeByte('('); | |
| 5406 | try f.renderType(w, lowered_condition_ty); | |
| 5407 | try w.writeByte(')'); | |
| 5319 | 5408 | } |
| 5320 | try f.writeCValue(writer, condition, .Other); | |
| 5321 | try writer.writeAll(") {"); | |
| 5322 | f.object.indent_writer.pushIndent(); | |
| 5409 | try f.writeCValue(w, condition, .Other); | |
| 5410 | try w.writeAll(") {"); | |
| 5411 | f.object.indent(); | |
| 5323 | 5412 | |
| 5324 | 5413 | const liveness = try f.liveness.getSwitchBr(gpa, inst, switch_br.cases_len + 1); |
| 5325 | 5414 | defer gpa.free(liveness.deaths); |
| ... | ... | @@ -5332,35 +5421,37 @@ fn airSwitchBr(f: *Function, inst: Air.Inst.Index, is_dispatch_loop: bool) !void |
| 5332 | 5421 | continue; |
| 5333 | 5422 | } |
| 5334 | 5423 | for (case.items) |item| { |
| 5335 | try f.object.indent_writer.insertNewline(); | |
| 5336 | try writer.writeAll("case "); | |
| 5424 | try f.object.newline(); | |
| 5425 | try w.writeAll("case "); | |
| 5337 | 5426 | const item_value = try f.air.value(item, pt); |
| 5338 | 5427 | // If `item_value` is a pointer with a known integer address, print the address |
| 5339 | 5428 | // with no cast to avoid a warning. |
| 5340 | 5429 | write_val: { |
| 5341 | 5430 | if (condition_ty.isPtrAtRuntime(zcu)) { |
| 5342 | 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 | 5433 | break :write_val; |
| 5345 | 5434 | } |
| 5346 | 5435 | } |
| 5347 | 5436 | if (condition_ty.isPtrAtRuntime(zcu)) { |
| 5348 | try writer.writeByte('('); | |
| 5349 | try f.renderType(writer, .usize); | |
| 5350 | try writer.writeByte(')'); | |
| 5437 | try w.writeByte('('); | |
| 5438 | try f.renderType(w, .usize); | |
| 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"); | |
| 5357 | f.object.indent_writer.pushIndent(); | |
| 5445 | try w.writeAll(" {"); | |
| 5446 | f.object.indent(); | |
| 5447 | try f.object.newline(); | |
| 5358 | 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 | 5452 | try genBodyResolveState(f, inst, liveness.deaths[case.idx], case.body, true); |
| 5362 | f.object.indent_writer.popIndent(); | |
| 5363 | try writer.writeByte('}'); | |
| 5453 | try f.object.outdent(); | |
| 5454 | try w.writeByte('}'); | |
| 5364 | 5455 | if (f.object.dg.expected_block) |_| |
| 5365 | 5456 | return f.fail("runtime code not allowed in naked function", .{}); |
| 5366 | 5457 | |
| ... | ... | @@ -5368,9 +5459,9 @@ fn airSwitchBr(f: *Function, inst: Air.Inst.Index, is_dispatch_loop: bool) !void |
| 5368 | 5459 | } |
| 5369 | 5460 | |
| 5370 | 5461 | const else_body = it.elseBody(); |
| 5371 | try f.object.indent_writer.insertNewline(); | |
| 5462 | try f.object.newline(); | |
| 5372 | 5463 | |
| 5373 | try writer.writeAll("default: "); | |
| 5464 | try w.writeAll("default: "); | |
| 5374 | 5465 | if (any_range_cases) { |
| 5375 | 5466 | // We will iterate the cases again to handle those with ranges, and generate |
| 5376 | 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 | 5469 | while (it.next()) |case| { |
| 5379 | 5470 | if (case.ranges.len == 0) continue; // handled above |
| 5380 | 5471 | |
| 5381 | try writer.writeAll("if ("); | |
| 5472 | try w.writeAll("if ("); | |
| 5382 | 5473 | for (case.items, 0..) |item, item_i| { |
| 5383 | if (item_i != 0) try writer.writeAll(" || "); | |
| 5384 | try f.writeCValue(writer, condition, .Other); | |
| 5385 | try writer.writeAll(" == "); | |
| 5386 | try f.object.dg.renderValue(writer, (try f.air.value(item, pt)).?, .Other); | |
| 5474 | if (item_i != 0) try w.writeAll(" || "); | |
| 5475 | try f.writeCValue(w, condition, .Other); | |
| 5476 | try w.writeAll(" == "); | |
| 5477 | try f.object.dg.renderValue(w, (try f.air.value(item, pt)).?, .Other); | |
| 5387 | 5478 | } |
| 5388 | 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 | 5481 | // "(x >= lower && x <= upper)" |
| 5391 | try writer.writeByte('('); | |
| 5392 | try f.writeCValue(writer, condition, .Other); | |
| 5393 | try writer.writeAll(" >= "); | |
| 5394 | try f.object.dg.renderValue(writer, (try f.air.value(range[0], pt)).?, .Other); | |
| 5395 | try writer.writeAll(" && "); | |
| 5396 | try f.writeCValue(writer, condition, .Other); | |
| 5397 | try writer.writeAll(" <= "); | |
| 5398 | try f.object.dg.renderValue(writer, (try f.air.value(range[1], pt)).?, .Other); | |
| 5399 | try writer.writeByte(')'); | |
| 5482 | try w.writeByte('('); | |
| 5483 | try f.writeCValue(w, condition, .Other); | |
| 5484 | try w.writeAll(" >= "); | |
| 5485 | try f.object.dg.renderValue(w, (try f.air.value(range[0], pt)).?, .Other); | |
| 5486 | try w.writeAll(" && "); | |
| 5487 | try f.writeCValue(w, condition, .Other); | |
| 5488 | try w.writeAll(" <= "); | |
| 5489 | try f.object.dg.renderValue(w, (try f.air.value(range[1], pt)).?, .Other); | |
| 5490 | try w.writeByte(')'); | |
| 5400 | 5491 | } |
| 5401 | try writer.writeAll(") {\n"); | |
| 5402 | f.object.indent_writer.pushIndent(); | |
| 5492 | try w.writeAll(") {"); | |
| 5493 | f.object.indent(); | |
| 5494 | try f.object.newline(); | |
| 5403 | 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 | 5498 | try genBodyResolveState(f, inst, liveness.deaths[case.idx], case.body, true); |
| 5407 | f.object.indent_writer.popIndent(); | |
| 5408 | try writer.writeByte('}'); | |
| 5499 | try f.object.outdent(); | |
| 5500 | try w.writeByte('}'); | |
| 5409 | 5501 | if (f.object.dg.expected_block) |_| |
| 5410 | 5502 | return f.fail("runtime code not allowed in naked function", .{}); |
| 5411 | 5503 | } |
| 5412 | 5504 | } |
| 5413 | 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 | 5508 | if (else_body.len > 0) { |
| 5417 | 5509 | // 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 | 5514 | try genBody(f, else_body); |
| 5423 | 5515 | if (f.object.dg.expected_block) |_| |
| 5424 | 5516 | return f.fail("runtime code not allowed in naked function", .{}); |
| 5425 | } else { | |
| 5426 | try writer.writeAll("zig_unreachable();"); | |
| 5427 | } | |
| 5428 | try f.object.indent_writer.insertNewline(); | |
| 5429 | ||
| 5430 | f.object.indent_writer.popIndent(); | |
| 5431 | try writer.writeAll("}\n"); | |
| 5517 | } else try airUnreach(&f.object); | |
| 5518 | try f.object.newline(); | |
| 5519 | try f.object.outdent(); | |
| 5520 | try w.writeAll("}\n"); | |
| 5432 | 5521 | } |
| 5433 | 5522 | |
| 5434 | 5523 | fn asmInputNeedsLocal(f: *Function, constraint: []const u8, value: CValue) bool { |
| ... | ... | @@ -5466,7 +5555,7 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5466 | 5555 | extra_i += inputs.len; |
| 5467 | 5556 | |
| 5468 | 5557 | const result = result: { |
| 5469 | const writer = f.object.writer(); | |
| 5558 | const w = &f.object.code.writer; | |
| 5470 | 5559 | const inst_ty = f.typeOfIndex(inst); |
| 5471 | 5560 | const inst_local = if (inst_ty.hasRuntimeBitsIgnoreComptime(zcu)) local: { |
| 5472 | 5561 | const inst_local = try f.allocLocalValue(.{ |
| ... | ... | @@ -5474,10 +5563,11 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5474 | 5563 | .alignas = CType.AlignAs.fromAbiAlignment(inst_ty.abiAlignment(zcu)), |
| 5475 | 5564 | }); |
| 5476 | 5565 | if (f.wantSafety()) { |
| 5477 | try f.writeCValue(writer, inst_local, .Other); | |
| 5478 | try writer.writeAll(" = "); | |
| 5479 | try f.writeCValue(writer, .{ .undef = inst_ty }, .Other); | |
| 5480 | try writer.writeAll(";\n"); | |
| 5566 | try f.writeCValue(w, inst_local, .Other); | |
| 5567 | try w.writeAll(" = "); | |
| 5568 | try f.writeCValue(w, .{ .undef = inst_ty }, .Other); | |
| 5569 | try w.writeByte(';'); | |
| 5570 | try f.object.newline(); | |
| 5481 | 5571 | } |
| 5482 | 5572 | break :local inst_local; |
| 5483 | 5573 | } else .none; |
| ... | ... | @@ -5501,21 +5591,22 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5501 | 5591 | const is_reg = constraint[1] == '{'; |
| 5502 | 5592 | if (is_reg) { |
| 5503 | 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 | 5595 | const output_local = try f.allocLocalValue(.{ |
| 5506 | 5596 | .ctype = try f.ctypeFromType(output_ty, .complete), |
| 5507 | 5597 | .alignas = CType.AlignAs.fromAbiAlignment(output_ty.abiAlignment(zcu)), |
| 5508 | 5598 | }); |
| 5509 | 5599 | try f.allocs.put(gpa, output_local.new_local, false); |
| 5510 | try f.object.dg.renderTypeAndName(writer, output_ty, output_local, .{}, .none, .complete); | |
| 5511 | try writer.writeAll(" __asm(\""); | |
| 5512 | try writer.writeAll(constraint["={".len .. constraint.len - "}".len]); | |
| 5513 | try writer.writeAll("\")"); | |
| 5600 | try f.object.dg.renderTypeAndName(w, output_ty, output_local, .{}, .none, .complete); | |
| 5601 | try w.writeAll(" __asm(\""); | |
| 5602 | try w.writeAll(constraint["={".len .. constraint.len - "}".len]); | |
| 5603 | try w.writeAll("\")"); | |
| 5514 | 5604 | if (f.wantSafety()) { |
| 5515 | try writer.writeAll(" = "); | |
| 5516 | try f.writeCValue(writer, .{ .undef = output_ty }, .Other); | |
| 5605 | try w.writeAll(" = "); | |
| 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 | 5612 | for (inputs) |input| { |
| ... | ... | @@ -5536,21 +5627,22 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5536 | 5627 | const input_val = try f.resolveInst(input); |
| 5537 | 5628 | if (asmInputNeedsLocal(f, constraint, input_val)) { |
| 5538 | 5629 | const input_ty = f.typeOf(input); |
| 5539 | if (is_reg) try writer.writeAll("register "); | |
| 5630 | if (is_reg) try w.writeAll("register "); | |
| 5540 | 5631 | const input_local = try f.allocLocalValue(.{ |
| 5541 | 5632 | .ctype = try f.ctypeFromType(input_ty, .complete), |
| 5542 | 5633 | .alignas = CType.AlignAs.fromAbiAlignment(input_ty.abiAlignment(zcu)), |
| 5543 | 5634 | }); |
| 5544 | 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 | 5637 | if (is_reg) { |
| 5547 | try writer.writeAll(" __asm(\""); | |
| 5548 | try writer.writeAll(constraint["{".len .. constraint.len - "}".len]); | |
| 5549 | try writer.writeAll("\")"); | |
| 5638 | try w.writeAll(" __asm(\""); | |
| 5639 | try w.writeAll(constraint["{".len .. constraint.len - "}".len]); | |
| 5640 | try w.writeAll("\")"); | |
| 5550 | 5641 | } |
| 5551 | try writer.writeAll(" = "); | |
| 5552 | try f.writeCValue(writer, input_val, .Other); | |
| 5553 | try writer.writeAll(";\n"); | |
| 5642 | try w.writeAll(" = "); | |
| 5643 | try f.writeCValue(w, input_val, .Other); | |
| 5644 | try w.writeByte(';'); | |
| 5645 | try f.object.newline(); | |
| 5554 | 5646 | } |
| 5555 | 5647 | } |
| 5556 | 5648 | for (0..clobbers_len) |_| { |
| ... | ... | @@ -5610,14 +5702,14 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5610 | 5702 | } |
| 5611 | 5703 | } |
| 5612 | 5704 | |
| 5613 | try writer.writeAll("__asm"); | |
| 5614 | if (is_volatile) try writer.writeAll(" volatile"); | |
| 5615 | try writer.print("({s}", .{fmtStringLiteral(fixed_asm_source[0..dst_i], null)}); | |
| 5705 | try w.writeAll("__asm"); | |
| 5706 | if (is_volatile) try w.writeAll(" volatile"); | |
| 5707 | try w.print("({f}", .{fmtStringLiteral(fixed_asm_source[0..dst_i], null)}); | |
| 5616 | 5708 | } |
| 5617 | 5709 | |
| 5618 | 5710 | extra_i = constraints_extra_begin; |
| 5619 | 5711 | var locals_index = locals_begin; |
| 5620 | try writer.writeByte(':'); | |
| 5712 | try w.writeByte(':'); | |
| 5621 | 5713 | for (outputs, 0..) |output, index| { |
| 5622 | 5714 | const extra_bytes = mem.sliceAsBytes(f.air.extra.items[extra_i..]); |
| 5623 | 5715 | const constraint = mem.sliceTo(extra_bytes, 0); |
| ... | ... | @@ -5626,22 +5718,22 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5626 | 5718 | // for the string, we still use the next u32 for the null terminator. |
| 5627 | 5719 | extra_i += (constraint.len + name.len + (2 + 3)) / 4; |
| 5628 | 5720 | |
| 5629 | if (index > 0) try writer.writeByte(','); | |
| 5630 | try writer.writeByte(' '); | |
| 5631 | if (!mem.eql(u8, name, "_")) try writer.print("[{s}]", .{name}); | |
| 5721 | if (index > 0) try w.writeByte(','); | |
| 5722 | try w.writeByte(' '); | |
| 5723 | if (!mem.eql(u8, name, "_")) try w.print("[{s}]", .{name}); | |
| 5632 | 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 | 5726 | if (is_reg) { |
| 5635 | try f.writeCValue(writer, .{ .local = locals_index }, .Other); | |
| 5727 | try f.writeCValue(w, .{ .local = locals_index }, .Other); | |
| 5636 | 5728 | locals_index += 1; |
| 5637 | 5729 | } else if (output == .none) { |
| 5638 | try f.writeCValue(writer, inst_local, .FunctionArgument); | |
| 5730 | try f.writeCValue(w, inst_local, .FunctionArgument); | |
| 5639 | 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 | 5737 | for (inputs, 0..) |input, index| { |
| 5646 | 5738 | const extra_bytes = mem.sliceAsBytes(f.air.extra.items[extra_i..]); |
| 5647 | 5739 | const constraint = mem.sliceTo(extra_bytes, 0); |
| ... | ... | @@ -5650,21 +5742,21 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5650 | 5742 | // for the string, we still use the next u32 for the null terminator. |
| 5651 | 5743 | extra_i += (constraint.len + name.len + (2 + 3)) / 4; |
| 5652 | 5744 | |
| 5653 | if (index > 0) try writer.writeByte(','); | |
| 5654 | try writer.writeByte(' '); | |
| 5655 | if (!mem.eql(u8, name, "_")) try writer.print("[{s}]", .{name}); | |
| 5745 | if (index > 0) try w.writeByte(','); | |
| 5746 | try w.writeByte(' '); | |
| 5747 | if (!mem.eql(u8, name, "_")) try w.print("[{s}]", .{name}); | |
| 5656 | 5748 | |
| 5657 | 5749 | const is_reg = constraint[0] == '{'; |
| 5658 | 5750 | const input_val = try f.resolveInst(input); |
| 5659 | try writer.print("{s}(", .{fmtStringLiteral(if (is_reg) "r" else constraint, null)}); | |
| 5660 | try f.writeCValue(writer, if (asmInputNeedsLocal(f, constraint, input_val)) local: { | |
| 5751 | try w.print("{f}(", .{fmtStringLiteral(if (is_reg) "r" else constraint, null)}); | |
| 5752 | try f.writeCValue(w, if (asmInputNeedsLocal(f, constraint, input_val)) local: { | |
| 5661 | 5753 | const input_local_idx = locals_index; |
| 5662 | 5754 | locals_index += 1; |
| 5663 | 5755 | break :local .{ .local = input_local_idx }; |
| 5664 | 5756 | } else input_val, .Other); |
| 5665 | try writer.writeByte(')'); | |
| 5757 | try w.writeByte(')'); | |
| 5666 | 5758 | } |
| 5667 | try writer.writeByte(':'); | |
| 5759 | try w.writeByte(':'); | |
| 5668 | 5760 | for (0..clobbers_len) |clobber_i| { |
| 5669 | 5761 | const clobber = mem.sliceTo(mem.sliceAsBytes(f.air.extra.items[extra_i..]), 0); |
| 5670 | 5762 | // 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 | 5765 | |
| 5674 | 5766 | if (clobber.len == 0) continue; |
| 5675 | 5767 | |
| 5676 | if (clobber_i > 0) try writer.writeByte(','); | |
| 5677 | try writer.print(" {s}", .{fmtStringLiteral(clobber, null)}); | |
| 5768 | if (clobber_i > 0) try w.writeByte(','); | |
| 5769 | try w.print(" {f}", .{fmtStringLiteral(clobber, null)}); | |
| 5678 | 5770 | } |
| 5679 | try writer.writeAll(");\n"); | |
| 5771 | try w.writeAll(");"); | |
| 5772 | try f.object.newline(); | |
| 5680 | 5773 | |
| 5681 | 5774 | extra_i = constraints_extra_begin; |
| 5682 | 5775 | locals_index = locals_begin; |
| ... | ... | @@ -5690,14 +5783,15 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5690 | 5783 | |
| 5691 | 5784 | const is_reg = constraint[1] == '{'; |
| 5692 | 5785 | if (is_reg) { |
| 5693 | try f.writeCValueDeref(writer, if (output == .none) | |
| 5786 | try f.writeCValueDeref(w, if (output == .none) | |
| 5694 | 5787 | .{ .local_ref = inst_local.new_local } |
| 5695 | 5788 | else |
| 5696 | 5789 | try f.resolveInst(output)); |
| 5697 | try writer.writeAll(" = "); | |
| 5698 | try f.writeCValue(writer, .{ .local = locals_index }, .Other); | |
| 5790 | try w.writeAll(" = "); | |
| 5791 | try f.writeCValue(w, .{ .local = locals_index }, .Other); | |
| 5699 | 5792 | locals_index += 1; |
| 5700 | try writer.writeAll(";\n"); | |
| 5793 | try w.writeByte(';'); | |
| 5794 | try f.object.newline(); | |
| 5701 | 5795 | } |
| 5702 | 5796 | } |
| 5703 | 5797 | |
| ... | ... | @@ -5727,14 +5821,14 @@ fn airIsNull( |
| 5727 | 5821 | const ctype_pool = &f.object.dg.ctype_pool; |
| 5728 | 5822 | const un_op = f.air.instructions.items(.data)[@intFromEnum(inst)].un_op; |
| 5729 | 5823 | |
| 5730 | const writer = f.object.writer(); | |
| 5824 | const w = &f.object.code.writer; | |
| 5731 | 5825 | const operand = try f.resolveInst(un_op); |
| 5732 | 5826 | try reap(f, inst, &.{un_op}); |
| 5733 | 5827 | |
| 5734 | 5828 | const local = try f.allocLocal(inst, .bool); |
| 5735 | const a = try Assignment.start(f, writer, .bool); | |
| 5736 | try f.writeCValue(writer, local, .Other); | |
| 5737 | try a.assign(f, writer); | |
| 5829 | const a = try Assignment.start(f, w, .bool); | |
| 5830 | try f.writeCValue(w, local, .Other); | |
| 5831 | try a.assign(f, w); | |
| 5738 | 5832 | |
| 5739 | 5833 | const operand_ty = f.typeOf(un_op); |
| 5740 | 5834 | const optional_ty = if (is_ptr) operand_ty.childType(zcu) else operand_ty; |
| ... | ... | @@ -5742,9 +5836,9 @@ fn airIsNull( |
| 5742 | 5836 | const rhs = switch (opt_ctype.info(ctype_pool)) { |
| 5743 | 5837 | .basic, .pointer => rhs: { |
| 5744 | 5838 | if (is_ptr) |
| 5745 | try f.writeCValueDeref(writer, operand) | |
| 5839 | try f.writeCValueDeref(w, operand) | |
| 5746 | 5840 | else |
| 5747 | try f.writeCValue(writer, operand, .Other); | |
| 5841 | try f.writeCValue(w, operand, .Other); | |
| 5748 | 5842 | break :rhs if (opt_ctype.isBool()) |
| 5749 | 5843 | "true" |
| 5750 | 5844 | else if (opt_ctype.isInteger()) |
| ... | ... | @@ -5756,24 +5850,24 @@ fn airIsNull( |
| 5756 | 5850 | .aggregate => |aggregate| switch (aggregate.fields.at(0, ctype_pool).name.index) { |
| 5757 | 5851 | .is_null, .payload => rhs: { |
| 5758 | 5852 | if (is_ptr) |
| 5759 | try f.writeCValueDerefMember(writer, operand, .{ .identifier = "is_null" }) | |
| 5853 | try f.writeCValueDerefMember(w, operand, .{ .identifier = "is_null" }) | |
| 5760 | 5854 | else |
| 5761 | try f.writeCValueMember(writer, operand, .{ .identifier = "is_null" }); | |
| 5855 | try f.writeCValueMember(w, operand, .{ .identifier = "is_null" }); | |
| 5762 | 5856 | break :rhs "true"; |
| 5763 | 5857 | }, |
| 5764 | 5858 | .ptr, .len => rhs: { |
| 5765 | 5859 | if (is_ptr) |
| 5766 | try f.writeCValueDerefMember(writer, operand, .{ .identifier = "ptr" }) | |
| 5860 | try f.writeCValueDerefMember(w, operand, .{ .identifier = "ptr" }) | |
| 5767 | 5861 | else |
| 5768 | try f.writeCValueMember(writer, operand, .{ .identifier = "ptr" }); | |
| 5862 | try f.writeCValueMember(w, operand, .{ .identifier = "ptr" }); | |
| 5769 | 5863 | break :rhs "NULL"; |
| 5770 | 5864 | }, |
| 5771 | 5865 | else => unreachable, |
| 5772 | 5866 | }, |
| 5773 | 5867 | }; |
| 5774 | try writer.writeAll(compareOperatorC(operator)); | |
| 5775 | try writer.writeAll(rhs); | |
| 5776 | try a.end(f, writer); | |
| 5868 | try w.writeAll(compareOperatorC(operator)); | |
| 5869 | try w.writeAll(rhs); | |
| 5870 | try a.end(f, w); | |
| 5777 | 5871 | return local; |
| 5778 | 5872 | } |
| 5779 | 5873 | |
| ... | ... | @@ -5795,16 +5889,16 @@ fn airOptionalPayload(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !CValue |
| 5795 | 5889 | .aligned, .array, .vector, .fwd_decl, .function => unreachable, |
| 5796 | 5890 | .aggregate => |aggregate| switch (aggregate.fields.at(0, ctype_pool).name.index) { |
| 5797 | 5891 | .is_null, .payload => { |
| 5798 | const writer = f.object.writer(); | |
| 5892 | const w = &f.object.code.writer; | |
| 5799 | 5893 | const local = try f.allocLocal(inst, inst_ty); |
| 5800 | const a = try Assignment.start(f, writer, try f.ctypeFromType(inst_ty, .complete)); | |
| 5801 | try f.writeCValue(writer, local, .Other); | |
| 5802 | try a.assign(f, writer); | |
| 5894 | const a = try Assignment.start(f, w, try f.ctypeFromType(inst_ty, .complete)); | |
| 5895 | try f.writeCValue(w, local, .Other); | |
| 5896 | try a.assign(f, w); | |
| 5803 | 5897 | if (is_ptr) { |
| 5804 | try writer.writeByte('&'); | |
| 5805 | try f.writeCValueDerefMember(writer, operand, .{ .identifier = "payload" }); | |
| 5806 | } else try f.writeCValueMember(writer, operand, .{ .identifier = "payload" }); | |
| 5807 | try a.end(f, writer); | |
| 5898 | try w.writeByte('&'); | |
| 5899 | try f.writeCValueDerefMember(w, operand, .{ .identifier = "payload" }); | |
| 5900 | } else try f.writeCValueMember(w, operand, .{ .identifier = "payload" }); | |
| 5901 | try a.end(f, w); | |
| 5808 | 5902 | return local; |
| 5809 | 5903 | }, |
| 5810 | 5904 | .ptr, .len => return f.moveCValue(inst, inst_ty, operand), |
| ... | ... | @@ -5817,7 +5911,7 @@ fn airOptionalPayloadPtrSet(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5817 | 5911 | const pt = f.object.dg.pt; |
| 5818 | 5912 | const zcu = pt.zcu; |
| 5819 | 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 | 5915 | const operand = try f.resolveInst(ty_op.operand); |
| 5822 | 5916 | try reap(f, inst, &.{ty_op.operand}); |
| 5823 | 5917 | const operand_ty = f.typeOf(ty_op.operand); |
| ... | ... | @@ -5826,40 +5920,40 @@ fn airOptionalPayloadPtrSet(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5826 | 5920 | const opt_ctype = try f.ctypeFromType(operand_ty.childType(zcu), .complete); |
| 5827 | 5921 | switch (opt_ctype.info(&f.object.dg.ctype_pool)) { |
| 5828 | 5922 | .basic => { |
| 5829 | const a = try Assignment.start(f, writer, opt_ctype); | |
| 5830 | try f.writeCValueDeref(writer, operand); | |
| 5831 | try a.assign(f, writer); | |
| 5832 | try f.object.dg.renderValue(writer, Value.false, .Other); | |
| 5833 | try a.end(f, writer); | |
| 5923 | const a = try Assignment.start(f, w, opt_ctype); | |
| 5924 | try f.writeCValueDeref(w, operand); | |
| 5925 | try a.assign(f, w); | |
| 5926 | try f.object.dg.renderValue(w, Value.false, .Other); | |
| 5927 | try a.end(f, w); | |
| 5834 | 5928 | return .none; |
| 5835 | 5929 | }, |
| 5836 | 5930 | .pointer => { |
| 5837 | 5931 | if (f.liveness.isUnused(inst)) return .none; |
| 5838 | 5932 | const local = try f.allocLocal(inst, inst_ty); |
| 5839 | const a = try Assignment.start(f, writer, opt_ctype); | |
| 5840 | try f.writeCValue(writer, local, .Other); | |
| 5841 | try a.assign(f, writer); | |
| 5842 | try f.writeCValue(writer, operand, .Other); | |
| 5843 | try a.end(f, writer); | |
| 5933 | const a = try Assignment.start(f, w, opt_ctype); | |
| 5934 | try f.writeCValue(w, local, .Other); | |
| 5935 | try a.assign(f, w); | |
| 5936 | try f.writeCValue(w, operand, .Other); | |
| 5937 | try a.end(f, w); | |
| 5844 | 5938 | return local; |
| 5845 | 5939 | }, |
| 5846 | 5940 | .aligned, .array, .vector, .fwd_decl, .function => unreachable, |
| 5847 | 5941 | .aggregate => { |
| 5848 | 5942 | { |
| 5849 | const a = try Assignment.start(f, writer, opt_ctype); | |
| 5850 | try f.writeCValueDerefMember(writer, operand, .{ .identifier = "is_null" }); | |
| 5851 | try a.assign(f, writer); | |
| 5852 | try f.object.dg.renderValue(writer, Value.false, .Other); | |
| 5853 | try a.end(f, writer); | |
| 5943 | const a = try Assignment.start(f, w, opt_ctype); | |
| 5944 | try f.writeCValueDerefMember(w, operand, .{ .identifier = "is_null" }); | |
| 5945 | try a.assign(f, w); | |
| 5946 | try f.object.dg.renderValue(w, Value.false, .Other); | |
| 5947 | try a.end(f, w); | |
| 5854 | 5948 | } |
| 5855 | 5949 | if (f.liveness.isUnused(inst)) return .none; |
| 5856 | 5950 | const local = try f.allocLocal(inst, inst_ty); |
| 5857 | const a = try Assignment.start(f, writer, opt_ctype); | |
| 5858 | try f.writeCValue(writer, local, .Other); | |
| 5859 | try a.assign(f, writer); | |
| 5860 | try writer.writeByte('&'); | |
| 5861 | try f.writeCValueDerefMember(writer, operand, .{ .identifier = "payload" }); | |
| 5862 | try a.end(f, writer); | |
| 5951 | const a = try Assignment.start(f, w, opt_ctype); | |
| 5952 | try f.writeCValue(w, local, .Other); | |
| 5953 | try a.assign(f, w); | |
| 5954 | try w.writeByte('&'); | |
| 5955 | try f.writeCValueDerefMember(w, operand, .{ .identifier = "payload" }); | |
| 5956 | try a.end(f, w); | |
| 5863 | 5957 | return local; |
| 5864 | 5958 | }, |
| 5865 | 5959 | } |
| ... | ... | @@ -5967,42 +6061,43 @@ fn airFieldParentPtr(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5967 | 6061 | const field_ptr_val = try f.resolveInst(extra.field_ptr); |
| 5968 | 6062 | try reap(f, inst, &.{extra.field_ptr}); |
| 5969 | 6063 | |
| 5970 | const writer = f.object.writer(); | |
| 6064 | const w = &f.object.code.writer; | |
| 5971 | 6065 | const local = try f.allocLocal(inst, container_ptr_ty); |
| 5972 | try f.writeCValue(writer, local, .Other); | |
| 5973 | try writer.writeAll(" = ("); | |
| 5974 | try f.renderType(writer, container_ptr_ty); | |
| 5975 | try writer.writeByte(')'); | |
| 6066 | try f.writeCValue(w, local, .Other); | |
| 6067 | try w.writeAll(" = ("); | |
| 6068 | try f.renderType(w, container_ptr_ty); | |
| 6069 | try w.writeByte(')'); | |
| 5976 | 6070 | |
| 5977 | 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 | 6073 | .field => |field| { |
| 5980 | 6074 | const u8_ptr_ty = try pt.adjustPtrTypeChild(field_ptr_ty, .u8); |
| 5981 | 6075 | |
| 5982 | try writer.writeAll("(("); | |
| 5983 | try f.renderType(writer, u8_ptr_ty); | |
| 5984 | try writer.writeByte(')'); | |
| 5985 | try f.writeCValue(writer, field_ptr_val, .Other); | |
| 5986 | try writer.writeAll(" - offsetof("); | |
| 5987 | try f.renderType(writer, container_ty); | |
| 5988 | try writer.writeAll(", "); | |
| 5989 | try f.writeCValue(writer, field, .Other); | |
| 5990 | try writer.writeAll("))"); | |
| 6076 | try w.writeAll("(("); | |
| 6077 | try f.renderType(w, u8_ptr_ty); | |
| 6078 | try w.writeByte(')'); | |
| 6079 | try f.writeCValue(w, field_ptr_val, .Other); | |
| 6080 | try w.writeAll(" - offsetof("); | |
| 6081 | try f.renderType(w, container_ty); | |
| 6082 | try w.writeAll(", "); | |
| 6083 | try f.writeCValue(w, field, .Other); | |
| 6084 | try w.writeAll("))"); | |
| 5991 | 6085 | }, |
| 5992 | 6086 | .byte_offset => |byte_offset| { |
| 5993 | 6087 | const u8_ptr_ty = try pt.adjustPtrTypeChild(field_ptr_ty, .u8); |
| 5994 | 6088 | |
| 5995 | try writer.writeAll("(("); | |
| 5996 | try f.renderType(writer, u8_ptr_ty); | |
| 5997 | try writer.writeByte(')'); | |
| 5998 | try f.writeCValue(writer, field_ptr_val, .Other); | |
| 5999 | try writer.print(" - {})", .{ | |
| 6000 | try f.fmtIntLiteral(try pt.intValue(.usize, byte_offset)), | |
| 6089 | try w.writeAll("(("); | |
| 6090 | try f.renderType(w, u8_ptr_ty); | |
| 6091 | try w.writeByte(')'); | |
| 6092 | try f.writeCValue(w, field_ptr_val, .Other); | |
| 6093 | try w.print(" - {f})", .{ | |
| 6094 | try f.fmtIntLiteralDec(try pt.intValue(.usize, byte_offset)), | |
| 6001 | 6095 | }); |
| 6002 | 6096 | }, |
| 6003 | 6097 | } |
| 6004 | 6098 | |
| 6005 | try writer.writeAll(";\n"); | |
| 6099 | try w.writeByte(';'); | |
| 6100 | try f.object.newline(); | |
| 6006 | 6101 | return local; |
| 6007 | 6102 | } |
| 6008 | 6103 | |
| ... | ... | @@ -6021,33 +6116,34 @@ fn fieldPtr( |
| 6021 | 6116 | // Ensure complete type definition is visible before accessing fields. |
| 6022 | 6117 | _ = try f.ctypeFromType(container_ty, .complete); |
| 6023 | 6118 | |
| 6024 | const writer = f.object.writer(); | |
| 6119 | const w = &f.object.code.writer; | |
| 6025 | 6120 | const local = try f.allocLocal(inst, field_ptr_ty); |
| 6026 | try f.writeCValue(writer, local, .Other); | |
| 6027 | try writer.writeAll(" = ("); | |
| 6028 | try f.renderType(writer, field_ptr_ty); | |
| 6029 | try writer.writeByte(')'); | |
| 6121 | try f.writeCValue(w, local, .Other); | |
| 6122 | try w.writeAll(" = ("); | |
| 6123 | try f.renderType(w, field_ptr_ty); | |
| 6124 | try w.writeByte(')'); | |
| 6030 | 6125 | |
| 6031 | 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 | 6128 | .field => |field| { |
| 6034 | try writer.writeByte('&'); | |
| 6035 | try f.writeCValueDerefMember(writer, container_ptr_val, field); | |
| 6129 | try w.writeByte('&'); | |
| 6130 | try f.writeCValueDerefMember(w, container_ptr_val, field); | |
| 6036 | 6131 | }, |
| 6037 | 6132 | .byte_offset => |byte_offset| { |
| 6038 | 6133 | const u8_ptr_ty = try pt.adjustPtrTypeChild(field_ptr_ty, .u8); |
| 6039 | 6134 | |
| 6040 | try writer.writeAll("(("); | |
| 6041 | try f.renderType(writer, u8_ptr_ty); | |
| 6042 | try writer.writeByte(')'); | |
| 6043 | try f.writeCValue(writer, container_ptr_val, .Other); | |
| 6044 | try writer.print(" + {})", .{ | |
| 6045 | try f.fmtIntLiteral(try pt.intValue(.usize, byte_offset)), | |
| 6135 | try w.writeAll("(("); | |
| 6136 | try f.renderType(w, u8_ptr_ty); | |
| 6137 | try w.writeByte(')'); | |
| 6138 | try f.writeCValue(w, container_ptr_val, .Other); | |
| 6139 | try w.print(" + {f})", .{ | |
| 6140 | try f.fmtIntLiteralDec(try pt.intValue(.usize, byte_offset)), | |
| 6046 | 6141 | }); |
| 6047 | 6142 | }, |
| 6048 | 6143 | } |
| 6049 | 6144 | |
| 6050 | try writer.writeAll(";\n"); | |
| 6145 | try w.writeByte(';'); | |
| 6146 | try f.object.newline(); | |
| 6051 | 6147 | return local; |
| 6052 | 6148 | } |
| 6053 | 6149 | |
| ... | ... | @@ -6067,7 +6163,7 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6067 | 6163 | const struct_byval = try f.resolveInst(extra.struct_operand); |
| 6068 | 6164 | try reap(f, inst, &.{extra.struct_operand}); |
| 6069 | 6165 | const struct_ty = f.typeOf(extra.struct_operand); |
| 6070 | const writer = f.object.writer(); | |
| 6166 | const w = &f.object.code.writer; | |
| 6071 | 6167 | |
| 6072 | 6168 | // Ensure complete type definition is visible before accessing fields. |
| 6073 | 6169 | _ = try f.ctypeFromType(struct_ty, .complete); |
| ... | ... | @@ -6094,42 +6190,44 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6094 | 6190 | const field_int_ty = try pt.intType(field_int_signedness, @as(u16, @intCast(inst_ty.bitSize(zcu)))); |
| 6095 | 6191 | |
| 6096 | 6192 | const temp_local = try f.allocLocal(inst, field_int_ty); |
| 6097 | try f.writeCValue(writer, temp_local, .Other); | |
| 6098 | try writer.writeAll(" = zig_wrap_"); | |
| 6099 | try f.object.dg.renderTypeForBuiltinFnName(writer, field_int_ty); | |
| 6100 | try writer.writeAll("(("); | |
| 6101 | try f.renderType(writer, field_int_ty); | |
| 6102 | try writer.writeByte(')'); | |
| 6193 | try f.writeCValue(w, temp_local, .Other); | |
| 6194 | try w.writeAll(" = zig_wrap_"); | |
| 6195 | try f.object.dg.renderTypeForBuiltinFnName(w, field_int_ty); | |
| 6196 | try w.writeAll("(("); | |
| 6197 | try f.renderType(w, field_int_ty); | |
| 6198 | try w.writeByte(')'); | |
| 6103 | 6199 | const cant_cast = int_info.bits > 64; |
| 6104 | 6200 | if (cant_cast) { |
| 6105 | 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_"); | |
| 6107 | try f.object.dg.renderTypeForBuiltinFnName(writer, struct_ty); | |
| 6108 | try writer.writeByte('('); | |
| 6202 | try w.writeAll("zig_lo_"); | |
| 6203 | try f.object.dg.renderTypeForBuiltinFnName(w, struct_ty); | |
| 6204 | try w.writeByte('('); | |
| 6109 | 6205 | } |
| 6110 | 6206 | if (bit_offset > 0) { |
| 6111 | try writer.writeAll("zig_shr_"); | |
| 6112 | try f.object.dg.renderTypeForBuiltinFnName(writer, struct_ty); | |
| 6113 | try writer.writeByte('('); | |
| 6207 | try w.writeAll("zig_shr_"); | |
| 6208 | try f.object.dg.renderTypeForBuiltinFnName(w, struct_ty); | |
| 6209 | try w.writeByte('('); | |
| 6114 | 6210 | } |
| 6115 | try f.writeCValue(writer, struct_byval, .Other); | |
| 6116 | if (bit_offset > 0) try writer.print(", {})", .{ | |
| 6117 | try f.fmtIntLiteral(try pt.intValue(bit_offset_ty, bit_offset)), | |
| 6211 | try f.writeCValue(w, struct_byval, .Other); | |
| 6212 | if (bit_offset > 0) try w.print(", {f})", .{ | |
| 6213 | try f.fmtIntLiteralDec(try pt.intValue(bit_offset_ty, bit_offset)), | |
| 6118 | 6214 | }); |
| 6119 | if (cant_cast) try writer.writeByte(')'); | |
| 6120 | try f.object.dg.renderBuiltinInfo(writer, field_int_ty, .bits); | |
| 6121 | try writer.writeAll(");\n"); | |
| 6215 | if (cant_cast) try w.writeByte(')'); | |
| 6216 | try f.object.dg.renderBuiltinInfo(w, field_int_ty, .bits); | |
| 6217 | try w.writeAll(");"); | |
| 6218 | try f.object.newline(); | |
| 6122 | 6219 | if (inst_ty.eql(field_int_ty, zcu)) return temp_local; |
| 6123 | 6220 | |
| 6124 | 6221 | const local = try f.allocLocal(inst, inst_ty); |
| 6125 | 6222 | if (local.new_local != temp_local.new_local) { |
| 6126 | try writer.writeAll("memcpy("); | |
| 6127 | try f.writeCValue(writer, .{ .local_ref = local.new_local }, .FunctionArgument); | |
| 6128 | try writer.writeAll(", "); | |
| 6129 | try f.writeCValue(writer, .{ .local_ref = temp_local.new_local }, .FunctionArgument); | |
| 6130 | try writer.writeAll(", sizeof("); | |
| 6131 | try f.renderType(writer, inst_ty); | |
| 6132 | try writer.writeAll("));\n"); | |
| 6223 | try w.writeAll("memcpy("); | |
| 6224 | try f.writeCValue(w, .{ .local_ref = local.new_local }, .FunctionArgument); | |
| 6225 | try w.writeAll(", "); | |
| 6226 | try f.writeCValue(w, .{ .local_ref = temp_local.new_local }, .FunctionArgument); | |
| 6227 | try w.writeAll(", sizeof("); | |
| 6228 | try f.renderType(w, inst_ty); | |
| 6229 | try w.writeAll("));"); | |
| 6230 | try f.object.newline(); | |
| 6133 | 6231 | } |
| 6134 | 6232 | try freeLocal(f, inst, temp_local.new_local, null); |
| 6135 | 6233 | return local; |
| ... | ... | @@ -6150,10 +6248,11 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6150 | 6248 | .@"packed" => { |
| 6151 | 6249 | const operand_lval = if (struct_byval == .constant) blk: { |
| 6152 | 6250 | const operand_local = try f.allocLocal(inst, struct_ty); |
| 6153 | try f.writeCValue(writer, operand_local, .Other); | |
| 6154 | try writer.writeAll(" = "); | |
| 6155 | try f.writeCValue(writer, struct_byval, .Other); | |
| 6156 | try writer.writeAll(";\n"); | |
| 6251 | try f.writeCValue(w, operand_local, .Other); | |
| 6252 | try w.writeAll(" = "); | |
| 6253 | try f.writeCValue(w, struct_byval, .Other); | |
| 6254 | try w.writeByte(';'); | |
| 6255 | try f.object.newline(); | |
| 6157 | 6256 | break :blk operand_local; |
| 6158 | 6257 | } else struct_byval; |
| 6159 | 6258 | const local = try f.allocLocal(inst, inst_ty); |
| ... | ... | @@ -6164,13 +6263,14 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6164 | 6263 | }, |
| 6165 | 6264 | else => true, |
| 6166 | 6265 | }) { |
| 6167 | try writer.writeAll("memcpy(&"); | |
| 6168 | try f.writeCValue(writer, local, .Other); | |
| 6169 | try writer.writeAll(", &"); | |
| 6170 | try f.writeCValue(writer, operand_lval, .Other); | |
| 6171 | try writer.writeAll(", sizeof("); | |
| 6172 | try f.renderType(writer, inst_ty); | |
| 6173 | try writer.writeAll("));\n"); | |
| 6266 | try w.writeAll("memcpy(&"); | |
| 6267 | try f.writeCValue(w, local, .Other); | |
| 6268 | try w.writeAll(", &"); | |
| 6269 | try f.writeCValue(w, operand_lval, .Other); | |
| 6270 | try w.writeAll(", sizeof("); | |
| 6271 | try f.renderType(w, inst_ty); | |
| 6272 | try w.writeAll("));"); | |
| 6273 | try f.object.newline(); | |
| 6174 | 6274 | } |
| 6175 | 6275 | try f.freeCValue(inst, operand_lval); |
| 6176 | 6276 | return local; |
| ... | ... | @@ -6181,11 +6281,11 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6181 | 6281 | }; |
| 6182 | 6282 | |
| 6183 | 6283 | const local = try f.allocLocal(inst, inst_ty); |
| 6184 | const a = try Assignment.start(f, writer, try f.ctypeFromType(inst_ty, .complete)); | |
| 6185 | try f.writeCValue(writer, local, .Other); | |
| 6186 | try a.assign(f, writer); | |
| 6187 | try f.writeCValueMember(writer, struct_byval, field_name); | |
| 6188 | try a.end(f, writer); | |
| 6284 | const a = try Assignment.start(f, w, try f.ctypeFromType(inst_ty, .complete)); | |
| 6285 | try f.writeCValue(w, local, .Other); | |
| 6286 | try a.assign(f, w); | |
| 6287 | try f.writeCValueMember(w, struct_byval, field_name); | |
| 6288 | try a.end(f, w); | |
| 6189 | 6289 | return local; |
| 6190 | 6290 | } |
| 6191 | 6291 | |
| ... | ... | @@ -6212,21 +6312,22 @@ fn airUnwrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6212 | 6312 | return local; |
| 6213 | 6313 | } |
| 6214 | 6314 | |
| 6215 | const writer = f.object.writer(); | |
| 6216 | try f.writeCValue(writer, local, .Other); | |
| 6217 | try writer.writeAll(" = "); | |
| 6315 | const w = &f.object.code.writer; | |
| 6316 | try f.writeCValue(w, local, .Other); | |
| 6317 | try w.writeAll(" = "); | |
| 6218 | 6318 | |
| 6219 | 6319 | if (!payload_ty.hasRuntimeBits(zcu)) |
| 6220 | try f.writeCValue(writer, operand, .Other) | |
| 6320 | try f.writeCValue(w, operand, .Other) | |
| 6221 | 6321 | else if (error_ty.errorSetIsEmpty(zcu)) |
| 6222 | try writer.print("{}", .{ | |
| 6223 | try f.fmtIntLiteral(try pt.intValue(try pt.errorIntType(), 0)), | |
| 6322 | try w.print("{f}", .{ | |
| 6323 | try f.fmtIntLiteralDec(try pt.intValue(try pt.errorIntType(), 0)), | |
| 6224 | 6324 | }) |
| 6225 | 6325 | else if (operand_is_ptr) |
| 6226 | try f.writeCValueDerefMember(writer, operand, .{ .identifier = "error" }) | |
| 6326 | try f.writeCValueDerefMember(w, operand, .{ .identifier = "error" }) | |
| 6227 | 6327 | else |
| 6228 | try f.writeCValueMember(writer, operand, .{ .identifier = "error" }); | |
| 6229 | try writer.writeAll(";\n"); | |
| 6328 | try f.writeCValueMember(w, operand, .{ .identifier = "error" }); | |
| 6329 | try w.writeByte(';'); | |
| 6330 | try f.object.newline(); | |
| 6230 | 6331 | return local; |
| 6231 | 6332 | } |
| 6232 | 6333 | |
| ... | ... | @@ -6241,29 +6342,30 @@ fn airUnwrapErrUnionPay(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !CValu |
| 6241 | 6342 | const operand_ty = f.typeOf(ty_op.operand); |
| 6242 | 6343 | const error_union_ty = if (is_ptr) operand_ty.childType(zcu) else operand_ty; |
| 6243 | 6344 | |
| 6244 | const writer = f.object.writer(); | |
| 6345 | const w = &f.object.code.writer; | |
| 6245 | 6346 | if (!error_union_ty.errorUnionPayload(zcu).hasRuntimeBits(zcu)) { |
| 6246 | 6347 | if (!is_ptr) return .none; |
| 6247 | 6348 | |
| 6248 | 6349 | const local = try f.allocLocal(inst, inst_ty); |
| 6249 | try f.writeCValue(writer, local, .Other); | |
| 6250 | try writer.writeAll(" = ("); | |
| 6251 | try f.renderType(writer, inst_ty); | |
| 6252 | try writer.writeByte(')'); | |
| 6253 | try f.writeCValue(writer, operand, .Other); | |
| 6254 | try writer.writeAll(";\n"); | |
| 6350 | try f.writeCValue(w, local, .Other); | |
| 6351 | try w.writeAll(" = ("); | |
| 6352 | try f.renderType(w, inst_ty); | |
| 6353 | try w.writeByte(')'); | |
| 6354 | try f.writeCValue(w, operand, .Other); | |
| 6355 | try w.writeByte(';'); | |
| 6356 | try f.object.newline(); | |
| 6255 | 6357 | return local; |
| 6256 | 6358 | } |
| 6257 | 6359 | |
| 6258 | 6360 | const local = try f.allocLocal(inst, inst_ty); |
| 6259 | const a = try Assignment.start(f, writer, try f.ctypeFromType(inst_ty, .complete)); | |
| 6260 | try f.writeCValue(writer, local, .Other); | |
| 6261 | try a.assign(f, writer); | |
| 6361 | const a = try Assignment.start(f, w, try f.ctypeFromType(inst_ty, .complete)); | |
| 6362 | try f.writeCValue(w, local, .Other); | |
| 6363 | try a.assign(f, w); | |
| 6262 | 6364 | if (is_ptr) { |
| 6263 | try writer.writeByte('&'); | |
| 6264 | try f.writeCValueDerefMember(writer, operand, .{ .identifier = "payload" }); | |
| 6265 | } else try f.writeCValueMember(writer, operand, .{ .identifier = "payload" }); | |
| 6266 | try a.end(f, writer); | |
| 6365 | try w.writeByte('&'); | |
| 6366 | try f.writeCValueDerefMember(w, operand, .{ .identifier = "payload" }); | |
| 6367 | } else try f.writeCValueMember(w, operand, .{ .identifier = "payload" }); | |
| 6368 | try a.end(f, w); | |
| 6267 | 6369 | return local; |
| 6268 | 6370 | } |
| 6269 | 6371 | |
| ... | ... | @@ -6282,21 +6384,21 @@ fn airWrapOptional(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6282 | 6384 | .aggregate => |aggregate| switch (aggregate.fields.at(0, ctype_pool).name.index) { |
| 6283 | 6385 | .is_null, .payload => { |
| 6284 | 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 | 6388 | const local = try f.allocLocal(inst, inst_ty); |
| 6287 | 6389 | { |
| 6288 | const a = try Assignment.start(f, writer, .bool); | |
| 6289 | try f.writeCValueMember(writer, local, .{ .identifier = "is_null" }); | |
| 6290 | try a.assign(f, writer); | |
| 6291 | try writer.writeAll("false"); | |
| 6292 | try a.end(f, writer); | |
| 6390 | const a = try Assignment.start(f, w, .bool); | |
| 6391 | try f.writeCValueMember(w, local, .{ .identifier = "is_null" }); | |
| 6392 | try a.assign(f, w); | |
| 6393 | try w.writeAll("false"); | |
| 6394 | try a.end(f, w); | |
| 6293 | 6395 | } |
| 6294 | 6396 | { |
| 6295 | const a = try Assignment.start(f, writer, operand_ctype); | |
| 6296 | try f.writeCValueMember(writer, local, .{ .identifier = "payload" }); | |
| 6297 | try a.assign(f, writer); | |
| 6298 | try f.writeCValue(writer, operand, .Other); | |
| 6299 | try a.end(f, writer); | |
| 6397 | const a = try Assignment.start(f, w, operand_ctype); | |
| 6398 | try f.writeCValueMember(w, local, .{ .identifier = "payload" }); | |
| 6399 | try a.assign(f, w); | |
| 6400 | try f.writeCValue(w, operand, .Other); | |
| 6401 | try a.end(f, w); | |
| 6300 | 6402 | } |
| 6301 | 6403 | return local; |
| 6302 | 6404 | }, |
| ... | ... | @@ -6318,7 +6420,7 @@ fn airWrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6318 | 6420 | const err = try f.resolveInst(ty_op.operand); |
| 6319 | 6421 | try reap(f, inst, &.{ty_op.operand}); |
| 6320 | 6422 | |
| 6321 | const writer = f.object.writer(); | |
| 6423 | const w = &f.object.code.writer; | |
| 6322 | 6424 | const local = try f.allocLocal(inst, inst_ty); |
| 6323 | 6425 | |
| 6324 | 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 | 6429 | } |
| 6328 | 6430 | |
| 6329 | 6431 | if (!repr_is_err) { |
| 6330 | const a = try Assignment.start(f, writer, try f.ctypeFromType(payload_ty, .complete)); | |
| 6331 | try f.writeCValueMember(writer, local, .{ .identifier = "payload" }); | |
| 6332 | try a.assign(f, writer); | |
| 6333 | try f.object.dg.renderUndefValue(writer, payload_ty, .Other); | |
| 6334 | try a.end(f, writer); | |
| 6432 | const a = try Assignment.start(f, w, try f.ctypeFromType(payload_ty, .complete)); | |
| 6433 | try f.writeCValueMember(w, local, .{ .identifier = "payload" }); | |
| 6434 | try a.assign(f, w); | |
| 6435 | try f.object.dg.renderUndefValue(w, payload_ty, .Other); | |
| 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 | 6440 | if (repr_is_err) |
| 6339 | try f.writeCValue(writer, local, .Other) | |
| 6441 | try f.writeCValue(w, local, .Other) | |
| 6340 | 6442 | else |
| 6341 | try f.writeCValueMember(writer, local, .{ .identifier = "error" }); | |
| 6342 | try a.assign(f, writer); | |
| 6343 | try f.writeCValue(writer, err, .Other); | |
| 6344 | try a.end(f, writer); | |
| 6443 | try f.writeCValueMember(w, local, .{ .identifier = "error" }); | |
| 6444 | try a.assign(f, w); | |
| 6445 | try f.writeCValue(w, err, .Other); | |
| 6446 | try a.end(f, w); | |
| 6345 | 6447 | } |
| 6346 | 6448 | return local; |
| 6347 | 6449 | } |
| ... | ... | @@ -6349,7 +6451,7 @@ fn airWrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6349 | 6451 | fn airErrUnionPayloadPtrSet(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6350 | 6452 | const pt = f.object.dg.pt; |
| 6351 | 6453 | const zcu = pt.zcu; |
| 6352 | const writer = f.object.writer(); | |
| 6454 | const w = &f.object.code.writer; | |
| 6353 | 6455 | const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| 6354 | 6456 | const inst_ty = f.typeOfIndex(inst); |
| 6355 | 6457 | const operand = try f.resolveInst(ty_op.operand); |
| ... | ... | @@ -6363,31 +6465,31 @@ fn airErrUnionPayloadPtrSet(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6363 | 6465 | |
| 6364 | 6466 | // First, set the non-error value. |
| 6365 | 6467 | if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) { |
| 6366 | const a = try Assignment.start(f, writer, try f.ctypeFromType(operand_ty, .complete)); | |
| 6367 | try f.writeCValueDeref(writer, operand); | |
| 6368 | try a.assign(f, writer); | |
| 6369 | try writer.print("{}", .{try f.fmtIntLiteral(no_err)}); | |
| 6370 | try a.end(f, writer); | |
| 6468 | const a = try Assignment.start(f, w, try f.ctypeFromType(operand_ty, .complete)); | |
| 6469 | try f.writeCValueDeref(w, operand); | |
| 6470 | try a.assign(f, w); | |
| 6471 | try w.print("{f}", .{try f.fmtIntLiteralDec(no_err)}); | |
| 6472 | try a.end(f, w); | |
| 6371 | 6473 | return .none; |
| 6372 | 6474 | } |
| 6373 | 6475 | { |
| 6374 | const a = try Assignment.start(f, writer, try f.ctypeFromType(err_int_ty, .complete)); | |
| 6375 | try f.writeCValueDerefMember(writer, operand, .{ .identifier = "error" }); | |
| 6376 | try a.assign(f, writer); | |
| 6377 | try writer.print("{}", .{try f.fmtIntLiteral(no_err)}); | |
| 6378 | try a.end(f, writer); | |
| 6476 | const a = try Assignment.start(f, w, try f.ctypeFromType(err_int_ty, .complete)); | |
| 6477 | try f.writeCValueDerefMember(w, operand, .{ .identifier = "error" }); | |
| 6478 | try a.assign(f, w); | |
| 6479 | try w.print("{f}", .{try f.fmtIntLiteralDec(no_err)}); | |
| 6480 | try a.end(f, w); | |
| 6379 | 6481 | } |
| 6380 | 6482 | |
| 6381 | 6483 | // Then return the payload pointer (only if it is used) |
| 6382 | 6484 | if (f.liveness.isUnused(inst)) return .none; |
| 6383 | 6485 | |
| 6384 | 6486 | const local = try f.allocLocal(inst, inst_ty); |
| 6385 | const a = try Assignment.start(f, writer, try f.ctypeFromType(inst_ty, .complete)); | |
| 6386 | try f.writeCValue(writer, local, .Other); | |
| 6387 | try a.assign(f, writer); | |
| 6388 | try writer.writeByte('&'); | |
| 6389 | try f.writeCValueDerefMember(writer, operand, .{ .identifier = "payload" }); | |
| 6390 | try a.end(f, writer); | |
| 6487 | const a = try Assignment.start(f, w, try f.ctypeFromType(inst_ty, .complete)); | |
| 6488 | try f.writeCValue(w, local, .Other); | |
| 6489 | try a.assign(f, w); | |
| 6490 | try w.writeByte('&'); | |
| 6491 | try f.writeCValueDerefMember(w, operand, .{ .identifier = "payload" }); | |
| 6492 | try a.end(f, w); | |
| 6391 | 6493 | return local; |
| 6392 | 6494 | } |
| 6393 | 6495 | |
| ... | ... | @@ -6418,24 +6520,24 @@ fn airWrapErrUnionPay(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6418 | 6520 | const err_ty = inst_ty.errorUnionSet(zcu); |
| 6419 | 6521 | try reap(f, inst, &.{ty_op.operand}); |
| 6420 | 6522 | |
| 6421 | const writer = f.object.writer(); | |
| 6523 | const w = &f.object.code.writer; | |
| 6422 | 6524 | const local = try f.allocLocal(inst, inst_ty); |
| 6423 | 6525 | if (!repr_is_err) { |
| 6424 | const a = try Assignment.start(f, writer, try f.ctypeFromType(payload_ty, .complete)); | |
| 6425 | try f.writeCValueMember(writer, local, .{ .identifier = "payload" }); | |
| 6426 | try a.assign(f, writer); | |
| 6427 | try f.writeCValue(writer, payload, .Other); | |
| 6428 | try a.end(f, writer); | |
| 6526 | const a = try Assignment.start(f, w, try f.ctypeFromType(payload_ty, .complete)); | |
| 6527 | try f.writeCValueMember(w, local, .{ .identifier = "payload" }); | |
| 6528 | try a.assign(f, w); | |
| 6529 | try f.writeCValue(w, payload, .Other); | |
| 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 | 6534 | if (repr_is_err) |
| 6433 | try f.writeCValue(writer, local, .Other) | |
| 6535 | try f.writeCValue(w, local, .Other) | |
| 6434 | 6536 | else |
| 6435 | try f.writeCValueMember(writer, local, .{ .identifier = "error" }); | |
| 6436 | try a.assign(f, writer); | |
| 6437 | try f.object.dg.renderValue(writer, try pt.intValue(try pt.errorIntType(), 0), .Other); | |
| 6438 | try a.end(f, writer); | |
| 6537 | try f.writeCValueMember(w, local, .{ .identifier = "error" }); | |
| 6538 | try a.assign(f, w); | |
| 6539 | try f.object.dg.renderValue(w, try pt.intValue(try pt.errorIntType(), 0), .Other); | |
| 6540 | try a.end(f, w); | |
| 6439 | 6541 | } |
| 6440 | 6542 | return local; |
| 6441 | 6543 | } |
| ... | ... | @@ -6445,7 +6547,7 @@ fn airIsErr(f: *Function, inst: Air.Inst.Index, is_ptr: bool, operator: []const |
| 6445 | 6547 | const zcu = pt.zcu; |
| 6446 | 6548 | const un_op = f.air.instructions.items(.data)[@intFromEnum(inst)].un_op; |
| 6447 | 6549 | |
| 6448 | const writer = f.object.writer(); | |
| 6550 | const w = &f.object.code.writer; | |
| 6449 | 6551 | const operand = try f.resolveInst(un_op); |
| 6450 | 6552 | try reap(f, inst, &.{un_op}); |
| 6451 | 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 | 6556 | const payload_ty = err_union_ty.errorUnionPayload(zcu); |
| 6455 | 6557 | const error_ty = err_union_ty.errorUnionSet(zcu); |
| 6456 | 6558 | |
| 6457 | const a = try Assignment.start(f, writer, .bool); | |
| 6458 | try f.writeCValue(writer, local, .Other); | |
| 6459 | try a.assign(f, writer); | |
| 6559 | const a = try Assignment.start(f, w, .bool); | |
| 6560 | try f.writeCValue(w, local, .Other); | |
| 6561 | try a.assign(f, w); | |
| 6460 | 6562 | const err_int_ty = try pt.errorIntType(); |
| 6461 | 6563 | if (!error_ty.errorSetIsEmpty(zcu)) |
| 6462 | 6564 | if (payload_ty.hasRuntimeBits(zcu)) |
| 6463 | 6565 | if (is_ptr) |
| 6464 | try f.writeCValueDerefMember(writer, operand, .{ .identifier = "error" }) | |
| 6566 | try f.writeCValueDerefMember(w, operand, .{ .identifier = "error" }) | |
| 6465 | 6567 | else |
| 6466 | try f.writeCValueMember(writer, operand, .{ .identifier = "error" }) | |
| 6568 | try f.writeCValueMember(w, operand, .{ .identifier = "error" }) | |
| 6467 | 6569 | else |
| 6468 | try f.writeCValue(writer, operand, .Other) | |
| 6570 | try f.writeCValue(w, operand, .Other) | |
| 6469 | 6571 | else |
| 6470 | try f.object.dg.renderValue(writer, try pt.intValue(err_int_ty, 0), .Other); | |
| 6471 | try writer.writeByte(' '); | |
| 6472 | try writer.writeAll(operator); | |
| 6473 | try writer.writeByte(' '); | |
| 6474 | try f.object.dg.renderValue(writer, try pt.intValue(err_int_ty, 0), .Other); | |
| 6475 | try a.end(f, writer); | |
| 6572 | try f.object.dg.renderValue(w, try pt.intValue(err_int_ty, 0), .Other); | |
| 6573 | try w.writeByte(' '); | |
| 6574 | try w.writeAll(operator); | |
| 6575 | try w.writeByte(' '); | |
| 6576 | try f.object.dg.renderValue(w, try pt.intValue(err_int_ty, 0), .Other); | |
| 6577 | try a.end(f, w); | |
| 6476 | 6578 | return local; |
| 6477 | 6579 | } |
| 6478 | 6580 | |
| ... | ... | @@ -6486,45 +6588,45 @@ fn airArrayToSlice(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6486 | 6588 | try reap(f, inst, &.{ty_op.operand}); |
| 6487 | 6589 | const inst_ty = f.typeOfIndex(inst); |
| 6488 | 6590 | const ptr_ty = inst_ty.slicePtrFieldType(zcu); |
| 6489 | const writer = f.object.writer(); | |
| 6591 | const w = &f.object.code.writer; | |
| 6490 | 6592 | const local = try f.allocLocal(inst, inst_ty); |
| 6491 | 6593 | const operand_ty = f.typeOf(ty_op.operand); |
| 6492 | 6594 | const array_ty = operand_ty.childType(zcu); |
| 6493 | 6595 | |
| 6494 | 6596 | { |
| 6495 | const a = try Assignment.start(f, writer, try f.ctypeFromType(ptr_ty, .complete)); | |
| 6496 | try f.writeCValueMember(writer, local, .{ .identifier = "ptr" }); | |
| 6497 | try a.assign(f, writer); | |
| 6597 | const a = try Assignment.start(f, w, try f.ctypeFromType(ptr_ty, .complete)); | |
| 6598 | try f.writeCValueMember(w, local, .{ .identifier = "ptr" }); | |
| 6599 | try a.assign(f, w); | |
| 6498 | 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 | 6602 | } else { |
| 6501 | 6603 | const ptr_ctype = try f.ctypeFromType(ptr_ty, .complete); |
| 6502 | 6604 | const ptr_child_ctype = ptr_ctype.info(ctype_pool).pointer.elem_ctype; |
| 6503 | 6605 | const elem_ty = array_ty.childType(zcu); |
| 6504 | 6606 | const elem_ctype = try f.ctypeFromType(elem_ty, .complete); |
| 6505 | 6607 | if (!ptr_child_ctype.eql(elem_ctype)) { |
| 6506 | try writer.writeByte('('); | |
| 6507 | try f.renderCType(writer, ptr_ctype); | |
| 6508 | try writer.writeByte(')'); | |
| 6608 | try w.writeByte('('); | |
| 6609 | try f.renderCType(w, ptr_ctype); | |
| 6610 | try w.writeByte(')'); | |
| 6509 | 6611 | } |
| 6510 | 6612 | const operand_ctype = try f.ctypeFromType(operand_ty, .complete); |
| 6511 | 6613 | const operand_child_ctype = operand_ctype.info(ctype_pool).pointer.elem_ctype; |
| 6512 | 6614 | if (operand_child_ctype.info(ctype_pool) == .array) { |
| 6513 | try writer.writeByte('&'); | |
| 6514 | try f.writeCValueDeref(writer, operand); | |
| 6515 | try writer.print("[{}]", .{try f.fmtIntLiteral(.zero_usize)}); | |
| 6516 | } else try f.writeCValue(writer, operand, .Other); | |
| 6615 | try w.writeByte('&'); | |
| 6616 | try f.writeCValueDeref(w, operand); | |
| 6617 | try w.print("[{f}]", .{try f.fmtIntLiteralDec(.zero_usize)}); | |
| 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); | |
| 6522 | try f.writeCValueMember(writer, local, .{ .identifier = "len" }); | |
| 6523 | try a.assign(f, writer); | |
| 6524 | try writer.print("{}", .{ | |
| 6525 | try f.fmtIntLiteral(try pt.intValue(.usize, array_ty.arrayLen(zcu))), | |
| 6623 | const a = try Assignment.start(f, w, .usize); | |
| 6624 | try f.writeCValueMember(w, local, .{ .identifier = "len" }); | |
| 6625 | try a.assign(f, w); | |
| 6626 | try w.print("{f}", .{ | |
| 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 | } |
| 6529 | 6631 | |
| 6530 | 6632 | return local; |
| ... | ... | @@ -6551,32 +6653,32 @@ fn airFloatCast(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6551 | 6653 | else |
| 6552 | 6654 | unreachable; |
| 6553 | 6655 | |
| 6554 | const writer = f.object.writer(); | |
| 6656 | const w = &f.object.code.writer; | |
| 6555 | 6657 | const local = try f.allocLocal(inst, inst_ty); |
| 6556 | const v = try Vectorize.start(f, inst, writer, operand_ty); | |
| 6557 | const a = try Assignment.start(f, writer, try f.ctypeFromType(scalar_ty, .complete)); | |
| 6558 | try f.writeCValue(writer, local, .Other); | |
| 6559 | try v.elem(f, writer); | |
| 6560 | try a.assign(f, writer); | |
| 6658 | const v = try Vectorize.start(f, inst, w, operand_ty); | |
| 6659 | const a = try Assignment.start(f, w, try f.ctypeFromType(scalar_ty, .complete)); | |
| 6660 | try f.writeCValue(w, local, .Other); | |
| 6661 | try v.elem(f, w); | |
| 6662 | try a.assign(f, w); | |
| 6561 | 6663 | if (inst_scalar_ty.isInt(zcu) and scalar_ty.isRuntimeFloat()) { |
| 6562 | try writer.writeAll("zig_wrap_"); | |
| 6563 | try f.object.dg.renderTypeForBuiltinFnName(writer, inst_scalar_ty); | |
| 6564 | try writer.writeByte('('); | |
| 6565 | } | |
| 6566 | try writer.writeAll("zig_"); | |
| 6567 | try writer.writeAll(operation); | |
| 6568 | try writer.writeAll(compilerRtAbbrev(scalar_ty, zcu, target)); | |
| 6569 | try writer.writeAll(compilerRtAbbrev(inst_scalar_ty, zcu, target)); | |
| 6570 | try writer.writeByte('('); | |
| 6571 | try f.writeCValue(writer, operand, .FunctionArgument); | |
| 6572 | try v.elem(f, writer); | |
| 6573 | try writer.writeByte(')'); | |
| 6664 | try w.writeAll("zig_wrap_"); | |
| 6665 | try f.object.dg.renderTypeForBuiltinFnName(w, inst_scalar_ty); | |
| 6666 | try w.writeByte('('); | |
| 6667 | } | |
| 6668 | try w.writeAll("zig_"); | |
| 6669 | try w.writeAll(operation); | |
| 6670 | try w.writeAll(compilerRtAbbrev(scalar_ty, zcu, target)); | |
| 6671 | try w.writeAll(compilerRtAbbrev(inst_scalar_ty, zcu, target)); | |
| 6672 | try w.writeByte('('); | |
| 6673 | try f.writeCValue(w, operand, .FunctionArgument); | |
| 6674 | try v.elem(f, w); | |
| 6675 | try w.writeByte(')'); | |
| 6574 | 6676 | if (inst_scalar_ty.isInt(zcu) and scalar_ty.isRuntimeFloat()) { |
| 6575 | try f.object.dg.renderBuiltinInfo(writer, inst_scalar_ty, .bits); | |
| 6576 | try writer.writeByte(')'); | |
| 6677 | try f.object.dg.renderBuiltinInfo(w, inst_scalar_ty, .bits); | |
| 6678 | try w.writeByte(')'); | |
| 6577 | 6679 | } |
| 6578 | try a.end(f, writer); | |
| 6579 | try v.end(f, inst, writer); | |
| 6680 | try a.end(f, w); | |
| 6681 | try v.end(f, inst, w); | |
| 6580 | 6682 | |
| 6581 | 6683 | return local; |
| 6582 | 6684 | } |
| ... | ... | @@ -6601,27 +6703,28 @@ fn airUnBuiltinCall( |
| 6601 | 6703 | const inst_scalar_ctype = try f.ctypeFromType(inst_scalar_ty, .complete); |
| 6602 | 6704 | const ref_ret = inst_scalar_ctype.info(&f.object.dg.ctype_pool) == .array; |
| 6603 | 6705 | |
| 6604 | const writer = f.object.writer(); | |
| 6706 | const w = &f.object.code.writer; | |
| 6605 | 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 | 6709 | if (!ref_ret) { |
| 6608 | try f.writeCValue(writer, local, .Other); | |
| 6609 | try v.elem(f, writer); | |
| 6610 | try writer.writeAll(" = "); | |
| 6710 | try f.writeCValue(w, local, .Other); | |
| 6711 | try v.elem(f, w); | |
| 6712 | try w.writeAll(" = "); | |
| 6611 | 6713 | } |
| 6612 | try writer.print("zig_{s}_", .{operation}); | |
| 6613 | try f.object.dg.renderTypeForBuiltinFnName(writer, scalar_ty); | |
| 6614 | try writer.writeByte('('); | |
| 6714 | try w.print("zig_{s}_", .{operation}); | |
| 6715 | try f.object.dg.renderTypeForBuiltinFnName(w, scalar_ty); | |
| 6716 | try w.writeByte('('); | |
| 6615 | 6717 | if (ref_ret) { |
| 6616 | try f.writeCValue(writer, local, .FunctionArgument); | |
| 6617 | try v.elem(f, writer); | |
| 6618 | try writer.writeAll(", "); | |
| 6718 | try f.writeCValue(w, local, .FunctionArgument); | |
| 6719 | try v.elem(f, w); | |
| 6720 | try w.writeAll(", "); | |
| 6619 | 6721 | } |
| 6620 | try f.writeCValue(writer, operand, .FunctionArgument); | |
| 6621 | try v.elem(f, writer); | |
| 6622 | try f.object.dg.renderBuiltinInfo(writer, scalar_ty, info); | |
| 6623 | try writer.writeAll(");\n"); | |
| 6624 | try v.end(f, inst, writer); | |
| 6722 | try f.writeCValue(w, operand, .FunctionArgument); | |
| 6723 | try v.elem(f, w); | |
| 6724 | try f.object.dg.renderBuiltinInfo(w, scalar_ty, info); | |
| 6725 | try w.writeAll(");"); | |
| 6726 | try f.object.newline(); | |
| 6727 | try v.end(f, inst, w); | |
| 6625 | 6728 | |
| 6626 | 6729 | return local; |
| 6627 | 6730 | } |
| ... | ... | @@ -6651,31 +6754,31 @@ fn airBinBuiltinCall( |
| 6651 | 6754 | const inst_scalar_ctype = try f.ctypeFromType(inst_scalar_ty, .complete); |
| 6652 | 6755 | const ref_ret = inst_scalar_ctype.info(&f.object.dg.ctype_pool) == .array; |
| 6653 | 6756 | |
| 6654 | const writer = f.object.writer(); | |
| 6757 | const w = &f.object.code.writer; | |
| 6655 | 6758 | const local = try f.allocLocal(inst, inst_ty); |
| 6656 | 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 | 6761 | if (!ref_ret) { |
| 6659 | try f.writeCValue(writer, local, .Other); | |
| 6660 | try v.elem(f, writer); | |
| 6661 | try writer.writeAll(" = "); | |
| 6762 | try f.writeCValue(w, local, .Other); | |
| 6763 | try v.elem(f, w); | |
| 6764 | try w.writeAll(" = "); | |
| 6662 | 6765 | } |
| 6663 | try writer.print("zig_{s}_", .{operation}); | |
| 6664 | try f.object.dg.renderTypeForBuiltinFnName(writer, scalar_ty); | |
| 6665 | try writer.writeByte('('); | |
| 6766 | try w.print("zig_{s}_", .{operation}); | |
| 6767 | try f.object.dg.renderTypeForBuiltinFnName(w, scalar_ty); | |
| 6768 | try w.writeByte('('); | |
| 6666 | 6769 | if (ref_ret) { |
| 6667 | try f.writeCValue(writer, local, .FunctionArgument); | |
| 6668 | try v.elem(f, writer); | |
| 6669 | try writer.writeAll(", "); | |
| 6670 | } | |
| 6671 | try f.writeCValue(writer, lhs, .FunctionArgument); | |
| 6672 | try v.elem(f, writer); | |
| 6673 | try writer.writeAll(", "); | |
| 6674 | try f.writeCValue(writer, rhs, .FunctionArgument); | |
| 6675 | if (f.typeOf(bin_op.rhs).isVector(zcu)) try v.elem(f, writer); | |
| 6676 | try f.object.dg.renderBuiltinInfo(writer, scalar_ty, info); | |
| 6677 | try writer.writeAll(");\n"); | |
| 6678 | try v.end(f, inst, writer); | |
| 6770 | try f.writeCValue(w, local, .FunctionArgument); | |
| 6771 | try v.elem(f, w); | |
| 6772 | try w.writeAll(", "); | |
| 6773 | } | |
| 6774 | try f.writeCValue(w, lhs, .FunctionArgument); | |
| 6775 | try v.elem(f, w); | |
| 6776 | try w.writeAll(", "); | |
| 6777 | try f.writeCValue(w, rhs, .FunctionArgument); | |
| 6778 | if (f.typeOf(bin_op.rhs).isVector(zcu)) try v.elem(f, w); | |
| 6779 | try f.object.dg.renderBuiltinInfo(w, scalar_ty, info); | |
| 6780 | try w.writeAll(");\n"); | |
| 6781 | try v.end(f, inst, w); | |
| 6679 | 6782 | |
| 6680 | 6783 | return local; |
| 6681 | 6784 | } |
| ... | ... | @@ -6702,38 +6805,39 @@ fn airCmpBuiltinCall( |
| 6702 | 6805 | const inst_scalar_ctype = try f.ctypeFromType(inst_scalar_ty, .complete); |
| 6703 | 6806 | const ref_ret = inst_scalar_ctype.info(&f.object.dg.ctype_pool) == .array; |
| 6704 | 6807 | |
| 6705 | const writer = f.object.writer(); | |
| 6808 | const w = &f.object.code.writer; | |
| 6706 | 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 | 6811 | if (!ref_ret) { |
| 6709 | try f.writeCValue(writer, local, .Other); | |
| 6710 | try v.elem(f, writer); | |
| 6711 | try writer.writeAll(" = "); | |
| 6812 | try f.writeCValue(w, local, .Other); | |
| 6813 | try v.elem(f, w); | |
| 6814 | try w.writeAll(" = "); | |
| 6712 | 6815 | } |
| 6713 | try writer.print("zig_{s}_", .{switch (operation) { | |
| 6816 | try w.print("zig_{s}_", .{switch (operation) { | |
| 6714 | 6817 | else => @tagName(operation), |
| 6715 | 6818 | .operator => compareOperatorAbbrev(operator), |
| 6716 | 6819 | }}); |
| 6717 | try f.object.dg.renderTypeForBuiltinFnName(writer, scalar_ty); | |
| 6718 | try writer.writeByte('('); | |
| 6820 | try f.object.dg.renderTypeForBuiltinFnName(w, scalar_ty); | |
| 6821 | try w.writeByte('('); | |
| 6719 | 6822 | if (ref_ret) { |
| 6720 | try f.writeCValue(writer, local, .FunctionArgument); | |
| 6721 | try v.elem(f, writer); | |
| 6722 | try writer.writeAll(", "); | |
| 6723 | } | |
| 6724 | try f.writeCValue(writer, lhs, .FunctionArgument); | |
| 6725 | try v.elem(f, writer); | |
| 6726 | try writer.writeAll(", "); | |
| 6727 | try f.writeCValue(writer, rhs, .FunctionArgument); | |
| 6728 | try v.elem(f, writer); | |
| 6729 | try f.object.dg.renderBuiltinInfo(writer, scalar_ty, info); | |
| 6730 | try writer.writeByte(')'); | |
| 6731 | if (!ref_ret) try writer.print("{s}{}", .{ | |
| 6823 | try f.writeCValue(w, local, .FunctionArgument); | |
| 6824 | try v.elem(f, w); | |
| 6825 | try w.writeAll(", "); | |
| 6826 | } | |
| 6827 | try f.writeCValue(w, lhs, .FunctionArgument); | |
| 6828 | try v.elem(f, w); | |
| 6829 | try w.writeAll(", "); | |
| 6830 | try f.writeCValue(w, rhs, .FunctionArgument); | |
| 6831 | try v.elem(f, w); | |
| 6832 | try f.object.dg.renderBuiltinInfo(w, scalar_ty, info); | |
| 6833 | try w.writeByte(')'); | |
| 6834 | if (!ref_ret) try w.print("{s}{f}", .{ | |
| 6732 | 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"); | |
| 6736 | try v.end(f, inst, writer); | |
| 6838 | try w.writeByte(';'); | |
| 6839 | try f.object.newline(); | |
| 6840 | try v.end(f, inst, w); | |
| 6737 | 6841 | |
| 6738 | 6842 | return local; |
| 6739 | 6843 | } |
| ... | ... | @@ -6751,7 +6855,7 @@ fn airCmpxchg(f: *Function, inst: Air.Inst.Index, flavor: [*:0]const u8) !CValue |
| 6751 | 6855 | const ty = ptr_ty.childType(zcu); |
| 6752 | 6856 | const ctype = try f.ctypeFromType(ty, .complete); |
| 6753 | 6857 | |
| 6754 | const writer = f.object.writer(); | |
| 6858 | const w = &f.object.code.writer; | |
| 6755 | 6859 | const new_value_mat = try Materialize.start(f, inst, ty, new_value); |
| 6756 | 6860 | try reap(f, inst, &.{ extra.ptr, extra.expected_value, extra.new_value }); |
| 6757 | 6861 | |
| ... | ... | @@ -6763,76 +6867,78 @@ fn airCmpxchg(f: *Function, inst: Air.Inst.Index, flavor: [*:0]const u8) !CValue |
| 6763 | 6867 | const local = try f.allocLocal(inst, inst_ty); |
| 6764 | 6868 | if (inst_ty.isPtrLikeOptional(zcu)) { |
| 6765 | 6869 | { |
| 6766 | const a = try Assignment.start(f, writer, ctype); | |
| 6767 | try f.writeCValue(writer, local, .Other); | |
| 6768 | try a.assign(f, writer); | |
| 6769 | try f.writeCValue(writer, expected_value, .Other); | |
| 6770 | try a.end(f, writer); | |
| 6870 | const a = try Assignment.start(f, w, ctype); | |
| 6871 | try f.writeCValue(w, local, .Other); | |
| 6872 | try a.assign(f, w); | |
| 6873 | try f.writeCValue(w, expected_value, .Other); | |
| 6874 | try a.end(f, w); | |
| 6771 | 6875 | } |
| 6772 | 6876 | |
| 6773 | try writer.writeAll("if ("); | |
| 6774 | try writer.print("zig_cmpxchg_{s}((zig_atomic(", .{flavor}); | |
| 6775 | try f.renderType(writer, ty); | |
| 6776 | try writer.writeByte(')'); | |
| 6777 | if (ptr_ty.isVolatilePtr(zcu)) try writer.writeAll(" volatile"); | |
| 6778 | try writer.writeAll(" *)"); | |
| 6779 | try f.writeCValue(writer, ptr, .Other); | |
| 6780 | try writer.writeAll(", "); | |
| 6781 | try f.writeCValue(writer, local, .FunctionArgument); | |
| 6782 | try writer.writeAll(", "); | |
| 6783 | try new_value_mat.mat(f, writer); | |
| 6784 | try writer.writeAll(", "); | |
| 6785 | try writeMemoryOrder(writer, extra.successOrder()); | |
| 6786 | try writer.writeAll(", "); | |
| 6787 | try writeMemoryOrder(writer, extra.failureOrder()); | |
| 6788 | try writer.writeAll(", "); | |
| 6789 | try f.object.dg.renderTypeForBuiltinFnName(writer, ty); | |
| 6790 | try writer.writeAll(", "); | |
| 6791 | try f.renderType(writer, repr_ty); | |
| 6792 | try writer.writeByte(')'); | |
| 6793 | try writer.writeAll(") {\n"); | |
| 6794 | f.object.indent_writer.pushIndent(); | |
| 6877 | try w.writeAll("if ("); | |
| 6878 | try w.print("zig_cmpxchg_{s}((zig_atomic(", .{flavor}); | |
| 6879 | try f.renderType(w, ty); | |
| 6880 | try w.writeByte(')'); | |
| 6881 | if (ptr_ty.isVolatilePtr(zcu)) try w.writeAll(" volatile"); | |
| 6882 | try w.writeAll(" *)"); | |
| 6883 | try f.writeCValue(w, ptr, .Other); | |
| 6884 | try w.writeAll(", "); | |
| 6885 | try f.writeCValue(w, local, .FunctionArgument); | |
| 6886 | try w.writeAll(", "); | |
| 6887 | try new_value_mat.mat(f, w); | |
| 6888 | try w.writeAll(", "); | |
| 6889 | try writeMemoryOrder(w, extra.successOrder()); | |
| 6890 | try w.writeAll(", "); | |
| 6891 | try writeMemoryOrder(w, extra.failureOrder()); | |
| 6892 | try w.writeAll(", "); | |
| 6893 | try f.object.dg.renderTypeForBuiltinFnName(w, ty); | |
| 6894 | try w.writeAll(", "); | |
| 6895 | try f.renderType(w, repr_ty); | |
| 6896 | try w.writeByte(')'); | |
| 6897 | try w.writeAll(") {"); | |
| 6898 | f.object.indent(); | |
| 6899 | try f.object.newline(); | |
| 6795 | 6900 | { |
| 6796 | const a = try Assignment.start(f, writer, ctype); | |
| 6797 | try f.writeCValue(writer, local, .Other); | |
| 6798 | try a.assign(f, writer); | |
| 6799 | try writer.writeAll("NULL"); | |
| 6800 | try a.end(f, writer); | |
| 6901 | const a = try Assignment.start(f, w, ctype); | |
| 6902 | try f.writeCValue(w, local, .Other); | |
| 6903 | try a.assign(f, w); | |
| 6904 | try w.writeAll("NULL"); | |
| 6905 | try a.end(f, w); | |
| 6801 | 6906 | } |
| 6802 | f.object.indent_writer.popIndent(); | |
| 6803 | try writer.writeAll("}\n"); | |
| 6907 | try f.object.outdent(); | |
| 6908 | try w.writeByte('}'); | |
| 6909 | try f.object.newline(); | |
| 6804 | 6910 | } else { |
| 6805 | 6911 | { |
| 6806 | const a = try Assignment.start(f, writer, ctype); | |
| 6807 | try f.writeCValueMember(writer, local, .{ .identifier = "payload" }); | |
| 6808 | try a.assign(f, writer); | |
| 6809 | try f.writeCValue(writer, expected_value, .Other); | |
| 6810 | try a.end(f, writer); | |
| 6912 | const a = try Assignment.start(f, w, ctype); | |
| 6913 | try f.writeCValueMember(w, local, .{ .identifier = "payload" }); | |
| 6914 | try a.assign(f, w); | |
| 6915 | try f.writeCValue(w, expected_value, .Other); | |
| 6916 | try a.end(f, w); | |
| 6811 | 6917 | } |
| 6812 | 6918 | { |
| 6813 | const a = try Assignment.start(f, writer, .bool); | |
| 6814 | try f.writeCValueMember(writer, local, .{ .identifier = "is_null" }); | |
| 6815 | try a.assign(f, writer); | |
| 6816 | try writer.print("zig_cmpxchg_{s}((zig_atomic(", .{flavor}); | |
| 6817 | try f.renderType(writer, ty); | |
| 6818 | try writer.writeByte(')'); | |
| 6819 | if (ptr_ty.isVolatilePtr(zcu)) try writer.writeAll(" volatile"); | |
| 6820 | try writer.writeAll(" *)"); | |
| 6821 | try f.writeCValue(writer, ptr, .Other); | |
| 6822 | try writer.writeAll(", "); | |
| 6823 | try f.writeCValueMember(writer, local, .{ .identifier = "payload" }); | |
| 6824 | try writer.writeAll(", "); | |
| 6825 | try new_value_mat.mat(f, writer); | |
| 6826 | try writer.writeAll(", "); | |
| 6827 | try writeMemoryOrder(writer, extra.successOrder()); | |
| 6828 | try writer.writeAll(", "); | |
| 6829 | try writeMemoryOrder(writer, extra.failureOrder()); | |
| 6830 | try writer.writeAll(", "); | |
| 6831 | try f.object.dg.renderTypeForBuiltinFnName(writer, ty); | |
| 6832 | try writer.writeAll(", "); | |
| 6833 | try f.renderType(writer, repr_ty); | |
| 6834 | try writer.writeByte(')'); | |
| 6835 | try a.end(f, writer); | |
| 6919 | const a = try Assignment.start(f, w, .bool); | |
| 6920 | try f.writeCValueMember(w, local, .{ .identifier = "is_null" }); | |
| 6921 | try a.assign(f, w); | |
| 6922 | try w.print("zig_cmpxchg_{s}((zig_atomic(", .{flavor}); | |
| 6923 | try f.renderType(w, ty); | |
| 6924 | try w.writeByte(')'); | |
| 6925 | if (ptr_ty.isVolatilePtr(zcu)) try w.writeAll(" volatile"); | |
| 6926 | try w.writeAll(" *)"); | |
| 6927 | try f.writeCValue(w, ptr, .Other); | |
| 6928 | try w.writeAll(", "); | |
| 6929 | try f.writeCValueMember(w, local, .{ .identifier = "payload" }); | |
| 6930 | try w.writeAll(", "); | |
| 6931 | try new_value_mat.mat(f, w); | |
| 6932 | try w.writeAll(", "); | |
| 6933 | try writeMemoryOrder(w, extra.successOrder()); | |
| 6934 | try w.writeAll(", "); | |
| 6935 | try writeMemoryOrder(w, extra.failureOrder()); | |
| 6936 | try w.writeAll(", "); | |
| 6937 | try f.object.dg.renderTypeForBuiltinFnName(w, ty); | |
| 6938 | try w.writeAll(", "); | |
| 6939 | try f.renderType(w, repr_ty); | |
| 6940 | try w.writeByte(')'); | |
| 6941 | try a.end(f, w); | |
| 6836 | 6942 | } |
| 6837 | 6943 | } |
| 6838 | 6944 | try new_value_mat.end(f, inst); |
| ... | ... | @@ -6856,7 +6962,7 @@ fn airAtomicRmw(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6856 | 6962 | const ptr = try f.resolveInst(pl_op.operand); |
| 6857 | 6963 | const operand = try f.resolveInst(extra.operand); |
| 6858 | 6964 | |
| 6859 | const writer = f.object.writer(); | |
| 6965 | const w = &f.object.code.writer; | |
| 6860 | 6966 | const operand_mat = try Materialize.start(f, inst, ty, operand); |
| 6861 | 6967 | try reap(f, inst, &.{ pl_op.operand, extra.operand }); |
| 6862 | 6968 | |
| ... | ... | @@ -6866,31 +6972,32 @@ fn airAtomicRmw(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6866 | 6972 | const repr_ty = if (is_float) pt.intType(.unsigned, repr_bits) catch unreachable else ty; |
| 6867 | 6973 | |
| 6868 | 6974 | const local = try f.allocLocal(inst, inst_ty); |
| 6869 | try writer.print("zig_atomicrmw_{s}", .{toAtomicRmwSuffix(extra.op())}); | |
| 6870 | if (is_float) try writer.writeAll("_float") else if (is_128) try writer.writeAll("_int128"); | |
| 6871 | try writer.writeByte('('); | |
| 6872 | try f.writeCValue(writer, local, .Other); | |
| 6873 | try writer.writeAll(", ("); | |
| 6975 | try w.print("zig_atomicrmw_{s}", .{toAtomicRmwSuffix(extra.op())}); | |
| 6976 | if (is_float) try w.writeAll("_float") else if (is_128) try w.writeAll("_int128"); | |
| 6977 | try w.writeByte('('); | |
| 6978 | try f.writeCValue(w, local, .Other); | |
| 6979 | try w.writeAll(", ("); | |
| 6874 | 6980 | const use_atomic = switch (extra.op()) { |
| 6875 | 6981 | else => true, |
| 6876 | 6982 | // These are missing from stdatomic.h, so no atomic types unless a fallback is used. |
| 6877 | 6983 | .Nand, .Min, .Max => is_float or is_128, |
| 6878 | 6984 | }; |
| 6879 | if (use_atomic) try writer.writeAll("zig_atomic("); | |
| 6880 | try f.renderType(writer, ty); | |
| 6881 | if (use_atomic) try writer.writeByte(')'); | |
| 6882 | if (ptr_ty.isVolatilePtr(zcu)) try writer.writeAll(" volatile"); | |
| 6883 | try writer.writeAll(" *)"); | |
| 6884 | try f.writeCValue(writer, ptr, .Other); | |
| 6885 | try writer.writeAll(", "); | |
| 6886 | try operand_mat.mat(f, writer); | |
| 6887 | try writer.writeAll(", "); | |
| 6888 | try writeMemoryOrder(writer, extra.ordering()); | |
| 6889 | try writer.writeAll(", "); | |
| 6890 | try f.object.dg.renderTypeForBuiltinFnName(writer, ty); | |
| 6891 | try writer.writeAll(", "); | |
| 6892 | try f.renderType(writer, repr_ty); | |
| 6893 | try writer.writeAll(");\n"); | |
| 6985 | if (use_atomic) try w.writeAll("zig_atomic("); | |
| 6986 | try f.renderType(w, ty); | |
| 6987 | if (use_atomic) try w.writeByte(')'); | |
| 6988 | if (ptr_ty.isVolatilePtr(zcu)) try w.writeAll(" volatile"); | |
| 6989 | try w.writeAll(" *)"); | |
| 6990 | try f.writeCValue(w, ptr, .Other); | |
| 6991 | try w.writeAll(", "); | |
| 6992 | try operand_mat.mat(f, w); | |
| 6993 | try w.writeAll(", "); | |
| 6994 | try writeMemoryOrder(w, extra.ordering()); | |
| 6995 | try w.writeAll(", "); | |
| 6996 | try f.object.dg.renderTypeForBuiltinFnName(w, ty); | |
| 6997 | try w.writeAll(", "); | |
| 6998 | try f.renderType(w, repr_ty); | |
| 6999 | try w.writeAll(");"); | |
| 7000 | try f.object.newline(); | |
| 6894 | 7001 | try operand_mat.end(f, inst); |
| 6895 | 7002 | |
| 6896 | 7003 | if (f.liveness.isUnused(inst)) { |
| ... | ... | @@ -6916,24 +7023,25 @@ fn airAtomicLoad(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6916 | 7023 | ty; |
| 6917 | 7024 | |
| 6918 | 7025 | const inst_ty = f.typeOfIndex(inst); |
| 6919 | const writer = f.object.writer(); | |
| 7026 | const w = &f.object.code.writer; | |
| 6920 | 7027 | const local = try f.allocLocal(inst, inst_ty); |
| 6921 | 7028 | |
| 6922 | try writer.writeAll("zig_atomic_load("); | |
| 6923 | try f.writeCValue(writer, local, .Other); | |
| 6924 | try writer.writeAll(", (zig_atomic("); | |
| 6925 | try f.renderType(writer, ty); | |
| 6926 | try writer.writeByte(')'); | |
| 6927 | if (ptr_ty.isVolatilePtr(zcu)) try writer.writeAll(" volatile"); | |
| 6928 | try writer.writeAll(" *)"); | |
| 6929 | try f.writeCValue(writer, ptr, .Other); | |
| 6930 | try writer.writeAll(", "); | |
| 6931 | try writeMemoryOrder(writer, atomic_load.order); | |
| 6932 | try writer.writeAll(", "); | |
| 6933 | try f.object.dg.renderTypeForBuiltinFnName(writer, ty); | |
| 6934 | try writer.writeAll(", "); | |
| 6935 | try f.renderType(writer, repr_ty); | |
| 6936 | try writer.writeAll(");\n"); | |
| 7029 | try w.writeAll("zig_atomic_load("); | |
| 7030 | try f.writeCValue(w, local, .Other); | |
| 7031 | try w.writeAll(", (zig_atomic("); | |
| 7032 | try f.renderType(w, ty); | |
| 7033 | try w.writeByte(')'); | |
| 7034 | if (ptr_ty.isVolatilePtr(zcu)) try w.writeAll(" volatile"); | |
| 7035 | try w.writeAll(" *)"); | |
| 7036 | try f.writeCValue(w, ptr, .Other); | |
| 7037 | try w.writeAll(", "); | |
| 7038 | try writeMemoryOrder(w, atomic_load.order); | |
| 7039 | try w.writeAll(", "); | |
| 7040 | try f.object.dg.renderTypeForBuiltinFnName(w, ty); | |
| 7041 | try w.writeAll(", "); | |
| 7042 | try f.renderType(w, repr_ty); | |
| 7043 | try w.writeAll(");"); | |
| 7044 | try f.object.newline(); | |
| 6937 | 7045 | |
| 6938 | 7046 | return local; |
| 6939 | 7047 | } |
| ... | ... | @@ -6947,7 +7055,7 @@ fn airAtomicStore(f: *Function, inst: Air.Inst.Index, order: [*:0]const u8) !CVa |
| 6947 | 7055 | const ptr = try f.resolveInst(bin_op.lhs); |
| 6948 | 7056 | const element = try f.resolveInst(bin_op.rhs); |
| 6949 | 7057 | |
| 6950 | const writer = f.object.writer(); | |
| 7058 | const w = &f.object.code.writer; | |
| 6951 | 7059 | const element_mat = try Materialize.start(f, inst, ty, element); |
| 6952 | 7060 | try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); |
| 6953 | 7061 | |
| ... | ... | @@ -6956,31 +7064,32 @@ fn airAtomicStore(f: *Function, inst: Air.Inst.Index, order: [*:0]const u8) !CVa |
| 6956 | 7064 | else |
| 6957 | 7065 | ty; |
| 6958 | 7066 | |
| 6959 | try writer.writeAll("zig_atomic_store((zig_atomic("); | |
| 6960 | try f.renderType(writer, ty); | |
| 6961 | try writer.writeByte(')'); | |
| 6962 | if (ptr_ty.isVolatilePtr(zcu)) try writer.writeAll(" volatile"); | |
| 6963 | try writer.writeAll(" *)"); | |
| 6964 | try f.writeCValue(writer, ptr, .Other); | |
| 6965 | try writer.writeAll(", "); | |
| 6966 | try element_mat.mat(f, writer); | |
| 6967 | try writer.print(", {s}, ", .{order}); | |
| 6968 | try f.object.dg.renderTypeForBuiltinFnName(writer, ty); | |
| 6969 | try writer.writeAll(", "); | |
| 6970 | try f.renderType(writer, repr_ty); | |
| 6971 | try writer.writeAll(");\n"); | |
| 7067 | try w.writeAll("zig_atomic_store((zig_atomic("); | |
| 7068 | try f.renderType(w, ty); | |
| 7069 | try w.writeByte(')'); | |
| 7070 | if (ptr_ty.isVolatilePtr(zcu)) try w.writeAll(" volatile"); | |
| 7071 | try w.writeAll(" *)"); | |
| 7072 | try f.writeCValue(w, ptr, .Other); | |
| 7073 | try w.writeAll(", "); | |
| 7074 | try element_mat.mat(f, w); | |
| 7075 | try w.print(", {s}, ", .{order}); | |
| 7076 | try f.object.dg.renderTypeForBuiltinFnName(w, ty); | |
| 7077 | try w.writeAll(", "); | |
| 7078 | try f.renderType(w, repr_ty); | |
| 7079 | try w.writeAll(");"); | |
| 7080 | try f.object.newline(); | |
| 6972 | 7081 | try element_mat.end(f, inst); |
| 6973 | 7082 | |
| 6974 | 7083 | return .none; |
| 6975 | 7084 | } |
| 6976 | 7085 | |
| 6977 | fn writeSliceOrPtr(f: *Function, writer: anytype, ptr: CValue, ptr_ty: Type) !void { | |
| 7086 | fn writeSliceOrPtr(f: *Function, w: *Writer, ptr: CValue, ptr_ty: Type) !void { | |
| 6978 | 7087 | const pt = f.object.dg.pt; |
| 6979 | 7088 | const zcu = pt.zcu; |
| 6980 | 7089 | if (ptr_ty.isSlice(zcu)) { |
| 6981 | try f.writeCValueMember(writer, ptr, .{ .identifier = "ptr" }); | |
| 7090 | try f.writeCValueMember(w, ptr, .{ .identifier = "ptr" }); | |
| 6982 | 7091 | } else { |
| 6983 | try f.writeCValue(writer, ptr, .FunctionArgument); | |
| 7092 | try f.writeCValue(w, ptr, .FunctionArgument); | |
| 6984 | 7093 | } |
| 6985 | 7094 | } |
| 6986 | 7095 | |
| ... | ... | @@ -6994,7 +7103,7 @@ fn airMemset(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue { |
| 6994 | 7103 | const elem_ty = f.typeOf(bin_op.rhs); |
| 6995 | 7104 | const elem_abi_size = elem_ty.abiSize(zcu); |
| 6996 | 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; | |
| 6998 | 7107 | |
| 6999 | 7108 | if (val_is_undef) { |
| 7000 | 7109 | if (!safety) { |
| ... | ... | @@ -7002,24 +7111,25 @@ fn airMemset(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue { |
| 7002 | 7111 | return .none; |
| 7003 | 7112 | } |
| 7004 | 7113 | |
| 7005 | try writer.writeAll("memset("); | |
| 7114 | try w.writeAll("memset("); | |
| 7006 | 7115 | switch (dest_ty.ptrSize(zcu)) { |
| 7007 | 7116 | .slice => { |
| 7008 | try f.writeCValueMember(writer, dest_slice, .{ .identifier = "ptr" }); | |
| 7009 | try writer.writeAll(", 0xaa, "); | |
| 7010 | try f.writeCValueMember(writer, dest_slice, .{ .identifier = "len" }); | |
| 7117 | try f.writeCValueMember(w, dest_slice, .{ .identifier = "ptr" }); | |
| 7118 | try w.writeAll(", 0xaa, "); | |
| 7119 | try f.writeCValueMember(w, dest_slice, .{ .identifier = "len" }); | |
| 7011 | 7120 | if (elem_abi_size > 1) { |
| 7012 | try writer.print(" * {d});\n", .{elem_abi_size}); | |
| 7013 | } else { | |
| 7014 | try writer.writeAll(");\n"); | |
| 7121 | try w.print(" * {d}", .{elem_abi_size}); | |
| 7015 | 7122 | } |
| 7123 | try w.writeAll(");"); | |
| 7124 | try f.object.newline(); | |
| 7016 | 7125 | }, |
| 7017 | 7126 | .one => { |
| 7018 | 7127 | const array_ty = dest_ty.childType(zcu); |
| 7019 | 7128 | const len = array_ty.arrayLen(zcu) * elem_abi_size; |
| 7020 | 7129 | |
| 7021 | try f.writeCValue(writer, dest_slice, .FunctionArgument); | |
| 7022 | try writer.print(", 0xaa, {d});\n", .{len}); | |
| 7130 | try f.writeCValue(w, dest_slice, .FunctionArgument); | |
| 7131 | try w.print(", 0xaa, {d});", .{len}); | |
| 7132 | try f.object.newline(); | |
| 7023 | 7133 | }, |
| 7024 | 7134 | .many, .c => unreachable, |
| 7025 | 7135 | } |
| ... | ... | @@ -7040,38 +7150,38 @@ fn airMemset(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue { |
| 7040 | 7150 | |
| 7041 | 7151 | const index = try f.allocLocal(inst, .usize); |
| 7042 | 7152 | |
| 7043 | try writer.writeAll("for ("); | |
| 7044 | try f.writeCValue(writer, index, .Other); | |
| 7045 | try writer.writeAll(" = "); | |
| 7046 | try f.object.dg.renderValue(writer, .zero_usize, .Other); | |
| 7047 | try writer.writeAll("; "); | |
| 7048 | try f.writeCValue(writer, index, .Other); | |
| 7049 | try writer.writeAll(" != "); | |
| 7153 | try w.writeAll("for ("); | |
| 7154 | try f.writeCValue(w, index, .Other); | |
| 7155 | try w.writeAll(" = "); | |
| 7156 | try f.object.dg.renderValue(w, .zero_usize, .Other); | |
| 7157 | try w.writeAll("; "); | |
| 7158 | try f.writeCValue(w, index, .Other); | |
| 7159 | try w.writeAll(" != "); | |
| 7050 | 7160 | switch (dest_ty.ptrSize(zcu)) { |
| 7051 | 7161 | .slice => { |
| 7052 | try f.writeCValueMember(writer, dest_slice, .{ .identifier = "len" }); | |
| 7162 | try f.writeCValueMember(w, dest_slice, .{ .identifier = "len" }); | |
| 7053 | 7163 | }, |
| 7054 | 7164 | .one => { |
| 7055 | 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 | 7168 | .many, .c => unreachable, |
| 7059 | 7169 | } |
| 7060 | try writer.writeAll("; ++"); | |
| 7061 | try f.writeCValue(writer, index, .Other); | |
| 7062 | try writer.writeAll(") "); | |
| 7063 | ||
| 7064 | const a = try Assignment.start(f, writer, try f.ctypeFromType(elem_ty, .complete)); | |
| 7065 | try writer.writeAll("(("); | |
| 7066 | try f.renderType(writer, elem_ptr_ty); | |
| 7067 | try writer.writeByte(')'); | |
| 7068 | try writeSliceOrPtr(f, writer, dest_slice, dest_ty); | |
| 7069 | try writer.writeAll(")["); | |
| 7070 | try f.writeCValue(writer, index, .Other); | |
| 7071 | try writer.writeByte(']'); | |
| 7072 | try a.assign(f, writer); | |
| 7073 | try f.writeCValue(writer, value, .Other); | |
| 7074 | try a.end(f, writer); | |
| 7170 | try w.writeAll("; ++"); | |
| 7171 | try f.writeCValue(w, index, .Other); | |
| 7172 | try w.writeAll(") "); | |
| 7173 | ||
| 7174 | const a = try Assignment.start(f, w, try f.ctypeFromType(elem_ty, .complete)); | |
| 7175 | try w.writeAll("(("); | |
| 7176 | try f.renderType(w, elem_ptr_ty); | |
| 7177 | try w.writeByte(')'); | |
| 7178 | try writeSliceOrPtr(f, w, dest_slice, dest_ty); | |
| 7179 | try w.writeAll(")["); | |
| 7180 | try f.writeCValue(w, index, .Other); | |
| 7181 | try w.writeByte(']'); | |
| 7182 | try a.assign(f, w); | |
| 7183 | try f.writeCValue(w, value, .Other); | |
| 7184 | try a.end(f, w); | |
| 7075 | 7185 | |
| 7076 | 7186 | try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); |
| 7077 | 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 | 7191 | |
| 7082 | 7192 | const bitcasted = try bitcast(f, .u8, value, elem_ty); |
| 7083 | 7193 | |
| 7084 | try writer.writeAll("memset("); | |
| 7194 | try w.writeAll("memset("); | |
| 7085 | 7195 | switch (dest_ty.ptrSize(zcu)) { |
| 7086 | 7196 | .slice => { |
| 7087 | try f.writeCValueMember(writer, dest_slice, .{ .identifier = "ptr" }); | |
| 7088 | try writer.writeAll(", "); | |
| 7089 | try f.writeCValue(writer, bitcasted, .FunctionArgument); | |
| 7090 | try writer.writeAll(", "); | |
| 7091 | try f.writeCValueMember(writer, dest_slice, .{ .identifier = "len" }); | |
| 7092 | try writer.writeAll(");\n"); | |
| 7197 | try f.writeCValueMember(w, dest_slice, .{ .identifier = "ptr" }); | |
| 7198 | try w.writeAll(", "); | |
| 7199 | try f.writeCValue(w, bitcasted, .FunctionArgument); | |
| 7200 | try w.writeAll(", "); | |
| 7201 | try f.writeCValueMember(w, dest_slice, .{ .identifier = "len" }); | |
| 7202 | try w.writeAll(");"); | |
| 7203 | try f.object.newline(); | |
| 7093 | 7204 | }, |
| 7094 | 7205 | .one => { |
| 7095 | 7206 | const array_ty = dest_ty.childType(zcu); |
| 7096 | 7207 | const len = array_ty.arrayLen(zcu) * elem_abi_size; |
| 7097 | 7208 | |
| 7098 | try f.writeCValue(writer, dest_slice, .FunctionArgument); | |
| 7099 | try writer.writeAll(", "); | |
| 7100 | try f.writeCValue(writer, bitcasted, .FunctionArgument); | |
| 7101 | try writer.print(", {d});\n", .{len}); | |
| 7209 | try f.writeCValue(w, dest_slice, .FunctionArgument); | |
| 7210 | try w.writeAll(", "); | |
| 7211 | try f.writeCValue(w, bitcasted, .FunctionArgument); | |
| 7212 | try w.print(", {d});", .{len}); | |
| 7213 | try f.object.newline(); | |
| 7102 | 7214 | }, |
| 7103 | 7215 | .many, .c => unreachable, |
| 7104 | 7216 | } |
| ... | ... | @@ -7115,36 +7227,38 @@ fn airMemcpy(f: *Function, inst: Air.Inst.Index, function_paren: []const u8) !CV |
| 7115 | 7227 | const src_ptr = try f.resolveInst(bin_op.rhs); |
| 7116 | 7228 | const dest_ty = f.typeOf(bin_op.lhs); |
| 7117 | 7229 | const src_ty = f.typeOf(bin_op.rhs); |
| 7118 | const writer = f.object.writer(); | |
| 7230 | const w = &f.object.code.writer; | |
| 7119 | 7231 | |
| 7120 | 7232 | if (dest_ty.ptrSize(zcu) != .one) { |
| 7121 | try writer.writeAll("if ("); | |
| 7122 | try writeArrayLen(f, writer, dest_ptr, dest_ty); | |
| 7123 | try writer.writeAll(" != 0) "); | |
| 7124 | } | |
| 7125 | try writer.writeAll(function_paren); | |
| 7126 | try writeSliceOrPtr(f, writer, dest_ptr, dest_ty); | |
| 7127 | try writer.writeAll(", "); | |
| 7128 | try writeSliceOrPtr(f, writer, src_ptr, src_ty); | |
| 7129 | try writer.writeAll(", "); | |
| 7130 | try writeArrayLen(f, writer, dest_ptr, dest_ty); | |
| 7131 | try writer.writeAll(" * sizeof("); | |
| 7132 | try f.renderType(writer, dest_ty.elemType2(zcu)); | |
| 7133 | try writer.writeAll("));\n"); | |
| 7233 | try w.writeAll("if ("); | |
| 7234 | try writeArrayLen(f, dest_ptr, dest_ty); | |
| 7235 | try w.writeAll(" != 0) "); | |
| 7236 | } | |
| 7237 | try w.writeAll(function_paren); | |
| 7238 | try writeSliceOrPtr(f, w, dest_ptr, dest_ty); | |
| 7239 | try w.writeAll(", "); | |
| 7240 | try writeSliceOrPtr(f, w, src_ptr, src_ty); | |
| 7241 | try w.writeAll(", "); | |
| 7242 | try writeArrayLen(f, dest_ptr, dest_ty); | |
| 7243 | try w.writeAll(" * sizeof("); | |
| 7244 | try f.renderType(w, dest_ty.elemType2(zcu)); | |
| 7245 | try w.writeAll("));"); | |
| 7246 | try f.object.newline(); | |
| 7134 | 7247 | |
| 7135 | 7248 | try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); |
| 7136 | 7249 | return .none; |
| 7137 | 7250 | } |
| 7138 | 7251 | |
| 7139 | fn writeArrayLen(f: *Function, writer: ArrayListWriter, dest_ptr: CValue, dest_ty: Type) !void { | |
| 7252 | fn writeArrayLen(f: *Function, dest_ptr: CValue, dest_ty: Type) !void { | |
| 7140 | 7253 | const pt = f.object.dg.pt; |
| 7141 | 7254 | const zcu = pt.zcu; |
| 7255 | const w = &f.object.code.writer; | |
| 7142 | 7256 | switch (dest_ty.ptrSize(zcu)) { |
| 7143 | .one => try writer.print("{}", .{ | |
| 7144 | try f.fmtIntLiteral(try pt.intValue(.usize, dest_ty.childType(zcu).arrayLen(zcu))), | |
| 7257 | .one => try w.print("{f}", .{ | |
| 7258 | try f.fmtIntLiteralDec(try pt.intValue(.usize, dest_ty.childType(zcu).arrayLen(zcu))), | |
| 7145 | 7259 | }), |
| 7146 | 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 | } |
| 7150 | 7264 | |
| ... | ... | @@ -7161,12 +7275,12 @@ fn airSetUnionTag(f: *Function, inst: Air.Inst.Index) !CValue { |
| 7161 | 7275 | if (layout.tag_size == 0) return .none; |
| 7162 | 7276 | const tag_ty = union_ty.unionTagTypeSafety(zcu).?; |
| 7163 | 7277 | |
| 7164 | const writer = f.object.writer(); | |
| 7165 | const a = try Assignment.start(f, writer, try f.ctypeFromType(tag_ty, .complete)); | |
| 7166 | try f.writeCValueDerefMember(writer, union_ptr, .{ .identifier = "tag" }); | |
| 7167 | try a.assign(f, writer); | |
| 7168 | try f.writeCValue(writer, new_tag, .Other); | |
| 7169 | try a.end(f, writer); | |
| 7278 | const w = &f.object.code.writer; | |
| 7279 | const a = try Assignment.start(f, w, try f.ctypeFromType(tag_ty, .complete)); | |
| 7280 | try f.writeCValueDerefMember(w, union_ptr, .{ .identifier = "tag" }); | |
| 7281 | try a.assign(f, w); | |
| 7282 | try f.writeCValue(w, new_tag, .Other); | |
| 7283 | try a.end(f, w); | |
| 7170 | 7284 | return .none; |
| 7171 | 7285 | } |
| 7172 | 7286 | |
| ... | ... | @@ -7183,13 +7297,13 @@ fn airGetUnionTag(f: *Function, inst: Air.Inst.Index) !CValue { |
| 7183 | 7297 | if (layout.tag_size == 0) return .none; |
| 7184 | 7298 | |
| 7185 | 7299 | const inst_ty = f.typeOfIndex(inst); |
| 7186 | const writer = f.object.writer(); | |
| 7300 | const w = &f.object.code.writer; | |
| 7187 | 7301 | const local = try f.allocLocal(inst, inst_ty); |
| 7188 | const a = try Assignment.start(f, writer, try f.ctypeFromType(inst_ty, .complete)); | |
| 7189 | try f.writeCValue(writer, local, .Other); | |
| 7190 | try a.assign(f, writer); | |
| 7191 | try f.writeCValueMember(writer, operand, .{ .identifier = "tag" }); | |
| 7192 | try a.end(f, writer); | |
| 7302 | const a = try Assignment.start(f, w, try f.ctypeFromType(inst_ty, .complete)); | |
| 7303 | try f.writeCValue(w, local, .Other); | |
| 7304 | try a.assign(f, w); | |
| 7305 | try f.writeCValueMember(w, operand, .{ .identifier = "tag" }); | |
| 7306 | try a.end(f, w); | |
| 7193 | 7307 | return local; |
| 7194 | 7308 | } |
| 7195 | 7309 | |
| ... | ... | @@ -7201,14 +7315,15 @@ fn airTagName(f: *Function, inst: Air.Inst.Index) !CValue { |
| 7201 | 7315 | const operand = try f.resolveInst(un_op); |
| 7202 | 7316 | try reap(f, inst, &.{un_op}); |
| 7203 | 7317 | |
| 7204 | const writer = f.object.writer(); | |
| 7318 | const w = &f.object.code.writer; | |
| 7205 | 7319 | const local = try f.allocLocal(inst, inst_ty); |
| 7206 | try f.writeCValue(writer, local, .Other); | |
| 7207 | try writer.print(" = {s}(", .{ | |
| 7320 | try f.writeCValue(w, local, .Other); | |
| 7321 | try w.print(" = {s}(", .{ | |
| 7208 | 7322 | try f.getLazyFnName(.{ .tag_name = enum_ty.toIntern() }), |
| 7209 | 7323 | }); |
| 7210 | try f.writeCValue(writer, operand, .Other); | |
| 7211 | try writer.writeAll(");\n"); | |
| 7324 | try f.writeCValue(w, operand, .Other); | |
| 7325 | try w.writeAll(");"); | |
| 7326 | try f.object.newline(); | |
| 7212 | 7327 | |
| 7213 | 7328 | return local; |
| 7214 | 7329 | } |
| ... | ... | @@ -7216,16 +7331,17 @@ fn airTagName(f: *Function, inst: Air.Inst.Index) !CValue { |
| 7216 | 7331 | fn airErrorName(f: *Function, inst: Air.Inst.Index) !CValue { |
| 7217 | 7332 | const un_op = f.air.instructions.items(.data)[@intFromEnum(inst)].un_op; |
| 7218 | 7333 | |
| 7219 | const writer = f.object.writer(); | |
| 7334 | const w = &f.object.code.writer; | |
| 7220 | 7335 | const inst_ty = f.typeOfIndex(inst); |
| 7221 | 7336 | const operand = try f.resolveInst(un_op); |
| 7222 | 7337 | try reap(f, inst, &.{un_op}); |
| 7223 | 7338 | const local = try f.allocLocal(inst, inst_ty); |
| 7224 | try f.writeCValue(writer, local, .Other); | |
| 7339 | try f.writeCValue(w, local, .Other); | |
| 7225 | 7340 | |
| 7226 | try writer.writeAll(" = zig_errorName["); | |
| 7227 | try f.writeCValue(writer, operand, .Other); | |
| 7228 | try writer.writeAll(" - 1];\n"); | |
| 7341 | try w.writeAll(" = zig_errorName["); | |
| 7342 | try f.writeCValue(w, operand, .Other); | |
| 7343 | try w.writeAll(" - 1];"); | |
| 7344 | try f.object.newline(); | |
| 7229 | 7345 | return local; |
| 7230 | 7346 | } |
| 7231 | 7347 | |
| ... | ... | @@ -7240,16 +7356,16 @@ fn airSplat(f: *Function, inst: Air.Inst.Index) !CValue { |
| 7240 | 7356 | const inst_ty = f.typeOfIndex(inst); |
| 7241 | 7357 | const inst_scalar_ty = inst_ty.scalarType(zcu); |
| 7242 | 7358 | |
| 7243 | const writer = f.object.writer(); | |
| 7359 | const w = &f.object.code.writer; | |
| 7244 | 7360 | const local = try f.allocLocal(inst, inst_ty); |
| 7245 | const v = try Vectorize.start(f, inst, writer, inst_ty); | |
| 7246 | const a = try Assignment.start(f, writer, try f.ctypeFromType(inst_scalar_ty, .complete)); | |
| 7247 | try f.writeCValue(writer, local, .Other); | |
| 7248 | try v.elem(f, writer); | |
| 7249 | try a.assign(f, writer); | |
| 7250 | try f.writeCValue(writer, operand, .Other); | |
| 7251 | try a.end(f, writer); | |
| 7252 | try v.end(f, inst, writer); | |
| 7361 | const v = try Vectorize.start(f, inst, w, inst_ty); | |
| 7362 | const a = try Assignment.start(f, w, try f.ctypeFromType(inst_scalar_ty, .complete)); | |
| 7363 | try f.writeCValue(w, local, .Other); | |
| 7364 | try v.elem(f, w); | |
| 7365 | try a.assign(f, w); | |
| 7366 | try f.writeCValue(w, operand, .Other); | |
| 7367 | try a.end(f, w); | |
| 7368 | try v.end(f, inst, w); | |
| 7253 | 7369 | |
| 7254 | 7370 | return local; |
| 7255 | 7371 | } |
| ... | ... | @@ -7265,22 +7381,23 @@ fn airSelect(f: *Function, inst: Air.Inst.Index) !CValue { |
| 7265 | 7381 | |
| 7266 | 7382 | const inst_ty = f.typeOfIndex(inst); |
| 7267 | 7383 | |
| 7268 | const writer = f.object.writer(); | |
| 7384 | const w = &f.object.code.writer; | |
| 7269 | 7385 | const local = try f.allocLocal(inst, inst_ty); |
| 7270 | const v = try Vectorize.start(f, inst, writer, inst_ty); | |
| 7271 | try f.writeCValue(writer, local, .Other); | |
| 7272 | try v.elem(f, writer); | |
| 7273 | try writer.writeAll(" = "); | |
| 7274 | try f.writeCValue(writer, pred, .Other); | |
| 7275 | try v.elem(f, writer); | |
| 7276 | try writer.writeAll(" ? "); | |
| 7277 | try f.writeCValue(writer, lhs, .Other); | |
| 7278 | try v.elem(f, writer); | |
| 7279 | try writer.writeAll(" : "); | |
| 7280 | try f.writeCValue(writer, rhs, .Other); | |
| 7281 | try v.elem(f, writer); | |
| 7282 | try writer.writeAll(";\n"); | |
| 7283 | try v.end(f, inst, writer); | |
| 7386 | const v = try Vectorize.start(f, inst, w, inst_ty); | |
| 7387 | try f.writeCValue(w, local, .Other); | |
| 7388 | try v.elem(f, w); | |
| 7389 | try w.writeAll(" = "); | |
| 7390 | try f.writeCValue(w, pred, .Other); | |
| 7391 | try v.elem(f, w); | |
| 7392 | try w.writeAll(" ? "); | |
| 7393 | try f.writeCValue(w, lhs, .Other); | |
| 7394 | try v.elem(f, w); | |
| 7395 | try w.writeAll(" : "); | |
| 7396 | try f.writeCValue(w, rhs, .Other); | |
| 7397 | try v.elem(f, w); | |
| 7398 | try w.writeByte(';'); | |
| 7399 | try f.object.newline(); | |
| 7400 | try v.end(f, inst, w); | |
| 7284 | 7401 | |
| 7285 | 7402 | return local; |
| 7286 | 7403 | } |
| ... | ... | @@ -7294,24 +7411,24 @@ fn airShuffleOne(f: *Function, inst: Air.Inst.Index) !CValue { |
| 7294 | 7411 | const operand = try f.resolveInst(unwrapped.operand); |
| 7295 | 7412 | const inst_ty = unwrapped.result_ty; |
| 7296 | 7413 | |
| 7297 | const writer = f.object.writer(); | |
| 7414 | const w = &f.object.code.writer; | |
| 7298 | 7415 | const local = try f.allocLocal(inst, inst_ty); |
| 7299 | 7416 | try reap(f, inst, &.{unwrapped.operand}); // local cannot alias operand |
| 7300 | 7417 | for (mask, 0..) |mask_elem, out_idx| { |
| 7301 | try f.writeCValue(writer, local, .Other); | |
| 7302 | try writer.writeByte('['); | |
| 7303 | try f.object.dg.renderValue(writer, try pt.intValue(.usize, out_idx), .Other); | |
| 7304 | try writer.writeAll("] = "); | |
| 7418 | try f.writeCValue(w, local, .Other); | |
| 7419 | try w.writeByte('['); | |
| 7420 | try f.object.dg.renderValue(w, try pt.intValue(.usize, out_idx), .Other); | |
| 7421 | try w.writeAll("] = "); | |
| 7305 | 7422 | switch (mask_elem.unwrap()) { |
| 7306 | 7423 | .elem => |src_idx| { |
| 7307 | try f.writeCValue(writer, operand, .Other); | |
| 7308 | try writer.writeByte('['); | |
| 7309 | try f.object.dg.renderValue(writer, try pt.intValue(.usize, src_idx), .Other); | |
| 7310 | try writer.writeByte(']'); | |
| 7424 | try f.writeCValue(w, operand, .Other); | |
| 7425 | try w.writeByte('['); | |
| 7426 | try f.object.dg.renderValue(w, try pt.intValue(.usize, src_idx), .Other); | |
| 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 | } |
| 7316 | 7433 | |
| 7317 | 7434 | return local; |
| ... | ... | @@ -7328,30 +7445,31 @@ fn airShuffleTwo(f: *Function, inst: Air.Inst.Index) !CValue { |
| 7328 | 7445 | const inst_ty = unwrapped.result_ty; |
| 7329 | 7446 | const elem_ty = inst_ty.childType(zcu); |
| 7330 | 7447 | |
| 7331 | const writer = f.object.writer(); | |
| 7448 | const w = &f.object.code.writer; | |
| 7332 | 7449 | const local = try f.allocLocal(inst, inst_ty); |
| 7333 | 7450 | try reap(f, inst, &.{ unwrapped.operand_a, unwrapped.operand_b }); // local cannot alias operands |
| 7334 | 7451 | for (mask, 0..) |mask_elem, out_idx| { |
| 7335 | try f.writeCValue(writer, local, .Other); | |
| 7336 | try writer.writeByte('['); | |
| 7337 | try f.object.dg.renderValue(writer, try pt.intValue(.usize, out_idx), .Other); | |
| 7338 | try writer.writeAll("] = "); | |
| 7452 | try f.writeCValue(w, local, .Other); | |
| 7453 | try w.writeByte('['); | |
| 7454 | try f.object.dg.renderValue(w, try pt.intValue(.usize, out_idx), .Other); | |
| 7455 | try w.writeAll("] = "); | |
| 7339 | 7456 | switch (mask_elem.unwrap()) { |
| 7340 | 7457 | .a_elem => |src_idx| { |
| 7341 | try f.writeCValue(writer, operand_a, .Other); | |
| 7342 | try writer.writeByte('['); | |
| 7343 | try f.object.dg.renderValue(writer, try pt.intValue(.usize, src_idx), .Other); | |
| 7344 | try writer.writeByte(']'); | |
| 7458 | try f.writeCValue(w, operand_a, .Other); | |
| 7459 | try w.writeByte('['); | |
| 7460 | try f.object.dg.renderValue(w, try pt.intValue(.usize, src_idx), .Other); | |
| 7461 | try w.writeByte(']'); | |
| 7345 | 7462 | }, |
| 7346 | 7463 | .b_elem => |src_idx| { |
| 7347 | try f.writeCValue(writer, operand_b, .Other); | |
| 7348 | try writer.writeByte('['); | |
| 7349 | try f.object.dg.renderValue(writer, try pt.intValue(.usize, src_idx), .Other); | |
| 7350 | try writer.writeByte(']'); | |
| 7464 | try f.writeCValue(w, operand_b, .Other); | |
| 7465 | try w.writeByte('['); | |
| 7466 | try f.object.dg.renderValue(w, try pt.intValue(.usize, src_idx), .Other); | |
| 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 | } |
| 7356 | 7474 | |
| 7357 | 7475 | return local; |
| ... | ... | @@ -7366,7 +7484,7 @@ fn airReduce(f: *Function, inst: Air.Inst.Index) !CValue { |
| 7366 | 7484 | const operand = try f.resolveInst(reduce.operand); |
| 7367 | 7485 | try reap(f, inst, &.{reduce.operand}); |
| 7368 | 7486 | const operand_ty = f.typeOf(reduce.operand); |
| 7369 | const writer = f.object.writer(); | |
| 7487 | const w = &f.object.code.writer; | |
| 7370 | 7488 | |
| 7371 | 7489 | const use_operator = scalar_ty.bitSize(zcu) <= 64; |
| 7372 | 7490 | const op: union(enum) { |
| ... | ... | @@ -7413,10 +7531,10 @@ fn airReduce(f: *Function, inst: Air.Inst.Index) !CValue { |
| 7413 | 7531 | // } |
| 7414 | 7532 | |
| 7415 | 7533 | const accum = try f.allocLocal(inst, scalar_ty); |
| 7416 | try f.writeCValue(writer, accum, .Other); | |
| 7417 | try writer.writeAll(" = "); | |
| 7534 | try f.writeCValue(w, accum, .Other); | |
| 7535 | try w.writeAll(" = "); | |
| 7418 | 7536 | |
| 7419 | try f.object.dg.renderValue(writer, switch (reduce.operation) { | |
| 7537 | try f.object.dg.renderValue(w, switch (reduce.operation) { | |
| 7420 | 7538 | .Or, .Xor => switch (scalar_ty.zigTypeTag(zcu)) { |
| 7421 | 7539 | .bool => Value.false, |
| 7422 | 7540 | .int => try pt.intValue(scalar_ty, 0), |
| ... | ... | @@ -7453,42 +7571,44 @@ fn airReduce(f: *Function, inst: Air.Inst.Index) !CValue { |
| 7453 | 7571 | else => unreachable, |
| 7454 | 7572 | }, |
| 7455 | 7573 | }, .Other); |
| 7456 | try writer.writeAll(";\n"); | |
| 7574 | try w.writeByte(';'); | |
| 7575 | try f.object.newline(); | |
| 7457 | 7576 | |
| 7458 | const v = try Vectorize.start(f, inst, writer, operand_ty); | |
| 7459 | try f.writeCValue(writer, accum, .Other); | |
| 7577 | const v = try Vectorize.start(f, inst, w, operand_ty); | |
| 7578 | try f.writeCValue(w, accum, .Other); | |
| 7460 | 7579 | switch (op) { |
| 7461 | 7580 | .builtin => |func| { |
| 7462 | try writer.print(" = zig_{s}_", .{func.operation}); | |
| 7463 | try f.object.dg.renderTypeForBuiltinFnName(writer, scalar_ty); | |
| 7464 | try writer.writeByte('('); | |
| 7465 | try f.writeCValue(writer, accum, .FunctionArgument); | |
| 7466 | try writer.writeAll(", "); | |
| 7467 | try f.writeCValue(writer, operand, .Other); | |
| 7468 | try v.elem(f, writer); | |
| 7469 | try f.object.dg.renderBuiltinInfo(writer, scalar_ty, func.info); | |
| 7470 | try writer.writeByte(')'); | |
| 7581 | try w.print(" = zig_{s}_", .{func.operation}); | |
| 7582 | try f.object.dg.renderTypeForBuiltinFnName(w, scalar_ty); | |
| 7583 | try w.writeByte('('); | |
| 7584 | try f.writeCValue(w, accum, .FunctionArgument); | |
| 7585 | try w.writeAll(", "); | |
| 7586 | try f.writeCValue(w, operand, .Other); | |
| 7587 | try v.elem(f, w); | |
| 7588 | try f.object.dg.renderBuiltinInfo(w, scalar_ty, func.info); | |
| 7589 | try w.writeByte(')'); | |
| 7471 | 7590 | }, |
| 7472 | 7591 | .infix => |ass| { |
| 7473 | try writer.writeAll(ass); | |
| 7474 | try f.writeCValue(writer, operand, .Other); | |
| 7475 | try v.elem(f, writer); | |
| 7592 | try w.writeAll(ass); | |
| 7593 | try f.writeCValue(w, operand, .Other); | |
| 7594 | try v.elem(f, w); | |
| 7476 | 7595 | }, |
| 7477 | 7596 | .ternary => |cmp| { |
| 7478 | try writer.writeAll(" = "); | |
| 7479 | try f.writeCValue(writer, accum, .Other); | |
| 7480 | try writer.writeAll(cmp); | |
| 7481 | try f.writeCValue(writer, operand, .Other); | |
| 7482 | try v.elem(f, writer); | |
| 7483 | try writer.writeAll(" ? "); | |
| 7484 | try f.writeCValue(writer, accum, .Other); | |
| 7485 | try writer.writeAll(" : "); | |
| 7486 | try f.writeCValue(writer, operand, .Other); | |
| 7487 | try v.elem(f, writer); | |
| 7597 | try w.writeAll(" = "); | |
| 7598 | try f.writeCValue(w, accum, .Other); | |
| 7599 | try w.writeAll(cmp); | |
| 7600 | try f.writeCValue(w, operand, .Other); | |
| 7601 | try v.elem(f, w); | |
| 7602 | try w.writeAll(" ? "); | |
| 7603 | try f.writeCValue(w, accum, .Other); | |
| 7604 | try w.writeAll(" : "); | |
| 7605 | try f.writeCValue(w, operand, .Other); | |
| 7606 | try v.elem(f, w); | |
| 7488 | 7607 | }, |
| 7489 | 7608 | } |
| 7490 | try writer.writeAll(";\n"); | |
| 7491 | try v.end(f, inst, writer); | |
| 7609 | try w.writeByte(';'); | |
| 7610 | try f.object.newline(); | |
| 7611 | try v.end(f, inst, w); | |
| 7492 | 7612 | |
| 7493 | 7613 | return accum; |
| 7494 | 7614 | } |
| ... | ... | @@ -7514,7 +7634,7 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue { |
| 7514 | 7634 | } |
| 7515 | 7635 | } |
| 7516 | 7636 | |
| 7517 | const writer = f.object.writer(); | |
| 7637 | const w = &f.object.code.writer; | |
| 7518 | 7638 | const local = try f.allocLocal(inst, inst_ty); |
| 7519 | 7639 | switch (ip.indexToKey(inst_ty.toIntern())) { |
| 7520 | 7640 | inline .array_type, .vector_type => |info, tag| { |
| ... | ... | @@ -7522,20 +7642,20 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue { |
| 7522 | 7642 | .ctype = try f.ctypeFromType(.fromInterned(info.child), .complete), |
| 7523 | 7643 | }; |
| 7524 | 7644 | for (resolved_elements, 0..) |element, i| { |
| 7525 | try a.restart(f, writer); | |
| 7526 | try f.writeCValue(writer, local, .Other); | |
| 7527 | try writer.print("[{d}]", .{i}); | |
| 7528 | try a.assign(f, writer); | |
| 7529 | try f.writeCValue(writer, element, .Other); | |
| 7530 | try a.end(f, writer); | |
| 7645 | try a.restart(f, w); | |
| 7646 | try f.writeCValue(w, local, .Other); | |
| 7647 | try w.print("[{d}]", .{i}); | |
| 7648 | try a.assign(f, w); | |
| 7649 | try f.writeCValue(w, element, .Other); | |
| 7650 | try a.end(f, w); | |
| 7531 | 7651 | } |
| 7532 | 7652 | if (tag == .array_type and info.sentinel != .none) { |
| 7533 | try a.restart(f, writer); | |
| 7534 | try f.writeCValue(writer, local, .Other); | |
| 7535 | try writer.print("[{d}]", .{info.len}); | |
| 7536 | try a.assign(f, writer); | |
| 7537 | try f.object.dg.renderValue(writer, Value.fromInterned(info.sentinel), .Other); | |
| 7538 | try a.end(f, writer); | |
| 7653 | try a.restart(f, w); | |
| 7654 | try f.writeCValue(w, local, .Other); | |
| 7655 | try w.print("[{d}]", .{info.len}); | |
| 7656 | try a.assign(f, w); | |
| 7657 | try f.object.dg.renderValue(w, Value.fromInterned(info.sentinel), .Other); | |
| 7658 | try a.end(f, w); | |
| 7539 | 7659 | } |
| 7540 | 7660 | }, |
| 7541 | 7661 | .struct_type => { |
| ... | ... | @@ -7547,19 +7667,19 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue { |
| 7547 | 7667 | const field_ty: Type = .fromInterned(loaded_struct.field_types.get(ip)[field_index]); |
| 7548 | 7668 | if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue; |
| 7549 | 7669 | |
| 7550 | const a = try Assignment.start(f, writer, try f.ctypeFromType(field_ty, .complete)); | |
| 7551 | try f.writeCValueMember(writer, local, if (loaded_struct.fieldName(ip, field_index).unwrap()) |field_name| | |
| 7670 | const a = try Assignment.start(f, w, try f.ctypeFromType(field_ty, .complete)); | |
| 7671 | try f.writeCValueMember(w, local, if (loaded_struct.fieldName(ip, field_index).unwrap()) |field_name| | |
| 7552 | 7672 | .{ .identifier = field_name.toSlice(ip) } |
| 7553 | 7673 | else |
| 7554 | 7674 | .{ .field = field_index }); |
| 7555 | try a.assign(f, writer); | |
| 7556 | try f.writeCValue(writer, resolved_elements[field_index], .Other); | |
| 7557 | try a.end(f, writer); | |
| 7675 | try a.assign(f, w); | |
| 7676 | try f.writeCValue(w, resolved_elements[field_index], .Other); | |
| 7677 | try a.end(f, w); | |
| 7558 | 7678 | } |
| 7559 | 7679 | }, |
| 7560 | 7680 | .@"packed" => { |
| 7561 | try f.writeCValue(writer, local, .Other); | |
| 7562 | try writer.writeAll(" = "); | |
| 7681 | try f.writeCValue(w, local, .Other); | |
| 7682 | try w.writeAll(" = "); | |
| 7563 | 7683 | |
| 7564 | 7684 | const backing_int_ty: Type = .fromInterned(loaded_struct.backingIntTypeUnordered(ip)); |
| 7565 | 7685 | const int_info = backing_int_ty.intInfo(zcu); |
| ... | ... | @@ -7575,9 +7695,9 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue { |
| 7575 | 7695 | if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue; |
| 7576 | 7696 | |
| 7577 | 7697 | if (!empty) { |
| 7578 | try writer.writeAll("zig_or_"); | |
| 7579 | try f.object.dg.renderTypeForBuiltinFnName(writer, inst_ty); | |
| 7580 | try writer.writeByte('('); | |
| 7698 | try w.writeAll("zig_or_"); | |
| 7699 | try f.object.dg.renderTypeForBuiltinFnName(w, inst_ty); | |
| 7700 | try w.writeByte('('); | |
| 7581 | 7701 | } |
| 7582 | 7702 | empty = false; |
| 7583 | 7703 | } |
| ... | ... | @@ -7587,57 +7707,58 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue { |
| 7587 | 7707 | const field_ty = inst_ty.fieldType(field_index, zcu); |
| 7588 | 7708 | if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue; |
| 7589 | 7709 | |
| 7590 | if (!empty) try writer.writeAll(", "); | |
| 7710 | if (!empty) try w.writeAll(", "); | |
| 7591 | 7711 | // TODO: Skip this entire shift if val is 0? |
| 7592 | try writer.writeAll("zig_shlw_"); | |
| 7593 | try f.object.dg.renderTypeForBuiltinFnName(writer, inst_ty); | |
| 7594 | try writer.writeByte('('); | |
| 7712 | try w.writeAll("zig_shlw_"); | |
| 7713 | try f.object.dg.renderTypeForBuiltinFnName(w, inst_ty); | |
| 7714 | try w.writeByte('('); | |
| 7595 | 7715 | |
| 7596 | 7716 | if (field_ty.isAbiInt(zcu)) { |
| 7597 | try writer.writeAll("zig_and_"); | |
| 7598 | try f.object.dg.renderTypeForBuiltinFnName(writer, inst_ty); | |
| 7599 | try writer.writeByte('('); | |
| 7717 | try w.writeAll("zig_and_"); | |
| 7718 | try f.object.dg.renderTypeForBuiltinFnName(w, inst_ty); | |
| 7719 | try w.writeByte('('); | |
| 7600 | 7720 | } |
| 7601 | 7721 | |
| 7602 | 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 | 7724 | } else { |
| 7605 | try writer.writeByte('('); | |
| 7606 | try f.renderType(writer, inst_ty); | |
| 7607 | try writer.writeByte(')'); | |
| 7725 | try w.writeByte('('); | |
| 7726 | try f.renderType(w, inst_ty); | |
| 7727 | try w.writeByte(')'); | |
| 7608 | 7728 | if (field_ty.isPtrAtRuntime(zcu)) { |
| 7609 | try writer.writeByte('('); | |
| 7610 | try f.renderType(writer, switch (int_info.signedness) { | |
| 7729 | try w.writeByte('('); | |
| 7730 | try f.renderType(w, switch (int_info.signedness) { | |
| 7611 | 7731 | .unsigned => .usize, |
| 7612 | 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 | } |
| 7618 | 7738 | |
| 7619 | 7739 | if (field_ty.isAbiInt(zcu)) { |
| 7620 | try writer.writeAll(", "); | |
| 7740 | try w.writeAll(", "); | |
| 7621 | 7741 | const field_int_info = field_ty.intInfo(zcu); |
| 7622 | 7742 | const field_mask = if (int_info.signedness == .signed and int_info.bits == field_int_info.bits) |
| 7623 | 7743 | try pt.intValue(backing_int_ty, -1) |
| 7624 | 7744 | else |
| 7625 | 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); | |
| 7627 | try writer.writeByte(')'); | |
| 7746 | try f.object.dg.renderValue(w, field_mask, .FunctionArgument); | |
| 7747 | try w.writeByte(')'); | |
| 7628 | 7748 | } |
| 7629 | 7749 | |
| 7630 | try writer.print(", {}", .{ | |
| 7631 | try f.fmtIntLiteral(try pt.intValue(bit_offset_ty, bit_offset)), | |
| 7750 | try w.print(", {f}", .{ | |
| 7751 | try f.fmtIntLiteralDec(try pt.intValue(bit_offset_ty, bit_offset)), | |
| 7632 | 7752 | }); |
| 7633 | try f.object.dg.renderBuiltinInfo(writer, inst_ty, .bits); | |
| 7634 | try writer.writeByte(')'); | |
| 7635 | if (!empty) try writer.writeByte(')'); | |
| 7753 | try f.object.dg.renderBuiltinInfo(w, inst_ty, .bits); | |
| 7754 | try w.writeByte(')'); | |
| 7755 | if (!empty) try w.writeByte(')'); | |
| 7636 | 7756 | |
| 7637 | 7757 | bit_offset += field_ty.bitSize(zcu); |
| 7638 | 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 | 7767 | const field_ty: Type = .fromInterned(tuple_info.types.get(ip)[field_index]); |
| 7647 | 7768 | if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue; |
| 7648 | 7769 | |
| 7649 | const a = try Assignment.start(f, writer, try f.ctypeFromType(field_ty, .complete)); | |
| 7650 | try f.writeCValueMember(writer, local, .{ .field = field_index }); | |
| 7651 | try a.assign(f, writer); | |
| 7652 | try f.writeCValue(writer, resolved_elements[field_index], .Other); | |
| 7653 | try a.end(f, writer); | |
| 7770 | const a = try Assignment.start(f, w, try f.ctypeFromType(field_ty, .complete)); | |
| 7771 | try f.writeCValueMember(w, local, .{ .field = field_index }); | |
| 7772 | try a.assign(f, w); | |
| 7773 | try f.writeCValue(w, resolved_elements[field_index], .Other); | |
| 7774 | try a.end(f, w); | |
| 7654 | 7775 | }, |
| 7655 | 7776 | else => unreachable, |
| 7656 | 7777 | } |
| ... | ... | @@ -7672,7 +7793,7 @@ fn airUnionInit(f: *Function, inst: Air.Inst.Index) !CValue { |
| 7672 | 7793 | const payload = try f.resolveInst(extra.init); |
| 7673 | 7794 | try reap(f, inst, &.{extra.init}); |
| 7674 | 7795 | |
| 7675 | const writer = f.object.writer(); | |
| 7796 | const w = &f.object.code.writer; | |
| 7676 | 7797 | const local = try f.allocLocal(inst, union_ty); |
| 7677 | 7798 | if (loaded_union.flagsUnordered(ip).layout == .@"packed") return f.moveCValue(inst, union_ty, payload); |
| 7678 | 7799 | |
| ... | ... | @@ -7682,20 +7803,20 @@ fn airUnionInit(f: *Function, inst: Air.Inst.Index) !CValue { |
| 7682 | 7803 | const field_index = tag_ty.enumFieldIndex(field_name, zcu).?; |
| 7683 | 7804 | const tag_val = try pt.enumValueFieldIndex(tag_ty, field_index); |
| 7684 | 7805 | |
| 7685 | const a = try Assignment.start(f, writer, try f.ctypeFromType(tag_ty, .complete)); | |
| 7686 | try f.writeCValueMember(writer, local, .{ .identifier = "tag" }); | |
| 7687 | try a.assign(f, writer); | |
| 7688 | try writer.print("{}", .{try f.fmtIntLiteral(try tag_val.intFromEnum(tag_ty, pt))}); | |
| 7689 | try a.end(f, writer); | |
| 7806 | const a = try Assignment.start(f, w, try f.ctypeFromType(tag_ty, .complete)); | |
| 7807 | try f.writeCValueMember(w, local, .{ .identifier = "tag" }); | |
| 7808 | try a.assign(f, w); | |
| 7809 | try w.print("{f}", .{try f.fmtIntLiteralDec(try tag_val.intFromEnum(tag_ty, pt))}); | |
| 7810 | try a.end(f, w); | |
| 7690 | 7811 | } |
| 7691 | 7812 | break :field .{ .payload_identifier = field_name.toSlice(ip) }; |
| 7692 | 7813 | } else .{ .identifier = field_name.toSlice(ip) }; |
| 7693 | 7814 | |
| 7694 | const a = try Assignment.start(f, writer, try f.ctypeFromType(payload_ty, .complete)); | |
| 7695 | try f.writeCValueMember(writer, local, field); | |
| 7696 | try a.assign(f, writer); | |
| 7697 | try f.writeCValue(writer, payload, .Other); | |
| 7698 | try a.end(f, writer); | |
| 7815 | const a = try Assignment.start(f, w, try f.ctypeFromType(payload_ty, .complete)); | |
| 7816 | try f.writeCValueMember(w, local, field); | |
| 7817 | try a.assign(f, w); | |
| 7818 | try f.writeCValue(w, payload, .Other); | |
| 7819 | try a.end(f, w); | |
| 7699 | 7820 | return local; |
| 7700 | 7821 | } |
| 7701 | 7822 | |
| ... | ... | @@ -7708,15 +7829,16 @@ fn airPrefetch(f: *Function, inst: Air.Inst.Index) !CValue { |
| 7708 | 7829 | const ptr = try f.resolveInst(prefetch.ptr); |
| 7709 | 7830 | try reap(f, inst, &.{prefetch.ptr}); |
| 7710 | 7831 | |
| 7711 | const writer = f.object.writer(); | |
| 7832 | const w = &f.object.code.writer; | |
| 7712 | 7833 | switch (prefetch.cache) { |
| 7713 | 7834 | .data => { |
| 7714 | try writer.writeAll("zig_prefetch("); | |
| 7835 | try w.writeAll("zig_prefetch("); | |
| 7715 | 7836 | if (ptr_ty.isSlice(zcu)) |
| 7716 | try f.writeCValueMember(writer, ptr, .{ .identifier = "ptr" }) | |
| 7837 | try f.writeCValueMember(w, ptr, .{ .identifier = "ptr" }) | |
| 7717 | 7838 | else |
| 7718 | try f.writeCValue(writer, ptr, .FunctionArgument); | |
| 7719 | try writer.print(", {d}, {d});\n", .{ @intFromEnum(prefetch.rw), prefetch.locality }); | |
| 7839 | try f.writeCValue(w, ptr, .FunctionArgument); | |
| 7840 | try w.print(", {d}, {d});", .{ @intFromEnum(prefetch.rw), prefetch.locality }); | |
| 7841 | try f.object.newline(); | |
| 7720 | 7842 | }, |
| 7721 | 7843 | // The available prefetch intrinsics do not accept a cache argument; only |
| 7722 | 7844 | // address, rw, and locality. |
| ... | ... | @@ -7729,13 +7851,14 @@ fn airPrefetch(f: *Function, inst: Air.Inst.Index) !CValue { |
| 7729 | 7851 | fn airWasmMemorySize(f: *Function, inst: Air.Inst.Index) !CValue { |
| 7730 | 7852 | const pl_op = f.air.instructions.items(.data)[@intFromEnum(inst)].pl_op; |
| 7731 | 7853 | |
| 7732 | const writer = f.object.writer(); | |
| 7854 | const w = &f.object.code.writer; | |
| 7733 | 7855 | const inst_ty = f.typeOfIndex(inst); |
| 7734 | 7856 | const local = try f.allocLocal(inst, inst_ty); |
| 7735 | try f.writeCValue(writer, local, .Other); | |
| 7857 | try f.writeCValue(w, local, .Other); | |
| 7736 | 7858 | |
| 7737 | try writer.writeAll(" = "); | |
| 7738 | try writer.print("zig_wasm_memory_size({d});\n", .{pl_op.payload}); | |
| 7859 | try w.writeAll(" = "); | |
| 7860 | try w.print("zig_wasm_memory_size({d});", .{pl_op.payload}); | |
| 7861 | try f.object.newline(); | |
| 7739 | 7862 | |
| 7740 | 7863 | return local; |
| 7741 | 7864 | } |
| ... | ... | @@ -7743,17 +7866,18 @@ fn airWasmMemorySize(f: *Function, inst: Air.Inst.Index) !CValue { |
| 7743 | 7866 | fn airWasmMemoryGrow(f: *Function, inst: Air.Inst.Index) !CValue { |
| 7744 | 7867 | const pl_op = f.air.instructions.items(.data)[@intFromEnum(inst)].pl_op; |
| 7745 | 7868 | |
| 7746 | const writer = f.object.writer(); | |
| 7869 | const w = &f.object.code.writer; | |
| 7747 | 7870 | const inst_ty = f.typeOfIndex(inst); |
| 7748 | 7871 | const operand = try f.resolveInst(pl_op.operand); |
| 7749 | 7872 | try reap(f, inst, &.{pl_op.operand}); |
| 7750 | 7873 | const local = try f.allocLocal(inst, inst_ty); |
| 7751 | try f.writeCValue(writer, local, .Other); | |
| 7874 | try f.writeCValue(w, local, .Other); | |
| 7752 | 7875 | |
| 7753 | try writer.writeAll(" = "); | |
| 7754 | try writer.print("zig_wasm_memory_grow({d}, ", .{pl_op.payload}); | |
| 7755 | try f.writeCValue(writer, operand, .FunctionArgument); | |
| 7756 | try writer.writeAll(");\n"); | |
| 7876 | try w.writeAll(" = "); | |
| 7877 | try w.print("zig_wasm_memory_grow({d}, ", .{pl_op.payload}); | |
| 7878 | try f.writeCValue(w, operand, .FunctionArgument); | |
| 7879 | try w.writeAll(");"); | |
| 7880 | try f.object.newline(); | |
| 7757 | 7881 | return local; |
| 7758 | 7882 | } |
| 7759 | 7883 | |
| ... | ... | @@ -7771,36 +7895,38 @@ fn airMulAdd(f: *Function, inst: Air.Inst.Index) !CValue { |
| 7771 | 7895 | const inst_ty = f.typeOfIndex(inst); |
| 7772 | 7896 | const inst_scalar_ty = inst_ty.scalarType(zcu); |
| 7773 | 7897 | |
| 7774 | const writer = f.object.writer(); | |
| 7898 | const w = &f.object.code.writer; | |
| 7775 | 7899 | const local = try f.allocLocal(inst, inst_ty); |
| 7776 | const v = try Vectorize.start(f, inst, writer, inst_ty); | |
| 7777 | try f.writeCValue(writer, local, .Other); | |
| 7778 | try v.elem(f, writer); | |
| 7779 | try writer.writeAll(" = zig_fma_"); | |
| 7780 | try f.object.dg.renderTypeForBuiltinFnName(writer, inst_scalar_ty); | |
| 7781 | try writer.writeByte('('); | |
| 7782 | try f.writeCValue(writer, mulend1, .FunctionArgument); | |
| 7783 | try v.elem(f, writer); | |
| 7784 | try writer.writeAll(", "); | |
| 7785 | try f.writeCValue(writer, mulend2, .FunctionArgument); | |
| 7786 | try v.elem(f, writer); | |
| 7787 | try writer.writeAll(", "); | |
| 7788 | try f.writeCValue(writer, addend, .FunctionArgument); | |
| 7789 | try v.elem(f, writer); | |
| 7790 | try writer.writeAll(");\n"); | |
| 7791 | try v.end(f, inst, writer); | |
| 7900 | const v = try Vectorize.start(f, inst, w, inst_ty); | |
| 7901 | try f.writeCValue(w, local, .Other); | |
| 7902 | try v.elem(f, w); | |
| 7903 | try w.writeAll(" = zig_fma_"); | |
| 7904 | try f.object.dg.renderTypeForBuiltinFnName(w, inst_scalar_ty); | |
| 7905 | try w.writeByte('('); | |
| 7906 | try f.writeCValue(w, mulend1, .FunctionArgument); | |
| 7907 | try v.elem(f, w); | |
| 7908 | try w.writeAll(", "); | |
| 7909 | try f.writeCValue(w, mulend2, .FunctionArgument); | |
| 7910 | try v.elem(f, w); | |
| 7911 | try w.writeAll(", "); | |
| 7912 | try f.writeCValue(w, addend, .FunctionArgument); | |
| 7913 | try v.elem(f, w); | |
| 7914 | try w.writeAll(");"); | |
| 7915 | try f.object.newline(); | |
| 7916 | try v.end(f, inst, w); | |
| 7792 | 7917 | |
| 7793 | 7918 | return local; |
| 7794 | 7919 | } |
| 7795 | 7920 | |
| 7796 | 7921 | fn airRuntimeNavPtr(f: *Function, inst: Air.Inst.Index) !CValue { |
| 7797 | 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 | 7924 | const local = try f.allocLocal(inst, .fromInterned(ty_nav.ty)); |
| 7800 | try f.writeCValue(writer, local, .Other); | |
| 7801 | try writer.writeAll(" = "); | |
| 7802 | try f.object.dg.renderNav(writer, ty_nav.nav, .Other); | |
| 7803 | try writer.writeAll(";\n"); | |
| 7925 | try f.writeCValue(w, local, .Other); | |
| 7926 | try w.writeAll(" = "); | |
| 7927 | try f.object.dg.renderNav(w, ty_nav.nav, .Other); | |
| 7928 | try w.writeByte(';'); | |
| 7929 | try f.object.newline(); | |
| 7804 | 7930 | return local; |
| 7805 | 7931 | } |
| 7806 | 7932 | |
| ... | ... | @@ -7812,15 +7938,16 @@ fn airCVaStart(f: *Function, inst: Air.Inst.Index) !CValue { |
| 7812 | 7938 | const function_info = (try f.ctypeFromType(function_ty, .complete)).info(&f.object.dg.ctype_pool).function; |
| 7813 | 7939 | assert(function_info.varargs); |
| 7814 | 7940 | |
| 7815 | const writer = f.object.writer(); | |
| 7941 | const w = &f.object.code.writer; | |
| 7816 | 7942 | const local = try f.allocLocal(inst, inst_ty); |
| 7817 | try writer.writeAll("va_start(*(va_list *)&"); | |
| 7818 | try f.writeCValue(writer, local, .Other); | |
| 7943 | try w.writeAll("va_start(*(va_list *)&"); | |
| 7944 | try f.writeCValue(w, local, .Other); | |
| 7819 | 7945 | if (function_info.param_ctypes.len > 0) { |
| 7820 | try writer.writeAll(", "); | |
| 7821 | try f.writeCValue(writer, .{ .arg = function_info.param_ctypes.len - 1 }, .FunctionArgument); | |
| 7946 | try w.writeAll(", "); | |
| 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 | 7951 | return local; |
| 7825 | 7952 | } |
| 7826 | 7953 | |
| ... | ... | @@ -7831,14 +7958,15 @@ fn airCVaArg(f: *Function, inst: Air.Inst.Index) !CValue { |
| 7831 | 7958 | const va_list = try f.resolveInst(ty_op.operand); |
| 7832 | 7959 | try reap(f, inst, &.{ty_op.operand}); |
| 7833 | 7960 | |
| 7834 | const writer = f.object.writer(); | |
| 7961 | const w = &f.object.code.writer; | |
| 7835 | 7962 | const local = try f.allocLocal(inst, inst_ty); |
| 7836 | try f.writeCValue(writer, local, .Other); | |
| 7837 | try writer.writeAll(" = va_arg(*(va_list *)"); | |
| 7838 | try f.writeCValue(writer, va_list, .Other); | |
| 7839 | try writer.writeAll(", "); | |
| 7840 | try f.renderType(writer, ty_op.ty.toType()); | |
| 7841 | try writer.writeAll(");\n"); | |
| 7963 | try f.writeCValue(w, local, .Other); | |
| 7964 | try w.writeAll(" = va_arg(*(va_list *)"); | |
| 7965 | try f.writeCValue(w, va_list, .Other); | |
| 7966 | try w.writeAll(", "); | |
| 7967 | try f.renderType(w, ty_op.ty.toType()); | |
| 7968 | try w.writeAll(");"); | |
| 7969 | try f.object.newline(); | |
| 7842 | 7970 | return local; |
| 7843 | 7971 | } |
| 7844 | 7972 | |
| ... | ... | @@ -7848,10 +7976,11 @@ fn airCVaEnd(f: *Function, inst: Air.Inst.Index) !CValue { |
| 7848 | 7976 | const va_list = try f.resolveInst(un_op); |
| 7849 | 7977 | try reap(f, inst, &.{un_op}); |
| 7850 | 7978 | |
| 7851 | const writer = f.object.writer(); | |
| 7852 | try writer.writeAll("va_end(*(va_list *)"); | |
| 7853 | try f.writeCValue(writer, va_list, .Other); | |
| 7854 | try writer.writeAll(");\n"); | |
| 7979 | const w = &f.object.code.writer; | |
| 7980 | try w.writeAll("va_end(*(va_list *)"); | |
| 7981 | try f.writeCValue(w, va_list, .Other); | |
| 7982 | try w.writeAll(");"); | |
| 7983 | try f.object.newline(); | |
| 7855 | 7984 | return .none; |
| 7856 | 7985 | } |
| 7857 | 7986 | |
| ... | ... | @@ -7862,13 +7991,14 @@ fn airCVaCopy(f: *Function, inst: Air.Inst.Index) !CValue { |
| 7862 | 7991 | const va_list = try f.resolveInst(ty_op.operand); |
| 7863 | 7992 | try reap(f, inst, &.{ty_op.operand}); |
| 7864 | 7993 | |
| 7865 | const writer = f.object.writer(); | |
| 7994 | const w = &f.object.code.writer; | |
| 7866 | 7995 | const local = try f.allocLocal(inst, inst_ty); |
| 7867 | try writer.writeAll("va_copy(*(va_list *)&"); | |
| 7868 | try f.writeCValue(writer, local, .Other); | |
| 7869 | try writer.writeAll(", *(va_list *)"); | |
| 7870 | try f.writeCValue(writer, va_list, .Other); | |
| 7871 | try writer.writeAll(");\n"); | |
| 7996 | try w.writeAll("va_copy(*(va_list *)&"); | |
| 7997 | try f.writeCValue(w, local, .Other); | |
| 7998 | try w.writeAll(", *(va_list *)"); | |
| 7999 | try f.writeCValue(w, va_list, .Other); | |
| 8000 | try w.writeAll(");"); | |
| 8001 | try f.object.newline(); | |
| 7872 | 8002 | return local; |
| 7873 | 8003 | } |
| 7874 | 8004 | |
| ... | ... | @@ -7883,7 +8013,7 @@ fn toMemoryOrder(order: std.builtin.AtomicOrder) [:0]const u8 { |
| 7883 | 8013 | }; |
| 7884 | 8014 | } |
| 7885 | 8015 | |
| 7886 | fn writeMemoryOrder(w: anytype, order: std.builtin.AtomicOrder) !void { | |
| 8016 | fn writeMemoryOrder(w: *Writer, order: std.builtin.AtomicOrder) !void { | |
| 7887 | 8017 | return w.writeAll(toMemoryOrder(order)); |
| 7888 | 8018 | } |
| 7889 | 8019 | |
| ... | ... | @@ -7970,93 +8100,6 @@ fn toAtomicRmwSuffix(order: std.builtin.AtomicRmwOp) []const u8 { |
| 7970 | 8100 | }; |
| 7971 | 8101 | } |
| 7972 | 8102 | |
| 7973 | const ArrayListWriter = ErrorOnlyGenericWriter(std.ArrayList(u8).Writer.Error); | |
| 7974 | ||
| 7975 | fn 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 | ||
| 7987 | fn 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. | |
| 8052 | fn 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 | ||
| 8060 | 8103 | fn toCIntBits(zig_bits: u32) ?u32 { |
| 8061 | 8104 | for (&[_]u8{ 8, 16, 32, 64, 128 }) |c_bits| { |
| 8062 | 8105 | if (zig_bits <= c_bits) { |
| ... | ... | @@ -8111,7 +8154,12 @@ fn compareOperatorC(operator: std.math.CompareOperator) []const u8 { |
| 8111 | 8154 | }; |
| 8112 | 8155 | } |
| 8113 | 8156 | |
| 8114 | fn StringLiteral(comptime WriterType: type) type { | |
| 8157 | const StringLiteral = struct { | |
| 8158 | len: usize, | |
| 8159 | cur_len: usize, | |
| 8160 | w: *Writer, | |
| 8161 | first: bool, | |
| 8162 | ||
| 8115 | 8163 | // MSVC throws C2078 if an array of size 65536 or greater is initialized with a string literal, |
| 8116 | 8164 | // regardless of the length of the string literal initializing it. Array initializer syntax is |
| 8117 | 8165 | // used instead. |
| ... | ... | @@ -8123,99 +8171,116 @@ fn StringLiteral(comptime WriterType: type) type { |
| 8123 | 8171 | const max_char_len = 4; |
| 8124 | 8172 | const max_literal_len = @min(16380 - max_char_len, 4095); |
| 8125 | 8173 | |
| 8126 | return struct { | |
| 8127 | len: u64, | |
| 8128 | cur_len: u64 = 0, | |
| 8129 | counting_writer: std.io.CountingWriter(WriterType), | |
| 8130 | ||
| 8131 | pub const Error = WriterType.Error; | |
| 8132 | ||
| 8133 | const Self = @This(); | |
| 8174 | fn init(w: *Writer, len: usize) StringLiteral { | |
| 8175 | return .{ | |
| 8176 | .cur_len = 0, | |
| 8177 | .len = len, | |
| 8178 | .w = w, | |
| 8179 | .first = true, | |
| 8180 | }; | |
| 8181 | } | |
| 8134 | 8182 | |
| 8135 | pub fn start(self: *Self) Error!void { | |
| 8136 | const writer = self.counting_writer.writer(); | |
| 8137 | if (self.len <= max_string_initializer_len) { | |
| 8138 | try writer.writeByte('\"'); | |
| 8139 | } else { | |
| 8140 | try writer.writeByte('{'); | |
| 8141 | } | |
| 8183 | pub fn start(sl: *StringLiteral) Writer.Error!void { | |
| 8184 | if (sl.len <= max_string_initializer_len) { | |
| 8185 | try sl.w.writeByte('\"'); | |
| 8186 | } else { | |
| 8187 | try sl.w.writeByte('{'); | |
| 8142 | 8188 | } |
| 8189 | } | |
| 8143 | 8190 | |
| 8144 | pub fn end(self: *Self) Error!void { | |
| 8145 | const writer = self.counting_writer.writer(); | |
| 8146 | if (self.len <= max_string_initializer_len) { | |
| 8147 | try writer.writeByte('\"'); | |
| 8148 | } else { | |
| 8149 | try writer.writeByte('}'); | |
| 8150 | } | |
| 8191 | pub fn end(sl: *StringLiteral) Writer.Error!void { | |
| 8192 | if (sl.len <= max_string_initializer_len) { | |
| 8193 | try sl.w.writeByte('\"'); | |
| 8194 | } else { | |
| 8195 | try sl.w.writeByte('}'); | |
| 8151 | 8196 | } |
| 8197 | } | |
| 8152 | 8198 | |
| 8153 | fn writeStringLiteralChar(writer: anytype, c: u8) !void { | |
| 8154 | switch (c) { | |
| 8155 | 7 => try writer.writeAll("\\a"), | |
| 8156 | 8 => try writer.writeAll("\\b"), | |
| 8157 | '\t' => try writer.writeAll("\\t"), | |
| 8158 | '\n' => try writer.writeAll("\\n"), | |
| 8159 | 11 => try writer.writeAll("\\v"), | |
| 8160 | 12 => try writer.writeAll("\\f"), | |
| 8161 | '\r' => try writer.writeAll("\\r"), | |
| 8162 | '"', '\'', '?', '\\' => try writer.print("\\{c}", .{c}), | |
| 8163 | else => switch (c) { | |
| 8164 | ' '...'~' => try writer.writeByte(c), | |
| 8165 | else => try writer.print("\\{o:0>3}", .{c}), | |
| 8166 | }, | |
| 8167 | } | |
| 8199 | fn writeStringLiteralChar(sl: *StringLiteral, c: u8) Writer.Error!usize { | |
| 8200 | const w = sl.w; | |
| 8201 | switch (c) { | |
| 8202 | 7 => { | |
| 8203 | try w.writeAll("\\a"); | |
| 8204 | return 2; | |
| 8205 | }, | |
| 8206 | 8 => { | |
| 8207 | try w.writeAll("\\b"); | |
| 8208 | return 2; | |
| 8209 | }, | |
| 8210 | '\t' => { | |
| 8211 | try w.writeAll("\\t"); | |
| 8212 | return 2; | |
| 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 | } | |
| 8169 | 8246 | |
| 8170 | pub fn writeChar(self: *Self, c: u8) Error!void { | |
| 8171 | const writer = self.counting_writer.writer(); | |
| 8172 | if (self.len <= max_string_initializer_len) { | |
| 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); | |
| 8247 | pub fn writeChar(sl: *StringLiteral, c: u8) Writer.Error!void { | |
| 8248 | if (sl.len <= max_string_initializer_len) { | |
| 8249 | if (sl.cur_len == 0 and !sl.first) try sl.w.writeAll("\"\""); | |
| 8178 | 8250 | |
| 8179 | const char_length = self.counting_writer.bytes_written - len; | |
| 8180 | assert(char_length <= max_char_len); | |
| 8181 | self.cur_len += char_length; | |
| 8251 | const char_len = try sl.writeStringLiteralChar(c); | |
| 8252 | assert(char_len <= max_char_len); | |
| 8253 | sl.cur_len += char_len; | |
| 8182 | 8254 | |
| 8183 | if (self.cur_len >= max_literal_len) self.cur_len = 0; | |
| 8184 | } else { | |
| 8185 | if (self.counting_writer.bytes_written > 1) try writer.writeByte(','); | |
| 8186 | try writer.print("'\\x{x}'", .{c}); | |
| 8255 | if (sl.cur_len >= max_literal_len) { | |
| 8256 | sl.cur_len = 0; | |
| 8257 | sl.first = false; | |
| 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 | }; | |
| 8190 | } | |
| 8191 | ||
| 8192 | fn 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 | } | |
| 8267 | } | |
| 8268 | }; | |
| 8201 | 8269 | |
| 8202 | const FormatStringContext = struct { str: []const u8, sentinel: ?u8 }; | |
| 8203 | fn formatStringLiteral( | |
| 8204 | data: FormatStringContext, | |
| 8205 | comptime fmt: []const u8, | |
| 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); | |
| 8270 | const FormatStringContext = struct { | |
| 8271 | str: []const u8, | |
| 8272 | sentinel: ?u8, | |
| 8273 | }; | |
| 8210 | 8274 | |
| 8211 | var literal = stringLiteral(writer, data.str.len + @intFromBool(data.sentinel != null)); | |
| 8275 | fn 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 | 8277 | try literal.start(); |
| 8213 | 8278 | for (data.str) |c| try literal.writeChar(c); |
| 8214 | 8279 | if (data.sentinel) |sentinel| if (sentinel != 0) try literal.writeChar(sentinel); |
| 8215 | 8280 | try literal.end(); |
| 8216 | 8281 | } |
| 8217 | 8282 | |
| 8218 | fn fmtStringLiteral(str: []const u8, sentinel: ?u8) std.fmt.Formatter(formatStringLiteral) { | |
| 8283 | fn fmtStringLiteral(str: []const u8, sentinel: ?u8) std.fmt.Formatter(FormatStringContext, formatStringLiteral) { | |
| 8219 | 8284 | return .{ .data = .{ .str = str, .sentinel = sentinel } }; |
| 8220 | 8285 | } |
| 8221 | 8286 | |
| ... | ... | @@ -8231,13 +8296,10 @@ const FormatIntLiteralContext = struct { |
| 8231 | 8296 | kind: CType.Kind, |
| 8232 | 8297 | ctype: CType, |
| 8233 | 8298 | val: Value, |
| 8299 | base: u8, | |
| 8300 | case: std.fmt.Case, | |
| 8234 | 8301 | }; |
| 8235 | fn formatIntLiteral( | |
| 8236 | data: FormatIntLiteralContext, | |
| 8237 | comptime fmt: []const u8, | |
| 8238 | options: std.fmt.FormatOptions, | |
| 8239 | writer: anytype, | |
| 8240 | ) @TypeOf(writer).Error!void { | |
| 8302 | fn formatIntLiteral(data: FormatIntLiteralContext, w: *std.io.Writer) std.io.Writer.Error!void { | |
| 8241 | 8303 | const pt = data.dg.pt; |
| 8242 | 8304 | const zcu = pt.zcu; |
| 8243 | 8305 | const target = &data.dg.mod.resolved_target.result; |
| ... | ... | @@ -8262,7 +8324,7 @@ fn formatIntLiteral( |
| 8262 | 8324 | |
| 8263 | 8325 | var int_buf: Value.BigIntSpace = undefined; |
| 8264 | 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 | 8328 | @memset(undef_limbs, undefPattern(BigIntLimb)); |
| 8267 | 8329 | |
| 8268 | 8330 | var undef_int = BigInt.Mutable{ |
| ... | ... | @@ -8280,7 +8342,7 @@ fn formatIntLiteral( |
| 8280 | 8342 | const one = BigInt.Mutable.init(&one_limbs, 1).toConst(); |
| 8281 | 8343 | |
| 8282 | 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 | 8346 | .len = undefined, |
| 8285 | 8347 | .positive = undefined, |
| 8286 | 8348 | }; |
| ... | ... | @@ -8317,46 +8379,29 @@ fn formatIntLiteral( |
| 8317 | 8379 | if (c_limb_info.count == 1) { |
| 8318 | 8380 | if (wrap.addWrap(int, one, data.int_info.signedness, c_bits) or |
| 8319 | 8381 | data.int_info.signedness == .signed and wrap.subWrap(int, one, data.int_info.signedness, c_bits)) |
| 8320 | return writer.print("{s}_{s}", .{ | |
| 8321 | data.ctype.getStandardDefineAbbrev() orelse return writer.print("zig_{s}Int_{c}{d}", .{ | |
| 8382 | return w.print("{s}_{s}", .{ | |
| 8383 | data.ctype.getStandardDefineAbbrev() orelse return w.print("zig_{s}Int_{c}{d}", .{ | |
| 8322 | 8384 | if (int.positive) "max" else "min", signAbbrev(data.int_info.signedness), c_bits, |
| 8323 | 8385 | }), |
| 8324 | 8386 | if (int.positive) "MAX" else "MIN", |
| 8325 | 8387 | }); |
| 8326 | 8388 | |
| 8327 | if (!int.positive) try writer.writeByte('-'); | |
| 8328 | try data.ctype.renderLiteralPrefix(writer, data.kind, ctype_pool); | |
| 8389 | if (!int.positive) try w.writeByte('-'); | |
| 8390 | try data.ctype.renderLiteralPrefix(w, data.kind, ctype_pool); | |
| 8329 | 8391 | |
| 8330 | const style: struct { base: u8, case: std.fmt.Case = undefined } = switch (fmt.len) { | |
| 8331 | 0 => .{ .base = 10 }, | |
| 8332 | 1 => switch (fmt[0]) { | |
| 8333 | 'b' => style: { | |
| 8334 | try writer.writeAll("0b"); | |
| 8335 | break :style .{ .base = 2 }; | |
| 8336 | }, | |
| 8337 | 'o' => style: { | |
| 8338 | try writer.writeByte('0'); | |
| 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); | |
| 8392 | switch (data.base) { | |
| 8393 | 2 => try w.writeAll("0b"), | |
| 8394 | 8 => try w.writeByte('0'), | |
| 8395 | 10 => {}, | |
| 8396 | 16 => try w.writeAll("0x"), | |
| 8397 | else => unreachable, | |
| 8398 | } | |
| 8399 | const string = int.abs().toStringAlloc(allocator, data.base, data.case) catch | |
| 8400 | return error.WriteFailed; | |
| 8356 | 8401 | defer allocator.free(string); |
| 8357 | try writer.writeAll(string); | |
| 8402 | try w.writeAll(string); | |
| 8358 | 8403 | } else { |
| 8359 | try data.ctype.renderLiteralPrefix(writer, data.kind, ctype_pool); | |
| 8404 | try data.ctype.renderLiteralPrefix(w, data.kind, ctype_pool); | |
| 8360 | 8405 | wrap.truncate(int, .unsigned, c_bits); |
| 8361 | 8406 | @memset(wrap.limbs[wrap.len..], 0); |
| 8362 | 8407 | wrap.len = wrap.limbs.len; |
| ... | ... | @@ -8399,17 +8444,20 @@ fn formatIntLiteral( |
| 8399 | 8444 | c_limb_ctype = c_limb_info.ctype; |
| 8400 | 8445 | } |
| 8401 | 8446 | |
| 8402 | if (limb_offset > 0) try writer.writeAll(", "); | |
| 8447 | if (limb_offset > 0) try w.writeAll(", "); | |
| 8403 | 8448 | try formatIntLiteral(.{ |
| 8404 | 8449 | .dg = data.dg, |
| 8405 | 8450 | .int_info = c_limb_int_info, |
| 8406 | 8451 | .kind = data.kind, |
| 8407 | 8452 | .ctype = c_limb_ctype, |
| 8408 | .val = try pt.intValue_big(.comptime_int, c_limb_mut.toConst()), | |
| 8409 | }, fmt, options, writer); | |
| 8453 | .val = pt.intValue_big(.comptime_int, c_limb_mut.toConst()) catch | |
| 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 | } |
| 8414 | 8462 | |
| 8415 | 8463 | const Materialize = struct { |
| ... | ... | @@ -8423,8 +8471,8 @@ const Materialize = struct { |
| 8423 | 8471 | } }; |
| 8424 | 8472 | } |
| 8425 | 8473 | |
| 8426 | pub fn mat(self: Materialize, f: *Function, writer: anytype) !void { | |
| 8427 | try f.writeCValue(writer, self.local, .Other); | |
| 8474 | pub fn mat(self: Materialize, f: *Function, w: *Writer) !void { | |
| 8475 | try f.writeCValue(w, self.local, .Other); | |
| 8428 | 8476 | } |
| 8429 | 8477 | |
| 8430 | 8478 | pub fn end(self: Materialize, f: *Function, inst: Air.Inst.Index) !void { |
| ... | ... | @@ -8435,36 +8483,37 @@ const Materialize = struct { |
| 8435 | 8483 | const Assignment = struct { |
| 8436 | 8484 | ctype: CType, |
| 8437 | 8485 | |
| 8438 | pub fn start(f: *Function, writer: anytype, ctype: CType) !Assignment { | |
| 8486 | pub fn start(f: *Function, w: *Writer, ctype: CType) !Assignment { | |
| 8439 | 8487 | const self: Assignment = .{ .ctype = ctype }; |
| 8440 | try self.restart(f, writer); | |
| 8488 | try self.restart(f, w); | |
| 8441 | 8489 | return self; |
| 8442 | 8490 | } |
| 8443 | 8491 | |
| 8444 | pub fn restart(self: Assignment, f: *Function, writer: anytype) !void { | |
| 8492 | pub fn restart(self: Assignment, f: *Function, w: *Writer) !void { | |
| 8445 | 8493 | switch (self.strategy(f)) { |
| 8446 | 8494 | .assign => {}, |
| 8447 | .memcpy => try writer.writeAll("memcpy("), | |
| 8495 | .memcpy => try w.writeAll("memcpy("), | |
| 8448 | 8496 | } |
| 8449 | 8497 | } |
| 8450 | 8498 | |
| 8451 | pub fn assign(self: Assignment, f: *Function, writer: anytype) !void { | |
| 8499 | pub fn assign(self: Assignment, f: *Function, w: *Writer) !void { | |
| 8452 | 8500 | switch (self.strategy(f)) { |
| 8453 | .assign => try writer.writeAll(" = "), | |
| 8454 | .memcpy => try writer.writeAll(", "), | |
| 8501 | .assign => try w.writeAll(" = "), | |
| 8502 | .memcpy => try w.writeAll(", "), | |
| 8455 | 8503 | } |
| 8456 | 8504 | } |
| 8457 | 8505 | |
| 8458 | pub fn end(self: Assignment, f: *Function, writer: anytype) !void { | |
| 8506 | pub fn end(self: Assignment, f: *Function, w: *Writer) !void { | |
| 8459 | 8507 | switch (self.strategy(f)) { |
| 8460 | 8508 | .assign => {}, |
| 8461 | 8509 | .memcpy => { |
| 8462 | try writer.writeAll(", sizeof("); | |
| 8463 | try f.renderCType(writer, self.ctype); | |
| 8464 | try writer.writeAll("))"); | |
| 8510 | try w.writeAll(", sizeof("); | |
| 8511 | try f.renderCType(w, self.ctype); | |
| 8512 | try w.writeAll("))"); | |
| 8465 | 8513 | }, |
| 8466 | 8514 | } |
| 8467 | try writer.writeAll(";\n"); | |
| 8515 | try w.writeByte(';'); | |
| 8516 | try f.object.newline(); | |
| 8468 | 8517 | } |
| 8469 | 8518 | |
| 8470 | 8519 | fn strategy(self: Assignment, f: *Function) enum { assign, memcpy } { |
| ... | ... | @@ -8478,37 +8527,39 @@ const Assignment = struct { |
| 8478 | 8527 | const Vectorize = struct { |
| 8479 | 8528 | index: CValue = .none, |
| 8480 | 8529 | |
| 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 | 8531 | const pt = f.object.dg.pt; |
| 8483 | 8532 | const zcu = pt.zcu; |
| 8484 | 8533 | return if (ty.zigTypeTag(zcu) == .vector) index: { |
| 8485 | 8534 | const local = try f.allocLocal(inst, .usize); |
| 8486 | 8535 | |
| 8487 | try writer.writeAll("for ("); | |
| 8488 | try f.writeCValue(writer, local, .Other); | |
| 8489 | try writer.print(" = {d}; ", .{try f.fmtIntLiteral(.zero_usize)}); | |
| 8490 | try f.writeCValue(writer, local, .Other); | |
| 8491 | try writer.print(" < {d}; ", .{try f.fmtIntLiteral(try pt.intValue(.usize, ty.vectorLen(zcu)))}); | |
| 8492 | try f.writeCValue(writer, local, .Other); | |
| 8493 | try writer.print(" += {d}) {{\n", .{try f.fmtIntLiteral(.one_usize)}); | |
| 8494 | f.object.indent_writer.pushIndent(); | |
| 8536 | try w.writeAll("for ("); | |
| 8537 | try f.writeCValue(w, local, .Other); | |
| 8538 | try w.print(" = {f}; ", .{try f.fmtIntLiteralDec(.zero_usize)}); | |
| 8539 | try f.writeCValue(w, local, .Other); | |
| 8540 | try w.print(" < {f}; ", .{try f.fmtIntLiteralDec(try pt.intValue(.usize, ty.vectorLen(zcu)))}); | |
| 8541 | try f.writeCValue(w, local, .Other); | |
| 8542 | try w.print(" += {f}) {{\n", .{try f.fmtIntLiteralDec(.one_usize)}); | |
| 8543 | f.object.indent(); | |
| 8544 | try f.object.newline(); | |
| 8495 | 8545 | |
| 8496 | 8546 | break :index .{ .index = local }; |
| 8497 | 8547 | } else .{}; |
| 8498 | 8548 | } |
| 8499 | 8549 | |
| 8500 | pub fn elem(self: Vectorize, f: *Function, writer: anytype) !void { | |
| 8550 | pub fn elem(self: Vectorize, f: *Function, w: *Writer) !void { | |
| 8501 | 8551 | if (self.index != .none) { |
| 8502 | try writer.writeByte('['); | |
| 8503 | try f.writeCValue(writer, self.index, .Other); | |
| 8504 | try writer.writeByte(']'); | |
| 8552 | try w.writeByte('['); | |
| 8553 | try f.writeCValue(w, self.index, .Other); | |
| 8554 | try w.writeByte(']'); | |
| 8505 | 8555 | } |
| 8506 | 8556 | } |
| 8507 | 8557 | |
| 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 | 8559 | if (self.index != .none) { |
| 8510 | f.object.indent_writer.popIndent(); | |
| 8511 | try writer.writeAll("}\n"); | |
| 8560 | try f.object.outdent(); | |
| 8561 | try w.writeByte('}'); | |
| 8562 | try f.object.newline(); | |
| 8512 | 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 | 209 | }; |
| 210 | 210 | } |
| 211 | 211 | |
| 212 | pub fn renderLiteralPrefix(ctype: CType, writer: anytype, kind: Kind, pool: *const Pool) @TypeOf(writer).Error!void { | |
| 212 | pub fn renderLiteralPrefix(ctype: CType, w: *Writer, kind: Kind, pool: *const Pool) Writer.Error!void { | |
| 213 | 213 | switch (ctype.info(pool)) { |
| 214 | 214 | .basic => |basic_info| switch (basic_info) { |
| 215 | 215 | .void => unreachable, |
| ... | ... | @@ -224,7 +224,7 @@ pub fn renderLiteralPrefix(ctype: CType, writer: anytype, kind: Kind, pool: *con |
| 224 | 224 | .uintptr_t, |
| 225 | 225 | .intptr_t, |
| 226 | 226 | => switch (kind) { |
| 227 | else => try writer.print("({s})", .{@tagName(basic_info)}), | |
| 227 | else => try w.print("({s})", .{@tagName(basic_info)}), | |
| 228 | 228 | .global => {}, |
| 229 | 229 | }, |
| 230 | 230 | .int, |
| ... | ... | @@ -246,7 +246,7 @@ pub fn renderLiteralPrefix(ctype: CType, writer: anytype, kind: Kind, pool: *con |
| 246 | 246 | .int32_t, |
| 247 | 247 | .uint64_t, |
| 248 | 248 | .int64_t, |
| 249 | => try writer.print("{s}_C(", .{ctype.getStandardDefineAbbrev().?}), | |
| 249 | => try w.print("{s}_C(", .{ctype.getStandardDefineAbbrev().?}), | |
| 250 | 250 | .zig_u128, |
| 251 | 251 | .zig_i128, |
| 252 | 252 | .zig_f16, |
| ... | ... | @@ -255,7 +255,7 @@ pub fn renderLiteralPrefix(ctype: CType, writer: anytype, kind: Kind, pool: *con |
| 255 | 255 | .zig_f80, |
| 256 | 256 | .zig_f128, |
| 257 | 257 | .zig_c_longdouble, |
| 258 | => try writer.print("zig_{s}_{s}(", .{ | |
| 258 | => try w.print("zig_{s}_{s}(", .{ | |
| 259 | 259 | switch (kind) { |
| 260 | 260 | else => "make", |
| 261 | 261 | .global => "init", |
| ... | ... | @@ -265,12 +265,12 @@ pub fn renderLiteralPrefix(ctype: CType, writer: anytype, kind: Kind, pool: *con |
| 265 | 265 | .va_list => unreachable, |
| 266 | 266 | _ => unreachable, |
| 267 | 267 | }, |
| 268 | .array, .vector => try writer.writeByte('{'), | |
| 268 | .array, .vector => try w.writeByte('{'), | |
| 269 | 269 | else => unreachable, |
| 270 | 270 | } |
| 271 | 271 | } |
| 272 | 272 | |
| 273 | pub fn renderLiteralSuffix(ctype: CType, writer: anytype, pool: *const Pool) @TypeOf(writer).Error!void { | |
| 273 | pub fn renderLiteralSuffix(ctype: CType, w: *Writer, pool: *const Pool) Writer.Error!void { | |
| 274 | 274 | switch (ctype.info(pool)) { |
| 275 | 275 | .basic => |basic_info| switch (basic_info) { |
| 276 | 276 | .void => unreachable, |
| ... | ... | @@ -280,20 +280,20 @@ pub fn renderLiteralSuffix(ctype: CType, writer: anytype, pool: *const Pool) @Ty |
| 280 | 280 | .short, |
| 281 | 281 | .int, |
| 282 | 282 | => {}, |
| 283 | .long => try writer.writeByte('l'), | |
| 284 | .@"long long" => try writer.writeAll("ll"), | |
| 283 | .long => try w.writeByte('l'), | |
| 284 | .@"long long" => try w.writeAll("ll"), | |
| 285 | 285 | .@"unsigned char", |
| 286 | 286 | .@"unsigned short", |
| 287 | 287 | .@"unsigned int", |
| 288 | => try writer.writeByte('u'), | |
| 288 | => try w.writeByte('u'), | |
| 289 | 289 | .@"unsigned long", |
| 290 | 290 | .size_t, |
| 291 | 291 | .uintptr_t, |
| 292 | => try writer.writeAll("ul"), | |
| 293 | .@"unsigned long long" => try writer.writeAll("ull"), | |
| 294 | .float => try writer.writeByte('f'), | |
| 292 | => try w.writeAll("ul"), | |
| 293 | .@"unsigned long long" => try w.writeAll("ull"), | |
| 294 | .float => try w.writeByte('f'), | |
| 295 | 295 | .double => {}, |
| 296 | .@"long double" => try writer.writeByte('l'), | |
| 296 | .@"long double" => try w.writeByte('l'), | |
| 297 | 297 | .bool, |
| 298 | 298 | .ptrdiff_t, |
| 299 | 299 | .intptr_t, |
| ... | ... | @@ -314,11 +314,11 @@ pub fn renderLiteralSuffix(ctype: CType, writer: anytype, pool: *const Pool) @Ty |
| 314 | 314 | .zig_f80, |
| 315 | 315 | .zig_f128, |
| 316 | 316 | .zig_c_longdouble, |
| 317 | => try writer.writeByte(')'), | |
| 317 | => try w.writeByte(')'), | |
| 318 | 318 | .va_list => unreachable, |
| 319 | 319 | _ => unreachable, |
| 320 | 320 | }, |
| 321 | .array, .vector => try writer.writeByte('}'), | |
| 321 | .array, .vector => try w.writeByte('}'), | |
| 322 | 322 | else => unreachable, |
| 323 | 323 | } |
| 324 | 324 | } |
| ... | ... | @@ -938,19 +938,13 @@ pub const Pool = struct { |
| 938 | 938 | index: String.Index, |
| 939 | 939 | |
| 940 | 940 | const FormatData = struct { string: String, pool: *const Pool }; |
| 941 | fn format( | |
| 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 ++ "'"); | |
| 941 | fn format(data: FormatData, writer: *Writer) Writer.Error!void { | |
| 948 | 942 | if (data.string.toSlice(data.pool)) |slice| |
| 949 | 943 | try writer.writeAll(slice) |
| 950 | 944 | else |
| 951 | 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 | 948 | return .{ .data = .{ .string = str, .pool = pool } }; |
| 955 | 949 | } |
| 956 | 950 | |
| ... | ... | @@ -2890,7 +2884,7 @@ pub const Pool = struct { |
| 2890 | 2884 | comptime fmt_str: []const u8, |
| 2891 | 2885 | fmt_args: anytype, |
| 2892 | 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 | 2888 | return pool.trailingString(allocator); |
| 2895 | 2889 | } |
| 2896 | 2890 | |
| ... | ... | @@ -3281,10 +3275,12 @@ pub const AlignAs = packed struct { |
| 3281 | 3275 | } |
| 3282 | 3276 | }; |
| 3283 | 3277 | |
| 3278 | const std = @import("std"); | |
| 3284 | 3279 | const assert = std.debug.assert; |
| 3280 | const Writer = std.io.Writer; | |
| 3281 | ||
| 3285 | 3282 | const CType = @This(); |
| 3286 | 3283 | const InternPool = @import("../../InternPool.zig"); |
| 3287 | 3284 | const Module = @import("../../Package/Module.zig"); |
| 3288 | const std = @import("std"); | |
| 3289 | 3285 | const Type = @import("../../Type.zig"); |
| 3290 | 3286 | const 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 | 239 | .none, |
| 240 | 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 | 243 | ver.min.major, |
| 244 | 244 | ver.min.minor, |
| 245 | 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 | 248 | ver.range.min.major, |
| 249 | 249 | ver.range.min.minor, |
| 250 | 250 | ver.range.min.patch, |
| ... | ... | @@ -295,13 +295,13 @@ pub fn targetTriple(allocator: Allocator, target: *const std.Target) ![]const u8 |
| 295 | 295 | .windows, |
| 296 | 296 | => {}, |
| 297 | 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 | 299 | ver.glibc.major, |
| 300 | 300 | ver.glibc.minor, |
| 301 | 301 | ver.glibc.patch, |
| 302 | 302 | }); |
| 303 | 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 | } |
| 307 | 307 | |
| ... | ... | @@ -746,12 +746,18 @@ pub const Object = struct { |
| 746 | 746 | try wip.finish(); |
| 747 | 747 | } |
| 748 | 748 | |
| 749 | fn genModuleLevelAssembly(object: *Object) !void { | |
| 750 | const writer = object.builder.setModuleAsm(); | |
| 749 | fn genModuleLevelAssembly(object: *Object) Allocator.Error!void { | |
| 750 | const b = &object.builder; | |
| 751 | const gpa = b.gpa; | |
| 752 | b.module_asm.clearRetainingCapacity(); | |
| 751 | 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 | } |
| 756 | 762 | |
| 757 | 763 | pub const EmitOptions = struct { |
| ... | ... | @@ -939,7 +945,9 @@ pub const Object = struct { |
| 939 | 945 | if (std.mem.eql(u8, path, "-")) { |
| 940 | 946 | o.builder.dump(); |
| 941 | 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 | } |
| 945 | 953 | |
| ... | ... | @@ -2486,7 +2494,7 @@ pub const Object = struct { |
| 2486 | 2494 | var union_name_buf: ?[:0]const u8 = null; |
| 2487 | 2495 | defer if (union_name_buf) |buf| gpa.free(buf); |
| 2488 | 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 | 2498 | break :name union_name_buf.?; |
| 2491 | 2499 | }; |
| 2492 | 2500 | |
| ... | ... | @@ -2680,10 +2688,12 @@ pub const Object = struct { |
| 2680 | 2688 | } |
| 2681 | 2689 | |
| 2682 | 2690 | fn allocTypeName(o: *Object, ty: Type) Allocator.Error![:0]const u8 { |
| 2683 | var buffer = std.ArrayList(u8).init(o.gpa); | |
| 2684 | errdefer buffer.deinit(); | |
| 2685 | try ty.print(buffer.writer(), o.pt); | |
| 2686 | return buffer.toOwnedSliceSentinel(0); | |
| 2691 | var aw: std.io.Writer.Allocating = .init(o.gpa); | |
| 2692 | defer aw.deinit(); | |
| 2693 | ty.print(&aw.writer, o.pt) catch |err| switch (err) { | |
| 2694 | error.WriteFailed => return error.OutOfMemory, | |
| 2695 | }; | |
| 2696 | return aw.toOwnedSliceSentinel(0); | |
| 2687 | 2697 | } |
| 2688 | 2698 | |
| 2689 | 2699 | /// If the llvm function does not exist, create it. |
| ... | ... | @@ -4482,7 +4492,7 @@ pub const Object = struct { |
| 4482 | 4492 | const target = &zcu.root_mod.resolved_target.result; |
| 4483 | 4493 | const function_index = try o.builder.addFunction( |
| 4484 | 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 | 4496 | toLlvmAddressSpace(.generic, target), |
| 4487 | 4497 | ); |
| 4488 | 4498 | |
| ... | ... | @@ -4633,7 +4643,7 @@ pub const NavGen = struct { |
| 4633 | 4643 | if (zcu.getTarget().cpu.arch.isWasm() and ty.zigTypeTag(zcu) == .@"fn") { |
| 4634 | 4644 | if (lib_name.toSlice(ip)) |lib_name_slice| { |
| 4635 | 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 | 7482 | llvm_param_types[llvm_param_i] = llvm_elem_ty; |
| 7473 | 7483 | } |
| 7474 | 7484 | |
| 7475 | try llvm_constraints.writer(self.gpa).print(",{d}", .{output_index}); | |
| 7485 | try llvm_constraints.print(self.gpa, ",{d}", .{output_index}); | |
| 7476 | 7486 | |
| 7477 | 7487 | // In the case of indirect inputs, LLVM requires the callsite to have |
| 7478 | 7488 | // an elementtype(<ty>) attribute. |
| ... | ... | @@ -7573,7 +7583,7 @@ pub const FuncGen = struct { |
| 7573 | 7583 | // we should validate the assembly in Sema; by now it is too late |
| 7574 | 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 | 7587 | if (byte == ':') { |
| 7578 | 7588 | try rendered_template.append(':'); |
| 7579 | 7589 | modifier_start = i + 1; |
| ... | ... | @@ -10370,7 +10380,7 @@ pub const FuncGen = struct { |
| 10370 | 10380 | const target = &zcu.root_mod.resolved_target.result; |
| 10371 | 10381 | const function_index = try o.builder.addFunction( |
| 10372 | 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 | 10384 | toLlvmAddressSpace(.generic, target), |
| 10375 | 10385 | ); |
| 10376 | 10386 |
src/codegen/spirv.zig+10-8| ... | ... | @@ -817,7 +817,7 @@ const NavGen = struct { |
| 817 | 817 | const result_ty_id = try self.resolveType(ty, repr); |
| 818 | 818 | const ip = &zcu.intern_pool; |
| 819 | 819 | |
| 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 | 821 | if (val.isUndefDeep(zcu)) { |
| 822 | 822 | return self.spv.constUndef(result_ty_id); |
| 823 | 823 | } |
| ... | ... | @@ -1147,7 +1147,7 @@ const NavGen = struct { |
| 1147 | 1147 | return result_ptr_id; |
| 1148 | 1148 | } |
| 1149 | 1149 | |
| 1150 | return self.fail("cannot perform pointer cast: '{}' to '{}'", .{ | |
| 1150 | return self.fail("cannot perform pointer cast: '{f}' to '{f}'", .{ | |
| 1151 | 1151 | parent_ptr_ty.fmt(pt), |
| 1152 | 1152 | oac.new_ptr_ty.fmt(pt), |
| 1153 | 1153 | }); |
| ... | ... | @@ -1260,10 +1260,12 @@ const NavGen = struct { |
| 1260 | 1260 | |
| 1261 | 1261 | // Turn a Zig type's name into a cache reference. |
| 1262 | 1262 | fn resolveTypeName(self: *NavGen, ty: Type) ![]const u8 { |
| 1263 | var name = std.ArrayList(u8).init(self.gpa); | |
| 1264 | defer name.deinit(); | |
| 1265 | try ty.print(name.writer(), self.pt); | |
| 1266 | return try name.toOwnedSlice(); | |
| 1263 | var aw: std.io.Writer.Allocating = .init(self.gpa); | |
| 1264 | defer aw.deinit(); | |
| 1265 | ty.print(&aw.writer, self.pt) catch |err| switch (err) { | |
| 1266 | error.WriteFailed => return error.OutOfMemory, | |
| 1267 | }; | |
| 1268 | return try aw.toOwnedSlice(); | |
| 1267 | 1269 | } |
| 1268 | 1270 | |
| 1269 | 1271 | /// Create an integer type suitable for storing at least 'bits' bits. |
| ... | ... | @@ -1462,7 +1464,7 @@ const NavGen = struct { |
| 1462 | 1464 | const pt = self.pt; |
| 1463 | 1465 | const zcu = pt.zcu; |
| 1464 | 1466 | const ip = &zcu.intern_pool; |
| 1465 | log.debug("resolveType: ty = {}", .{ty.fmt(pt)}); | |
| 1467 | log.debug("resolveType: ty = {f}", .{ty.fmt(pt)}); | |
| 1466 | 1468 | const target = self.spv.target; |
| 1467 | 1469 | |
| 1468 | 1470 | const section = &self.spv.sections.types_globals_constants; |
| ... | ... | @@ -3068,7 +3070,7 @@ const NavGen = struct { |
| 3068 | 3070 | try self.func.body.emit(self.spv.gpa, .OpFunctionEnd, {}); |
| 3069 | 3071 | try self.spv.addFunction(spv_decl_index, self.func); |
| 3070 | 3072 | |
| 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)}); | |
| 3072 | 3074 | |
| 3073 | 3075 | try self.spv.sections.types_globals_constants.emit(self.spv.gpa, .OpExtInst, .{ |
| 3074 | 3076 | .id_result_type = ptr_ty_id, |
src/codegen/spirv/spec.zig+3-7| ... | ... | @@ -1,6 +1,7 @@ |
| 1 | 1 | //! This file is auto-generated by tools/gen_spirv_spec.zig. |
| 2 | 2 | |
| 3 | 3 | const std = @import("std"); |
| 4 | const assert = std.debug.assert; | |
| 4 | 5 | |
| 5 | 6 | pub const Version = packed struct(Word) { |
| 6 | 7 | padding: u8 = 0, |
| ... | ... | @@ -18,15 +19,10 @@ pub const IdResult = enum(Word) { |
| 18 | 19 | none, |
| 19 | 20 | _, |
| 20 | 21 | |
| 21 | pub fn format( | |
| 22 | self: IdResult, | |
| 23 | comptime _: []const u8, | |
| 24 | _: std.fmt.FormatOptions, | |
| 25 | writer: anytype, | |
| 26 | ) @TypeOf(writer).Error!void { | |
| 22 | pub fn format(self: IdResult, writer: *std.io.Writer) std.io.Writer.Error!void { | |
| 27 | 23 | switch (self) { |
| 28 | 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 | 80 | var fba = std.heap.FixedBufferAllocator.init(&crash_heap); |
| 81 | 81 | const allocator = fba.allocator(); |
| 82 | 82 | |
| 83 | const stderr = io.getStdErr().writer(); | |
| 83 | var stderr_fw = std.fs.File.stderr().writer(&.{}); | |
| 84 | const stderr = &stderr_fw.interface; | |
| 84 | 85 | const block: *Sema.Block = anal.block; |
| 85 | 86 | const zcu = anal.sema.pt.zcu; |
| 86 | 87 | |
| 87 | 88 | const file, const src_base_node = Zcu.LazySrcLoc.resolveBaseNode(block.src_base_inst, zcu) orelse { |
| 88 | 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 | 91 | return; |
| 91 | 92 | }; |
| 92 | 93 | |
| 93 | 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)}); | |
| 95 | 96 | |
| 96 | 97 | print_zir.renderInstructionContext( |
| 97 | 98 | allocator, |
| ... | ... | @@ -107,7 +108,7 @@ fn dumpStatusReport() !void { |
| 107 | 108 | }; |
| 108 | 109 | try stderr.print( |
| 109 | 110 | \\ For full context, use the command |
| 110 | \\ zig ast-check -t {} | |
| 111 | \\ zig ast-check -t {f} | |
| 111 | 112 | \\ |
| 112 | 113 | \\ |
| 113 | 114 | , .{file.path.fmt(zcu.comp)}); |
| ... | ... | @@ -116,7 +117,7 @@ fn dumpStatusReport() !void { |
| 116 | 117 | while (parent) |curr| { |
| 117 | 118 | fba.reset(); |
| 118 | 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 | 121 | _, const cur_block_src_base_node = Zcu.LazySrcLoc.resolveBaseNode(curr.block.src_base_inst, zcu) orelse { |
| 121 | 122 | try stderr.writeAll(" > [lost instruction; this should not happen]\n"); |
| 122 | 123 | parent = curr.parent; |
| ... | ... | @@ -139,7 +140,7 @@ fn dumpStatusReport() !void { |
| 139 | 140 | parent = curr.parent; |
| 140 | 141 | } |
| 141 | 142 | |
| 142 | try stderr.writeAll("\n"); | |
| 143 | try stderr.writeByte('\n'); | |
| 143 | 144 | } |
| 144 | 145 | |
| 145 | 146 | var crash_heap: [16 * 4096]u8 = undefined; |
| ... | ... | @@ -268,11 +269,12 @@ const StackContext = union(enum) { |
| 268 | 269 | debug.dumpCurrentStackTrace(ct.ret_addr); |
| 269 | 270 | }, |
| 270 | 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 | 276 | .not_supported => { |
| 274 | const stderr = io.getStdErr().writer(); | |
| 275 | stderr.writeAll("Stack trace not supported on this platform.\n") catch {}; | |
| 277 | std.fs.File.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 | 381 | |
| 380 | 382 | state.recover_stage = .release_mutex; |
| 381 | 383 | |
| 382 | const stderr = io.getStdErr().writer(); | |
| 384 | var stderr_fw = std.fs.File.stderr().writer(&.{}); | |
| 385 | const stderr = &stderr_fw.interface; | |
| 383 | 386 | if (builtin.single_threaded) { |
| 384 | 387 | stderr.print("panic: ", .{}) catch goTo(releaseMutex, .{state}); |
| 385 | 388 | } else { |
| ... | ... | @@ -406,7 +409,8 @@ const PanicSwitch = struct { |
| 406 | 409 | recover(state, trace, stack, msg); |
| 407 | 410 | |
| 408 | 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 | 414 | stderr.writeAll("\nOriginal Error:\n") catch {}; |
| 411 | 415 | goTo(reportStack, .{state}); |
| 412 | 416 | } |
| ... | ... | @@ -477,7 +481,8 @@ const PanicSwitch = struct { |
| 477 | 481 | recover(state, trace, stack, msg); |
| 478 | 482 | |
| 479 | 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 | 486 | stderr.writeAll("Aborting...\n") catch {}; |
| 482 | 487 | goTo(abort, .{}); |
| 483 | 488 | } |
| ... | ... | @@ -505,7 +510,8 @@ const PanicSwitch = struct { |
| 505 | 510 | // lower the verbosity, and restore it at the end if we don't panic. |
| 506 | 511 | state.recover_verbosity = .message_only; |
| 507 | 512 | |
| 508 | const stderr = io.getStdErr().writer(); | |
| 513 | var stderr_fw = std.fs.File.stderr().writer(&.{}); | |
| 514 | const stderr = &stderr_fw.interface; | |
| 509 | 515 | stderr.writeAll("\nPanicked during a panic: ") catch {}; |
| 510 | 516 | stderr.writeAll(msg) catch {}; |
| 511 | 517 | stderr.writeAll("\nInner panic stack:\n") catch {}; |
| ... | ... | @@ -519,10 +525,11 @@ const PanicSwitch = struct { |
| 519 | 525 | .message_only => { |
| 520 | 526 | state.recover_verbosity = .silent; |
| 521 | 527 | |
| 522 | const stderr = io.getStdErr().writer(); | |
| 528 | var stderr_fw = std.fs.File.stderr().writer(&.{}); | |
| 529 | const stderr = &stderr_fw.interface; | |
| 523 | 530 | stderr.writeAll("\nPanicked while dumping inner panic stack: ") catch {}; |
| 524 | 531 | stderr.writeAll(msg) catch {}; |
| 525 | stderr.writeAll("\n") catch {}; | |
| 532 | stderr.writeByte('\n') catch {}; | |
| 526 | 533 | |
| 527 | 534 | // If we succeed, restore all the way to dumping the stack. |
| 528 | 535 | state.recover_verbosity = .message_and_stack; |
src/deprecated.zig created+431| ... | ... | @@ -0,0 +1,431 @@ |
| 1 | //! Deprecated. Stop using this API | |
| 2 | ||
| 3 | const std = @import("std"); | |
| 4 | const math = std.math; | |
| 5 | const mem = std.mem; | |
| 6 | const Allocator = mem.Allocator; | |
| 7 | const assert = std.debug.assert; | |
| 8 | const testing = std.testing; | |
| 9 | ||
| 10 | pub 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 | ||
| 304 | test "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 | ||
| 312 | test "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 | ||
| 400 | test 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 | 78 | .ast_gen, |
| 79 | 79 | .sema, |
| 80 | 80 | .legalize, |
| 81 | .c_compiler, | |
| 81 | 82 | .llvm_backend, |
| 82 | 83 | .c_backend, |
| 83 | 84 | .wasm_backend, |
| ... | ... | @@ -127,6 +128,7 @@ pub const Env = enum { |
| 127 | 128 | .clang_command, |
| 128 | 129 | .cc_command, |
| 129 | 130 | .translate_c_command, |
| 131 | .c_compiler, | |
| 130 | 132 | => true, |
| 131 | 133 | else => false, |
| 132 | 134 | }, |
| ... | ... | @@ -152,6 +154,7 @@ pub const Env = enum { |
| 152 | 154 | else => Env.ast_gen.supports(feature), |
| 153 | 155 | }, |
| 154 | 156 | .cbe => switch (feature) { |
| 157 | .legalize, | |
| 155 | 158 | .c_backend, |
| 156 | 159 | .c_linker, |
| 157 | 160 | => true, |
| ... | ... | @@ -248,6 +251,8 @@ pub const Feature = enum { |
| 248 | 251 | sema, |
| 249 | 252 | legalize, |
| 250 | 253 | |
| 254 | c_compiler, | |
| 255 | ||
| 251 | 256 | llvm_backend, |
| 252 | 257 | c_backend, |
| 253 | 258 | wasm_backend, |
src/fmt.zig+13-13| ... | ... | @@ -1,3 +1,11 @@ |
| 1 | const std = @import("std"); | |
| 2 | const mem = std.mem; | |
| 3 | const fs = std.fs; | |
| 4 | const process = std.process; | |
| 5 | const Allocator = std.mem.Allocator; | |
| 6 | const Color = std.zig.Color; | |
| 7 | const fatal = std.process.fatal; | |
| 8 | ||
| 1 | 9 | const usage_fmt = |
| 2 | 10 | \\Usage: zig fmt [file]... |
| 3 | 11 | \\ |
| ... | ... | @@ -52,7 +60,7 @@ pub fn run( |
| 52 | 60 | const arg = args[i]; |
| 53 | 61 | if (mem.startsWith(u8, arg, "-")) { |
| 54 | 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 | 64 | try stdout.writeAll(usage_fmt); |
| 57 | 65 | return process.cleanExit(); |
| 58 | 66 | } else if (mem.eql(u8, arg, "--color")) { |
| ... | ... | @@ -93,7 +101,7 @@ pub fn run( |
| 93 | 101 | fatal("cannot use --stdin with positional arguments", .{}); |
| 94 | 102 | } |
| 95 | 103 | |
| 96 | const stdin = std.io.getStdIn(); | |
| 104 | const stdin: fs.File = .stdin(); | |
| 97 | 105 | const source_code = std.zig.readSourceFileToEndAlloc(gpa, stdin, null) catch |err| { |
| 98 | 106 | fatal("unable to read stdin: {}", .{err}); |
| 99 | 107 | }; |
| ... | ... | @@ -146,7 +154,7 @@ pub fn run( |
| 146 | 154 | process.exit(code); |
| 147 | 155 | } |
| 148 | 156 | |
| 149 | return std.io.getStdOut().writeAll(formatted); | |
| 157 | return std.fs.File.stdout().writeAll(formatted); | |
| 150 | 158 | } |
| 151 | 159 | |
| 152 | 160 | if (input_files.items.len == 0) { |
| ... | ... | @@ -363,7 +371,7 @@ fn fmtPathFile( |
| 363 | 371 | return; |
| 364 | 372 | |
| 365 | 373 | if (check_mode) { |
| 366 | const stdout = std.io.getStdOut().writer(); | |
| 374 | const stdout = std.fs.File.stdout().deprecatedWriter(); | |
| 367 | 375 | try stdout.print("{s}\n", .{file_path}); |
| 368 | 376 | fmt.any_error = true; |
| 369 | 377 | } else { |
| ... | ... | @@ -372,15 +380,7 @@ fn fmtPathFile( |
| 372 | 380 | |
| 373 | 381 | try af.file.writeAll(fmt.out_buffer.items); |
| 374 | 382 | try af.finish(); |
| 375 | const stdout = std.io.getStdOut().writer(); | |
| 383 | const stdout = std.fs.File.stdout().deprecatedWriter(); | |
| 376 | 384 | try stdout.print("{s}\n", .{file_path}); |
| 377 | 385 | } |
| 378 | 386 | } |
| 379 | ||
| 380 | const std = @import("std"); | |
| 381 | const mem = std.mem; | |
| 382 | const fs = std.fs; | |
| 383 | const process = std.process; | |
| 384 | const Allocator = std.mem.Allocator; | |
| 385 | const Color = std.zig.Color; | |
| 386 | const 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 | 497 | .lt => continue, |
| 498 | 498 | .gt => { |
| 499 | 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 | 501 | return error.InvalidTargetLibCVersion; |
| 502 | 502 | }, |
| 503 | 503 | } |
| 504 | 504 | } else blk: { |
| 505 | 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 | 507 | target_version, metadata.all_versions[latest_index], |
| 508 | 508 | }); |
| 509 | 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 | 736 | .lt => continue, |
| 737 | 737 | .gt => { |
| 738 | 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 | 740 | return error.InvalidTargetGLibCVersion; |
| 741 | 741 | }, |
| 742 | 742 | } |
| 743 | 743 | } else blk: { |
| 744 | 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 | 746 | target_version, metadata.all_versions[latest_index], |
| 747 | 747 | }); |
| 748 | 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 | 268 | const skip_linker_dependencies = !target.os.tag.isDarwin(); |
| 269 | 269 | const linker_allow_shlib_undefined = target.os.tag.isDarwin(); |
| 270 | 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 | 272 | else |
| 273 | 273 | null; |
| 274 | 274 | // 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 | 306 | if (comp.verbose_cc) print: { |
| 307 | 307 | std.debug.lockStdErr(); |
| 308 | 308 | defer std.debug.unlockStdErr(); |
| 309 | const stderr = std.io.getStdErr().writer(); | |
| 309 | const stderr = std.fs.File.stderr().deprecatedWriter(); | |
| 310 | 310 | nosuspend stderr.print("def file: {s}\n", .{def_file_path}) catch break :print; |
| 311 | 311 | nosuspend stderr.print("include dir: {s}\n", .{include_dir}) catch break :print; |
| 312 | 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 | 326 | |
| 327 | 327 | for (aro_comp.diagnostics.list.items) |diagnostic| { |
| 328 | 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 | 330 | return error.AroPreprocessorFailed; |
| 331 | 331 | } |
| 332 | 332 | } |
| ... | ... | @@ -335,7 +335,7 @@ pub fn buildImportLib(comp: *Compilation, lib_name: []const u8) !void { |
| 335 | 335 | // new scope to ensure definition file is written before passing the path to WriteImportLibrary |
| 336 | 336 | const def_final_file = try o_dir.createFile(final_def_basename, .{ .truncate = true }); |
| 337 | 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 | } |
| 340 | 340 | |
| 341 | 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 | 442 | .lt => continue, |
| 443 | 443 | .gt => { |
| 444 | 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 | 446 | return error.InvalidTargetLibCVersion; |
| 447 | 447 | }, |
| 448 | 448 | } |
| 449 | 449 | } else blk: { |
| 450 | 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 | 452 | target_version, metadata.all_versions[latest_index], |
| 453 | 453 | }); |
| 454 | 454 | break :blk latest_index; |
src/link.zig+30-28| ... | ... | @@ -323,7 +323,7 @@ pub const Diags = struct { |
| 323 | 323 | const main_msg = try m; |
| 324 | 324 | errdefer gpa.free(main_msg); |
| 325 | 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 | 327 | errdefer gpa.free(note); |
| 328 | 328 | const notes = try gpa.create([1]Msg); |
| 329 | 329 | errdefer gpa.destroy(notes); |
| ... | ... | @@ -838,8 +838,10 @@ pub const File = struct { |
| 838 | 838 | const cached_pp_file_path = the_key.status.success.object_path; |
| 839 | 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 | 840 | const diags = &base.comp.link_diags; |
| 841 | return diags.fail("failed to copy '{'}' to '{'}': {s}", .{ | |
| 842 | @as(Path, cached_pp_file_path), @as(Path, emit), @errorName(err), | |
| 841 | return diags.fail("failed to copy '{f}' to '{f}': {s}", .{ | |
| 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 | 847 | return; |
| ... | ... | @@ -1351,7 +1353,7 @@ pub fn doPrelinkTask(comp: *Compilation, task: PrelinkTask) void { |
| 1351 | 1353 | .search_strategy = .paths_first, |
| 1352 | 1354 | }) catch |archive_err| switch (archive_err) { |
| 1353 | 1355 | 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 | 1359 | error.LinkFailure => return, // error reported via diags |
| ... | ... | @@ -1874,7 +1876,7 @@ pub fn resolveInputs( |
| 1874 | 1876 | )) |lib_result| { |
| 1875 | 1877 | switch (lib_result) { |
| 1876 | 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 | 1882 | continue; |
| ... | ... | @@ -1928,10 +1930,10 @@ fn resolveLibInput( |
| 1928 | 1930 | .root_dir = lib_directory, |
| 1929 | 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 | 1934 | var file = test_path.root_dir.handle.openFile(test_path.sub_path, .{}) catch |err| switch (err) { |
| 1933 | 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 | 1938 | errdefer file.close(); |
| 1937 | 1939 | return finishResolveLibInput(resolved_inputs, test_path, file, link_mode, name_query.query); |
| ... | ... | @@ -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 | 1953 | switch (try resolvePathInputLib(gpa, arena, unresolved_inputs, resolved_inputs, ld_script_bytes, target, .{ |
| 1952 | 1954 | .path = test_path, |
| 1953 | 1955 | .query = name_query.query, |
| ... | ... | @@ -1964,10 +1966,10 @@ fn resolveLibInput( |
| 1964 | 1966 | .root_dir = lib_directory, |
| 1965 | 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 | 1970 | var file = test_path.root_dir.handle.openFile(test_path.sub_path, .{}) catch |err| switch (err) { |
| 1969 | 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 | 1973 | test_path, @errorName(e), |
| 1972 | 1974 | }), |
| 1973 | 1975 | }; |
| ... | ... | @@ -1982,10 +1984,10 @@ fn resolveLibInput( |
| 1982 | 1984 | .root_dir = lib_directory, |
| 1983 | 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 | 1988 | var file = test_path.root_dir.handle.openFile(test_path.sub_path, .{}) catch |err| switch (err) { |
| 1987 | 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 | 1992 | errdefer file.close(); |
| 1991 | 1993 | return finishResolveLibInput(resolved_inputs, test_path, file, link_mode, name_query.query); |
| ... | ... | @@ -2037,7 +2039,7 @@ fn resolvePathInput( |
| 2037 | 2039 | .shared_library => return try resolvePathInputLib(gpa, arena, unresolved_inputs, resolved_inputs, ld_script_bytes, target, pq, .dynamic, color), |
| 2038 | 2040 | .object => { |
| 2039 | 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 | 2043 | errdefer file.close(); |
| 2042 | 2044 | try resolved_inputs.append(gpa, .{ .object = .{ |
| 2043 | 2045 | .path = pq.path, |
| ... | ... | @@ -2049,7 +2051,7 @@ fn resolvePathInput( |
| 2049 | 2051 | }, |
| 2050 | 2052 | .res => { |
| 2051 | 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 | 2055 | errdefer file.close(); |
| 2054 | 2056 | try resolved_inputs.append(gpa, .{ .res = .{ |
| 2055 | 2057 | .path = pq.path, |
| ... | ... | @@ -2057,7 +2059,7 @@ fn resolvePathInput( |
| 2057 | 2059 | } }); |
| 2058 | 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 | } |
| 2063 | 2065 | |
| ... | ... | @@ -2086,14 +2088,14 @@ fn resolvePathInputLib( |
| 2086 | 2088 | }) { |
| 2087 | 2089 | var file = test_path.root_dir.handle.openFile(test_path.sub_path, .{}) catch |err| switch (err) { |
| 2088 | 2090 | error.FileNotFound => return .no_match, |
| 2089 | else => |e| fatal("unable to search for {s} library '{'}': {s}", .{ | |
| 2090 | @tagName(link_mode), test_path, @errorName(e), | |
| 2091 | else => |e| fatal("unable to search for {s} library '{f}': {s}", .{ | |
| 2092 | @tagName(link_mode), std.fmt.alt(test_path, .formatEscapeChar), @errorName(e), | |
| 2091 | 2093 | }), |
| 2092 | 2094 | }; |
| 2093 | 2095 | errdefer file.close(); |
| 2094 | 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}", .{ | |
| 2096 | test_path, @errorName(err), | |
| 2097 | const n = file.preadAll(ld_script_bytes.items, 0) catch |err| fatal("failed to read '{f}': {s}", .{ | |
| 2098 | std.fmt.alt(test_path, .formatEscapeChar), @errorName(err), | |
| 2097 | 2099 | }); |
| 2098 | 2100 | const buf = ld_script_bytes.items[0..n]; |
| 2099 | 2101 | if (mem.startsWith(u8, buf, std.elf.MAGIC) or mem.startsWith(u8, buf, std.elf.ARMAG)) { |
| ... | ... | @@ -2101,14 +2103,14 @@ fn resolvePathInputLib( |
| 2101 | 2103 | return finishResolveLibInput(resolved_inputs, test_path, file, link_mode, pq.query); |
| 2102 | 2104 | } |
| 2103 | 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 | 2107 | 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 | 2109 | try ld_script_bytes.resize(gpa, size); |
| 2108 | 2110 | const buf2 = ld_script_bytes.items[n..]; |
| 2109 | 2111 | const n2 = file.preadAll(buf2, n) catch |err| |
| 2110 | fatal("failed to read {}: {s}", .{ test_path, @errorName(err) }); | |
| 2111 | if (n2 != buf2.len) fatal("failed to read {}: unexpected end of file", .{test_path}); | |
| 2112 | fatal("failed to read {f}: {s}", .{ test_path, @errorName(err) }); | |
| 2113 | if (n2 != buf2.len) fatal("failed to read {f}: unexpected end of file", .{test_path}); | |
| 2112 | 2114 | var diags = Diags.init(gpa); |
| 2113 | 2115 | defer diags.deinit(); |
| 2114 | 2116 | const ld_script_result = LdScript.parse(gpa, &diags, test_path, ld_script_bytes.items); |
| ... | ... | @@ -2128,7 +2130,7 @@ fn resolvePathInputLib( |
| 2128 | 2130 | } |
| 2129 | 2131 | |
| 2130 | 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 | 2134 | defer ld_script.deinit(gpa); |
| 2133 | 2135 | |
| 2134 | 2136 | try unresolved_inputs.ensureUnusedCapacity(gpa, ld_script.args.len); |
| ... | ... | @@ -2159,7 +2161,7 @@ fn resolvePathInputLib( |
| 2159 | 2161 | |
| 2160 | 2162 | var file = test_path.root_dir.handle.openFile(test_path.sub_path, .{}) catch |err| switch (err) { |
| 2161 | 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 | 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 | 2194 | |
| 2193 | 2195 | pub fn openObjectInput(diags: *Diags, path: Path) error{LinkFailure}!Input { |
| 2194 | 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 | } |
| 2198 | 2200 | |
| 2199 | 2201 | pub fn openArchiveInput(diags: *Diags, path: Path, must_link: bool, hidden: bool) error{LinkFailure}!Input { |
| 2200 | 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 | } |
| 2204 | 2206 | |
| 2205 | 2207 | pub fn openDsoInput(diags: *Diags, path: Path, needed: bool, weak: bool, reexport: bool) error{LinkFailure}!Input { |
| 2206 | 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 | } |
| 2210 | 2212 |
src/link/C.zig+177-153| ... | ... | @@ -25,34 +25,34 @@ base: link.File, |
| 25 | 25 | /// This linker backend does not try to incrementally link output C source code. |
| 26 | 26 | /// Instead, it tracks all declarations in this table, and iterates over it |
| 27 | 27 | /// in the flush function, stitching pre-rendered pieces of C code together. |
| 28 | navs: std.AutoArrayHashMapUnmanaged(InternPool.Nav.Index, AvBlock) = .empty, | |
| 28 | navs: std.AutoArrayHashMapUnmanaged(InternPool.Nav.Index, AvBlock), | |
| 29 | 29 | /// All the string bytes of rendered C code, all squished into one array. |
| 30 | 30 | /// While in progress, a separate buffer is used, and then when finished, the |
| 31 | 31 | /// buffer is copied into this one. |
| 32 | string_bytes: std.ArrayListUnmanaged(u8) = .empty, | |
| 32 | string_bytes: std.ArrayListUnmanaged(u8), | |
| 33 | 33 | /// Tracks all the anonymous decls that are used by all the decls so they can |
| 34 | 34 | /// be rendered during flush(). |
| 35 | uavs: std.AutoArrayHashMapUnmanaged(InternPool.Index, AvBlock) = .empty, | |
| 35 | uavs: std.AutoArrayHashMapUnmanaged(InternPool.Index, AvBlock), | |
| 36 | 36 | /// Sparse set of uavs that are overaligned. Underaligned anon decls are |
| 37 | 37 | /// lowered the same as ABI-aligned anon decls. The keys here are a subset of |
| 38 | 38 | /// the keys of `uavs`. |
| 39 | aligned_uavs: std.AutoArrayHashMapUnmanaged(InternPool.Index, Alignment) = .empty, | |
| 39 | aligned_uavs: std.AutoArrayHashMapUnmanaged(InternPool.Index, Alignment), | |
| 40 | 40 | |
| 41 | exported_navs: std.AutoArrayHashMapUnmanaged(InternPool.Nav.Index, ExportedBlock) = .empty, | |
| 42 | exported_uavs: std.AutoArrayHashMapUnmanaged(InternPool.Index, ExportedBlock) = .empty, | |
| 41 | exported_navs: std.AutoArrayHashMapUnmanaged(InternPool.Nav.Index, ExportedBlock), | |
| 42 | exported_uavs: std.AutoArrayHashMapUnmanaged(InternPool.Index, ExportedBlock), | |
| 43 | 43 | |
| 44 | 44 | /// Optimization, `updateDecl` reuses this buffer rather than creating a new |
| 45 | 45 | /// one with every call. |
| 46 | fwd_decl_buf: std.ArrayListUnmanaged(u8) = .empty, | |
| 46 | fwd_decl_buf: []u8, | |
| 47 | 47 | /// Optimization, `updateDecl` reuses this buffer rather than creating a new |
| 48 | 48 | /// one with every call. |
| 49 | code_buf: std.ArrayListUnmanaged(u8) = .empty, | |
| 50 | /// Optimization, `flush` reuses this buffer rather than creating a new | |
| 49 | code_header_buf: []u8, | |
| 50 | /// Optimization, `updateDecl` reuses this buffer rather than creating a new | |
| 51 | 51 | /// one with every call. |
| 52 | lazy_fwd_decl_buf: std.ArrayListUnmanaged(u8) = .empty, | |
| 52 | code_buf: []u8, | |
| 53 | 53 | /// Optimization, `flush` reuses this buffer rather than creating a new |
| 54 | 54 | /// one with every call. |
| 55 | lazy_code_buf: std.ArrayListUnmanaged(u8) = .empty, | |
| 55 | scratch_buf: []u32, | |
| 56 | 56 | |
| 57 | 57 | /// A reference into `string_bytes`. |
| 58 | 58 | const String = extern struct { |
| ... | ... | @@ -63,15 +63,23 @@ const String = extern struct { |
| 63 | 63 | .start = 0, |
| 64 | 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 | }; |
| 67 | 75 | |
| 68 | 76 | /// Per-declaration data. |
| 69 | 77 | pub const AvBlock = struct { |
| 70 | code: String = String.empty, | |
| 71 | fwd_decl: String = String.empty, | |
| 78 | fwd_decl: String = .empty, | |
| 79 | code: String = .empty, | |
| 72 | 80 | /// Each `Decl` stores a set of used `CType`s. In `flush()`, we iterate |
| 73 | 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 | 83 | /// May contain string references to ctype_pool |
| 76 | 84 | lazy_fns: codegen.LazyFnMap = .{}, |
| 77 | 85 | |
| ... | ... | @@ -84,7 +92,7 @@ pub const AvBlock = struct { |
| 84 | 92 | |
| 85 | 93 | /// Per-exported-symbol data. |
| 86 | 94 | pub const ExportedBlock = struct { |
| 87 | fwd_decl: String = String.empty, | |
| 95 | fwd_decl: String = .empty, | |
| 88 | 96 | }; |
| 89 | 97 | |
| 90 | 98 | pub fn getString(this: C, s: String) []const u8 { |
| ... | ... | @@ -147,6 +155,16 @@ pub fn createEmpty( |
| 147 | 155 | .file = file, |
| 148 | 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 | }; |
| 151 | 169 | |
| 152 | 170 | return c_file; |
| ... | ... | @@ -170,10 +188,10 @@ pub fn deinit(self: *C) void { |
| 170 | 188 | self.exported_uavs.deinit(gpa); |
| 171 | 189 | |
| 172 | 190 | self.string_bytes.deinit(gpa); |
| 173 | self.fwd_decl_buf.deinit(gpa); | |
| 174 | self.code_buf.deinit(gpa); | |
| 175 | self.lazy_fwd_decl_buf.deinit(gpa); | |
| 176 | self.lazy_code_buf.deinit(gpa); | |
| 191 | gpa.free(self.fwd_decl_buf); | |
| 192 | gpa.free(self.code_header_buf); | |
| 193 | gpa.free(self.code_buf); | |
| 194 | gpa.free(self.scratch_buf); | |
| 177 | 195 | } |
| 178 | 196 | |
| 179 | 197 | pub fn updateFunc( |
| ... | ... | @@ -194,20 +212,17 @@ pub fn updateFunc( |
| 194 | 212 | .ctype_pool = mir.c.ctype_pool.move(), |
| 195 | 213 | .lazy_fns = mir.c.lazy_fns.move(), |
| 196 | 214 | }; |
| 197 | gop.value_ptr.code = try self.addString(mir.c.code); | |
| 198 | 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 | 219 | try self.addUavsFromCodegen(&mir.c.uavs); |
| 200 | 220 | } |
| 201 | 221 | |
| 202 | fn updateUav(self: *C, pt: Zcu.PerThread, i: usize) !void { | |
| 222 | fn updateUav(self: *C, pt: Zcu.PerThread, i: usize) link.File.FlushError!void { | |
| 203 | 223 | const gpa = self.base.comp.gpa; |
| 204 | 224 | const uav = self.uavs.keys()[i]; |
| 205 | 225 | |
| 206 | const fwd_decl = &self.fwd_decl_buf; | |
| 207 | const code = &self.code_buf; | |
| 208 | fwd_decl.clearRetainingCapacity(); | |
| 209 | code.clearRetainingCapacity(); | |
| 210 | ||
| 211 | 226 | var object: codegen.Object = .{ |
| 212 | 227 | .dg = .{ |
| 213 | 228 | .gpa = gpa, |
| ... | ... | @@ -217,21 +232,24 @@ fn updateUav(self: *C, pt: Zcu.PerThread, i: usize) !void { |
| 217 | 232 | .pass = .{ .uav = uav }, |
| 218 | 233 | .is_naked_fn = false, |
| 219 | 234 | .expected_block = null, |
| 220 | .fwd_decl = fwd_decl.toManaged(gpa), | |
| 221 | .ctype_pool = codegen.CType.Pool.empty, | |
| 222 | .scratch = .{}, | |
| 235 | .fwd_decl = undefined, | |
| 236 | .ctype_pool = .empty, | |
| 237 | .scratch = .initBuffer(self.scratch_buf), | |
| 223 | 238 | .uavs = .empty, |
| 224 | 239 | }, |
| 225 | .code = code.toManaged(gpa), | |
| 226 | .indent_writer = undefined, // set later so we can get a pointer to object.code | |
| 240 | .code_header = undefined, | |
| 241 | .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 | 246 | defer { |
| 230 | 247 | object.dg.uavs.deinit(gpa); |
| 231 | fwd_decl.* = object.dg.fwd_decl.moveToUnmanaged(); | |
| 232 | 248 | object.dg.ctype_pool.deinit(object.dg.gpa); |
| 233 | object.dg.scratch.deinit(gpa); | |
| 234 | code.* = object.code.moveToUnmanaged(); | |
| 249 | ||
| 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 | 254 | try object.dg.ctype_pool.init(gpa); |
| 237 | 255 | |
| ... | ... | @@ -243,15 +261,15 @@ fn updateUav(self: *C, pt: Zcu.PerThread, i: usize) !void { |
| 243 | 261 | //try zcu.failed_decls.put(gpa, decl_index, object.dg.error_msg.?); |
| 244 | 262 | //return; |
| 245 | 263 | }, |
| 246 | else => |e| return e, | |
| 264 | error.WriteFailed, error.OutOfMemory => return error.OutOfMemory, | |
| 247 | 265 | }; |
| 248 | 266 | |
| 249 | 267 | try self.addUavsFromCodegen(&object.dg.uavs); |
| 250 | 268 | |
| 251 | 269 | object.dg.ctype_pool.freeUnusedCapacity(gpa); |
| 252 | 270 | self.uavs.values()[i] = .{ |
| 253 | .code = try self.addString(object.code.items), | |
| 254 | .fwd_decl = try self.addString(object.dg.fwd_decl.items), | |
| 271 | .fwd_decl = try self.addString(object.dg.fwd_decl.getWritten()), | |
| 272 | .code = try self.addString(object.code.getWritten()), | |
| 255 | 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 | 295 | errdefer _ = self.navs.pop(); |
| 278 | 296 | if (!gop.found_existing) gop.value_ptr.* = .{}; |
| 279 | 297 | const ctype_pool = &gop.value_ptr.ctype_pool; |
| 280 | const fwd_decl = &self.fwd_decl_buf; | |
| 281 | const code = &self.code_buf; | |
| 282 | 298 | try ctype_pool.init(gpa); |
| 283 | 299 | ctype_pool.clearRetainingCapacity(); |
| 284 | fwd_decl.clearRetainingCapacity(); | |
| 285 | code.clearRetainingCapacity(); | |
| 286 | 300 | |
| 287 | 301 | var object: codegen.Object = .{ |
| 288 | 302 | .dg = .{ |
| ... | ... | @@ -293,22 +307,25 @@ pub fn updateNav(self: *C, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) l |
| 293 | 307 | .pass = .{ .nav = nav_index }, |
| 294 | 308 | .is_naked_fn = false, |
| 295 | 309 | .expected_block = null, |
| 296 | .fwd_decl = fwd_decl.toManaged(gpa), | |
| 310 | .fwd_decl = undefined, | |
| 297 | 311 | .ctype_pool = ctype_pool.*, |
| 298 | .scratch = .{}, | |
| 312 | .scratch = .initBuffer(self.scratch_buf), | |
| 299 | 313 | .uavs = .empty, |
| 300 | 314 | }, |
| 301 | .code = code.toManaged(gpa), | |
| 302 | .indent_writer = undefined, // set later so we can get a pointer to object.code | |
| 315 | .code_header = undefined, | |
| 316 | .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 | 321 | defer { |
| 306 | 322 | object.dg.uavs.deinit(gpa); |
| 307 | fwd_decl.* = object.dg.fwd_decl.moveToUnmanaged(); | |
| 308 | 323 | ctype_pool.* = object.dg.ctype_pool.move(); |
| 309 | 324 | ctype_pool.freeUnusedCapacity(gpa); |
| 310 | object.dg.scratch.deinit(gpa); | |
| 311 | code.* = object.code.moveToUnmanaged(); | |
| 325 | ||
| 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 | } |
| 313 | 330 | |
| 314 | 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 | 333 | error.CodegenFail => return, |
| 317 | 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); | |
| 322 | gop.value_ptr.fwd_decl = try self.addString(object.dg.fwd_decl.items); | |
| 338 | gop.value_ptr.fwd_decl = try self.addString(object.dg.fwd_decl.getWritten()); | |
| 339 | gop.value_ptr.code = try self.addString(object.code.getWritten()); | |
| 323 | 340 | try self.addUavsFromCodegen(&object.dg.uavs); |
| 324 | 341 | } |
| 325 | 342 | |
| ... | ... | @@ -331,19 +348,14 @@ pub fn updateLineNumber(self: *C, pt: Zcu.PerThread, ti_id: InternPool.TrackedIn |
| 331 | 348 | _ = ti_id; |
| 332 | 349 | } |
| 333 | 350 | |
| 334 | fn abiDefines(self: *C, target: *const std.Target) !std.ArrayList(u8) { | |
| 335 | const gpa = self.base.comp.gpa; | |
| 336 | var defines = std.ArrayList(u8).init(gpa); | |
| 337 | errdefer defines.deinit(); | |
| 338 | const writer = defines.writer(); | |
| 351 | fn abiDefines(w: *std.io.Writer, target: *const std.Target) !void { | |
| 339 | 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 | 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 | 357 | target.cMaxIntAlignment(), |
| 345 | 358 | }); |
| 346 | return defines; | |
| 347 | 359 | } |
| 348 | 360 | |
| 349 | 361 | pub 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 | 386 | // emit-h is in `flushEmitH` below. |
| 375 | 387 | |
| 376 | 388 | var f: Flush = .{ |
| 377 | .ctype_pool = codegen.CType.Pool.empty, | |
| 378 | .lazy_ctype_pool = codegen.CType.Pool.empty, | |
| 389 | .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 | 401 | defer f.deinit(gpa); |
| 381 | 402 | |
| 382 | const abi_defines = try self.abiDefines(zcu.getTarget()); | |
| 383 | defer abi_defines.deinit(); | |
| 403 | var abi_defines_aw: std.io.Writer.Allocating = .init(gpa); | |
| 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 | }; | |
| 384 | 408 | |
| 385 | 409 | // Covers defines, zig.h, ctypes, asm, lazy fwd. |
| 386 | 410 | try f.all_buffers.ensureUnusedCapacity(gpa, 5); |
| 387 | 411 | |
| 388 | f.appendBufAssumeCapacity(abi_defines.items); | |
| 412 | f.appendBufAssumeCapacity(abi_defines_aw.getWritten()); | |
| 389 | 413 | f.appendBufAssumeCapacity(zig_h); |
| 390 | 414 | |
| 391 | 415 | const ctypes_index = f.all_buffers.items.len; |
| 392 | 416 | f.all_buffers.items.len += 1; |
| 393 | 417 | |
| 394 | { | |
| 395 | var asm_buf = f.asm_buf.toManaged(gpa); | |
| 396 | defer f.asm_buf = asm_buf.moveToUnmanaged(); | |
| 397 | try codegen.genGlobalAsm(zcu, asm_buf.writer()); | |
| 398 | f.appendBufAssumeCapacity(asm_buf.items); | |
| 399 | } | |
| 418 | var asm_aw: std.io.Writer.Allocating = .init(gpa); | |
| 419 | defer asm_aw.deinit(); | |
| 420 | codegen.genGlobalAsm(zcu, &asm_aw.writer) catch |err| switch (err) { | |
| 421 | error.WriteFailed => return error.OutOfMemory, | |
| 422 | }; | |
| 423 | f.appendBufAssumeCapacity(asm_aw.getWritten()); | |
| 400 | 424 | |
| 401 | 425 | const lazy_index = f.all_buffers.items.len; |
| 402 | 426 | f.all_buffers.items.len += 1; |
| 403 | 427 | |
| 404 | self.lazy_fwd_decl_buf.clearRetainingCapacity(); | |
| 405 | self.lazy_code_buf.clearRetainingCapacity(); | |
| 406 | 428 | try f.lazy_ctype_pool.init(gpa); |
| 407 | try self.flushErrDecls(pt, &f.lazy_ctype_pool); | |
| 429 | try self.flushErrDecls(pt, &f); | |
| 408 | 430 | |
| 409 | 431 | // Unlike other backends, the .c code we are emitting has order-dependent decls. |
| 410 | 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 | 484 | } |
| 463 | 485 | } |
| 464 | 486 | |
| 465 | f.all_buffers.items[ctypes_index] = .{ | |
| 466 | .base = if (f.ctypes_buf.items.len > 0) f.ctypes_buf.items.ptr else "", | |
| 467 | .len = f.ctypes_buf.items.len, | |
| 468 | }; | |
| 469 | f.file_size += f.ctypes_buf.items.len; | |
| 487 | f.all_buffers.items[ctypes_index] = f.ctypes.items; | |
| 488 | f.file_size += f.ctypes.items.len; | |
| 470 | 489 | |
| 471 | const lazy_fwd_decl_len = self.lazy_fwd_decl_buf.items.len; | |
| 472 | f.all_buffers.items[lazy_index] = .{ | |
| 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; | |
| 490 | f.all_buffers.items[lazy_index] = f.lazy_fwd_decl.items; | |
| 491 | f.file_size += f.lazy_fwd_decl.items.len; | |
| 477 | 492 | |
| 478 | 493 | // Now the code. |
| 479 | 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 | 496 | for (self.uavs.keys(), self.uavs.values()) |uav, av_block| f.appendCodeAssumeCapacity( |
| 482 | 497 | if (self.exported_uavs.contains(uav)) .default else switch (ip.indexToKey(uav)) { |
| 483 | 498 | .@"extern" => .zig_extern, |
| ... | ... | @@ -493,31 +508,35 @@ pub fn flush(self: *C, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.P |
| 493 | 508 | |
| 494 | 509 | const file = self.base.file.?; |
| 495 | 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}", .{ | |
| 497 | self.base.emit, @errorName(err), | |
| 498 | }); | |
| 511 | var fw = file.writer(&.{}); | |
| 512 | var w = &fw.interface; | |
| 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 | } |
| 500 | 519 | |
| 501 | 520 | const Flush = struct { |
| 502 | 521 | ctype_pool: codegen.CType.Pool, |
| 503 | ctype_global_from_decl_map: std.ArrayListUnmanaged(codegen.CType) = .empty, | |
| 504 | ctypes_buf: std.ArrayListUnmanaged(u8) = .empty, | |
| 522 | ctype_global_from_decl_map: std.ArrayListUnmanaged(codegen.CType), | |
| 523 | ctypes: std.ArrayListUnmanaged(u8), | |
| 505 | 524 | |
| 506 | 525 | lazy_ctype_pool: codegen.CType.Pool, |
| 507 | lazy_fns: LazyFns = .{}, | |
| 508 | ||
| 509 | asm_buf: std.ArrayListUnmanaged(u8) = .empty, | |
| 526 | lazy_fns: LazyFns, | |
| 527 | lazy_fwd_decl: std.ArrayListUnmanaged(u8), | |
| 528 | lazy_code: std.ArrayListUnmanaged(u8), | |
| 510 | 529 | |
| 511 | 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 | 532 | /// Keeps track of the total bytes of `all_buffers`. |
| 514 | file_size: u64 = 0, | |
| 533 | file_size: u64, | |
| 515 | 534 | |
| 516 | 535 | const LazyFns = std.AutoHashMapUnmanaged(codegen.LazyFnKey, void); |
| 517 | 536 | |
| 518 | 537 | fn appendBufAssumeCapacity(f: *Flush, buf: []const u8) void { |
| 519 | 538 | if (buf.len == 0) return; |
| 520 | f.all_buffers.appendAssumeCapacity(.{ .base = buf.ptr, .len = buf.len }); | |
| 539 | f.all_buffers.appendAssumeCapacity(buf); | |
| 521 | 540 | f.file_size += buf.len; |
| 522 | 541 | } |
| 523 | 542 | |
| ... | ... | @@ -532,14 +551,15 @@ const Flush = struct { |
| 532 | 551 | } |
| 533 | 552 | |
| 534 | 553 | fn deinit(f: *Flush, gpa: Allocator) void { |
| 535 | f.all_buffers.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); | |
| 554 | f.ctype_pool.deinit(gpa); | |
| 540 | 555 | assert(f.ctype_global_from_decl_map.items.len == 0); |
| 541 | 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 | }; |
| 545 | 565 | |
| ... | ... | @@ -562,9 +582,9 @@ fn flushCTypes( |
| 562 | 582 | try global_from_decl_map.ensureTotalCapacity(gpa, decl_ctype_pool.items.len); |
| 563 | 583 | defer global_from_decl_map.clearRetainingCapacity(); |
| 564 | 584 | |
| 565 | var ctypes_buf = f.ctypes_buf.toManaged(gpa); | |
| 566 | defer f.ctypes_buf = ctypes_buf.moveToUnmanaged(); | |
| 567 | const writer = ctypes_buf.writer(); | |
| 585 | var ctypes_aw: std.io.Writer.Allocating = .fromArrayList(gpa, &f.ctypes); | |
| 586 | const ctypes_bw = &ctypes_aw.writer; | |
| 587 | defer f.ctypes = ctypes_aw.toArrayList(); | |
| 568 | 588 | |
| 569 | 589 | for (0..decl_ctype_pool.items.len) |decl_ctype_pool_index| { |
| 570 | 590 | const PoolAdapter = struct { |
| ... | ... | @@ -591,26 +611,25 @@ fn flushCTypes( |
| 591 | 611 | PoolAdapter{ .global_from_decl_map = global_from_decl_map.items }, |
| 592 | 612 | ); |
| 593 | 613 | global_from_decl_map.appendAssumeCapacity(global_ctype); |
| 594 | try codegen.genTypeDecl( | |
| 614 | codegen.genTypeDecl( | |
| 595 | 615 | zcu, |
| 596 | writer, | |
| 616 | ctypes_bw, | |
| 597 | 617 | global_ctype_pool, |
| 598 | 618 | global_ctype, |
| 599 | 619 | pass, |
| 600 | 620 | decl_ctype_pool, |
| 601 | 621 | decl_ctype, |
| 602 | 622 | found_existing, |
| 603 | ); | |
| 623 | ) catch |err| switch (err) { | |
| 624 | error.WriteFailed => return error.OutOfMemory, | |
| 625 | }; | |
| 604 | 626 | } |
| 605 | 627 | } |
| 606 | 628 | |
| 607 | fn flushErrDecls(self: *C, pt: Zcu.PerThread, ctype_pool: *codegen.CType.Pool) FlushDeclError!void { | |
| 629 | fn flushErrDecls(self: *C, pt: Zcu.PerThread, f: *Flush) FlushDeclError!void { | |
| 608 | 630 | const gpa = self.base.comp.gpa; |
| 609 | 631 | |
| 610 | const fwd_decl = &self.lazy_fwd_decl_buf; | |
| 611 | const code = &self.lazy_code_buf; | |
| 612 | ||
| 613 | var object = codegen.Object{ | |
| 632 | var object: codegen.Object = .{ | |
| 614 | 633 | .dg = .{ |
| 615 | 634 | .gpa = gpa, |
| 616 | 635 | .pt = pt, |
| ... | ... | @@ -619,27 +638,30 @@ fn flushErrDecls(self: *C, pt: Zcu.PerThread, ctype_pool: *codegen.CType.Pool) F |
| 619 | 638 | .pass = .flush, |
| 620 | 639 | .is_naked_fn = false, |
| 621 | 640 | .expected_block = null, |
| 622 | .fwd_decl = fwd_decl.toManaged(gpa), | |
| 623 | .ctype_pool = ctype_pool.*, | |
| 624 | .scratch = .{}, | |
| 641 | .fwd_decl = undefined, | |
| 642 | .ctype_pool = f.lazy_ctype_pool, | |
| 643 | .scratch = .initBuffer(self.scratch_buf), | |
| 625 | 644 | .uavs = .empty, |
| 626 | 645 | }, |
| 627 | .code = code.toManaged(gpa), | |
| 628 | .indent_writer = undefined, // set later so we can get a pointer to object.code | |
| 646 | .code_header = undefined, | |
| 647 | .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 | 652 | defer { |
| 632 | 653 | object.dg.uavs.deinit(gpa); |
| 633 | fwd_decl.* = object.dg.fwd_decl.moveToUnmanaged(); | |
| 634 | ctype_pool.* = object.dg.ctype_pool.move(); | |
| 635 | ctype_pool.freeUnusedCapacity(gpa); | |
| 636 | object.dg.scratch.deinit(gpa); | |
| 637 | code.* = object.code.moveToUnmanaged(); | |
| 654 | f.lazy_ctype_pool = object.dg.ctype_pool.move(); | |
| 655 | f.lazy_ctype_pool.freeUnusedCapacity(gpa); | |
| 656 | ||
| 657 | f.lazy_fwd_decl = object.dg.fwd_decl.toArrayList(); | |
| 658 | f.lazy_code = object.code.toArrayList(); | |
| 659 | self.scratch_buf = object.dg.scratch.allocatedSlice(); | |
| 638 | 660 | } |
| 639 | 661 | |
| 640 | 662 | codegen.genErrDecls(&object) catch |err| switch (err) { |
| 641 | 663 | error.AnalysisFail => unreachable, |
| 642 | else => |e| return e, | |
| 664 | error.WriteFailed, error.OutOfMemory => return error.OutOfMemory, | |
| 643 | 665 | }; |
| 644 | 666 | |
| 645 | 667 | try self.addUavsFromCodegen(&object.dg.uavs); |
| ... | ... | @@ -649,16 +671,13 @@ fn flushLazyFn( |
| 649 | 671 | self: *C, |
| 650 | 672 | pt: Zcu.PerThread, |
| 651 | 673 | mod: *Module, |
| 652 | ctype_pool: *codegen.CType.Pool, | |
| 674 | f: *Flush, | |
| 653 | 675 | lazy_ctype_pool: *const codegen.CType.Pool, |
| 654 | 676 | lazy_fn: codegen.LazyFnMap.Entry, |
| 655 | 677 | ) FlushDeclError!void { |
| 656 | 678 | const gpa = self.base.comp.gpa; |
| 657 | 679 | |
| 658 | const fwd_decl = &self.lazy_fwd_decl_buf; | |
| 659 | const code = &self.lazy_code_buf; | |
| 660 | ||
| 661 | var object = codegen.Object{ | |
| 680 | var object: codegen.Object = .{ | |
| 662 | 681 | .dg = .{ |
| 663 | 682 | .gpa = gpa, |
| 664 | 683 | .pt = pt, |
| ... | ... | @@ -667,29 +686,32 @@ fn flushLazyFn( |
| 667 | 686 | .pass = .flush, |
| 668 | 687 | .is_naked_fn = false, |
| 669 | 688 | .expected_block = null, |
| 670 | .fwd_decl = fwd_decl.toManaged(gpa), | |
| 671 | .ctype_pool = ctype_pool.*, | |
| 672 | .scratch = .{}, | |
| 689 | .fwd_decl = undefined, | |
| 690 | .ctype_pool = f.lazy_ctype_pool, | |
| 691 | .scratch = .initBuffer(self.scratch_buf), | |
| 673 | 692 | .uavs = .empty, |
| 674 | 693 | }, |
| 675 | .code = code.toManaged(gpa), | |
| 676 | .indent_writer = undefined, // set later so we can get a pointer to object.code | |
| 694 | .code_header = undefined, | |
| 695 | .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 | 700 | defer { |
| 680 | 701 | // If this assert trips just handle the anon_decl_deps the same as |
| 681 | 702 | // `updateFunc()` does. |
| 682 | 703 | assert(object.dg.uavs.count() == 0); |
| 683 | fwd_decl.* = object.dg.fwd_decl.moveToUnmanaged(); | |
| 684 | ctype_pool.* = object.dg.ctype_pool.move(); | |
| 685 | ctype_pool.freeUnusedCapacity(gpa); | |
| 686 | object.dg.scratch.deinit(gpa); | |
| 687 | code.* = object.code.moveToUnmanaged(); | |
| 704 | f.lazy_ctype_pool = object.dg.ctype_pool.move(); | |
| 705 | f.lazy_ctype_pool.freeUnusedCapacity(gpa); | |
| 706 | ||
| 707 | f.lazy_fwd_decl = object.dg.fwd_decl.toArrayList(); | |
| 708 | f.lazy_code = object.code.toArrayList(); | |
| 709 | self.scratch_buf = object.dg.scratch.allocatedSlice(); | |
| 688 | 710 | } |
| 689 | 711 | |
| 690 | 712 | codegen.genLazyFn(&object, lazy_ctype_pool, lazy_fn) catch |err| switch (err) { |
| 691 | 713 | error.AnalysisFail => unreachable, |
| 692 | else => |e| return e, | |
| 714 | error.WriteFailed, error.OutOfMemory => return error.OutOfMemory, | |
| 693 | 715 | }; |
| 694 | 716 | } |
| 695 | 717 | |
| ... | ... | @@ -709,7 +731,7 @@ fn flushLazyFns( |
| 709 | 731 | const gop = f.lazy_fns.getOrPutAssumeCapacity(entry.key_ptr.*); |
| 710 | 732 | if (gop.found_existing) continue; |
| 711 | 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 | } |
| 715 | 737 | |
| ... | ... | @@ -802,8 +824,6 @@ pub fn updateExports( |
| 802 | 824 | }, |
| 803 | 825 | }; |
| 804 | 826 | const ctype_pool = &decl_block.ctype_pool; |
| 805 | const fwd_decl = &self.fwd_decl_buf; | |
| 806 | fwd_decl.clearRetainingCapacity(); | |
| 807 | 827 | var dg: codegen.DeclGen = .{ |
| 808 | 828 | .gpa = gpa, |
| 809 | 829 | .pt = pt, |
| ... | ... | @@ -812,20 +832,24 @@ pub fn updateExports( |
| 812 | 832 | .pass = pass, |
| 813 | 833 | .is_naked_fn = false, |
| 814 | 834 | .expected_block = null, |
| 815 | .fwd_decl = fwd_decl.toManaged(gpa), | |
| 835 | .fwd_decl = undefined, | |
| 816 | 836 | .ctype_pool = decl_block.ctype_pool, |
| 817 | .scratch = .{}, | |
| 837 | .scratch = .initBuffer(self.scratch_buf), | |
| 818 | 838 | .uavs = .empty, |
| 819 | 839 | }; |
| 840 | dg.fwd_decl = .initOwnedSlice(gpa, self.fwd_decl_buf); | |
| 820 | 841 | defer { |
| 821 | 842 | assert(dg.uavs.count() == 0); |
| 822 | fwd_decl.* = dg.fwd_decl.moveToUnmanaged(); | |
| 823 | 843 | ctype_pool.* = dg.ctype_pool.move(); |
| 824 | 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); | |
| 828 | exported_block.* = .{ .fwd_decl = try self.addString(dg.fwd_decl.items) }; | |
| 849 | codegen.genExports(&dg, exported, export_indices) catch |err| switch (err) { | |
| 850 | error.WriteFailed, error.OutOfMemory => return error.OutOfMemory, | |
| 851 | }; | |
| 852 | exported_block.* = .{ .fwd_decl = try self.addString(dg.fwd_decl.getWritten()) }; | |
| 829 | 853 | } |
| 830 | 854 | |
| 831 | 855 | pub 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 | 830 | const buffer = try allocator.alloc(u8, code.len); |
| 831 | 831 | defer allocator.free(buffer); |
| 832 | 832 | const memread = try std.os.windows.ReadProcessMemory(handle, pvaddr, buffer); |
| 833 | log.debug("to write: {x}", .{std.fmt.fmtSliceHexLower(code)}); | |
| 834 | log.debug("in memory: {x}", .{std.fmt.fmtSliceHexLower(memread)}); | |
| 833 | log.debug("to write: {x}", .{code}); | |
| 834 | log.debug("in memory: {x}", .{memread}); | |
| 835 | 835 | } |
| 836 | 836 | |
| 837 | 837 | fn writeMemProtected(handle: std.process.Child.Id, pvaddr: std.os.windows.LPVOID, code: []const u8) !void { |
| ... | ... | @@ -1213,7 +1213,7 @@ fn updateLazySymbolAtom( |
| 1213 | 1213 | var code_buffer: std.ArrayListUnmanaged(u8) = .empty; |
| 1214 | 1214 | defer code_buffer.deinit(gpa); |
| 1215 | 1215 | |
| 1216 | const name = try allocPrint(gpa, "__lazy_{s}_{}", .{ | |
| 1216 | const name = try allocPrint(gpa, "__lazy_{s}_{f}", .{ | |
| 1217 | 1217 | @tagName(sym.kind), |
| 1218 | 1218 | Type.fromInterned(sym.ty).fmt(pt), |
| 1219 | 1219 | }); |
| ... | ... | @@ -1333,7 +1333,7 @@ fn updateNavCode( |
| 1333 | 1333 | const ip = &zcu.intern_pool; |
| 1334 | 1334 | const nav = ip.getNav(nav_index); |
| 1335 | 1335 | |
| 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 }); | |
| 1337 | 1337 | |
| 1338 | 1338 | const target = &zcu.navFileScope(nav_index).mod.?.resolved_target.result; |
| 1339 | 1339 | const required_alignment = switch (pt.navAlignment(nav_index)) { |
| ... | ... | @@ -1361,7 +1361,7 @@ fn updateNavCode( |
| 1361 | 1361 | error.OutOfMemory => return error.OutOfMemory, |
| 1362 | 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 | 1365 | log.debug(" (required alignment 0x{x}", .{required_alignment}); |
| 1366 | 1366 | |
| 1367 | 1367 | if (vaddr != sym.value) { |
| ... | ... | @@ -1389,7 +1389,7 @@ fn updateNavCode( |
| 1389 | 1389 | else => |e| return coff.base.cgFail(nav_index, "failed to allocate atom: {s}", .{@errorName(e)}), |
| 1390 | 1390 | }; |
| 1391 | 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 | 1393 | coff.getAtomPtr(atom_index).size = code_len; |
| 1394 | 1394 | sym.value = vaddr; |
| 1395 | 1395 | |
| ... | ... | @@ -1454,7 +1454,7 @@ pub fn updateExports( |
| 1454 | 1454 | |
| 1455 | 1455 | for (export_indices) |export_idx| { |
| 1456 | 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)}); | |
| 1458 | 1458 | |
| 1459 | 1459 | if (exp.opts.section.toSlice(&zcu.intern_pool)) |section_name| { |
| 1460 | 1460 | if (!mem.eql(u8, section_name, ".text")) { |
| ... | ... | @@ -1530,7 +1530,7 @@ pub fn deleteExport( |
| 1530 | 1530 | const gpa = coff.base.comp.gpa; |
| 1531 | 1531 | const sym_loc = SymbolWithLoc{ .sym_index = sym_index.*, .file = null }; |
| 1532 | 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 | 1534 | assert(sym.storage_class == .EXTERNAL and sym.section_number != .UNDEFINED); |
| 1535 | 1535 | sym.* = .{ |
| 1536 | 1536 | .name = [_]u8{0} ** 8, |
| ... | ... | @@ -1748,7 +1748,7 @@ pub fn getNavVAddr( |
| 1748 | 1748 | const zcu = pt.zcu; |
| 1749 | 1749 | const ip = &zcu.intern_pool; |
| 1750 | 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 | 1752 | const sym_index = if (nav.getExtern(ip)) |e| |
| 1753 | 1753 | try coff.getGlobalSymbol(nav.name.toSlice(ip), e.lib_name.toSlice(ip)) |
| 1754 | 1754 | else |
| ... | ... | @@ -2588,7 +2588,7 @@ fn logSymtab(coff: *Coff) void { |
| 2588 | 2588 | .DEBUG => unreachable, // TODO |
| 2589 | 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 | 2592 | sym_id, |
| 2593 | 2593 | coff.getSymbolName(.{ .sym_index = @as(u32, @intCast(sym_id)), .file = null }), |
| 2594 | 2594 | sym.value, |
| ... | ... | @@ -2605,7 +2605,7 @@ fn logSymtab(coff: *Coff) void { |
| 2605 | 2605 | } |
| 2606 | 2606 | |
| 2607 | 2607 | log.debug("GOT entries:", .{}); |
| 2608 | log.debug("{}", .{coff.got_table}); | |
| 2608 | log.debug("{f}", .{coff.got_table}); | |
| 2609 | 2609 | } |
| 2610 | 2610 | |
| 2611 | 2611 | fn logSections(coff: *Coff) void { |
| ... | ... | @@ -2625,7 +2625,7 @@ fn logImportTables(coff: *const Coff) void { |
| 2625 | 2625 | log.debug("import tables:", .{}); |
| 2626 | 2626 | for (coff.import_tables.keys(), 0..) |off, i| { |
| 2627 | 2627 | const itable = coff.import_tables.values()[i]; |
| 2628 | log.debug("{}", .{itable.fmtDebug(.{ | |
| 2628 | log.debug("{f}", .{itable.fmtDebug(.{ | |
| 2629 | 2629 | .coff = coff, |
| 2630 | 2630 | .index = i, |
| 2631 | 2631 | .name_off = off, |
| ... | ... | @@ -3061,40 +3061,25 @@ const ImportTable = struct { |
| 3061 | 3061 | return base_vaddr + index * @sizeOf(u64); |
| 3062 | 3062 | } |
| 3063 | 3063 | |
| 3064 | const FormatContext = struct { | |
| 3064 | const Format = struct { | |
| 3065 | 3065 | itab: ImportTable, |
| 3066 | 3066 | ctx: Context, |
| 3067 | }; | |
| 3068 | 3067 | |
| 3069 | fn format(itab: ImportTable, comptime unused_format_string: []const u8, options: std.fmt.FormatOptions, writer: anytype) !void { | |
| 3070 | _ = itab; | |
| 3071 | _ = unused_format_string; | |
| 3072 | _ = options; | |
| 3073 | _ = writer; | |
| 3074 | @compileError("do not format ImportTable directly; use itab.fmtDebug()"); | |
| 3075 | } | |
| 3076 | ||
| 3077 | fn format2( | |
| 3078 | fmt_ctx: FormatContext, | |
| 3079 | comptime unused_format_string: []const u8, | |
| 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 | }); | |
| 3068 | fn default(f: Format, writer: *std.io.Writer) std.io.Writer.Error!void { | |
| 3069 | const lib_name = f.ctx.coff.temp_strtab.getAssumeExists(f.ctx.name_off); | |
| 3070 | const base_vaddr = getBaseAddress(f.ctx); | |
| 3071 | try writer.print("IAT({s}.dll) @{x}:", .{ lib_name, base_vaddr }); | |
| 3072 | for (f.itab.entries.items, 0..) |entry, i| { | |
| 3073 | try writer.print("\n {d}@{?x} => {s}", .{ | |
| 3074 | i, | |
| 3075 | f.itab.getImportAddress(entry, f.ctx), | |
| 3076 | f.ctx.coff.getSymbolName(entry), | |
| 3077 | }); | |
| 3078 | } | |
| 3094 | 3079 | } |
| 3095 | } | |
| 3080 | }; | |
| 3096 | 3081 | |
| 3097 | fn fmtDebug(itab: ImportTable, ctx: Context) fmt.Formatter(format2) { | |
| 3082 | fn fmtDebug(itab: ImportTable, ctx: Context) fmt.Formatter(Format, Format.default) { | |
| 3098 | 3083 | return .{ .data = .{ .itab = itab, .ctx = ctx } }; |
| 3099 | 3084 | } |
| 3100 | 3085 |
src/link/Dwarf.zig+12-12| ... | ... | @@ -973,7 +973,7 @@ const Entry = struct { |
| 973 | 973 | else |
| 974 | 974 | .main; |
| 975 | 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 | 977 | Type.fromInterned(ty).fmt(.{ .tid = .main, .zcu = zcu }), |
| 978 | 978 | @intFromEnum(ty), |
| 979 | 979 | }); |
| ... | ... | @@ -981,7 +981,7 @@ const Entry = struct { |
| 981 | 981 | for (dwarf.navs.keys(), dwarf.navs.values()) |nav, other_entry| { |
| 982 | 982 | const nav_unit = dwarf.getUnit(zcu.fileByIndex(ip.getNav(nav).srcInst(ip).resolveFile(ip)).mod.?) catch unreachable; |
| 983 | 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 | 987 | @panic("missing dwarf relocation target"); |
| ... | ... | @@ -1957,7 +1957,7 @@ pub const WipNav = struct { |
| 1957 | 1957 | .{ .debug_output = .{ .dwarf = wip_nav } }, |
| 1958 | 1958 | ); |
| 1959 | 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 | 1961 | unreachable; |
| 1962 | 1962 | } |
| 1963 | 1963 | } |
| ... | ... | @@ -2427,7 +2427,7 @@ fn initWipNavInner( |
| 2427 | 2427 | const inst_info = nav.srcInst(ip).resolveFull(ip).?; |
| 2428 | 2428 | const file = zcu.fileByIndex(inst_info.file); |
| 2429 | 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 | 2431 | file.sub_file_path, |
| 2432 | 2432 | decl.src_line + 1, |
| 2433 | 2433 | decl.src_column + 1, |
| ... | ... | @@ -2632,7 +2632,7 @@ pub fn finishWipNavFunc( |
| 2632 | 2632 | const ip = &zcu.intern_pool; |
| 2633 | 2633 | const nav = ip.getNav(nav_index); |
| 2634 | 2634 | assert(wip_nav.func != .none); |
| 2635 | log.debug("finishWipNavFunc({})", .{nav.fqn.fmt(ip)}); | |
| 2635 | log.debug("finishWipNavFunc({f})", .{nav.fqn.fmt(ip)}); | |
| 2636 | 2636 | |
| 2637 | 2637 | { |
| 2638 | 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 | 2733 | const zcu = pt.zcu; |
| 2734 | 2734 | const ip = &zcu.intern_pool; |
| 2735 | 2735 | const nav = ip.getNav(nav_index); |
| 2736 | log.debug("finishWipNav({})", .{nav.fqn.fmt(ip)}); | |
| 2736 | log.debug("finishWipNav({f})", .{nav.fqn.fmt(ip)}); | |
| 2737 | 2737 | |
| 2738 | 2738 | try dwarf.debug_info.section.replaceEntry(wip_nav.unit, wip_nav.entry, dwarf, wip_nav.debug_info.items); |
| 2739 | 2739 | if (wip_nav.debug_line.items.len > 0) { |
| ... | ... | @@ -2765,7 +2765,7 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo |
| 2765 | 2765 | const inst_info = nav.srcInst(ip).resolveFull(ip).?; |
| 2766 | 2766 | const file = zcu.fileByIndex(inst_info.file); |
| 2767 | 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 | 2769 | file.sub_file_path, |
| 2770 | 2770 | decl.src_line + 1, |
| 2771 | 2771 | decl.src_column + 1, |
| ... | ... | @@ -3215,7 +3215,7 @@ fn updateLazyType( |
| 3215 | 3215 | const ty: Type = .fromInterned(type_index); |
| 3216 | 3216 | switch (type_index) { |
| 3217 | 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 | } |
| 3220 | 3220 | |
| 3221 | 3221 | var wip_nav: WipNav = .{ |
| ... | ... | @@ -3243,7 +3243,7 @@ fn updateLazyType( |
| 3243 | 3243 | const diw = wip_nav.debug_info.writer(dwarf.gpa); |
| 3244 | 3244 | const name = switch (type_index) { |
| 3245 | 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 | 3248 | defer dwarf.gpa.free(name); |
| 3249 | 3249 | |
| ... | ... | @@ -3718,7 +3718,7 @@ fn updateLazyValue( |
| 3718 | 3718 | const zcu = pt.zcu; |
| 3719 | 3719 | const ip = &zcu.intern_pool; |
| 3720 | 3720 | assert(ip.typeOf(value_index) != .type_type); |
| 3721 | log.debug("updateLazyValue(@as({}, {}))", .{ | |
| 3721 | log.debug("updateLazyValue(@as({f}, {f}))", .{ | |
| 3722 | 3722 | Value.fromInterned(value_index).typeOf(zcu).fmt(pt), |
| 3723 | 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 | 4110 | const ip = &zcu.intern_pool; |
| 4111 | 4111 | const ty: Type = .fromInterned(type_index); |
| 4112 | 4112 | const ty_src_loc = ty.srcLoc(zcu); |
| 4113 | log.debug("updateContainerType({})", .{ty.fmt(pt)}); | |
| 4113 | log.debug("updateContainerType({f})", .{ty.fmt(pt)}); | |
| 4114 | 4114 | |
| 4115 | 4115 | const inst_info = ty.typeDeclInst(zcu).?.resolveFull(ip).?; |
| 4116 | 4116 | const file = zcu.fileByIndex(inst_info.file); |
| ... | ... | @@ -4239,7 +4239,7 @@ pub fn updateContainerType(dwarf: *Dwarf, pt: Zcu.PerThread, type_index: InternP |
| 4239 | 4239 | }; |
| 4240 | 4240 | defer wip_nav.deinit(); |
| 4241 | 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 | 4243 | defer dwarf.gpa.free(name); |
| 4244 | 4244 | |
| 4245 | 4245 | switch (ip.indexToKey(type_index)) { |
src/link/Elf.zig+36-72| ... | ... | @@ -702,7 +702,7 @@ pub fn allocateChunk(self: *Elf, args: struct { |
| 702 | 702 | shdr.sh_addr + res.value, |
| 703 | 703 | shdr.sh_offset + res.value, |
| 704 | 704 | }); |
| 705 | log.debug(" placement {}, {s}", .{ | |
| 705 | log.debug(" placement {f}, {s}", .{ | |
| 706 | 706 | res.placement, |
| 707 | 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 | 869 | // Dump the state for easy debugging. |
| 870 | 870 | // State can be dumped via `--debug-log link_state`. |
| 871 | 871 | if (build_options.enable_logging) { |
| 872 | state_log.debug("{}", .{self.dumpState()}); | |
| 872 | state_log.debug("{f}", .{self.dumpState()}); | |
| 873 | 873 | } |
| 874 | 874 | |
| 875 | 875 | // 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 | 3544 | } |
| 3545 | 3545 | |
| 3546 | 3546 | pub 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 | 3548 | relocation.fmtRelocType(opts.type, self.getTarget().cpu.arch), |
| 3549 | 3549 | opts.offset, |
| 3550 | 3550 | opts.sym, |
| ... | ... | @@ -3791,7 +3791,7 @@ fn reportUndefinedSymbols(self: *Elf, undefs: anytype) !void { |
| 3791 | 3791 | for (refs.items[0..nrefs]) |ref| { |
| 3792 | 3792 | const atom_ptr = self.atom(ref).?; |
| 3793 | 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 | } |
| 3796 | 3796 | |
| 3797 | 3797 | if (refs.items.len > max_notes) { |
| ... | ... | @@ -3813,12 +3813,12 @@ fn reportDuplicates(self: *Elf, dupes: anytype) error{ HasDuplicates, OutOfMemor |
| 3813 | 3813 | |
| 3814 | 3814 | var err = try diags.addErrorWithNotes(nnotes + 1); |
| 3815 | 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()}); | |
| 3817 | 3817 | |
| 3818 | 3818 | var inote: usize = 0; |
| 3819 | 3819 | while (inote < @min(notes.items.len, max_notes)) : (inote += 1) { |
| 3820 | 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 | } |
| 3823 | 3823 | |
| 3824 | 3824 | if (notes.items.len > max_notes) { |
| ... | ... | @@ -3847,7 +3847,7 @@ pub fn addFileError( |
| 3847 | 3847 | const diags = &self.base.comp.link_diags; |
| 3848 | 3848 | var err = try diags.addErrorWithNotes(1); |
| 3849 | 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 | } |
| 3852 | 3852 | |
| 3853 | 3853 | pub fn failFile( |
| ... | ... | @@ -3860,28 +3860,21 @@ pub fn failFile( |
| 3860 | 3860 | return error.LinkFailure; |
| 3861 | 3861 | } |
| 3862 | 3862 | |
| 3863 | const FormatShdrCtx = struct { | |
| 3863 | const FormatShdr = struct { | |
| 3864 | 3864 | elf_file: *Elf, |
| 3865 | 3865 | shdr: elf.Elf64_Shdr, |
| 3866 | 3866 | }; |
| 3867 | 3867 | |
| 3868 | fn fmtShdr(self: *Elf, shdr: elf.Elf64_Shdr) std.fmt.Formatter(formatShdr) { | |
| 3868 | fn fmtShdr(self: *Elf, shdr: elf.Elf64_Shdr) std.fmt.Formatter(FormatShdr, formatShdr) { | |
| 3869 | 3869 | return .{ .data = .{ |
| 3870 | 3870 | .shdr = shdr, |
| 3871 | 3871 | .elf_file = self, |
| 3872 | 3872 | } }; |
| 3873 | 3873 | } |
| 3874 | 3874 | |
| 3875 | fn formatShdr( | |
| 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; | |
| 3875 | fn formatShdr(ctx: FormatShdr, writer: *std.io.Writer) std.io.Writer.Error!void { | |
| 3883 | 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 | 3878 | ctx.elf_file.getShString(shdr.sh_name), shdr.sh_offset, |
| 3886 | 3879 | shdr.sh_addr, shdr.sh_addralign, |
| 3887 | 3880 | shdr.sh_size, shdr.sh_entsize, |
| ... | ... | @@ -3889,18 +3882,11 @@ fn formatShdr( |
| 3889 | 3882 | }); |
| 3890 | 3883 | } |
| 3891 | 3884 | |
| 3892 | pub fn fmtShdrFlags(sh_flags: u64) std.fmt.Formatter(formatShdrFlags) { | |
| 3885 | pub fn fmtShdrFlags(sh_flags: u64) std.fmt.Formatter(u64, formatShdrFlags) { | |
| 3893 | 3886 | return .{ .data = sh_flags }; |
| 3894 | 3887 | } |
| 3895 | 3888 | |
| 3896 | fn formatShdrFlags( | |
| 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; | |
| 3889 | fn formatShdrFlags(sh_flags: u64, writer: *std.io.Writer) std.io.Writer.Error!void { | |
| 3904 | 3890 | if (elf.SHF_WRITE & sh_flags != 0) { |
| 3905 | 3891 | try writer.writeAll("W"); |
| 3906 | 3892 | } |
| ... | ... | @@ -3945,26 +3931,19 @@ fn formatShdrFlags( |
| 3945 | 3931 | } |
| 3946 | 3932 | } |
| 3947 | 3933 | |
| 3948 | const FormatPhdrCtx = struct { | |
| 3934 | const FormatPhdr = struct { | |
| 3949 | 3935 | elf_file: *Elf, |
| 3950 | 3936 | phdr: elf.Elf64_Phdr, |
| 3951 | 3937 | }; |
| 3952 | 3938 | |
| 3953 | fn fmtPhdr(self: *Elf, phdr: elf.Elf64_Phdr) std.fmt.Formatter(formatPhdr) { | |
| 3939 | fn fmtPhdr(self: *Elf, phdr: elf.Elf64_Phdr) std.fmt.Formatter(FormatPhdr, formatPhdr) { | |
| 3954 | 3940 | return .{ .data = .{ |
| 3955 | 3941 | .phdr = phdr, |
| 3956 | 3942 | .elf_file = self, |
| 3957 | 3943 | } }; |
| 3958 | 3944 | } |
| 3959 | 3945 | |
| 3960 | fn formatPhdr( | |
| 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; | |
| 3946 | fn formatPhdr(ctx: FormatPhdr, writer: *std.io.Writer) std.io.Writer.Error!void { | |
| 3968 | 3947 | const phdr = ctx.phdr; |
| 3969 | 3948 | const write = phdr.p_flags & elf.PF_W != 0; |
| 3970 | 3949 | const read = phdr.p_flags & elf.PF_R != 0; |
| ... | ... | @@ -3991,24 +3970,16 @@ fn formatPhdr( |
| 3991 | 3970 | }); |
| 3992 | 3971 | } |
| 3993 | 3972 | |
| 3994 | pub fn dumpState(self: *Elf) std.fmt.Formatter(fmtDumpState) { | |
| 3973 | pub fn dumpState(self: *Elf) std.fmt.Formatter(*Elf, fmtDumpState) { | |
| 3995 | 3974 | return .{ .data = self }; |
| 3996 | 3975 | } |
| 3997 | 3976 | |
| 3998 | fn fmtDumpState( | |
| 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 | ||
| 3977 | fn fmtDumpState(self: *Elf, writer: *std.io.Writer) std.io.Writer.Error!void { | |
| 4007 | 3978 | const shared_objects = self.shared_objects.values(); |
| 4008 | 3979 | |
| 4009 | 3980 | if (self.zigObjectPtr()) |zig_object| { |
| 4010 | 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 | 3983 | zig_object.fmtAtoms(self), |
| 4013 | 3984 | zig_object.fmtSymtab(self), |
| 4014 | 3985 | }); |
| ... | ... | @@ -4017,10 +3988,10 @@ fn fmtDumpState( |
| 4017 | 3988 | |
| 4018 | 3989 | for (self.objects.items) |index| { |
| 4019 | 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 | 3992 | if (!object.alive) try writer.writeAll(" : [*]"); |
| 4022 | 3993 | try writer.writeByte('\n'); |
| 4023 | try writer.print("{}{}{}{}{}\n", .{ | |
| 3994 | try writer.print("{f}{f}{f}{f}{f}\n", .{ | |
| 4024 | 3995 | object.fmtAtoms(self), |
| 4025 | 3996 | object.fmtCies(self), |
| 4026 | 3997 | object.fmtFdes(self), |
| ... | ... | @@ -4031,51 +4002,51 @@ fn fmtDumpState( |
| 4031 | 4002 | |
| 4032 | 4003 | for (shared_objects) |index| { |
| 4033 | 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 | 4006 | index, shared_object.path, shared_object.needed, |
| 4036 | 4007 | }); |
| 4037 | 4008 | if (!shared_object.alive) try writer.writeAll(" : [*]"); |
| 4038 | 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 | } |
| 4041 | 4012 | |
| 4042 | 4013 | if (self.linker_defined_index) |index| { |
| 4043 | 4014 | const linker_defined = self.file(index).?.linker_defined; |
| 4044 | 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 | } |
| 4047 | 4018 | |
| 4048 | 4019 | const slice = self.sections.slice(); |
| 4049 | 4020 | { |
| 4050 | 4021 | try writer.writeAll("atom lists\n"); |
| 4051 | 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 | } |
| 4055 | 4026 | |
| 4056 | 4027 | if (self.requiresThunks()) { |
| 4057 | 4028 | try writer.writeAll("thunks\n"); |
| 4058 | 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 | } |
| 4062 | 4033 | |
| 4063 | try writer.print("{}\n", .{self.got.fmt(self)}); | |
| 4064 | try writer.print("{}\n", .{self.plt.fmt(self)}); | |
| 4034 | try writer.print("{f}\n", .{self.got.fmt(self)}); | |
| 4035 | try writer.print("{f}\n", .{self.plt.fmt(self)}); | |
| 4065 | 4036 | |
| 4066 | 4037 | try writer.writeAll("Output groups\n"); |
| 4067 | 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 | } |
| 4070 | 4041 | |
| 4071 | 4042 | try writer.writeAll("\nOutput merge sections\n"); |
| 4072 | 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 | } |
| 4075 | 4046 | |
| 4076 | 4047 | try writer.writeAll("\nOutput shdrs\n"); |
| 4077 | 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 | 4050 | shndx, |
| 4080 | 4051 | phndx, |
| 4081 | 4052 | self.fmtShdr(shdr), |
| ... | ... | @@ -4083,7 +4054,7 @@ fn fmtDumpState( |
| 4083 | 4054 | } |
| 4084 | 4055 | try writer.writeAll("\nOutput phdrs\n"); |
| 4085 | 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 | } |
| 4089 | 4060 | |
| ... | ... | @@ -4221,15 +4192,8 @@ pub const Ref = struct { |
| 4221 | 4192 | return ref.index == other.index and ref.file == other.file; |
| 4222 | 4193 | } |
| 4223 | 4194 | |
| 4224 | pub fn format( | |
| 4225 | ref: Ref, | |
| 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 }); | |
| 4195 | pub fn format(ref: Ref, writer: *std.io.Writer) std.io.Writer.Error!void { | |
| 4196 | try writer.print("ref({d},{d})", .{ ref.index, ref.file }); | |
| 4233 | 4197 | } |
| 4234 | 4198 | }; |
| 4235 | 4199 | |
| ... | ... | @@ -4424,7 +4388,7 @@ fn createThunks(elf_file: *Elf, atom_list: *AtomList) !void { |
| 4424 | 4388 | for (atom_list.atoms.keys()[start..i]) |ref| { |
| 4425 | 4389 | const atom_ptr = elf_file.atom(ref).?; |
| 4426 | 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 | 4392 | for (atom_ptr.relocs(elf_file)) |rel| { |
| 4429 | 4393 | const is_reachable = switch (cpu_arch) { |
| 4430 | 4394 | .aarch64 => r: { |
| ... | ... | @@ -4453,7 +4417,7 @@ fn createThunks(elf_file: *Elf, atom_list: *AtomList) !void { |
| 4453 | 4417 | |
| 4454 | 4418 | thunk_ptr.value = try advance(atom_list, thunk_ptr.size(elf_file), Atom.Alignment.fromNonzeroByteUnits(2)); |
| 4455 | 4419 | |
| 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 | } |
| 4459 | 4423 |
src/link/Elf/Archive.zig+17-44| ... | ... | @@ -44,8 +44,8 @@ pub fn parse( |
| 44 | 44 | pos += @sizeOf(elf.ar_hdr); |
| 45 | 45 | |
| 46 | 46 | if (!mem.eql(u8, &hdr.ar_fmag, elf.ARFMAG)) { |
| 47 | return diags.failParse(path, "invalid archive header delimiter: {s}", .{ | |
| 48 | std.fmt.fmtSliceEscapeLower(&hdr.ar_fmag), | |
| 47 | return diags.failParse(path, "invalid archive header delimiter: {f}", .{ | |
| 48 | std.ascii.hexEscape(&hdr.ar_fmag, .lower), | |
| 49 | 49 | }); |
| 50 | 50 | } |
| 51 | 51 | |
| ... | ... | @@ -83,7 +83,7 @@ pub fn parse( |
| 83 | 83 | .alive = false, |
| 84 | 84 | }; |
| 85 | 85 | |
| 86 | log.debug("extracting object '{}' from archive '{}'", .{ | |
| 86 | log.debug("extracting object '{f}' from archive '{f}'", .{ | |
| 87 | 87 | @as(Path, object.path), @as(Path, path), |
| 88 | 88 | }); |
| 89 | 89 | |
| ... | ... | @@ -201,48 +201,28 @@ pub const ArSymtab = struct { |
| 201 | 201 | } |
| 202 | 202 | } |
| 203 | 203 | |
| 204 | pub fn format( | |
| 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 { | |
| 204 | const Format = struct { | |
| 218 | 205 | ar: ArSymtab, |
| 219 | 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 | }; |
| 221 | 218 | |
| 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 | 220 | return .{ .data = .{ |
| 224 | 221 | .ar = ar, |
| 225 | 222 | .elf_file = elf_file, |
| 226 | 223 | } }; |
| 227 | 224 | } |
| 228 | 225 | |
| 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 | 226 | const Entry = struct { |
| 247 | 227 | /// Offset into the string table. |
| 248 | 228 | off: u32, |
| ... | ... | @@ -280,15 +260,8 @@ pub const ArStrtab = struct { |
| 280 | 260 | try writer.writeAll(ar.buffer.items); |
| 281 | 261 | } |
| 282 | 262 | |
| 283 | pub fn format( | |
| 284 | ar: ArStrtab, | |
| 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)}); | |
| 263 | pub fn format(ar: ArStrtab, writer: *std.io.Writer) std.io.Writer.Error!void { | |
| 264 | try writer.print("{f}", .{std.ascii.hexEscape(ar.buffer.items, .lower)}); | |
| 292 | 265 | } |
| 293 | 266 | }; |
| 294 | 267 |
src/link/Elf/Atom.zig+57-79| ... | ... | @@ -142,7 +142,7 @@ pub fn freeListEligible(self: Atom, elf_file: *Elf) bool { |
| 142 | 142 | } |
| 143 | 143 | |
| 144 | 144 | pub 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) }); | |
| 146 | 146 | |
| 147 | 147 | const comp = elf_file.base.comp; |
| 148 | 148 | const gpa = comp.gpa; |
| ... | ... | @@ -243,7 +243,7 @@ pub fn writeRelocs(self: Atom, elf_file: *Elf, out_relocs: *std.ArrayList(elf.El |
| 243 | 243 | }, |
| 244 | 244 | } |
| 245 | 245 | |
| 246 | relocs_log.debug(" {s}: [{x} => {d}({s})] + {x}", .{ | |
| 246 | relocs_log.debug(" {f}: [{x} => {d}({s})] + {x}", .{ | |
| 247 | 247 | relocation.fmtRelocType(rel.r_type(), cpu_arch), |
| 248 | 248 | r_offset, |
| 249 | 249 | r_sym, |
| ... | ... | @@ -316,7 +316,7 @@ pub fn scanRelocs(self: Atom, elf_file: *Elf, code: ?[]const u8, undefs: anytype |
| 316 | 316 | }; |
| 317 | 317 | // Violation of One Definition Rule for COMDATs. |
| 318 | 318 | // 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 | 320 | file_ptr.fmtPath(), |
| 321 | 321 | self.name(elf_file), |
| 322 | 322 | sym_name, |
| ... | ... | @@ -519,11 +519,11 @@ fn dataType(symbol: *const Symbol, elf_file: *Elf) u2 { |
| 519 | 519 | fn reportUnhandledRelocError(self: Atom, rel: elf.Elf64_Rela, elf_file: *Elf) RelocError!void { |
| 520 | 520 | const diags = &elf_file.base.comp.link_diags; |
| 521 | 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 | 523 | relocation.fmtRelocType(rel.r_type(), elf_file.getTarget().cpu.arch), |
| 524 | 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 | 527 | return error.RelocFailure; |
| 528 | 528 | } |
| 529 | 529 | |
| ... | ... | @@ -539,7 +539,7 @@ fn reportTextRelocError( |
| 539 | 539 | rel.r_offset, |
| 540 | 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 | 543 | return error.RelocFailure; |
| 544 | 544 | } |
| 545 | 545 | |
| ... | ... | @@ -555,7 +555,7 @@ fn reportPicError( |
| 555 | 555 | rel.r_offset, |
| 556 | 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 | 559 | err.addNote("recompile with -fPIC", .{}); |
| 560 | 560 | return error.RelocFailure; |
| 561 | 561 | } |
| ... | ... | @@ -572,7 +572,7 @@ fn reportNoPicError( |
| 572 | 572 | rel.r_offset, |
| 573 | 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 | 576 | err.addNote("recompile with -fno-PIC", .{}); |
| 577 | 577 | return error.RelocFailure; |
| 578 | 578 | } |
| ... | ... | @@ -652,7 +652,7 @@ pub fn resolveRelocsAlloc(self: Atom, elf_file: *Elf, code: []u8) RelocError!voi |
| 652 | 652 | // Address of the dynamic thread pointer. |
| 653 | 653 | const DTP = elf_file.dtpAddress(); |
| 654 | 654 | |
| 655 | relocs_log.debug(" {s}: {x}: [{x} => {x}] GOT({x}) ({s})", .{ | |
| 655 | relocs_log.debug(" {f}: {x}: [{x} => {x}] GOT({x}) ({s})", .{ | |
| 656 | 656 | relocation.fmtRelocType(rel.r_type(), cpu_arch), |
| 657 | 657 | r_offset, |
| 658 | 658 | P, |
| ... | ... | @@ -823,7 +823,7 @@ pub fn resolveRelocsNonAlloc(self: Atom, elf_file: *Elf, code: []u8, undefs: any |
| 823 | 823 | }; |
| 824 | 824 | // Violation of One Definition Rule for COMDATs. |
| 825 | 825 | // 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 | 827 | file_ptr.fmtPath(), |
| 828 | 828 | self.name(elf_file), |
| 829 | 829 | sym_name, |
| ... | ... | @@ -855,7 +855,7 @@ pub fn resolveRelocsNonAlloc(self: Atom, elf_file: *Elf, code: []u8, undefs: any |
| 855 | 855 | |
| 856 | 856 | const args = ResolveArgs{ P, A, S, GOT, 0, 0, DTP }; |
| 857 | 857 | |
| 858 | relocs_log.debug(" {}: {x}: [{x} => {x}] ({s})", .{ | |
| 858 | relocs_log.debug(" {f}: {x}: [{x} => {x}] ({s})", .{ | |
| 859 | 859 | relocation.fmtRelocType(rel.r_type(), cpu_arch), |
| 860 | 860 | rel.r_offset, |
| 861 | 861 | P, |
| ... | ... | @@ -904,65 +904,45 @@ pub fn setExtra(atom: Atom, extras: Extra, elf_file: *Elf) void { |
| 904 | 904 | atom.file(elf_file).?.setAtomExtra(atom.extra_index, extras); |
| 905 | 905 | } |
| 906 | 906 | |
| 907 | pub fn format( | |
| 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 | ||
| 920 | pub fn fmt(atom: Atom, elf_file: *Elf) std.fmt.Formatter(format2) { | |
| 907 | pub fn fmt(atom: Atom, elf_file: *Elf) std.fmt.Formatter(Format, Format.default) { | |
| 921 | 908 | return .{ .data = .{ |
| 922 | 909 | .atom = atom, |
| 923 | 910 | .elf_file = elf_file, |
| 924 | 911 | } }; |
| 925 | 912 | } |
| 926 | 913 | |
| 927 | const FormatContext = struct { | |
| 914 | const Format = struct { | |
| 928 | 915 | atom: Atom, |
| 929 | 916 | elf_file: *Elf, |
| 930 | }; | |
| 931 | 917 | |
| 932 | fn format2( | |
| 933 | ctx: FormatContext, | |
| 934 | comptime unused_fmt_string: []const u8, | |
| 935 | options: std.fmt.FormatOptions, | |
| 936 | writer: anytype, | |
| 937 | ) !void { | |
| 938 | _ = options; | |
| 939 | _ = unused_fmt_string; | |
| 940 | const atom = ctx.atom; | |
| 941 | const elf_file = ctx.elf_file; | |
| 942 | try writer.print("atom({d}) : {s} : @{x} : shdr({d}) : align({x}) : size({x}) : prev({}) : next({})", .{ | |
| 943 | atom.atom_index, atom.name(elf_file), atom.address(elf_file), | |
| 944 | atom.output_section_index, atom.alignment.toByteUnits() orelse 0, atom.size, | |
| 945 | atom.prev_atom_ref, atom.next_atom_ref, | |
| 946 | }); | |
| 947 | if (atom.file(elf_file)) |atom_file| switch (atom_file) { | |
| 948 | .object => |object| { | |
| 949 | if (atom.fdes(object).len > 0) { | |
| 950 | try writer.writeAll(" : fdes{ "); | |
| 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(", "); | |
| 918 | fn default(f: Format, w: *std.io.Writer) std.io.Writer.Error!void { | |
| 919 | const atom = f.atom; | |
| 920 | const elf_file = f.elf_file; | |
| 921 | try w.print("atom({d}) : {s} : @{x} : shdr({d}) : align({x}) : size({x}) : prev({f}) : next({f})", .{ | |
| 922 | atom.atom_index, atom.name(elf_file), atom.address(elf_file), | |
| 923 | atom.output_section_index, atom.alignment.toByteUnits() orelse 0, atom.size, | |
| 924 | atom.prev_atom_ref, atom.next_atom_ref, | |
| 925 | }); | |
| 926 | if (atom.file(elf_file)) |atom_file| switch (atom_file) { | |
| 927 | .object => |object| { | |
| 928 | if (atom.fdes(object).len > 0) { | |
| 929 | try w.writeAll(" : fdes{ "); | |
| 930 | const extras = atom.extra(elf_file); | |
| 931 | for (atom.fdes(object), extras.fde_start..) |fde, i| { | |
| 932 | try w.print("{d}", .{i}); | |
| 933 | if (!fde.alive) try w.writeAll("([*])"); | |
| 934 | if (i - extras.fde_start < extras.fde_count - 1) try w.writeAll(", "); | |
| 935 | } | |
| 936 | try w.writeAll(" }"); | |
| 956 | 937 | } |
| 957 | try writer.writeAll(" }"); | |
| 958 | } | |
| 959 | }, | |
| 960 | else => {}, | |
| 961 | }; | |
| 962 | if (!atom.alive) { | |
| 963 | try writer.writeAll(" : [*]"); | |
| 938 | }, | |
| 939 | else => {}, | |
| 940 | }; | |
| 941 | if (!atom.alive) { | |
| 942 | try w.writeAll(" : [*]"); | |
| 943 | } | |
| 964 | 944 | } |
| 965 | } | |
| 945 | }; | |
| 966 | 946 | |
| 967 | 947 | pub const Index = u32; |
| 968 | 948 | |
| ... | ... | @@ -1189,7 +1169,7 @@ const x86_64 = struct { |
| 1189 | 1169 | x86_64.relaxGotPcTlsDesc(code[r_offset - 3 ..], t) catch { |
| 1190 | 1170 | var err = try diags.addErrorWithNotes(1); |
| 1191 | 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 | 1173 | atom.file(elf_file).?.fmtPath(), |
| 1194 | 1174 | atom.name(elf_file), |
| 1195 | 1175 | rel.r_offset, |
| ... | ... | @@ -1285,7 +1265,7 @@ const x86_64 = struct { |
| 1285 | 1265 | }, t), |
| 1286 | 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 | 1269 | const nop: Instruction = try .new(.none, .nop, &.{}, t); |
| 1290 | 1270 | try encode(&.{ nop, inst }, code); |
| 1291 | 1271 | } |
| ... | ... | @@ -1296,7 +1276,7 @@ const x86_64 = struct { |
| 1296 | 1276 | switch (old_inst.encoding.mnemonic) { |
| 1297 | 1277 | .mov => { |
| 1298 | 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 | 1280 | try encode(&.{inst}, code); |
| 1301 | 1281 | }, |
| 1302 | 1282 | else => return error.RelaxFailure, |
| ... | ... | @@ -1330,11 +1310,11 @@ const x86_64 = struct { |
| 1330 | 1310 | |
| 1331 | 1311 | else => { |
| 1332 | 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 | 1314 | relocation.fmtRelocType(rels[0].r_type(), .x86_64), |
| 1335 | 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 | 1318 | self.file(elf_file).?.fmtPath(), |
| 1339 | 1319 | self.name(elf_file), |
| 1340 | 1320 | rels[0].r_offset, |
| ... | ... | @@ -1386,11 +1366,11 @@ const x86_64 = struct { |
| 1386 | 1366 | |
| 1387 | 1367 | else => { |
| 1388 | 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 | 1370 | relocation.fmtRelocType(rels[0].r_type(), .x86_64), |
| 1391 | 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 | 1374 | self.file(elf_file).?.fmtPath(), |
| 1395 | 1375 | self.name(elf_file), |
| 1396 | 1376 | rels[0].r_offset, |
| ... | ... | @@ -1410,7 +1390,8 @@ const x86_64 = struct { |
| 1410 | 1390 | // TODO: hack to force imm32s in the assembler |
| 1411 | 1391 | .{ .imm = .s(-129) }, |
| 1412 | 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 | 1395 | return true; |
| 1415 | 1396 | }, |
| 1416 | 1397 | else => return false, |
| ... | ... | @@ -1427,7 +1408,7 @@ const x86_64 = struct { |
| 1427 | 1408 | // TODO: hack to force imm32s in the assembler |
| 1428 | 1409 | .{ .imm = .s(-129) }, |
| 1429 | 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 | 1412 | encode(&.{inst}, code) catch unreachable; |
| 1432 | 1413 | }, |
| 1433 | 1414 | else => unreachable, |
| ... | ... | @@ -1444,7 +1425,7 @@ const x86_64 = struct { |
| 1444 | 1425 | // TODO: hack to force imm32s in the assembler |
| 1445 | 1426 | .{ .imm = .s(-129) }, |
| 1446 | 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 | 1429 | try encode(&.{inst}, code); |
| 1449 | 1430 | }, |
| 1450 | 1431 | else => return error.RelaxFailure, |
| ... | ... | @@ -1476,7 +1457,7 @@ const x86_64 = struct { |
| 1476 | 1457 | std.mem.writeInt(i32, insts[12..][0..4], value, .little); |
| 1477 | 1458 | try stream.seekBy(-4); |
| 1478 | 1459 | try writer.writeAll(&insts); |
| 1479 | relocs_log.debug(" relaxing {} and {}", .{ | |
| 1460 | relocs_log.debug(" relaxing {f} and {f}", .{ | |
| 1480 | 1461 | relocation.fmtRelocType(rels[0].r_type(), .x86_64), |
| 1481 | 1462 | relocation.fmtRelocType(rels[1].r_type(), .x86_64), |
| 1482 | 1463 | }); |
| ... | ... | @@ -1484,11 +1465,11 @@ const x86_64 = struct { |
| 1484 | 1465 | |
| 1485 | 1466 | else => { |
| 1486 | 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 | 1469 | relocation.fmtRelocType(rels[0].r_type(), .x86_64), |
| 1489 | 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 | 1473 | self.file(elf_file).?.fmtPath(), |
| 1493 | 1474 | self.name(elf_file), |
| 1494 | 1475 | rels[0].r_offset, |
| ... | ... | @@ -1505,11 +1486,8 @@ const x86_64 = struct { |
| 1505 | 1486 | } |
| 1506 | 1487 | |
| 1507 | 1488 | fn encode(insts: []const Instruction, code: []u8) !void { |
| 1508 | var stream = std.io.fixedBufferStream(code); | |
| 1509 | const writer = stream.writer(); | |
| 1510 | for (insts) |inst| { | |
| 1511 | try inst.encode(writer, .{}); | |
| 1512 | } | |
| 1489 | var stream: std.io.Writer = .fixed(code); | |
| 1490 | for (insts) |inst| try inst.encode(&stream, .{}); | |
| 1513 | 1491 | } |
| 1514 | 1492 | |
| 1515 | 1493 | const bits = @import("../../arch/x86_64/bits.zig"); |
| ... | ... | @@ -1675,7 +1653,7 @@ const aarch64 = struct { |
| 1675 | 1653 | // TODO: relax |
| 1676 | 1654 | var err = try diags.addErrorWithNotes(1); |
| 1677 | 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 | 1657 | atom.file(elf_file).?.fmtPath(), |
| 1680 | 1658 | atom.name(elf_file), |
| 1681 | 1659 | r_offset, |
| ... | ... | @@ -1965,7 +1943,7 @@ const riscv = struct { |
| 1965 | 1943 | // TODO: implement searching forward |
| 1966 | 1944 | var err = try diags.addErrorWithNotes(1); |
| 1967 | 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 | 1947 | atom.file(elf_file).?.fmtPath(), |
| 1970 | 1948 | atom.name(elf_file), |
| 1971 | 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 | 108 | const off = math.cast(usize, atom_ptr.value - list.value) orelse return error.Overflow; |
| 109 | 109 | const size = math.cast(usize, atom_ptr.size) orelse return error.Overflow; |
| 110 | 110 | |
| 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 }); | |
| 112 | 112 | |
| 113 | 113 | const object = atom_ptr.file(elf_file).?.object; |
| 114 | 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 | 144 | const off = math.cast(usize, atom_ptr.value - list.value) orelse return error.Overflow; |
| 145 | 145 | const size = math.cast(usize, atom_ptr.size) orelse return error.Overflow; |
| 146 | 146 | |
| 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 }); | |
| 148 | 148 | |
| 149 | 149 | const object = atom_ptr.file(elf_file).?.object; |
| 150 | 150 | const code = try object.codeDecompressAlloc(elf_file, ref.index); |
| ... | ... | @@ -167,44 +167,29 @@ pub fn lastAtom(list: AtomList, elf_file: *Elf) *Atom { |
| 167 | 167 | return elf_file.atom(list.atoms.keys()[list.atoms.keys().len - 1]).?; |
| 168 | 168 | } |
| 169 | 169 | |
| 170 | pub fn format( | |
| 171 | list: AtomList, | |
| 172 | comptime unused_fmt_string: []const u8, | |
| 173 | options: std.fmt.FormatOptions, | |
| 174 | writer: anytype, | |
| 175 | ) !void { | |
| 176 | _ = list; | |
| 177 | _ = unused_fmt_string; | |
| 178 | _ = options; | |
| 179 | _ = writer; | |
| 180 | @compileError("do not format AtomList directly"); | |
| 181 | } | |
| 182 | ||
| 183 | const FormatCtx = struct { AtomList, *Elf }; | |
| 184 | ||
| 185 | pub fn fmt(list: AtomList, elf_file: *Elf) std.fmt.Formatter(format2) { | |
| 186 | return .{ .data = .{ list, elf_file } }; | |
| 187 | } | |
| 188 | ||
| 189 | fn 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(", "); | |
| 170 | const Format = struct { | |
| 171 | atom_list: AtomList, | |
| 172 | elf_file: *Elf, | |
| 173 | ||
| 174 | fn default(f: Format, writer: *std.io.Writer) std.io.Writer.Error!void { | |
| 175 | const list = f.atom_list; | |
| 176 | try writer.print("list : @{x} : shdr({d}) : align({x}) : size({x})", .{ | |
| 177 | list.address(f.elf_file), | |
| 178 | list.output_section_index, | |
| 179 | list.alignment.toByteUnits() orelse 0, | |
| 180 | list.size, | |
| 181 | }); | |
| 182 | try writer.writeAll(" : atoms{ "); | |
| 183 | for (list.atoms.keys(), 0..) |ref, i| { | |
| 184 | try writer.print("{f}", .{ref}); | |
| 185 | if (i < list.atoms.keys().len - 1) try writer.writeAll(", "); | |
| 186 | } | |
| 187 | try writer.writeAll(" }"); | |
| 206 | 188 | } |
| 207 | try writer.writeAll(" }"); | |
| 189 | }; | |
| 190 | ||
| 191 | pub 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 | } |
| 209 | 194 | |
| 210 | 195 | const 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 | 147 | for (slice.items(.shdr)) |shdr| { |
| 148 | 148 | // TODO use getOrPut for incremental so that we don't create duplicates |
| 149 | 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 | 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 | 153 | defer gpa.free(stop_name); |
| 154 | 154 | |
| 155 | 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 | 437 | } |
| 438 | 438 | } |
| 439 | 439 | |
| 440 | pub fn fmtSymtab(self: *LinkerDefined, elf_file: *Elf) std.fmt.Formatter(formatSymtab) { | |
| 440 | pub fn fmtSymtab(self: *LinkerDefined, elf_file: *Elf) std.fmt.Formatter(Format, Format.symtab) { | |
| 441 | 441 | return .{ .data = .{ |
| 442 | 442 | .self = self, |
| 443 | 443 | .elf_file = elf_file, |
| 444 | 444 | } }; |
| 445 | 445 | } |
| 446 | 446 | |
| 447 | const FormatContext = struct { | |
| 447 | const Format = struct { | |
| 448 | 448 | self: *LinkerDefined, |
| 449 | 449 | elf_file: *Elf, |
| 450 | }; | |
| 451 | 450 | |
| 452 | fn formatSymtab( | |
| 453 | ctx: FormatContext, | |
| 454 | comptime unused_fmt_string: []const u8, | |
| 455 | options: std.fmt.FormatOptions, | |
| 456 | writer: anytype, | |
| 457 | ) !void { | |
| 458 | _ = unused_fmt_string; | |
| 459 | _ = options; | |
| 460 | const self = ctx.self; | |
| 461 | const elf_file = ctx.elf_file; | |
| 462 | try writer.writeAll(" globals\n"); | |
| 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)}); | |
| 451 | fn symtab(ctx: Format, writer: *std.io.Writer) std.io.Writer.Error!void { | |
| 452 | const self = ctx.self; | |
| 453 | const elf_file = ctx.elf_file; | |
| 454 | try writer.writeAll(" globals\n"); | |
| 455 | for (self.symbols.items, 0..) |sym, i| { | |
| 456 | const ref = self.resolveSymbol(@intCast(i), elf_file); | |
| 457 | if (elf_file.symbol(ref)) |ref_sym| { | |
| 458 | try writer.print(" {f}\n", .{ref_sym.fmt(elf_file)}); | |
| 459 | } else { | |
| 460 | try writer.print(" {s} : unclaimed\n", .{sym.name(elf_file)}); | |
| 461 | } | |
| 469 | 462 | } |
| 470 | 463 | } |
| 471 | } | |
| 464 | }; | |
| 472 | 465 | |
| 473 | 466 | const assert = std.debug.assert; |
| 474 | 467 | const elf = std.elf; |
src/link/Elf/Merge.zig+31-71| ... | ... | @@ -157,54 +157,34 @@ pub const Section = struct { |
| 157 | 157 | } |
| 158 | 158 | }; |
| 159 | 159 | |
| 160 | pub fn format( | |
| 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) { | |
| 160 | pub fn fmt(msec: Section, elf_file: *Elf) std.fmt.Formatter(Format, Format.default) { | |
| 174 | 161 | return .{ .data = .{ |
| 175 | 162 | .msec = msec, |
| 176 | 163 | .elf_file = elf_file, |
| 177 | 164 | } }; |
| 178 | 165 | } |
| 179 | 166 | |
| 180 | const FormatContext = struct { | |
| 167 | const Format = struct { | |
| 181 | 168 | msec: Section, |
| 182 | 169 | elf_file: *Elf, |
| 183 | }; | |
| 184 | 170 | |
| 185 | pub fn format2( | |
| 186 | ctx: FormatContext, | |
| 187 | comptime unused_fmt_string: []const u8, | |
| 188 | options: std.fmt.FormatOptions, | |
| 189 | writer: anytype, | |
| 190 | ) !void { | |
| 191 | _ = options; | |
| 192 | _ = unused_fmt_string; | |
| 193 | const msec = ctx.msec; | |
| 194 | const elf_file = ctx.elf_file; | |
| 195 | try writer.print("{s} : @{x} : size({x}) : align({x}) : entsize({x}) : type({x}) : flags({x})\n", .{ | |
| 196 | msec.name(elf_file), | |
| 197 | msec.address(elf_file), | |
| 198 | msec.size, | |
| 199 | msec.alignment.toByteUnits() orelse 0, | |
| 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)}); | |
| 171 | pub fn default(f: Format, writer: *std.io.Writer) std.io.Writer.Error!void { | |
| 172 | const msec = f.msec; | |
| 173 | const elf_file = f.elf_file; | |
| 174 | try writer.print("{s} : @{x} : size({x}) : align({x}) : entsize({x}) : type({x}) : flags({x})\n", .{ | |
| 175 | msec.name(elf_file), | |
| 176 | msec.address(elf_file), | |
| 177 | msec.size, | |
| 178 | msec.alignment.toByteUnits() orelse 0, | |
| 179 | msec.entsize, | |
| 180 | msec.type, | |
| 181 | msec.flags, | |
| 182 | }); | |
| 183 | for (msec.subsections.items) |msub| { | |
| 184 | try writer.print(" {f}\n", .{msub.fmt(elf_file)}); | |
| 185 | } | |
| 206 | 186 | } |
| 207 | } | |
| 187 | }; | |
| 208 | 188 | |
| 209 | 189 | pub const Index = u32; |
| 210 | 190 | }; |
| ... | ... | @@ -231,48 +211,28 @@ pub const Subsection = struct { |
| 231 | 211 | return msec.bytes.items[msub.string_index..][0..msub.size]; |
| 232 | 212 | } |
| 233 | 213 | |
| 234 | pub fn format( | |
| 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) { | |
| 214 | pub fn fmt(msub: Subsection, elf_file: *Elf) std.fmt.Formatter(Format, Format.default) { | |
| 248 | 215 | return .{ .data = .{ |
| 249 | 216 | .msub = msub, |
| 250 | 217 | .elf_file = elf_file, |
| 251 | 218 | } }; |
| 252 | 219 | } |
| 253 | 220 | |
| 254 | const FormatContext = struct { | |
| 221 | const Format = struct { | |
| 255 | 222 | msub: Subsection, |
| 256 | 223 | elf_file: *Elf, |
| 257 | }; | |
| 258 | 224 | |
| 259 | pub fn format2( | |
| 260 | ctx: FormatContext, | |
| 261 | comptime unused_fmt_string: []const u8, | |
| 262 | options: std.fmt.FormatOptions, | |
| 263 | writer: anytype, | |
| 264 | ) !void { | |
| 265 | _ = options; | |
| 266 | _ = unused_fmt_string; | |
| 267 | const msub = ctx.msub; | |
| 268 | const elf_file = ctx.elf_file; | |
| 269 | try writer.print("@{x} : align({x}) : size({x})", .{ | |
| 270 | msub.address(elf_file), | |
| 271 | msub.alignment, | |
| 272 | msub.size, | |
| 273 | }); | |
| 274 | if (!msub.alive) try writer.writeAll(" : [*]"); | |
| 275 | } | |
| 225 | pub fn default(ctx: Format, writer: *std.io.Writer) std.io.Writer.Error!void { | |
| 226 | const msub = ctx.msub; | |
| 227 | const elf_file = ctx.elf_file; | |
| 228 | try writer.print("@{x} : align({x}) : size({x})", .{ | |
| 229 | msub.address(elf_file), | |
| 230 | msub.alignment, | |
| 231 | msub.size, | |
| 232 | }); | |
| 233 | if (!msub.alive) try writer.writeAll(" : [*]"); | |
| 234 | } | |
| 235 | }; | |
| 276 | 236 | |
| 277 | 237 | pub const Index = u32; |
| 278 | 238 | }; |
src/link/Elf/Object.zig+75-133| ... | ... | @@ -281,7 +281,7 @@ fn initAtoms( |
| 281 | 281 | elf.SHT_GROUP => { |
| 282 | 282 | if (shdr.sh_info >= self.symtab.items.len) { |
| 283 | 283 | // 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 | 285 | continue; |
| 286 | 286 | } |
| 287 | 287 | const group_info_sym = self.symtab.items[shdr.sh_info]; |
| ... | ... | @@ -488,10 +488,7 @@ fn parseEhFrame( |
| 488 | 488 | if (cie.offset == cie_ptr) break @as(u32, @intCast(cie_index)); |
| 489 | 489 | } else { |
| 490 | 490 | // TODO convert into an error |
| 491 | log.debug("{s}: no matching CIE found for FDE at offset {x}", .{ | |
| 492 | self.fmtPath(), | |
| 493 | fde.offset, | |
| 494 | }); | |
| 491 | log.debug("{f}: no matching CIE found for FDE at offset {x}", .{ self.fmtPath(), fde.offset }); | |
| 495 | 492 | continue; |
| 496 | 493 | }; |
| 497 | 494 | fde.cie_index = cie_index; |
| ... | ... | @@ -582,7 +579,7 @@ pub fn scanRelocs(self: *Object, elf_file: *Elf, undefs: anytype) !void { |
| 582 | 579 | if (sym.flags.import) { |
| 583 | 580 | if (sym.type(elf_file) != elf.STT_FUNC) |
| 584 | 581 | // 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 | 583 | self.fmtPath(), sym.name(elf_file), |
| 587 | 584 | }); |
| 588 | 585 | sym.flags.needs_plt = true; |
| ... | ... | @@ -796,7 +793,7 @@ pub fn initInputMergeSections(self: *Object, elf_file: *Elf) !void { |
| 796 | 793 | if (!isNull(data[end .. end + sh_entsize])) { |
| 797 | 794 | var err = try diags.addErrorWithNotes(1); |
| 798 | 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 | 797 | return error.LinkFailure; |
| 801 | 798 | } |
| 802 | 799 | end += sh_entsize; |
| ... | ... | @@ -811,7 +808,7 @@ pub fn initInputMergeSections(self: *Object, elf_file: *Elf) !void { |
| 811 | 808 | if (shdr.sh_size % sh_entsize != 0) { |
| 812 | 809 | var err = try diags.addErrorWithNotes(1); |
| 813 | 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 | 812 | return error.LinkFailure; |
| 816 | 813 | } |
| 817 | 814 | |
| ... | ... | @@ -889,7 +886,7 @@ pub fn resolveMergeSubsections(self: *Object, elf_file: *Elf) error{ |
| 889 | 886 | var err = try diags.addErrorWithNotes(2); |
| 890 | 887 | try err.addMsg("invalid symbol value: {x}", .{esym.st_value}); |
| 891 | 888 | err.addNote("for symbol {s}", .{sym.name(elf_file)}); |
| 892 | err.addNote("in {}", .{self.fmtPath()}); | |
| 889 | err.addNote("in {f}", .{self.fmtPath()}); | |
| 893 | 890 | return error.LinkFailure; |
| 894 | 891 | }; |
| 895 | 892 | |
| ... | ... | @@ -914,7 +911,7 @@ pub fn resolveMergeSubsections(self: *Object, elf_file: *Elf) error{ |
| 914 | 911 | const res = imsec.findSubsection(@intCast(@as(i64, @intCast(esym.st_value)) + rel.r_addend)) orelse { |
| 915 | 912 | var err = try diags.addErrorWithNotes(1); |
| 916 | 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 | 915 | return error.LinkFailure; |
| 919 | 916 | }; |
| 920 | 917 | |
| ... | ... | @@ -1432,171 +1429,116 @@ pub fn group(self: *Object, index: Elf.Group.Index) *Elf.Group { |
| 1432 | 1429 | return &self.groups.items[index]; |
| 1433 | 1430 | } |
| 1434 | 1431 | |
| 1435 | pub fn format( | |
| 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 | ||
| 1448 | pub fn fmtSymtab(self: *Object, elf_file: *Elf) std.fmt.Formatter(formatSymtab) { | |
| 1432 | pub fn fmtSymtab(self: *Object, elf_file: *Elf) std.fmt.Formatter(Format, Format.symtab) { | |
| 1449 | 1433 | return .{ .data = .{ |
| 1450 | 1434 | .object = self, |
| 1451 | 1435 | .elf_file = elf_file, |
| 1452 | 1436 | } }; |
| 1453 | 1437 | } |
| 1454 | 1438 | |
| 1455 | const FormatContext = struct { | |
| 1439 | const Format = struct { | |
| 1456 | 1440 | object: *Object, |
| 1457 | 1441 | elf_file: *Elf, |
| 1458 | }; | |
| 1459 | 1442 | |
| 1460 | fn formatSymtab( | |
| 1461 | ctx: FormatContext, | |
| 1462 | comptime unused_fmt_string: []const u8, | |
| 1463 | options: std.fmt.FormatOptions, | |
| 1464 | writer: anytype, | |
| 1465 | ) !void { | |
| 1466 | _ = unused_fmt_string; | |
| 1467 | _ = options; | |
| 1468 | const object = ctx.object; | |
| 1469 | const elf_file = ctx.elf_file; | |
| 1470 | try writer.writeAll(" locals\n"); | |
| 1471 | for (object.locals()) |sym| { | |
| 1472 | try writer.print(" {}\n", .{sym.fmt(elf_file)}); | |
| 1443 | fn symtab(f: Format, writer: *std.io.Writer) std.io.Writer.Error!void { | |
| 1444 | const object = f.object; | |
| 1445 | const elf_file = f.elf_file; | |
| 1446 | try writer.writeAll(" locals\n"); | |
| 1447 | for (object.locals()) |sym| { | |
| 1448 | try writer.print(" {f}\n", .{sym.fmt(elf_file)}); | |
| 1449 | } | |
| 1450 | try writer.writeAll(" globals\n"); | |
| 1451 | for (object.globals(), 0..) |sym, i| { | |
| 1452 | const first_global = object.first_global.?; | |
| 1453 | const ref = object.resolveSymbol(@intCast(i + first_global), elf_file); | |
| 1454 | if (elf_file.symbol(ref)) |ref_sym| { | |
| 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"); | |
| 1475 | for (object.globals(), 0..) |sym, i| { | |
| 1476 | const first_global = object.first_global.?; | |
| 1477 | const ref = object.resolveSymbol(@intCast(i + first_global), elf_file); | |
| 1478 | if (elf_file.symbol(ref)) |ref_sym| { | |
| 1479 | try writer.print(" {}\n", .{ref_sym.fmt(elf_file)}); | |
| 1480 | } else { | |
| 1481 | try writer.print(" {s} : unclaimed\n", .{sym.name(elf_file)}); | |
| 1461 | ||
| 1462 | fn atoms(f: Format, writer: *std.io.Writer) std.io.Writer.Error!void { | |
| 1463 | const object = f.object; | |
| 1464 | try writer.writeAll(" atoms\n"); | |
| 1465 | for (object.atoms_indexes.items) |atom_index| { | |
| 1466 | const atom_ptr = object.atom(atom_index) orelse continue; | |
| 1467 | try writer.print(" {f}\n", .{atom_ptr.fmt(f.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 | } | |
| 1485 | 1478 | |
| 1486 | pub 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 | ||
| 1505 | pub fn fmtAtoms(self: *Object, elf_file: *Elf) std.fmt.Formatter(Format, Format.atoms) { | |
| 1487 | 1506 | return .{ .data = .{ |
| 1488 | 1507 | .object = self, |
| 1489 | 1508 | .elf_file = elf_file, |
| 1490 | 1509 | } }; |
| 1491 | 1510 | } |
| 1492 | 1511 | |
| 1493 | fn formatAtoms( | |
| 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 | ||
| 1509 | pub fn fmtCies(self: *Object, elf_file: *Elf) std.fmt.Formatter(formatCies) { | |
| 1512 | pub fn fmtCies(self: *Object, elf_file: *Elf) std.fmt.Formatter(Format, Format.cies) { | |
| 1510 | 1513 | return .{ .data = .{ |
| 1511 | 1514 | .object = self, |
| 1512 | 1515 | .elf_file = elf_file, |
| 1513 | 1516 | } }; |
| 1514 | 1517 | } |
| 1515 | 1518 | |
| 1516 | fn formatCies( | |
| 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 | ||
| 1531 | pub fn fmtFdes(self: *Object, elf_file: *Elf) std.fmt.Formatter(formatFdes) { | |
| 1519 | pub fn fmtFdes(self: *Object, elf_file: *Elf) std.fmt.Formatter(Format, Format.fdes) { | |
| 1532 | 1520 | return .{ .data = .{ |
| 1533 | 1521 | .object = self, |
| 1534 | 1522 | .elf_file = elf_file, |
| 1535 | 1523 | } }; |
| 1536 | 1524 | } |
| 1537 | 1525 | |
| 1538 | fn formatFdes( | |
| 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 | ||
| 1553 | pub fn fmtGroups(self: *Object, elf_file: *Elf) std.fmt.Formatter(formatGroups) { | |
| 1526 | pub fn fmtGroups(self: *Object, elf_file: *Elf) std.fmt.Formatter(Format, Format.groups) { | |
| 1554 | 1527 | return .{ .data = .{ |
| 1555 | 1528 | .object = self, |
| 1556 | 1529 | .elf_file = elf_file, |
| 1557 | 1530 | } }; |
| 1558 | 1531 | } |
| 1559 | 1532 | |
| 1560 | fn formatGroups( | |
| 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 | ||
| 1584 | pub fn fmtPath(self: Object) std.fmt.Formatter(formatPath) { | |
| 1533 | pub fn fmtPath(self: Object) std.fmt.Formatter(Object, formatPath) { | |
| 1585 | 1534 | return .{ .data = self }; |
| 1586 | 1535 | } |
| 1587 | 1536 | |
| 1588 | fn formatPath( | |
| 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; | |
| 1537 | fn formatPath(object: Object, writer: *std.io.Writer) std.io.Writer.Error!void { | |
| 1596 | 1538 | if (object.archive) |ar| { |
| 1597 | try writer.print("{}({})", .{ ar.path, object.path }); | |
| 1539 | try writer.print("{f}({f})", .{ ar.path, object.path }); | |
| 1598 | 1540 | } else { |
| 1599 | try writer.print("{}", .{object.path}); | |
| 1541 | try writer.print("{f}", .{object.path}); | |
| 1600 | 1542 | } |
| 1601 | 1543 | } |
| 1602 | 1544 |
src/link/Elf/SharedObject.zig+14-34| ... | ... | @@ -509,51 +509,31 @@ pub fn setSymbolExtra(self: *SharedObject, index: u32, extra: Symbol.Extra) void |
| 509 | 509 | } |
| 510 | 510 | } |
| 511 | 511 | |
| 512 | pub fn format( | |
| 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 | ||
| 525 | pub fn fmtSymtab(self: SharedObject, elf_file: *Elf) std.fmt.Formatter(formatSymtab) { | |
| 512 | pub fn fmtSymtab(self: SharedObject, elf_file: *Elf) std.fmt.Formatter(Format, Format.symtab) { | |
| 526 | 513 | return .{ .data = .{ |
| 527 | 514 | .shared = self, |
| 528 | 515 | .elf_file = elf_file, |
| 529 | 516 | } }; |
| 530 | 517 | } |
| 531 | 518 | |
| 532 | const FormatContext = struct { | |
| 519 | const Format = struct { | |
| 533 | 520 | shared: SharedObject, |
| 534 | 521 | elf_file: *Elf, |
| 535 | }; | |
| 536 | 522 | |
| 537 | fn formatSymtab( | |
| 538 | ctx: FormatContext, | |
| 539 | comptime unused_fmt_string: []const u8, | |
| 540 | options: std.fmt.FormatOptions, | |
| 541 | writer: anytype, | |
| 542 | ) !void { | |
| 543 | _ = unused_fmt_string; | |
| 544 | _ = options; | |
| 545 | const shared = ctx.shared; | |
| 546 | const elf_file = ctx.elf_file; | |
| 547 | try writer.writeAll(" globals\n"); | |
| 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)}); | |
| 523 | fn symtab(f: Format, writer: *std.io.Writer) std.io.Writer.Error!void { | |
| 524 | const shared = f.shared; | |
| 525 | const elf_file = f.elf_file; | |
| 526 | try writer.writeAll(" globals\n"); | |
| 527 | for (shared.symbols.items, 0..) |sym, i| { | |
| 528 | const ref = shared.resolveSymbol(@intCast(i), elf_file); | |
| 529 | if (elf_file.symbol(ref)) |ref_sym| { | |
| 530 | try writer.print(" {f}\n", .{ref_sym.fmt(elf_file)}); | |
| 531 | } else { | |
| 532 | try writer.print(" {s} : unclaimed\n", .{sym.name(elf_file)}); | |
| 533 | } | |
| 554 | 534 | } |
| 555 | 535 | } |
| 556 | } | |
| 536 | }; | |
| 557 | 537 | |
| 558 | 538 | const SharedObject = @This(); |
| 559 | 539 |
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 | 316 | out.st_size = esym.st_size; |
| 317 | 317 | } |
| 318 | 318 | |
| 319 | pub fn format( | |
| 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 | ||
| 332 | const FormatContext = struct { | |
| 319 | const Format = struct { | |
| 333 | 320 | symbol: Symbol, |
| 334 | 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 | }; |
| 336 | 370 | |
| 337 | pub fn fmtName(symbol: Symbol, elf_file: *Elf) std.fmt.Formatter(formatName) { | |
| 371 | pub fn fmtName(symbol: Symbol, elf_file: *Elf) std.fmt.Formatter(Format, Format.name) { | |
| 338 | 372 | return .{ .data = .{ |
| 339 | 373 | .symbol = symbol, |
| 340 | 374 | .elf_file = elf_file, |
| 341 | 375 | } }; |
| 342 | 376 | } |
| 343 | 377 | |
| 344 | fn formatName( | |
| 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 | ||
| 366 | pub fn fmt(symbol: Symbol, elf_file: *Elf) std.fmt.Formatter(format2) { | |
| 378 | pub fn fmt(symbol: Symbol, elf_file: *Elf) std.fmt.Formatter(Format, Format.default) { | |
| 367 | 379 | return .{ .data = .{ |
| 368 | 380 | .symbol = symbol, |
| 369 | 381 | .elf_file = elf_file, |
| 370 | 382 | } }; |
| 371 | 383 | } |
| 372 | 384 | |
| 373 | fn 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 | ||
| 412 | 385 | pub const Flags = packed struct { |
| 413 | 386 | /// Whether the symbol is imported at runtime. |
| 414 | 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 | 65 | }; |
| 66 | 66 | } |
| 67 | 67 | |
| 68 | pub fn format( | |
| 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 | ||
| 81 | pub fn fmt(thunk: Thunk, elf_file: *Elf) std.fmt.Formatter(format2) { | |
| 68 | pub fn fmt(thunk: Thunk, elf_file: *Elf) std.fmt.Formatter(Format, Format.default) { | |
| 82 | 69 | return .{ .data = .{ |
| 83 | 70 | .thunk = thunk, |
| 84 | 71 | .elf_file = elf_file, |
| 85 | 72 | } }; |
| 86 | 73 | } |
| 87 | 74 | |
| 88 | const FormatContext = struct { | |
| 75 | const Format = struct { | |
| 89 | 76 | thunk: Thunk, |
| 90 | 77 | elf_file: *Elf, |
| 91 | }; | |
| 92 | 78 | |
| 93 | fn format2( | |
| 94 | ctx: FormatContext, | |
| 95 | comptime unused_fmt_string: []const u8, | |
| 96 | options: std.fmt.FormatOptions, | |
| 97 | writer: anytype, | |
| 98 | ) !void { | |
| 99 | _ = options; | |
| 100 | _ = unused_fmt_string; | |
| 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 }); | |
| 79 | fn default(f: Format, writer: *std.io.Writer) std.io.Writer.Error!void { | |
| 80 | const thunk = f.thunk; | |
| 81 | const elf_file = f.elf_file; | |
| 82 | try writer.print("@{x} : size({x})\n", .{ thunk.value, thunk.size(elf_file) }); | |
| 83 | for (thunk.symbols.keys()) |ref| { | |
| 84 | const sym = elf_file.symbol(ref).?; | |
| 85 | try writer.print(" {f} : {s} : @{x}\n", .{ ref, sym.name(elf_file), sym.value }); | |
| 86 | } | |
| 107 | 87 | } |
| 108 | } | |
| 88 | }; | |
| 109 | 89 | |
| 110 | 90 | pub const Index = u32; |
| 111 | 91 |
src/link/Elf/ZigObject.zig+46-60| ... | ... | @@ -803,9 +803,9 @@ pub fn initRelaSections(self: *ZigObject, elf_file: *Elf) !void { |
| 803 | 803 | const out_shndx = atom_ptr.output_section_index; |
| 804 | 804 | const out_shdr = elf_file.sections.items(.shdr)[out_shndx]; |
| 805 | 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 | 807 | elf_file.getShString(out_shdr.sh_name), |
| 808 | }); | |
| 808 | }, 0); | |
| 809 | 809 | defer gpa.free(rela_sect_name); |
| 810 | 810 | _ = elf_file.sectionByName(rela_sect_name) orelse |
| 811 | 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 | 824 | const out_shndx = atom_ptr.output_section_index; |
| 825 | 825 | const out_shdr = elf_file.sections.items(.shdr)[out_shndx]; |
| 826 | 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 | 828 | elf_file.getShString(out_shdr.sh_name), |
| 829 | }); | |
| 829 | }, 0); | |
| 830 | 830 | defer gpa.free(rela_sect_name); |
| 831 | 831 | const out_rela_shndx = elf_file.sectionByName(rela_sect_name).?; |
| 832 | 832 | const out_rela_shdr = &elf_file.sections.items(.shdr)[out_rela_shndx]; |
| ... | ... | @@ -925,7 +925,7 @@ pub fn getNavVAddr( |
| 925 | 925 | const zcu = pt.zcu; |
| 926 | 926 | const ip = &zcu.intern_pool; |
| 927 | 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 | 929 | const this_sym_index = if (nav.getExtern(ip)) |@"extern"| try self.getGlobalSymbol( |
| 930 | 930 | elf_file, |
| 931 | 931 | nav.name.toSlice(ip), |
| ... | ... | @@ -1268,7 +1268,7 @@ fn updateNavCode( |
| 1268 | 1268 | const ip = &zcu.intern_pool; |
| 1269 | 1269 | const nav = ip.getNav(nav_index); |
| 1270 | 1270 | |
| 1271 | log.debug("updateNavCode {}({d})", .{ nav.fqn.fmt(ip), nav_index }); | |
| 1271 | log.debug("updateNavCode {f}({d})", .{ nav.fqn.fmt(ip), nav_index }); | |
| 1272 | 1272 | |
| 1273 | 1273 | const target = &zcu.navFileScope(nav_index).mod.?.resolved_target.result; |
| 1274 | 1274 | const required_alignment = switch (pt.navAlignment(nav_index)) { |
| ... | ... | @@ -1302,7 +1302,7 @@ fn updateNavCode( |
| 1302 | 1302 | self.allocateAtom(atom_ptr, true, elf_file) catch |err| |
| 1303 | 1303 | return elf_file.base.cgFail(nav_index, "failed to allocate atom: {s}", .{@errorName(err)}); |
| 1304 | 1304 | |
| 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 | 1306 | if (old_vaddr != atom_ptr.value) { |
| 1307 | 1307 | sym.value = 0; |
| 1308 | 1308 | esym.st_value = 0; |
| ... | ... | @@ -1347,7 +1347,7 @@ fn updateNavCode( |
| 1347 | 1347 | const file_offset = atom_ptr.offset(elf_file); |
| 1348 | 1348 | elf_file.base.file.?.pwriteAll(code, file_offset) catch |err| |
| 1349 | 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 | } |
| 1353 | 1353 | |
| ... | ... | @@ -1365,7 +1365,7 @@ fn updateTlv( |
| 1365 | 1365 | const gpa = zcu.gpa; |
| 1366 | 1366 | const nav = ip.getNav(nav_index); |
| 1367 | 1367 | |
| 1368 | log.debug("updateTlv {}({d})", .{ nav.fqn.fmt(ip), nav_index }); | |
| 1368 | log.debug("updateTlv {f}({d})", .{ nav.fqn.fmt(ip), nav_index }); | |
| 1369 | 1369 | |
| 1370 | 1370 | const required_alignment = pt.navAlignment(nav_index); |
| 1371 | 1371 | |
| ... | ... | @@ -1424,7 +1424,7 @@ pub fn updateFunc( |
| 1424 | 1424 | const gpa = elf_file.base.comp.gpa; |
| 1425 | 1425 | const func = zcu.funcInfo(func_index); |
| 1426 | 1426 | |
| 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 }); | |
| 1428 | 1428 | |
| 1429 | 1429 | const sym_index = try self.getOrCreateMetadataForNav(zcu, func.owner_nav); |
| 1430 | 1430 | self.atom(self.symbol(sym_index).ref.index).?.freeRelocs(self); |
| ... | ... | @@ -1447,7 +1447,7 @@ pub fn updateFunc( |
| 1447 | 1447 | const code = code_buffer.items; |
| 1448 | 1448 | |
| 1449 | 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 | 1451 | shndx, |
| 1452 | 1452 | elf_file.getShString(elf_file.sections.items(.shdr)[shndx].sh_name), |
| 1453 | 1453 | ip.getNav(func.owner_nav).fqn.fmt(ip), |
| ... | ... | @@ -1529,7 +1529,7 @@ pub fn updateNav( |
| 1529 | 1529 | const ip = &zcu.intern_pool; |
| 1530 | 1530 | const nav = ip.getNav(nav_index); |
| 1531 | 1531 | |
| 1532 | log.debug("updateNav {}({d})", .{ nav.fqn.fmt(ip), nav_index }); | |
| 1532 | log.debug("updateNav {f}({d})", .{ nav.fqn.fmt(ip), nav_index }); | |
| 1533 | 1533 | |
| 1534 | 1534 | const nav_init = switch (ip.indexToKey(nav.status.fully_resolved.val)) { |
| 1535 | 1535 | .func => .none, |
| ... | ... | @@ -1576,7 +1576,7 @@ pub fn updateNav( |
| 1576 | 1576 | const code = code_buffer.items; |
| 1577 | 1577 | |
| 1578 | 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 | 1580 | shndx, |
| 1581 | 1581 | elf_file.getShString(elf_file.sections.items(.shdr)[shndx].sh_name), |
| 1582 | 1582 | nav.fqn.fmt(ip), |
| ... | ... | @@ -1622,7 +1622,7 @@ fn updateLazySymbol( |
| 1622 | 1622 | defer code_buffer.deinit(gpa); |
| 1623 | 1623 | |
| 1624 | 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 | 1626 | @tagName(sym.kind), |
| 1627 | 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 | 1941 | .requires_padding = requires_padding, |
| 1942 | 1942 | }); |
| 1943 | 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 | 1945 | atom_ptr.name(elf_file), |
| 1946 | 1946 | atom_ptr.offset(elf_file), |
| 1947 | 1947 | alloc_res.placement, |
| ... | ... | @@ -1986,7 +1986,7 @@ pub fn allocateAtom(self: *ZigObject, atom_ptr: *Atom, requires_padding: bool, e |
| 1986 | 1986 | atom_ptr.next_atom_ref = .{ .index = 0, .file = 0 }; |
| 1987 | 1987 | } |
| 1988 | 1988 | |
| 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 | } |
| 1991 | 1991 | |
| 1992 | 1992 | pub fn resetShdrIndexes(self: *ZigObject, backlinks: []const u32) void { |
| ... | ... | @@ -2195,60 +2195,46 @@ pub fn setSymbolExtra(self: *ZigObject, index: u32, extra: Symbol.Extra) void { |
| 2195 | 2195 | } |
| 2196 | 2196 | } |
| 2197 | 2197 | |
| 2198 | pub fn fmtSymtab(self: *ZigObject, elf_file: *Elf) std.fmt.Formatter(formatSymtab) { | |
| 2199 | return .{ .data = .{ | |
| 2200 | .self = self, | |
| 2201 | .elf_file = elf_file, | |
| 2202 | } }; | |
| 2203 | } | |
| 2204 | ||
| 2205 | const FormatContext = struct { | |
| 2198 | const Format = struct { | |
| 2206 | 2199 | self: *ZigObject, |
| 2207 | 2200 | elf_file: *Elf, |
| 2208 | }; | |
| 2209 | 2201 | |
| 2210 | fn formatSymtab( | |
| 2211 | ctx: FormatContext, | |
| 2212 | comptime unused_fmt_string: []const u8, | |
| 2213 | options: std.fmt.FormatOptions, | |
| 2214 | writer: anytype, | |
| 2215 | ) !void { | |
| 2216 | _ = unused_fmt_string; | |
| 2217 | _ = options; | |
| 2218 | const self = ctx.self; | |
| 2219 | const elf_file = ctx.elf_file; | |
| 2220 | try writer.writeAll(" locals\n"); | |
| 2221 | for (self.local_symbols.items) |index| { | |
| 2222 | const local = self.symbols.items[index]; | |
| 2223 | try writer.print(" {}\n", .{local.fmt(elf_file)}); | |
| 2202 | fn symtab(f: Format, writer: *std.io.Writer) std.io.Writer.Error!void { | |
| 2203 | const self = f.self; | |
| 2204 | const elf_file = f.elf_file; | |
| 2205 | try writer.writeAll(" locals\n"); | |
| 2206 | for (self.local_symbols.items) |index| { | |
| 2207 | const local = self.symbols.items[index]; | |
| 2208 | try writer.print(" {f}\n", .{local.fmt(elf_file)}); | |
| 2209 | } | |
| 2210 | try writer.writeAll(" globals\n"); | |
| 2211 | for (f.self.global_symbols.items) |index| { | |
| 2212 | const global = self.symbols.items[index]; | |
| 2213 | try writer.print(" {f}\n", .{global.fmt(elf_file)}); | |
| 2214 | } | |
| 2224 | 2215 | } |
| 2225 | try writer.writeAll(" globals\n"); | |
| 2226 | for (ctx.self.global_symbols.items) |index| { | |
| 2227 | const global = self.symbols.items[index]; | |
| 2228 | try writer.print(" {}\n", .{global.fmt(elf_file)}); | |
| 2216 | ||
| 2217 | fn atoms(f: Format, writer: *std.io.Writer) std.io.Writer.Error!void { | |
| 2218 | try writer.writeAll(" atoms\n"); | |
| 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 | }; | |
| 2231 | 2225 | |
| 2232 | pub fn fmtAtoms(self: *ZigObject, elf_file: *Elf) std.fmt.Formatter(formatAtoms) { | |
| 2226 | pub fn fmtSymtab(self: *ZigObject, elf_file: *Elf) std.fmt.Formatter(Format, Format.symtab) { | |
| 2233 | 2227 | return .{ .data = .{ |
| 2234 | 2228 | .self = self, |
| 2235 | 2229 | .elf_file = elf_file, |
| 2236 | 2230 | } }; |
| 2237 | 2231 | } |
| 2238 | 2232 | |
| 2239 | fn formatAtoms( | |
| 2240 | ctx: FormatContext, | |
| 2241 | comptime unused_fmt_string: []const u8, | |
| 2242 | options: std.fmt.FormatOptions, | |
| 2243 | writer: anytype, | |
| 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 | } | |
| 2233 | pub fn fmtAtoms(self: *ZigObject, elf_file: *Elf) std.fmt.Formatter(Format, Format.atoms) { | |
| 2234 | return .{ .data = .{ | |
| 2235 | .self = self, | |
| 2236 | .elf_file = elf_file, | |
| 2237 | } }; | |
| 2252 | 2238 | } |
| 2253 | 2239 | |
| 2254 | 2240 | const ElfSym = struct { |
| ... | ... | @@ -2285,7 +2271,7 @@ fn checkNavAllocated(pt: Zcu.PerThread, index: InternPool.Nav.Index, meta: AvMet |
| 2285 | 2271 | const zcu = pt.zcu; |
| 2286 | 2272 | const ip = &zcu.intern_pool; |
| 2287 | 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 | 2275 | nav.fqn.fmt(ip), |
| 2290 | 2276 | index, |
| 2291 | 2277 | meta.symbol_index, |
| ... | ... | @@ -2298,7 +2284,7 @@ fn checkUavAllocated(pt: Zcu.PerThread, index: InternPool.Index, meta: AvMetadat |
| 2298 | 2284 | const zcu = pt.zcu; |
| 2299 | 2285 | const uav = Value.fromInterned(index); |
| 2300 | 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 | 2288 | ty.fmt(pt), |
| 2303 | 2289 | index, |
| 2304 | 2290 | meta.symbol_index, |
src/link/Elf/eh_frame.zig+34-74| ... | ... | @@ -47,52 +47,32 @@ pub const Fde = struct { |
| 47 | 47 | return object.relocs.items[fde.rel_index..][0..fde.rel_num]; |
| 48 | 48 | } |
| 49 | 49 | |
| 50 | pub fn format( | |
| 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) { | |
| 50 | pub fn fmt(fde: Fde, elf_file: *Elf) std.fmt.Formatter(Format, Format.default) { | |
| 64 | 51 | return .{ .data = .{ |
| 65 | 52 | .fde = fde, |
| 66 | 53 | .elf_file = elf_file, |
| 67 | 54 | } }; |
| 68 | 55 | } |
| 69 | 56 | |
| 70 | const FdeFormatContext = struct { | |
| 57 | const Format = struct { | |
| 71 | 58 | fde: Fde, |
| 72 | 59 | elf_file: *Elf, |
| 73 | }; | |
| 74 | 60 | |
| 75 | fn format2( | |
| 76 | ctx: FdeFormatContext, | |
| 77 | comptime unused_fmt_string: []const u8, | |
| 78 | options: std.fmt.FormatOptions, | |
| 79 | writer: anytype, | |
| 80 | ) !void { | |
| 81 | _ = unused_fmt_string; | |
| 82 | _ = options; | |
| 83 | const fde = ctx.fde; | |
| 84 | const elf_file = ctx.elf_file; | |
| 85 | const base_addr = fde.address(elf_file); | |
| 86 | const object = elf_file.file(fde.file_index).?.object; | |
| 87 | const atom_name = fde.atom(object).name(elf_file); | |
| 88 | try writer.print("@{x} : size({x}) : cie({d}) : {s}", .{ | |
| 89 | base_addr + fde.out_offset, | |
| 90 | fde.calcSize(), | |
| 91 | fde.cie_index, | |
| 92 | atom_name, | |
| 93 | }); | |
| 94 | if (!fde.alive) try writer.writeAll(" : [*]"); | |
| 95 | } | |
| 61 | fn default(f: Format, writer: *std.io.Writer) std.io.Writer.Error!void { | |
| 62 | const fde = f.fde; | |
| 63 | const elf_file = f.elf_file; | |
| 64 | const base_addr = fde.address(elf_file); | |
| 65 | const object = elf_file.file(fde.file_index).?.object; | |
| 66 | const atom_name = fde.atom(object).name(elf_file); | |
| 67 | try writer.print("@{x} : size({x}) : cie({d}) : {s}", .{ | |
| 68 | base_addr + fde.out_offset, | |
| 69 | fde.calcSize(), | |
| 70 | fde.cie_index, | |
| 71 | atom_name, | |
| 72 | }); | |
| 73 | if (!fde.alive) try writer.writeAll(" : [*]"); | |
| 74 | } | |
| 75 | }; | |
| 96 | 76 | }; |
| 97 | 77 | |
| 98 | 78 | pub const Cie = struct { |
| ... | ... | @@ -150,48 +130,28 @@ pub const Cie = struct { |
| 150 | 130 | return true; |
| 151 | 131 | } |
| 152 | 132 | |
| 153 | pub fn format( | |
| 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) { | |
| 133 | pub fn fmt(cie: Cie, elf_file: *Elf) std.fmt.Formatter(Format, Format.default) { | |
| 167 | 134 | return .{ .data = .{ |
| 168 | 135 | .cie = cie, |
| 169 | 136 | .elf_file = elf_file, |
| 170 | 137 | } }; |
| 171 | 138 | } |
| 172 | 139 | |
| 173 | const CieFormatContext = struct { | |
| 140 | const Format = struct { | |
| 174 | 141 | cie: Cie, |
| 175 | 142 | elf_file: *Elf, |
| 176 | }; | |
| 177 | 143 | |
| 178 | fn format2( | |
| 179 | ctx: CieFormatContext, | |
| 180 | comptime unused_fmt_string: []const u8, | |
| 181 | options: std.fmt.FormatOptions, | |
| 182 | writer: anytype, | |
| 183 | ) !void { | |
| 184 | _ = unused_fmt_string; | |
| 185 | _ = options; | |
| 186 | const cie = ctx.cie; | |
| 187 | const elf_file = ctx.elf_file; | |
| 188 | const base_addr = cie.address(elf_file); | |
| 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 | } | |
| 144 | fn default(f: Format, writer: *std.io.Writer) std.io.Writer.Error!void { | |
| 145 | const cie = f.cie; | |
| 146 | const elf_file = f.elf_file; | |
| 147 | const base_addr = cie.address(elf_file); | |
| 148 | try writer.print("@{x} : size({x})", .{ | |
| 149 | base_addr + cie.out_offset, | |
| 150 | cie.calcSize(), | |
| 151 | }); | |
| 152 | if (!cie.alive) try writer.writeAll(" : [*]"); | |
| 153 | } | |
| 154 | }; | |
| 195 | 155 | }; |
| 196 | 156 | |
| 197 | 157 | pub const Iterator = struct { |
| ... | ... | @@ -316,7 +276,7 @@ fn resolveReloc(rec: anytype, sym: *const Symbol, rel: elf.Elf64_Rela, elf_file: |
| 316 | 276 | const S = math.cast(i64, sym.address(.{}, elf_file)) orelse return error.Overflow; |
| 317 | 277 | const A = rel.r_addend; |
| 318 | 278 | |
| 319 | relocs_log.debug(" {s}: {x}: [{x} => {x}] ({s})", .{ | |
| 279 | relocs_log.debug(" {f}: {x}: [{x} => {x}] ({s})", .{ | |
| 320 | 280 | relocation.fmtRelocType(rel.r_type(), cpu_arch), |
| 321 | 281 | offset, |
| 322 | 282 | P, |
| ... | ... | @@ -438,7 +398,7 @@ fn emitReloc(elf_file: *Elf, r_offset: u64, sym: *const Symbol, rel: elf.Elf64_R |
| 438 | 398 | }, |
| 439 | 399 | } |
| 440 | 400 | |
| 441 | relocs_log.debug(" {s}: [{x} => {d}({s})] + {x}", .{ | |
| 401 | relocs_log.debug(" {f}: [{x} => {d}({s})] + {x}", .{ | |
| 442 | 402 | relocation.fmtRelocType(r_type, cpu_arch), |
| 443 | 403 | r_offset, |
| 444 | 404 | r_sym, |
| ... | ... | @@ -607,11 +567,11 @@ const riscv = struct { |
| 607 | 567 | fn reportInvalidReloc(rec: anytype, elf_file: *Elf, rel: elf.Elf64_Rela) !void { |
| 608 | 568 | const diags = &elf_file.base.comp.link_diags; |
| 609 | 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 | 571 | relocation.fmtRelocType(rel.r_type(), elf_file.getTarget().cpu.arch), |
| 612 | 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 | 575 | return error.RelocFailure; |
| 616 | 576 | } |
| 617 | 577 |
src/link/Elf/file.zig+4-11| ... | ... | @@ -10,23 +10,16 @@ pub const File = union(enum) { |
| 10 | 10 | }; |
| 11 | 11 | } |
| 12 | 12 | |
| 13 | pub fn fmtPath(file: File) std.fmt.Formatter(formatPath) { | |
| 13 | pub fn fmtPath(file: File) std.fmt.Formatter(File, formatPath) { | |
| 14 | 14 | return .{ .data = file }; |
| 15 | 15 | } |
| 16 | 16 | |
| 17 | fn formatPath( | |
| 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; | |
| 17 | fn formatPath(file: File, writer: *std.io.Writer) std.io.Writer.Error!void { | |
| 25 | 18 | switch (file) { |
| 26 | 19 | .zig_object => |zo| try writer.writeAll(zo.basename), |
| 27 | 20 | .linker_defined => try writer.writeAll("(linker defined)"), |
| 28 | .object => |x| try writer.print("{}", .{x.fmtPath()}), | |
| 29 | .shared_object => |x| try writer.print("{}", .{@as(Path, x.path)}), | |
| 21 | .object => |x| try writer.print("{f}", .{x.fmtPath()}), | |
| 22 | .shared_object => |x| try writer.print("{f}", .{@as(Path, x.path)}), | |
| 30 | 23 | } |
| 31 | 24 | } |
| 32 | 25 |
src/link/Elf/gc.zig+6-13| ... | ... | @@ -111,7 +111,7 @@ fn markLive(atom: *Atom, elf_file: *Elf) void { |
| 111 | 111 | const target_sym = elf_file.symbol(ref) orelse continue; |
| 112 | 112 | const target_atom = target_sym.atom(elf_file) orelse continue; |
| 113 | 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 | 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 | 128 | } |
| 129 | 129 | const target_atom = target_sym.atom(elf_file) orelse continue; |
| 130 | 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 | 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 | 163 | } |
| 164 | 164 | |
| 165 | 165 | pub fn dumpPrunedAtoms(elf_file: *Elf) !void { |
| 166 | const stderr = std.io.getStdErr().writer(); | |
| 166 | const stderr = std.fs.File.stderr().deprecatedWriter(); | |
| 167 | 167 | for (elf_file.objects.items) |index| { |
| 168 | 168 | const file = elf_file.file(index).?; |
| 169 | 169 | for (file.atoms()) |atom_index| { |
| 170 | 170 | const atom = file.atom(atom_index) orelse continue; |
| 171 | 171 | if (!atom.alive) |
| 172 | 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 | 174 | atom.name(elf_file), |
| 175 | 175 | atom.file(elf_file).?.fmtPath(), |
| 176 | 176 | }); |
| ... | ... | @@ -185,15 +185,8 @@ const Level = struct { |
| 185 | 185 | self.value += 1; |
| 186 | 186 | } |
| 187 | 187 | |
| 188 | pub fn format( | |
| 189 | self: *const @This(), | |
| 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); | |
| 188 | pub fn format(self: *const @This(), w: *std.io.Writer) std.io.Writer.Error!void { | |
| 189 | try w.splatByteAll(' ', self.value); | |
| 197 | 190 | } |
| 198 | 191 | }; |
| 199 | 192 |
src/link/Elf/relocatable.zig+4-4| ... | ... | @@ -31,7 +31,7 @@ pub fn flushStaticLib(elf_file: *Elf, comp: *Compilation) !void { |
| 31 | 31 | try elf_file.allocateNonAllocSections(); |
| 32 | 32 | |
| 33 | 33 | if (build_options.enable_logging) { |
| 34 | state_log.debug("{}", .{elf_file.dumpState()}); | |
| 34 | state_log.debug("{f}", .{elf_file.dumpState()}); | |
| 35 | 35 | } |
| 36 | 36 | |
| 37 | 37 | try elf_file.writeMergeSections(); |
| ... | ... | @@ -96,8 +96,8 @@ pub fn flushStaticLib(elf_file: *Elf, comp: *Compilation) !void { |
| 96 | 96 | }; |
| 97 | 97 | |
| 98 | 98 | if (build_options.enable_logging) { |
| 99 | state_log.debug("ar_symtab\n{}\n", .{ar_symtab.fmt(elf_file)}); | |
| 100 | state_log.debug("ar_strtab\n{}\n", .{ar_strtab}); | |
| 99 | state_log.debug("ar_symtab\n{f}\n", .{ar_symtab.fmt(elf_file)}); | |
| 100 | state_log.debug("ar_strtab\n{f}\n", .{ar_strtab}); | |
| 101 | 101 | } |
| 102 | 102 | |
| 103 | 103 | var buffer = std.ArrayList(u8).init(gpa); |
| ... | ... | @@ -170,7 +170,7 @@ pub fn flushObject(elf_file: *Elf, comp: *Compilation) !void { |
| 170 | 170 | try elf_file.allocateNonAllocSections(); |
| 171 | 171 | |
| 172 | 172 | if (build_options.enable_logging) { |
| 173 | state_log.debug("{}", .{elf_file.dumpState()}); | |
| 173 | state_log.debug("{f}", .{elf_file.dumpState()}); | |
| 174 | 174 | } |
| 175 | 175 | |
| 176 | 176 | try writeAtoms(elf_file); |
src/link/Elf/relocation.zig+2-9| ... | ... | @@ -141,21 +141,14 @@ const FormatRelocTypeCtx = struct { |
| 141 | 141 | cpu_arch: std.Target.Cpu.Arch, |
| 142 | 142 | }; |
| 143 | 143 | |
| 144 | pub fn fmtRelocType(r_type: u32, cpu_arch: std.Target.Cpu.Arch) std.fmt.Formatter(formatRelocType) { | |
| 144 | pub fn fmtRelocType(r_type: u32, cpu_arch: std.Target.Cpu.Arch) std.fmt.Formatter(FormatRelocTypeCtx, formatRelocType) { | |
| 145 | 145 | return .{ .data = .{ |
| 146 | 146 | .r_type = r_type, |
| 147 | 147 | .cpu_arch = cpu_arch, |
| 148 | 148 | } }; |
| 149 | 149 | } |
| 150 | 150 | |
| 151 | fn formatRelocType( | |
| 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; | |
| 151 | fn formatRelocType(ctx: FormatRelocTypeCtx, writer: *std.io.Writer) std.io.Writer.Error!void { | |
| 159 | 152 | const r_type = ctx.r_type; |
| 160 | 153 | switch (ctx.cpu_arch) { |
| 161 | 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 | 606 | } |
| 607 | 607 | } |
| 608 | 608 | |
| 609 | const FormatCtx = struct { | |
| 609 | const Format = struct { | |
| 610 | 610 | got: GotSection, |
| 611 | 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 | }; |
| 613 | 629 | |
| 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 | 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 | }; |
| 641 | 634 | |
| 642 | 635 | pub const PltSection = struct { |
| ... | ... | @@ -703,7 +696,7 @@ pub const PltSection = struct { |
| 703 | 696 | const r_sym: u64 = extra.dynamic; |
| 704 | 697 | const r_type = relocation.encode(.jump_slot, cpu_arch); |
| 705 | 698 | |
| 706 | relocs_log.debug(" {s}: [{x} => {d}({s})] + 0", .{ | |
| 699 | relocs_log.debug(" {f}: [{x} => {d}({s})] + 0", .{ | |
| 707 | 700 | relocation.fmtRelocType(r_type, cpu_arch), |
| 708 | 701 | r_offset, |
| 709 | 702 | r_sym, |
| ... | ... | @@ -749,38 +742,31 @@ pub const PltSection = struct { |
| 749 | 742 | } |
| 750 | 743 | } |
| 751 | 744 | |
| 752 | const FormatCtx = struct { | |
| 745 | const Format = struct { | |
| 753 | 746 | plt: PltSection, |
| 754 | 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 | }; |
| 756 | 765 | |
| 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 | 767 | return .{ .data = .{ .plt = plt, .elf_file = elf_file } }; |
| 759 | 768 | } |
| 760 | 769 | |
| 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 | 770 | const x86_64 = struct { |
| 785 | 771 | fn write(plt: PltSection, elf_file: *Elf, writer: anytype) !void { |
| 786 | 772 | const shdrs = elf_file.sections.items(.shdr); |
src/link/LdScript.zig+2-2| ... | ... | @@ -41,8 +41,8 @@ pub fn parse( |
| 41 | 41 | try line_col.append(gpa, .{ .line = line, .column = column }); |
| 42 | 42 | switch (tok.id) { |
| 43 | 43 | .invalid => { |
| 44 | return diags.failParse(path, "invalid token in LD script: '{s}' ({d}:{d})", .{ | |
| 45 | std.fmt.fmtSliceEscapeLower(tok.get(data)), line, column, | |
| 44 | return diags.failParse(path, "invalid token in LD script: '{f}' ({d}:{d})", .{ | |
| 45 | std.ascii.hexEscape(tok.get(data), .lower), line, column, | |
| 46 | 46 | }); |
| 47 | 47 | }, |
| 48 | 48 | .new_line => { |
src/link/Lld.zig+12-16| ... | ... | @@ -294,7 +294,7 @@ fn linkAsArchive(lld: *Lld, arena: Allocator) !void { |
| 294 | 294 | break :p try comp.resolveEmitPathFlush(arena, .temp, base.zcu_object_basename.?); |
| 295 | 295 | } else null; |
| 296 | 296 | |
| 297 | log.debug("zcu_obj_path={?}", .{zcu_obj_path}); | |
| 297 | log.debug("zcu_obj_path={?f}", .{zcu_obj_path}); | |
| 298 | 298 | |
| 299 | 299 | const compiler_rt_path: ?Cache.Path = if (comp.compiler_rt_strat == .obj) |
| 300 | 300 | comp.compiler_rt_obj.?.full_object_path |
| ... | ... | @@ -437,7 +437,7 @@ fn coffLink(lld: *Lld, arena: Allocator) !void { |
| 437 | 437 | try argv.append(try allocPrint(arena, "-PDBALTPATH:{s}", .{out_pdb_basename})); |
| 438 | 438 | } |
| 439 | 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 | } |
| 442 | 442 | |
| 443 | 443 | if (target_util.llvmMachineAbi(target)) |mabi| { |
| ... | ... | @@ -507,7 +507,7 @@ fn coffLink(lld: *Lld, arena: Allocator) !void { |
| 507 | 507 | |
| 508 | 508 | if (comp.emit_implib) |raw_emit_path| { |
| 509 | 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 | } |
| 512 | 512 | |
| 513 | 513 | if (comp.config.link_libc) { |
| ... | ... | @@ -533,7 +533,7 @@ fn coffLink(lld: *Lld, arena: Allocator) !void { |
| 533 | 533 | }, |
| 534 | 534 | .object, .archive => |obj| { |
| 535 | 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 | 537 | } else { |
| 538 | 538 | argv.appendAssumeCapacity(try obj.path.toString(arena)); |
| 539 | 539 | } |
| ... | ... | @@ -933,9 +933,7 @@ fn elfLink(lld: *Lld, arena: Allocator) !void { |
| 933 | 933 | .fast, .uuid, .sha1, .md5 => try argv.append(try std.fmt.allocPrint(arena, "--build-id={s}", .{ |
| 934 | 934 | @tagName(base.build_id), |
| 935 | 935 | })), |
| 936 | .hexstring => |hs| try argv.append(try std.fmt.allocPrint(arena, "--build-id=0x{s}", .{ | |
| 937 | std.fmt.fmtSliceHexLower(hs.toSlice()), | |
| 938 | })), | |
| 936 | .hexstring => |hs| try argv.append(try std.fmt.allocPrint(arena, "--build-id=0x{x}", .{hs.toSlice()})), | |
| 939 | 937 | } |
| 940 | 938 | |
| 941 | 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 | 1216 | if (target.os.versionRange().gnuLibCVersion().?.order(rem_in) != .lt) continue; |
| 1219 | 1217 | } |
| 1220 | 1218 | |
| 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 | 1220 | comp.glibc_so_files.?.dir_path, fs.path.sep, lib.name, lib.sover, |
| 1223 | 1221 | }); |
| 1224 | 1222 | try argv.append(lib_path); |
| ... | ... | @@ -1231,14 +1229,14 @@ fn elfLink(lld: *Lld, arena: Allocator) !void { |
| 1231 | 1229 | })); |
| 1232 | 1230 | } else if (target.isFreeBSDLibC()) { |
| 1233 | 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 | 1233 | comp.freebsd_so_files.?.dir_path, fs.path.sep, lib.name, lib.sover, |
| 1236 | 1234 | }); |
| 1237 | 1235 | try argv.append(lib_path); |
| 1238 | 1236 | } |
| 1239 | 1237 | } else if (target.isNetBSDLibC()) { |
| 1240 | 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 | 1240 | comp.netbsd_so_files.?.dir_path, fs.path.sep, lib.name, lib.sover, |
| 1243 | 1241 | }); |
| 1244 | 1242 | try argv.append(lib_path); |
| ... | ... | @@ -1511,9 +1509,7 @@ fn wasmLink(lld: *Lld, arena: Allocator) !void { |
| 1511 | 1509 | .fast, .uuid, .sha1 => try argv.append(try std.fmt.allocPrint(arena, "--build-id={s}", .{ |
| 1512 | 1510 | @tagName(base.build_id), |
| 1513 | 1511 | })), |
| 1514 | .hexstring => |hs| try argv.append(try std.fmt.allocPrint(arena, "--build-id=0x{s}", .{ | |
| 1515 | std.fmt.fmtSliceHexLower(hs.toSlice()), | |
| 1516 | })), | |
| 1512 | .hexstring => |hs| try argv.append(try std.fmt.allocPrint(arena, "--build-id=0x{x}", .{hs.toSlice()})), | |
| 1517 | 1513 | .md5 => {}, |
| 1518 | 1514 | } |
| 1519 | 1515 | |
| ... | ... | @@ -1653,7 +1649,7 @@ fn spawnLld( |
| 1653 | 1649 | child.stderr_behavior = .Pipe; |
| 1654 | 1650 | |
| 1655 | 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 | 1653 | break :term child.wait(); |
| 1658 | 1654 | }) catch |first_err| term: { |
| 1659 | 1655 | const err = switch (first_err) { |
| ... | ... | @@ -1667,7 +1663,7 @@ fn spawnLld( |
| 1667 | 1663 | log.warn("failed to delete response file {s}: {s}", .{ rsp_path, @errorName(err) }); |
| 1668 | 1664 | { |
| 1669 | 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 | 1667 | const rsp_writer = rsp_buf.writer(); |
| 1672 | 1668 | for (argv[2..]) |arg| { |
| 1673 | 1669 | try rsp_writer.writeByte('"'); |
| ... | ... | @@ -1701,7 +1697,7 @@ fn spawnLld( |
| 1701 | 1697 | rsp_child.stderr_behavior = .Pipe; |
| 1702 | 1698 | |
| 1703 | 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 | 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 | 543 | self.allocateSyntheticSymbols(); |
| 544 | 544 | |
| 545 | 545 | if (build_options.enable_logging) { |
| 546 | state_log.debug("{}", .{self.dumpState()}); | |
| 546 | state_log.debug("{f}", .{self.dumpState()}); | |
| 547 | 547 | } |
| 548 | 548 | |
| 549 | 549 | // 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 | 677 | |
| 678 | 678 | try argv.append("-platform_version"); |
| 679 | 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})); | |
| 681 | 681 | |
| 682 | 682 | if (self.sdk_version) |ver| { |
| 683 | 683 | try argv.append(try std.fmt.allocPrint(arena, "{d}.{d}", .{ ver.major, ver.minor })); |
| 684 | 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 | } |
| 687 | 687 | |
| 688 | 688 | if (comp.sysroot) |syslibroot| { |
| ... | ... | @@ -863,7 +863,7 @@ pub fn classifyInputFile(self: *MachO, input: link.Input) !void { |
| 863 | 863 | |
| 864 | 864 | const path, const file = input.pathAndFile().?; |
| 865 | 865 | // 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}); | |
| 867 | 867 | |
| 868 | 868 | const fh = try self.addFileHandle(file); |
| 869 | 869 | var buffer: [Archive.SARMAG]u8 = undefined; |
| ... | ... | @@ -1591,7 +1591,7 @@ fn reportUndefs(self: *MachO) !void { |
| 1591 | 1591 | const ref = refs.items[inote]; |
| 1592 | 1592 | const file = self.getFile(ref.file).?; |
| 1593 | 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 | } |
| 1596 | 1596 | |
| 1597 | 1597 | if (refs.items.len > max_notes) { |
| ... | ... | @@ -3791,7 +3791,7 @@ pub fn reportParseError2( |
| 3791 | 3791 | const diags = &self.base.comp.link_diags; |
| 3792 | 3792 | var err = try diags.addErrorWithNotes(1); |
| 3793 | 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 | } |
| 3796 | 3796 | |
| 3797 | 3797 | fn reportMissingDependencyError( |
| ... | ... | @@ -3806,7 +3806,7 @@ fn reportMissingDependencyError( |
| 3806 | 3806 | var err = try diags.addErrorWithNotes(2 + checked_paths.len); |
| 3807 | 3807 | try err.addMsg(format, args); |
| 3808 | 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 | 3810 | for (checked_paths) |p| { |
| 3811 | 3811 | err.addNote("tried {s}", .{p}); |
| 3812 | 3812 | } |
| ... | ... | @@ -3823,7 +3823,7 @@ fn reportDependencyError( |
| 3823 | 3823 | var err = try diags.addErrorWithNotes(2); |
| 3824 | 3824 | try err.addMsg(format, args); |
| 3825 | 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 | } |
| 3828 | 3828 | |
| 3829 | 3829 | fn reportDuplicates(self: *MachO) error{ HasDuplicates, OutOfMemory }!void { |
| ... | ... | @@ -3853,12 +3853,12 @@ fn reportDuplicates(self: *MachO) error{ HasDuplicates, OutOfMemory }!void { |
| 3853 | 3853 | |
| 3854 | 3854 | var err = try diags.addErrorWithNotes(nnotes + 1); |
| 3855 | 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()}); | |
| 3857 | 3857 | |
| 3858 | 3858 | var inote: usize = 0; |
| 3859 | 3859 | while (inote < @min(notes.items.len, max_notes)) : (inote += 1) { |
| 3860 | 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 | } |
| 3863 | 3863 | |
| 3864 | 3864 | if (notes.items.len > max_notes) { |
| ... | ... | @@ -3900,35 +3900,28 @@ pub fn ptraceDetach(self: *MachO, pid: std.posix.pid_t) !void { |
| 3900 | 3900 | self.hot_state.mach_task = null; |
| 3901 | 3901 | } |
| 3902 | 3902 | |
| 3903 | pub fn dumpState(self: *MachO) std.fmt.Formatter(fmtDumpState) { | |
| 3903 | pub fn dumpState(self: *MachO) std.fmt.Formatter(*MachO, fmtDumpState) { | |
| 3904 | 3904 | return .{ .data = self }; |
| 3905 | 3905 | } |
| 3906 | 3906 | |
| 3907 | fn fmtDumpState( | |
| 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; | |
| 3907 | fn fmtDumpState(self: *MachO, w: *Writer) Writer.Error!void { | |
| 3915 | 3908 | if (self.getZigObject()) |zo| { |
| 3916 | try writer.print("zig_object({d}) : {s}\n", .{ zo.index, zo.basename }); | |
| 3917 | try writer.print("{}{}\n", .{ | |
| 3909 | try w.print("zig_object({d}) : {s}\n", .{ zo.index, zo.basename }); | |
| 3910 | try w.print("{f}{f}\n", .{ | |
| 3918 | 3911 | zo.fmtAtoms(self), |
| 3919 | 3912 | zo.fmtSymtab(self), |
| 3920 | 3913 | }); |
| 3921 | 3914 | } |
| 3922 | 3915 | for (self.objects.items) |index| { |
| 3923 | 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 | 3918 | index, |
| 3926 | 3919 | object.fmtPath(), |
| 3927 | 3920 | object.hasDebugInfo(), |
| 3928 | 3921 | }); |
| 3929 | if (!object.alive) try writer.writeAll(" : ([*])"); | |
| 3930 | try writer.writeByte('\n'); | |
| 3931 | try writer.print("{}{}{}{}{}\n", .{ | |
| 3922 | if (!object.alive) try w.writeAll(" : ([*])"); | |
| 3923 | try w.writeByte('\n'); | |
| 3924 | try w.print("{f}{f}{f}{f}{f}\n", .{ | |
| 3932 | 3925 | object.fmtAtoms(self), |
| 3933 | 3926 | object.fmtCies(self), |
| 3934 | 3927 | object.fmtFdes(self), |
| ... | ... | @@ -3938,48 +3931,41 @@ fn fmtDumpState( |
| 3938 | 3931 | } |
| 3939 | 3932 | for (self.dylibs.items) |index| { |
| 3940 | 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 | 3935 | index, |
| 3943 | 3936 | @as(Path, dylib.path), |
| 3944 | 3937 | dylib.needed, |
| 3945 | 3938 | dylib.weak, |
| 3946 | 3939 | }); |
| 3947 | if (!dylib.isAlive(self)) try writer.writeAll(" : ([*])"); | |
| 3948 | try writer.writeByte('\n'); | |
| 3949 | try writer.print("{}\n", .{dylib.fmtSymtab(self)}); | |
| 3940 | if (!dylib.isAlive(self)) try w.writeAll(" : ([*])"); | |
| 3941 | try w.writeByte('\n'); | |
| 3942 | try w.print("{f}\n", .{dylib.fmtSymtab(self)}); | |
| 3950 | 3943 | } |
| 3951 | 3944 | if (self.getInternalObject()) |internal| { |
| 3952 | try writer.print("internal({d}) : internal\n", .{internal.index}); | |
| 3953 | try writer.print("{}{}\n", .{ internal.fmtAtoms(self), internal.fmtSymtab(self) }); | |
| 3945 | try w.print("internal({d}) : internal\n", .{internal.index}); | |
| 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 | 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)}); | |
| 3960 | try writer.print("objc_stubs\n{}\n", .{self.objc_stubs.fmt(self)}); | |
| 3961 | try writer.print("got\n{}\n", .{self.got.fmt(self)}); | |
| 3962 | try writer.print("tlv_ptr\n{}\n", .{self.tlv_ptr.fmt(self)}); | |
| 3963 | try writer.writeByte('\n'); | |
| 3964 | try writer.print("sections\n{}\n", .{self.fmtSections()}); | |
| 3965 | try writer.print("segments\n{}\n", .{self.fmtSegments()}); | |
| 3952 | try w.print("stubs\n{f}\n", .{self.stubs.fmt(self)}); | |
| 3953 | try w.print("objc_stubs\n{f}\n", .{self.objc_stubs.fmt(self)}); | |
| 3954 | try w.print("got\n{f}\n", .{self.got.fmt(self)}); | |
| 3955 | try w.print("tlv_ptr\n{f}\n", .{self.tlv_ptr.fmt(self)}); | |
| 3956 | try w.writeByte('\n'); | |
| 3957 | try w.print("sections\n{f}\n", .{self.fmtSections()}); | |
| 3958 | try w.print("segments\n{f}\n", .{self.fmtSegments()}); | |
| 3966 | 3959 | } |
| 3967 | 3960 | |
| 3968 | fn fmtSections(self: *MachO) std.fmt.Formatter(formatSections) { | |
| 3961 | fn fmtSections(self: *MachO) std.fmt.Formatter(*MachO, formatSections) { | |
| 3969 | 3962 | return .{ .data = self }; |
| 3970 | 3963 | } |
| 3971 | 3964 | |
| 3972 | fn formatSections( | |
| 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; | |
| 3965 | fn formatSections(self: *MachO, w: *Writer) Writer.Error!void { | |
| 3980 | 3966 | const slice = self.sections.slice(); |
| 3981 | 3967 | for (slice.items(.header), slice.items(.segment_id), 0..) |header, seg_id, i| { |
| 3982 | try writer.print( | |
| 3968 | try w.print( | |
| 3983 | 3969 | "sect({d}) : seg({d}) : {s},{s} : @{x} ({x}) : align({x}) : size({x}) : relocs({x};{d})\n", |
| 3984 | 3970 | .{ |
| 3985 | 3971 | i, seg_id, header.segName(), header.sectName(), header.addr, header.offset, |
| ... | ... | @@ -3989,38 +3975,24 @@ fn formatSections( |
| 3989 | 3975 | } |
| 3990 | 3976 | } |
| 3991 | 3977 | |
| 3992 | fn fmtSegments(self: *MachO) std.fmt.Formatter(formatSegments) { | |
| 3978 | fn fmtSegments(self: *MachO) std.fmt.Formatter(*MachO, formatSegments) { | |
| 3993 | 3979 | return .{ .data = self }; |
| 3994 | 3980 | } |
| 3995 | 3981 | |
| 3996 | fn formatSegments( | |
| 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; | |
| 3982 | fn formatSegments(self: *MachO, w: *Writer) Writer.Error!void { | |
| 4004 | 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 | 3985 | i, seg.segName(), seg.vmaddr, seg.vmaddr + seg.vmsize, |
| 4007 | 3986 | seg.fileoff, seg.fileoff + seg.filesize, |
| 4008 | 3987 | }); |
| 4009 | 3988 | } |
| 4010 | 3989 | } |
| 4011 | 3990 | |
| 4012 | pub fn fmtSectType(tt: u8) std.fmt.Formatter(formatSectType) { | |
| 3991 | pub fn fmtSectType(tt: u8) std.fmt.Formatter(u8, formatSectType) { | |
| 4013 | 3992 | return .{ .data = tt }; |
| 4014 | 3993 | } |
| 4015 | 3994 | |
| 4016 | fn formatSectType( | |
| 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; | |
| 3995 | fn formatSectType(tt: u8, w: *Writer) Writer.Error!void { | |
| 4024 | 3996 | const name = switch (tt) { |
| 4025 | 3997 | macho.S_REGULAR => "REGULAR", |
| 4026 | 3998 | macho.S_ZEROFILL => "ZEROFILL", |
| ... | ... | @@ -4044,9 +4016,9 @@ fn formatSectType( |
| 4044 | 4016 | macho.S_THREAD_LOCAL_VARIABLE_POINTERS => "THREAD_LOCAL_VARIABLE_POINTERS", |
| 4045 | 4017 | macho.S_THREAD_LOCAL_INIT_FUNCTION_POINTERS => "THREAD_LOCAL_INIT_FUNCTION_POINTERS", |
| 4046 | 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 | } |
| 4051 | 4023 | |
| 4052 | 4024 | const is_hot_update_compatible = switch (builtin.target.os.tag) { |
| ... | ... | @@ -4279,34 +4251,27 @@ pub const Platform = struct { |
| 4279 | 4251 | return false; |
| 4280 | 4252 | } |
| 4281 | 4253 | |
| 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 | 4255 | return .{ .data = .{ .platform = plat, .cpu_arch = cpu_arch } }; |
| 4284 | 4256 | } |
| 4285 | 4257 | |
| 4286 | const FmtCtx = struct { | |
| 4258 | const Format = struct { | |
| 4287 | 4259 | platform: Platform, |
| 4288 | 4260 | cpu_arch: std.Target.Cpu.Arch, |
| 4289 | }; | |
| 4290 | 4261 | |
| 4291 | pub fn formatTarget( | |
| 4292 | ctx: FmtCtx, | |
| 4293 | comptime unused_fmt_string: []const u8, | |
| 4294 | options: std.fmt.FormatOptions, | |
| 4295 | writer: anytype, | |
| 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)}); | |
| 4262 | pub fn target(f: Format, w: *Writer) Writer.Error!void { | |
| 4263 | try w.print("{s}-{s}", .{ @tagName(f.cpu_arch), @tagName(f.platform.os_tag) }); | |
| 4264 | if (f.platform.abi != .none) { | |
| 4265 | try w.print("-{s}", .{@tagName(f.platform.abi)}); | |
| 4266 | } | |
| 4302 | 4267 | } |
| 4303 | } | |
| 4268 | }; | |
| 4304 | 4269 | |
| 4305 | 4270 | /// Caller owns the memory. |
| 4306 | 4271 | pub fn allocPrintTarget(plat: Platform, gpa: Allocator, cpu_arch: std.Target.Cpu.Arch) error{OutOfMemory}![]u8 { |
| 4307 | 4272 | var buffer = std.ArrayList(u8).init(gpa); |
| 4308 | 4273 | defer buffer.deinit(); |
| 4309 | try buffer.writer().print("{}", .{plat.fmtTarget(cpu_arch)}); | |
| 4274 | try buffer.writer().print("{f}", .{plat.fmtTarget(cpu_arch)}); | |
| 4310 | 4275 | return buffer.toOwnedSlice(); |
| 4311 | 4276 | } |
| 4312 | 4277 | |
| ... | ... | @@ -4507,15 +4472,8 @@ pub const Ref = struct { |
| 4507 | 4472 | }; |
| 4508 | 4473 | } |
| 4509 | 4474 | |
| 4510 | pub fn format( | |
| 4511 | ref: Ref, | |
| 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 }); | |
| 4475 | pub fn format(ref: Ref, bw: *Writer) Writer.Error!void { | |
| 4476 | try bw.print("%{d} in file({d})", .{ ref.index, ref.file }); | |
| 4519 | 4477 | } |
| 4520 | 4478 | }; |
| 4521 | 4479 | |
| ... | ... | @@ -5315,7 +5273,7 @@ fn createThunks(macho_file: *MachO, sect_id: u8) !void { |
| 5315 | 5273 | try scanThunkRelocs(thunk_index, gpa, atoms[start..i], macho_file); |
| 5316 | 5274 | thunk.value = advanceSection(header, thunk.size(), .@"4"); |
| 5317 | 5275 | |
| 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 | } |
| 5321 | 5279 | |
| ... | ... | @@ -5414,6 +5372,7 @@ const macho = std.macho; |
| 5414 | 5372 | const math = std.math; |
| 5415 | 5373 | const mem = std.mem; |
| 5416 | 5374 | const meta = std.meta; |
| 5375 | const Writer = std.io.Writer; | |
| 5417 | 5376 | |
| 5418 | 5377 | const aarch64 = @import("../arch/aarch64/bits.zig"); |
| 5419 | 5378 | const 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 | 29 | pos += @sizeOf(ar_hdr); |
| 30 | 30 | |
| 31 | 31 | if (!mem.eql(u8, &hdr.ar_fmag, ARFMAG)) { |
| 32 | return diags.failParse(path, "invalid header delimiter: expected '{s}', found '{s}'", .{ | |
| 33 | std.fmt.fmtSliceEscapeLower(ARFMAG), std.fmt.fmtSliceEscapeLower(&hdr.ar_fmag), | |
| 32 | return diags.failParse(path, "invalid header delimiter: expected '{f}', found '{f}'", .{ | |
| 33 | std.ascii.hexEscape(ARFMAG, .lower), std.ascii.hexEscape(&hdr.ar_fmag, .lower), | |
| 34 | 34 | }); |
| 35 | 35 | } |
| 36 | 36 | |
| ... | ... | @@ -71,7 +71,7 @@ pub fn unpack(self: *Archive, macho_file: *MachO, path: Path, handle_index: File |
| 71 | 71 | .mtime = hdr.date() catch 0, |
| 72 | 72 | }; |
| 73 | 73 | |
| 74 | log.debug("extracting object '{}' from archive '{}'", .{ object.path, path }); | |
| 74 | log.debug("extracting object '{f}' from archive '{f}'", .{ object.path, path }); | |
| 75 | 75 | |
| 76 | 76 | try self.objects.append(gpa, object); |
| 77 | 77 | } |
| ... | ... | @@ -230,32 +230,25 @@ pub const ArSymtab = struct { |
| 230 | 230 | } |
| 231 | 231 | } |
| 232 | 232 | |
| 233 | const FormatContext = struct { | |
| 233 | const PrintFormat = struct { | |
| 234 | 234 | ar: ArSymtab, |
| 235 | 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 | }; |
| 237 | 247 | |
| 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 | 249 | return .{ .data = .{ .ar = ar, .macho_file = macho_file } }; |
| 240 | 250 | } |
| 241 | 251 | |
| 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 | 252 | const Entry = struct { |
| 260 | 253 | /// Symbol name offset |
| 261 | 254 | off: u32, |
| ... | ... | @@ -304,8 +297,9 @@ const log = std.log.scoped(.link); |
| 304 | 297 | const macho = std.macho; |
| 305 | 298 | const mem = std.mem; |
| 306 | 299 | const std = @import("std"); |
| 307 | const Allocator = mem.Allocator; | |
| 300 | const Allocator = std.mem.Allocator; | |
| 308 | 301 | const Path = std.Build.Cache.Path; |
| 302 | const Writer = std.io.Writer; | |
| 309 | 303 | |
| 310 | 304 | const Archive = @This(); |
| 311 | 305 | const 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 | 602 | }; |
| 603 | 603 | try macho_file.reportParseError2( |
| 604 | 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 | 607 | name, |
| 608 | 608 | self.getAddress(macho_file), |
| ... | ... | @@ -653,7 +653,7 @@ fn resolveRelocInner( |
| 653 | 653 | const divExact = struct { |
| 654 | 654 | fn divExact(atom: Atom, r: Relocation, num: u12, den: u12, ctx: *MachO) !u12 { |
| 655 | 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 | 657 | atom.getName(ctx), |
| 658 | 658 | r.fmtPretty(ctx.getTarget().cpu.arch), |
| 659 | 659 | r.offset, |
| ... | ... | @@ -664,14 +664,14 @@ fn resolveRelocInner( |
| 664 | 664 | }.divExact; |
| 665 | 665 | |
| 666 | 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 | 668 | P, |
| 669 | 669 | rel_offset, |
| 670 | 670 | rel.fmtPretty(cpu_arch), |
| 671 | 671 | S + A - SUB, |
| 672 | 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 | 675 | P, |
| 676 | 676 | rel_offset, |
| 677 | 677 | rel.fmtPretty(cpu_arch), |
| ... | ... | @@ -900,19 +900,19 @@ const x86_64 = struct { |
| 900 | 900 | switch (old_inst.encoding.mnemonic) { |
| 901 | 901 | .mov => { |
| 902 | 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 | 904 | encode(&.{inst}, code) catch return error.RelaxFail; |
| 905 | 905 | }, |
| 906 | 906 | else => |x| { |
| 907 | 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 | 909 | self.getName(macho_file), |
| 910 | 910 | self.getAddress(macho_file), |
| 911 | 911 | rel.offset, |
| 912 | 912 | rel.fmtPretty(.x86_64), |
| 913 | 913 | }); |
| 914 | 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 | 916 | return error.RelaxFailUnexpectedInstruction; |
| 917 | 917 | }, |
| 918 | 918 | } |
| ... | ... | @@ -924,7 +924,7 @@ const x86_64 = struct { |
| 924 | 924 | switch (old_inst.encoding.mnemonic) { |
| 925 | 925 | .mov => { |
| 926 | 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 | 928 | encode(&.{inst}, code) catch return error.RelaxFail; |
| 929 | 929 | }, |
| 930 | 930 | else => return error.RelaxFail, |
| ... | ... | @@ -938,11 +938,8 @@ const x86_64 = struct { |
| 938 | 938 | } |
| 939 | 939 | |
| 940 | 940 | fn encode(insts: []const Instruction, code: []u8) !void { |
| 941 | var stream = std.io.fixedBufferStream(code); | |
| 942 | const writer = stream.writer(); | |
| 943 | for (insts) |inst| { | |
| 944 | try inst.encode(writer, .{}); | |
| 945 | } | |
| 941 | var stream: Writer = .fixed(code); | |
| 942 | for (insts) |inst| try inst.encode(&stream, .{}); | |
| 946 | 943 | } |
| 947 | 944 | |
| 948 | 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 | 1000 | } |
| 1004 | 1001 | |
| 1005 | 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 | 1004 | rel.fmtPretty(cpu_arch), |
| 1008 | 1005 | r_address, |
| 1009 | 1006 | r_symbolnum, |
| ... | ... | @@ -1011,7 +1008,7 @@ pub fn writeRelocs(self: Atom, macho_file: *MachO, code: []u8, buffer: []macho.r |
| 1011 | 1008 | macho_file.sections.items(.header)[r_symbolnum - 1].sectName(), |
| 1012 | 1009 | addend, |
| 1013 | 1010 | }), |
| 1014 | .@"extern" => relocs_log.debug(" {}: [{x} => {d}({s})] + {x}", .{ | |
| 1011 | .@"extern" => relocs_log.debug(" {f}: [{x} => {d}({s})] + {x}", .{ | |
| 1015 | 1012 | rel.fmtPretty(cpu_arch), |
| 1016 | 1013 | r_address, |
| 1017 | 1014 | r_symbolnum, |
| ... | ... | @@ -1117,60 +1114,40 @@ pub fn writeRelocs(self: Atom, macho_file: *MachO, code: []u8, buffer: []macho.r |
| 1117 | 1114 | assert(i == buffer.len); |
| 1118 | 1115 | } |
| 1119 | 1116 | |
| 1120 | pub fn format( | |
| 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 | ||
| 1133 | pub fn fmt(atom: Atom, macho_file: *MachO) std.fmt.Formatter(format2) { | |
| 1117 | pub fn fmt(atom: Atom, macho_file: *MachO) std.fmt.Formatter(Format, Format.print) { | |
| 1134 | 1118 | return .{ .data = .{ |
| 1135 | 1119 | .atom = atom, |
| 1136 | 1120 | .macho_file = macho_file, |
| 1137 | 1121 | } }; |
| 1138 | 1122 | } |
| 1139 | 1123 | |
| 1140 | const FormatContext = struct { | |
| 1124 | const Format = struct { | |
| 1141 | 1125 | atom: Atom, |
| 1142 | 1126 | macho_file: *MachO, |
| 1143 | }; | |
| 1144 | 1127 | |
| 1145 | fn format2( | |
| 1146 | ctx: FormatContext, | |
| 1147 | comptime unused_fmt_string: []const u8, | |
| 1148 | options: std.fmt.FormatOptions, | |
| 1149 | writer: anytype, | |
| 1150 | ) !void { | |
| 1151 | _ = options; | |
| 1152 | _ = unused_fmt_string; | |
| 1153 | const atom = ctx.atom; | |
| 1154 | const macho_file = ctx.macho_file; | |
| 1155 | const file = atom.getFile(macho_file); | |
| 1156 | try writer.print("atom({d}) : {s} : @{x} : sect({d}) : align({x}) : size({x}) : nreloc({d}) : thunk({d})", .{ | |
| 1157 | atom.atom_index, atom.getName(macho_file), atom.getAddress(macho_file), | |
| 1158 | atom.out_n_sect, atom.alignment, atom.size, | |
| 1159 | atom.getRelocs(macho_file).len, atom.getExtra(macho_file).thunk, | |
| 1160 | }); | |
| 1161 | if (!atom.isAlive()) try writer.writeAll(" : [*]"); | |
| 1162 | if (atom.getUnwindRecords(macho_file).len > 0) { | |
| 1163 | try writer.writeAll(" : unwind{ "); | |
| 1164 | const extra = atom.getExtra(macho_file); | |
| 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(", "); | |
| 1128 | fn print(f: Format, w: *Writer) Writer.Error!void { | |
| 1129 | const atom = f.atom; | |
| 1130 | const macho_file = f.macho_file; | |
| 1131 | const file = atom.getFile(macho_file); | |
| 1132 | try w.print("atom({d}) : {s} : @{x} : sect({d}) : align({x}) : size({x}) : nreloc({d}) : thunk({d})", .{ | |
| 1133 | atom.atom_index, atom.getName(macho_file), atom.getAddress(macho_file), | |
| 1134 | atom.out_n_sect, atom.alignment, atom.size, | |
| 1135 | atom.getRelocs(macho_file).len, atom.getExtra(macho_file).thunk, | |
| 1136 | }); | |
| 1137 | if (!atom.isAlive()) try w.writeAll(" : [*]"); | |
| 1138 | if (atom.getUnwindRecords(macho_file).len > 0) { | |
| 1139 | try w.writeAll(" : unwind{ "); | |
| 1140 | const extra = atom.getExtra(macho_file); | |
| 1141 | for (atom.getUnwindRecords(macho_file), extra.unwind_index..) |index, i| { | |
| 1142 | const rec = file.object.getUnwindRecord(index); | |
| 1143 | try w.print("{d}", .{index}); | |
| 1144 | if (!rec.alive) try w.writeAll("([*])"); | |
| 1145 | if (i < extra.unwind_index + extra.unwind_count - 1) try w.writeAll(", "); | |
| 1146 | } | |
| 1147 | try w.writeAll(" }"); | |
| 1170 | 1148 | } |
| 1171 | try writer.writeAll(" }"); | |
| 1172 | 1149 | } |
| 1173 | } | |
| 1150 | }; | |
| 1174 | 1151 | |
| 1175 | 1152 | pub const Index = u32; |
| 1176 | 1153 | |
| ... | ... | @@ -1205,19 +1182,20 @@ pub const Extra = struct { |
| 1205 | 1182 | |
| 1206 | 1183 | pub const Alignment = @import("../../InternPool.zig").Alignment; |
| 1207 | 1184 | |
| 1208 | const aarch64 = @import("../aarch64.zig"); | |
| 1185 | const std = @import("std"); | |
| 1209 | 1186 | const assert = std.debug.assert; |
| 1210 | 1187 | const macho = std.macho; |
| 1211 | 1188 | const math = std.math; |
| 1212 | 1189 | const mem = std.mem; |
| 1213 | 1190 | const log = std.log.scoped(.link); |
| 1214 | 1191 | const relocs_log = std.log.scoped(.link_relocs); |
| 1215 | const std = @import("std"); | |
| 1216 | const trace = @import("../../tracy.zig").trace; | |
| 1217 | ||
| 1192 | const Writer = std.io.Writer; | |
| 1218 | 1193 | const Allocator = mem.Allocator; |
| 1219 | const Atom = @This(); | |
| 1220 | 1194 | const AtomicBool = std.atomic.Value(bool); |
| 1195 | ||
| 1196 | const aarch64 = @import("../aarch64.zig"); | |
| 1197 | const trace = @import("../../tracy.zig").trace; | |
| 1198 | const Atom = @This(); | |
| 1221 | 1199 | const File = @import("file.zig").File; |
| 1222 | 1200 | const MachO = @import("../MachO.zig"); |
| 1223 | 1201 | const Object = @import("Object.zig"); |
src/link/MachO/DebugSymbols.zig+1| ... | ... | @@ -460,6 +460,7 @@ const math = std.math; |
| 460 | 460 | const mem = std.mem; |
| 461 | 461 | const padToIdeal = MachO.padToIdeal; |
| 462 | 462 | const trace = @import("../../tracy.zig").trace; |
| 463 | const Writer = std.io.Writer; | |
| 463 | 464 | |
| 464 | 465 | const Allocator = mem.Allocator; |
| 465 | 466 | const MachO = @import("../MachO.zig"); |
src/link/MachO/Dylib.zig+24-43| ... | ... | @@ -61,7 +61,7 @@ fn parseBinary(self: *Dylib, macho_file: *MachO) !void { |
| 61 | 61 | const file = macho_file.getFileHandle(self.file_handle); |
| 62 | 62 | const offset = self.offset; |
| 63 | 63 | |
| 64 | log.debug("parsing dylib from binary: {}", .{@as(Path, self.path)}); | |
| 64 | log.debug("parsing dylib from binary: {f}", .{@as(Path, self.path)}); | |
| 65 | 65 | |
| 66 | 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 | 140 | |
| 141 | 141 | if (self.platform) |platform| { |
| 142 | 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 | 144 | platform.fmtTarget(macho_file.getTarget().cpu.arch), |
| 145 | 145 | }); |
| 146 | 146 | return error.InvalidTarget; |
| ... | ... | @@ -148,7 +148,7 @@ fn parseBinary(self: *Dylib, macho_file: *MachO) !void { |
| 148 | 148 | // TODO: this can cause the CI to fail so I'm commenting this check out so that |
| 149 | 149 | // I can work out the rest of the changes first |
| 150 | 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 | 152 | // macho_file.platform.fmtTarget(macho_file.getTarget().cpu.arch), |
| 153 | 153 | // macho_file.platform.version, |
| 154 | 154 | // platform.version, |
| ... | ... | @@ -267,7 +267,7 @@ fn parseTbd(self: *Dylib, macho_file: *MachO) !void { |
| 267 | 267 | |
| 268 | 268 | const gpa = macho_file.base.comp.gpa; |
| 269 | 269 | |
| 270 | log.debug("parsing dylib from stub: {}", .{self.path}); | |
| 270 | log.debug("parsing dylib from stub: {f}", .{self.path}); | |
| 271 | 271 | |
| 272 | 272 | const file = macho_file.getFileHandle(self.file_handle); |
| 273 | 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 | 691 | } |
| 692 | 692 | } |
| 693 | 693 | |
| 694 | pub fn format( | |
| 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 | ||
| 707 | pub fn fmtSymtab(self: *Dylib, macho_file: *MachO) std.fmt.Formatter(formatSymtab) { | |
| 694 | pub fn fmtSymtab(self: *Dylib, macho_file: *MachO) std.fmt.Formatter(Format, Format.symtab) { | |
| 708 | 695 | return .{ .data = .{ |
| 709 | 696 | .dylib = self, |
| 710 | 697 | .macho_file = macho_file, |
| 711 | 698 | } }; |
| 712 | 699 | } |
| 713 | 700 | |
| 714 | const FormatContext = struct { | |
| 701 | const Format = struct { | |
| 715 | 702 | dylib: *Dylib, |
| 716 | 703 | macho_file: *MachO, |
| 717 | }; | |
| 718 | 704 | |
| 719 | fn formatSymtab( | |
| 720 | ctx: FormatContext, | |
| 721 | comptime unused_fmt_string: []const u8, | |
| 722 | options: std.fmt.FormatOptions, | |
| 723 | writer: anytype, | |
| 724 | ) !void { | |
| 725 | _ = unused_fmt_string; | |
| 726 | _ = options; | |
| 727 | const dylib = ctx.dylib; | |
| 728 | const macho_file = ctx.macho_file; | |
| 729 | try writer.writeAll(" globals\n"); | |
| 730 | for (dylib.symbols.items, 0..) |sym, i| { | |
| 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)}); | |
| 705 | fn symtab(f: Format, w: *Writer) Writer.Error!void { | |
| 706 | const dylib = f.dylib; | |
| 707 | const macho_file = f.macho_file; | |
| 708 | try w.writeAll(" globals\n"); | |
| 709 | for (dylib.symbols.items, 0..) |sym, i| { | |
| 710 | const ref = dylib.getSymbolRef(@intCast(i), macho_file); | |
| 711 | if (ref.getFile(macho_file) == null) { | |
| 712 | // TODO any better way of handling this? | |
| 713 | try w.print(" {s} : unclaimed\n", .{sym.getName(macho_file)}); | |
| 714 | } else { | |
| 715 | try w.print(" {f}\n", .{ref.getSymbol(macho_file).?.fmt(macho_file)}); | |
| 716 | } | |
| 737 | 717 | } |
| 738 | 718 | } |
| 739 | } | |
| 719 | }; | |
| 740 | 720 | |
| 741 | 721 | pub const TargetMatcher = struct { |
| 742 | 722 | allocator: Allocator, |
| ... | ... | @@ -948,19 +928,17 @@ const Export = struct { |
| 948 | 928 | }; |
| 949 | 929 | }; |
| 950 | 930 | |
| 931 | const std = @import("std"); | |
| 951 | 932 | const assert = std.debug.assert; |
| 952 | const fat = @import("fat.zig"); | |
| 953 | 933 | const fs = std.fs; |
| 954 | 934 | const fmt = std.fmt; |
| 955 | 935 | const log = std.log.scoped(.link); |
| 956 | 936 | const macho = std.macho; |
| 957 | 937 | const math = std.math; |
| 958 | 938 | const mem = std.mem; |
| 959 | const tapi = @import("../tapi.zig"); | |
| 960 | const trace = @import("../../tracy.zig").trace; | |
| 961 | const std = @import("std"); | |
| 962 | 939 | const Allocator = mem.Allocator; |
| 963 | 940 | const Path = std.Build.Cache.Path; |
| 941 | const Writer = std.io.Writer; | |
| 964 | 942 | |
| 965 | 943 | const Dylib = @This(); |
| 966 | 944 | const File = @import("file.zig").File; |
| ... | ... | @@ -969,3 +947,6 @@ const LoadCommandIterator = macho.LoadCommandIterator; |
| 969 | 947 | const MachO = @import("../MachO.zig"); |
| 970 | 948 | const Symbol = @import("Symbol.zig"); |
| 971 | 949 | const Tbd = tapi.Tbd; |
| 950 | const fat = @import("fat.zig"); | |
| 951 | const tapi = @import("../tapi.zig"); | |
| 952 | const trace = @import("../../tracy.zig").trace; |
src/link/MachO/InternalObject.zig+27-40| ... | ... | @@ -836,62 +836,48 @@ fn needsObjcMsgsendSymbol(self: InternalObject) bool { |
| 836 | 836 | return false; |
| 837 | 837 | } |
| 838 | 838 | |
| 839 | const FormatContext = struct { | |
| 839 | const Format = struct { | |
| 840 | 840 | self: *InternalObject, |
| 841 | 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 | }; |
| 843 | 866 | |
| 844 | pub fn fmtAtoms(self: *InternalObject, macho_file: *MachO) std.fmt.Formatter(formatAtoms) { | |
| 867 | pub fn fmtAtoms(self: *InternalObject, macho_file: *MachO) std.fmt.Formatter(Format, Format.atoms) { | |
| 845 | 868 | return .{ .data = .{ |
| 846 | 869 | .self = self, |
| 847 | 870 | .macho_file = macho_file, |
| 848 | 871 | } }; |
| 849 | 872 | } |
| 850 | 873 | |
| 851 | fn formatAtoms( | |
| 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 | ||
| 866 | pub fn fmtSymtab(self: *InternalObject, macho_file: *MachO) std.fmt.Formatter(formatSymtab) { | |
| 874 | pub fn fmtSymtab(self: *InternalObject, macho_file: *MachO) std.fmt.Formatter(Format, Format.symtab) { | |
| 867 | 875 | return .{ .data = .{ |
| 868 | 876 | .self = self, |
| 869 | 877 | .macho_file = macho_file, |
| 870 | 878 | } }; |
| 871 | 879 | } |
| 872 | 880 | |
| 873 | fn 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 | ||
| 895 | 881 | const Section = struct { |
| 896 | 882 | header: macho.section_64, |
| 897 | 883 | relocs: std.ArrayListUnmanaged(Relocation) = .empty, |
| ... | ... | @@ -908,6 +894,7 @@ const macho = std.macho; |
| 908 | 894 | const mem = std.mem; |
| 909 | 895 | const std = @import("std"); |
| 910 | 896 | const trace = @import("../../tracy.zig").trace; |
| 897 | const Writer = std.io.Writer; | |
| 911 | 898 | |
| 912 | 899 | const Allocator = std.mem.Allocator; |
| 913 | 900 | const 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 | 72 | const tracy = trace(@src()); |
| 73 | 73 | defer tracy.end(); |
| 74 | 74 | |
| 75 | log.debug("parsing {}", .{self.fmtPath()}); | |
| 75 | log.debug("parsing {f}", .{self.fmtPath()}); | |
| 76 | 76 | |
| 77 | 77 | const gpa = macho_file.base.comp.gpa; |
| 78 | 78 | const handle = macho_file.getFileHandle(self.file_handle); |
| ... | ... | @@ -239,7 +239,7 @@ pub fn parse(self: *Object, macho_file: *MachO) !void { |
| 239 | 239 | |
| 240 | 240 | if (self.platform) |platform| { |
| 241 | 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 | 243 | platform.fmtTarget(cpu_arch), |
| 244 | 244 | }); |
| 245 | 245 | return error.InvalidTarget; |
| ... | ... | @@ -247,7 +247,7 @@ pub fn parse(self: *Object, macho_file: *MachO) !void { |
| 247 | 247 | // TODO: this causes the CI to fail so I'm commenting this check out so that |
| 248 | 248 | // I can work out the rest of the changes first |
| 249 | 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 | 251 | // macho_file.platform.fmtTarget(macho_file.getTarget().cpu.arch), |
| 252 | 252 | // macho_file.platform.version, |
| 253 | 253 | // platform.version, |
| ... | ... | @@ -308,7 +308,9 @@ fn initSubsections(self: *Object, allocator: Allocator, nlists: anytype) !void { |
| 308 | 308 | } else nlists.len; |
| 309 | 309 | |
| 310 | 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 | 314 | defer allocator.free(name); |
| 313 | 315 | const size = if (nlist_start == nlist_end) sect.size else nlists[nlist_start].nlist.n_value - sect.addr; |
| 314 | 316 | const atom_index = try self.addAtom(allocator, .{ |
| ... | ... | @@ -364,7 +366,9 @@ fn initSubsections(self: *Object, allocator: Allocator, nlists: anytype) !void { |
| 364 | 366 | // which cannot be contained in any non-zero atom (since then this atom |
| 365 | 367 | // would exceed section boundaries). In order to facilitate this behaviour, |
| 366 | 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 | 372 | defer allocator.free(name); |
| 369 | 373 | const atom_index = try self.addAtom(allocator, .{ |
| 370 | 374 | .name = try self.addString(allocator, name), |
| ... | ... | @@ -394,7 +398,7 @@ fn initSections(self: *Object, allocator: Allocator, nlists: anytype) !void { |
| 394 | 398 | if (isFixedSizeLiteral(sect)) continue; |
| 395 | 399 | if (isPtrLiteral(sect)) continue; |
| 396 | 400 | |
| 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 | 402 | defer allocator.free(name); |
| 399 | 403 | |
| 400 | 404 | const atom_index = try self.addAtom(allocator, .{ |
| ... | ... | @@ -462,7 +466,7 @@ fn initCstringLiterals(self: *Object, allocator: Allocator, file: File.Handle, m |
| 462 | 466 | } |
| 463 | 467 | end += 1; |
| 464 | 468 | |
| 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 | 470 | defer allocator.free(name); |
| 467 | 471 | const name_str = try self.addString(allocator, name); |
| 468 | 472 | |
| ... | ... | @@ -529,7 +533,7 @@ fn initFixedSizeLiterals(self: *Object, allocator: Allocator, macho_file: *MachO |
| 529 | 533 | pos += rec_size; |
| 530 | 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 | 537 | defer allocator.free(name); |
| 534 | 538 | const name_str = try self.addString(allocator, name); |
| 535 | 539 | |
| ... | ... | @@ -587,7 +591,7 @@ fn initPointerLiterals(self: *Object, allocator: Allocator, macho_file: *MachO) |
| 587 | 591 | for (0..num_ptrs) |i| { |
| 588 | 592 | const pos: u32 = @as(u32, @intCast(i)) * rec_size; |
| 589 | 593 | |
| 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 | 595 | defer allocator.free(name); |
| 592 | 596 | const name_str = try self.addString(allocator, name); |
| 593 | 597 | |
| ... | ... | @@ -1558,7 +1562,7 @@ pub fn convertTentativeDefinitions(self: *Object, macho_file: *MachO) !void { |
| 1558 | 1562 | const nlist = &self.symtab.items(.nlist)[nlist_idx]; |
| 1559 | 1563 | const nlist_atom = &self.symtab.items(.atom)[nlist_idx]; |
| 1560 | 1564 | |
| 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 | 1566 | defer gpa.free(name); |
| 1563 | 1567 | |
| 1564 | 1568 | const alignment = (nlist.n_desc >> 8) & 0x0f; |
| ... | ... | @@ -2512,172 +2516,114 @@ pub fn readSectionData(self: Object, allocator: Allocator, file: File.Handle, n_ |
| 2512 | 2516 | return data; |
| 2513 | 2517 | } |
| 2514 | 2518 | |
| 2515 | pub fn format( | |
| 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 | ||
| 2528 | const FormatContext = struct { | |
| 2519 | const Format = struct { | |
| 2529 | 2520 | object: *Object, |
| 2530 | 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 | }; |
| 2532 | 2580 | |
| 2533 | pub fn fmtAtoms(self: *Object, macho_file: *MachO) std.fmt.Formatter(formatAtoms) { | |
| 2581 | pub fn fmtAtoms(self: *Object, macho_file: *MachO) std.fmt.Formatter(Format, Format.atoms) { | |
| 2534 | 2582 | return .{ .data = .{ |
| 2535 | 2583 | .object = self, |
| 2536 | 2584 | .macho_file = macho_file, |
| 2537 | 2585 | } }; |
| 2538 | 2586 | } |
| 2539 | 2587 | |
| 2540 | fn formatAtoms( | |
| 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 | ||
| 2557 | pub fn fmtCies(self: *Object, macho_file: *MachO) std.fmt.Formatter(formatCies) { | |
| 2588 | pub fn fmtCies(self: *Object, macho_file: *MachO) std.fmt.Formatter(Format, Format.cies) { | |
| 2558 | 2589 | return .{ .data = .{ |
| 2559 | 2590 | .object = self, |
| 2560 | 2591 | .macho_file = macho_file, |
| 2561 | 2592 | } }; |
| 2562 | 2593 | } |
| 2563 | 2594 | |
| 2564 | fn formatCies( | |
| 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 | ||
| 2579 | pub fn fmtFdes(self: *Object, macho_file: *MachO) std.fmt.Formatter(formatFdes) { | |
| 2595 | pub fn fmtFdes(self: *Object, macho_file: *MachO) std.fmt.Formatter(Format, Format.fdes) { | |
| 2580 | 2596 | return .{ .data = .{ |
| 2581 | 2597 | .object = self, |
| 2582 | 2598 | .macho_file = macho_file, |
| 2583 | 2599 | } }; |
| 2584 | 2600 | } |
| 2585 | 2601 | |
| 2586 | fn formatFdes( | |
| 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 | ||
| 2601 | pub fn fmtUnwindRecords(self: *Object, macho_file: *MachO) std.fmt.Formatter(formatUnwindRecords) { | |
| 2602 | pub fn fmtUnwindRecords(self: *Object, macho_file: *MachO) std.fmt.Formatter(Format, Format.unwindRecords) { | |
| 2602 | 2603 | return .{ .data = .{ |
| 2603 | 2604 | .object = self, |
| 2604 | 2605 | .macho_file = macho_file, |
| 2605 | 2606 | } }; |
| 2606 | 2607 | } |
| 2607 | 2608 | |
| 2608 | fn formatUnwindRecords( | |
| 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 | ||
| 2624 | pub fn fmtSymtab(self: *Object, macho_file: *MachO) std.fmt.Formatter(formatSymtab) { | |
| 2609 | pub fn fmtSymtab(self: *Object, macho_file: *MachO) std.fmt.Formatter(Format, Format.symtab) { | |
| 2625 | 2610 | return .{ .data = .{ |
| 2626 | 2611 | .object = self, |
| 2627 | 2612 | .macho_file = macho_file, |
| 2628 | 2613 | } }; |
| 2629 | 2614 | } |
| 2630 | 2615 | |
| 2631 | fn formatSymtab( | |
| 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 | ||
| 2663 | pub fn fmtPath(self: Object) std.fmt.Formatter(formatPath) { | |
| 2616 | pub fn fmtPath(self: Object) std.fmt.Formatter(Object, formatPath) { | |
| 2664 | 2617 | return .{ .data = self }; |
| 2665 | 2618 | } |
| 2666 | 2619 | |
| 2667 | fn formatPath( | |
| 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; | |
| 2620 | fn formatPath(object: Object, w: *Writer) Writer.Error!void { | |
| 2675 | 2621 | if (object.in_archive) |ar| { |
| 2676 | try writer.print("{}({s})", .{ | |
| 2677 | @as(Path, ar.path), object.path.basename(), | |
| 2622 | try w.print("{f}({s})", .{ | |
| 2623 | ar.path, object.path.basename(), | |
| 2678 | 2624 | }); |
| 2679 | 2625 | } else { |
| 2680 | try writer.print("{}", .{@as(Path, object.path)}); | |
| 2626 | try w.print("{f}", .{object.path}); | |
| 2681 | 2627 | } |
| 2682 | 2628 | } |
| 2683 | 2629 | |
| ... | ... | @@ -2731,42 +2677,25 @@ const StabFile = struct { |
| 2731 | 2677 | return object.symbols.items[index]; |
| 2732 | 2678 | } |
| 2733 | 2679 | |
| 2734 | pub fn format( | |
| 2680 | const Format = struct { | |
| 2735 | 2681 | stab: Stab, |
| 2736 | comptime unused_fmt_string: []const u8, | |
| 2737 | options: std.fmt.FormatOptions, | |
| 2738 | writer: anytype, | |
| 2739 | ) !void { | |
| 2740 | _ = stab; | |
| 2741 | _ = unused_fmt_string; | |
| 2742 | _ = options; | |
| 2743 | _ = writer; | |
| 2744 | @compileError("do not format stabs directly"); | |
| 2745 | } | |
| 2746 | ||
| 2747 | const StabFormatContext = struct { Stab, Object }; | |
| 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.?}); | |
| 2682 | object: Object, | |
| 2683 | ||
| 2684 | fn default(f: Stab.Format, w: *Writer) Writer.Error!void { | |
| 2685 | const stab = f.stab; | |
| 2686 | const sym = stab.getSymbol(f.object).?; | |
| 2687 | if (stab.is_func) { | |
| 2688 | try w.print("func({d})", .{stab.index.?}); | |
| 2689 | } else if (sym.visibility == .global) { | |
| 2690 | try w.print("gsym({d})", .{stab.index.?}); | |
| 2691 | } else { | |
| 2692 | try w.print("stsym({d})", .{stab.index.?}); | |
| 2693 | } | |
| 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 | 3086 | } |
| 3158 | 3087 | }; |
| 3159 | 3088 | |
| 3089 | const std = @import("std"); | |
| 3160 | 3090 | const assert = std.debug.assert; |
| 3161 | const eh_frame = @import("eh_frame.zig"); | |
| 3162 | 3091 | const log = std.log.scoped(.link); |
| 3163 | 3092 | const macho = std.macho; |
| 3164 | 3093 | const math = std.math; |
| 3165 | 3094 | const mem = std.mem; |
| 3166 | const trace = @import("../../tracy.zig").trace; | |
| 3167 | const std = @import("std"); | |
| 3168 | 3095 | const Path = std.Build.Cache.Path; |
| 3096 | const Allocator = std.mem.Allocator; | |
| 3097 | const Writer = std.io.Writer; | |
| 3169 | 3098 | |
| 3170 | const Allocator = mem.Allocator; | |
| 3099 | const eh_frame = @import("eh_frame.zig"); | |
| 3100 | const trace = @import("../../tracy.zig").trace; | |
| 3171 | 3101 | const Archive = @import("Archive.zig"); |
| 3172 | 3102 | const Atom = @import("Atom.zig"); |
| 3173 | 3103 | const 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 | 70 | return lhs.offset < rhs.offset; |
| 71 | 71 | } |
| 72 | 72 | |
| 73 | const FormatCtx = struct { Relocation, std.Target.Cpu.Arch }; | |
| 74 | ||
| 75 | pub fn fmtPretty(rel: Relocation, cpu_arch: std.Target.Cpu.Arch) std.fmt.Formatter(formatPretty) { | |
| 76 | return .{ .data = .{ rel, cpu_arch } }; | |
| 73 | pub fn fmtPretty(rel: Relocation, cpu_arch: std.Target.Cpu.Arch) std.fmt.Formatter(Format, Format.pretty) { | |
| 74 | return .{ .data = .{ .relocation = rel, .arch = cpu_arch } }; | |
| 77 | 75 | } |
| 78 | 76 | |
| 79 | fn formatPretty( | |
| 80 | ctx: FormatCtx, | |
| 81 | comptime unused_fmt_string: []const u8, | |
| 82 | options: std.fmt.FormatOptions, | |
| 83 | writer: anytype, | |
| 84 | ) !void { | |
| 85 | _ = options; | |
| 86 | _ = unused_fmt_string; | |
| 87 | const rel, const cpu_arch = ctx; | |
| 88 | const str = switch (rel.type) { | |
| 89 | .signed => "X86_64_RELOC_SIGNED", | |
| 90 | .signed1 => "X86_64_RELOC_SIGNED_1", | |
| 91 | .signed2 => "X86_64_RELOC_SIGNED_2", | |
| 92 | .signed4 => "X86_64_RELOC_SIGNED_4", | |
| 93 | .got_load => "X86_64_RELOC_GOT_LOAD", | |
| 94 | .tlv => "X86_64_RELOC_TLV", | |
| 95 | .page => "ARM64_RELOC_PAGE21", | |
| 96 | .pageoff => "ARM64_RELOC_PAGEOFF12", | |
| 97 | .got_load_page => "ARM64_RELOC_GOT_LOAD_PAGE21", | |
| 98 | .got_load_pageoff => "ARM64_RELOC_GOT_LOAD_PAGEOFF12", | |
| 99 | .tlvp_page => "ARM64_RELOC_TLVP_LOAD_PAGE21", | |
| 100 | .tlvp_pageoff => "ARM64_RELOC_TLVP_LOAD_PAGEOFF12", | |
| 101 | .branch => switch (cpu_arch) { | |
| 102 | .x86_64 => "X86_64_RELOC_BRANCH", | |
| 103 | .aarch64 => "ARM64_RELOC_BRANCH26", | |
| 104 | else => unreachable, | |
| 105 | }, | |
| 106 | .got => switch (cpu_arch) { | |
| 107 | .x86_64 => "X86_64_RELOC_GOT", | |
| 108 | .aarch64 => "ARM64_RELOC_POINTER_TO_GOT", | |
| 109 | else => unreachable, | |
| 110 | }, | |
| 111 | .subtractor => switch (cpu_arch) { | |
| 112 | .x86_64 => "X86_64_RELOC_SUBTRACTOR", | |
| 113 | .aarch64 => "ARM64_RELOC_SUBTRACTOR", | |
| 114 | else => unreachable, | |
| 115 | }, | |
| 116 | .unsigned => switch (cpu_arch) { | |
| 117 | .x86_64 => "X86_64_RELOC_UNSIGNED", | |
| 118 | .aarch64 => "ARM64_RELOC_UNSIGNED", | |
| 119 | else => unreachable, | |
| 120 | }, | |
| 121 | }; | |
| 122 | try writer.writeAll(str); | |
| 123 | } | |
| 77 | const Format = struct { | |
| 78 | relocation: Relocation, | |
| 79 | arch: std.Target.Cpu.Arch, | |
| 80 | ||
| 81 | fn pretty(f: Format, w: *Writer) Writer.Error!void { | |
| 82 | try w.writeAll(switch (f.relocation.type) { | |
| 83 | .signed => "X86_64_RELOC_SIGNED", | |
| 84 | .signed1 => "X86_64_RELOC_SIGNED_1", | |
| 85 | .signed2 => "X86_64_RELOC_SIGNED_2", | |
| 86 | .signed4 => "X86_64_RELOC_SIGNED_4", | |
| 87 | .got_load => "X86_64_RELOC_GOT_LOAD", | |
| 88 | .tlv => "X86_64_RELOC_TLV", | |
| 89 | .page => "ARM64_RELOC_PAGE21", | |
| 90 | .pageoff => "ARM64_RELOC_PAGEOFF12", | |
| 91 | .got_load_page => "ARM64_RELOC_GOT_LOAD_PAGE21", | |
| 92 | .got_load_pageoff => "ARM64_RELOC_GOT_LOAD_PAGEOFF12", | |
| 93 | .tlvp_page => "ARM64_RELOC_TLVP_LOAD_PAGE21", | |
| 94 | .tlvp_pageoff => "ARM64_RELOC_TLVP_LOAD_PAGEOFF12", | |
| 95 | .branch => switch (f.arch) { | |
| 96 | .x86_64 => "X86_64_RELOC_BRANCH", | |
| 97 | .aarch64 => "ARM64_RELOC_BRANCH26", | |
| 98 | else => unreachable, | |
| 99 | }, | |
| 100 | .got => switch (f.arch) { | |
| 101 | .x86_64 => "X86_64_RELOC_GOT", | |
| 102 | .aarch64 => "ARM64_RELOC_POINTER_TO_GOT", | |
| 103 | else => unreachable, | |
| 104 | }, | |
| 105 | .subtractor => switch (f.arch) { | |
| 106 | .x86_64 => "X86_64_RELOC_SUBTRACTOR", | |
| 107 | .aarch64 => "ARM64_RELOC_SUBTRACTOR", | |
| 108 | else => unreachable, | |
| 109 | }, | |
| 110 | .unsigned => switch (f.arch) { | |
| 111 | .x86_64 => "X86_64_RELOC_UNSIGNED", | |
| 112 | .aarch64 => "ARM64_RELOC_UNSIGNED", | |
| 113 | else => unreachable, | |
| 114 | }, | |
| 115 | }); | |
| 116 | } | |
| 117 | }; | |
| 124 | 118 | |
| 125 | 119 | pub const Type = enum { |
| 126 | 120 | // x86_64 |
| ... | ... | @@ -164,10 +158,11 @@ pub const Type = enum { |
| 164 | 158 | |
| 165 | 159 | const Tag = enum { local, @"extern" }; |
| 166 | 160 | |
| 161 | const std = @import("std"); | |
| 167 | 162 | const assert = std.debug.assert; |
| 168 | 163 | const macho = std.macho; |
| 169 | 164 | const math = std.math; |
| 170 | const std = @import("std"); | |
| 165 | const Writer = std.io.Writer; | |
| 171 | 166 | |
| 172 | 167 | const Atom = @import("Atom.zig"); |
| 173 | 168 | const 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 | 286 | } |
| 287 | 287 | } |
| 288 | 288 | |
| 289 | pub fn format( | |
| 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 | ||
| 302 | const FormatContext = struct { | |
| 303 | symbol: Symbol, | |
| 304 | macho_file: *MachO, | |
| 305 | }; | |
| 306 | ||
| 307 | pub fn fmt(symbol: Symbol, macho_file: *MachO) std.fmt.Formatter(format2) { | |
| 289 | pub fn fmt(symbol: Symbol, macho_file: *MachO) std.fmt.Formatter(Format, Format.default) { | |
| 308 | 290 | return .{ .data = .{ |
| 309 | 291 | .symbol = symbol, |
| 310 | 292 | .macho_file = macho_file, |
| 311 | 293 | } }; |
| 312 | 294 | } |
| 313 | 295 | |
| 314 | fn format2( | |
| 315 | ctx: FormatContext, | |
| 316 | comptime unused_fmt_string: []const u8, | |
| 317 | options: std.fmt.FormatOptions, | |
| 318 | writer: anytype, | |
| 319 | ) !void { | |
| 320 | _ = options; | |
| 321 | _ = unused_fmt_string; | |
| 322 | const symbol = ctx.symbol; | |
| 323 | try writer.print("%{d} : {s} : @{x}", .{ | |
| 324 | symbol.nlist_idx, | |
| 325 | symbol.getName(ctx.macho_file), | |
| 326 | symbol.getAddress(.{}, ctx.macho_file), | |
| 327 | }); | |
| 328 | if (symbol.getFile(ctx.macho_file)) |file| { | |
| 329 | if (symbol.getOutputSectionIndex(ctx.macho_file) != 0) { | |
| 330 | try writer.print(" : sect({d})", .{symbol.getOutputSectionIndex(ctx.macho_file)}); | |
| 331 | } | |
| 332 | if (symbol.getAtom(ctx.macho_file)) |atom| { | |
| 333 | try writer.print(" : atom({d})", .{atom.atom_index}); | |
| 334 | } | |
| 335 | var buf: [3]u8 = .{'_'} ** 3; | |
| 336 | if (symbol.flags.@"export") buf[0] = 'E'; | |
| 337 | if (symbol.flags.import) buf[1] = 'I'; | |
| 338 | switch (symbol.visibility) { | |
| 339 | .local => buf[2] = 'L', | |
| 340 | .hidden => buf[2] = 'H', | |
| 341 | .global => buf[2] = 'G', | |
| 342 | } | |
| 343 | try writer.print(" : {s}", .{&buf}); | |
| 344 | if (symbol.flags.weak) try writer.writeAll(" : weak"); | |
| 345 | if (symbol.isSymbolStab(ctx.macho_file)) try writer.writeAll(" : stab"); | |
| 346 | switch (file) { | |
| 347 | .zig_object => |x| try writer.print(" : zig_object({d})", .{x.index}), | |
| 348 | .internal => |x| try writer.print(" : internal({d})", .{x.index}), | |
| 349 | .object => |x| try writer.print(" : object({d})", .{x.index}), | |
| 350 | .dylib => |x| try writer.print(" : dylib({d})", .{x.index}), | |
| 351 | } | |
| 352 | } else try writer.writeAll(" : unresolved"); | |
| 353 | } | |
| 296 | const Format = struct { | |
| 297 | symbol: Symbol, | |
| 298 | macho_file: *MachO, | |
| 299 | ||
| 300 | fn default(f: Format, w: *Writer) Writer.Error!void { | |
| 301 | const symbol = f.symbol; | |
| 302 | try w.print("%{d} : {s} : @{x}", .{ | |
| 303 | symbol.nlist_idx, | |
| 304 | symbol.getName(f.macho_file), | |
| 305 | symbol.getAddress(.{}, f.macho_file), | |
| 306 | }); | |
| 307 | if (symbol.getFile(f.macho_file)) |file| { | |
| 308 | if (symbol.getOutputSectionIndex(f.macho_file) != 0) { | |
| 309 | try w.print(" : sect({d})", .{symbol.getOutputSectionIndex(f.macho_file)}); | |
| 310 | } | |
| 311 | if (symbol.getAtom(f.macho_file)) |atom| { | |
| 312 | try w.print(" : atom({d})", .{atom.atom_index}); | |
| 313 | } | |
| 314 | var buf: [3]u8 = .{'_'} ** 3; | |
| 315 | if (symbol.flags.@"export") buf[0] = 'E'; | |
| 316 | if (symbol.flags.import) buf[1] = 'I'; | |
| 317 | switch (symbol.visibility) { | |
| 318 | .local => buf[2] = 'L', | |
| 319 | .hidden => buf[2] = 'H', | |
| 320 | .global => buf[2] = 'G', | |
| 321 | } | |
| 322 | try w.print(" : {s}", .{&buf}); | |
| 323 | if (symbol.flags.weak) try w.writeAll(" : weak"); | |
| 324 | if (symbol.isSymbolStab(f.macho_file)) try w.writeAll(" : stab"); | |
| 325 | switch (file) { | |
| 326 | .zig_object => |x| try w.print(" : zig_object({d})", .{x.index}), | |
| 327 | .internal => |x| try w.print(" : internal({d})", .{x.index}), | |
| 328 | .object => |x| try w.print(" : object({d})", .{x.index}), | |
| 329 | .dylib => |x| try w.print(" : dylib({d})", .{x.index}), | |
| 330 | } | |
| 331 | } else try w.writeAll(" : unresolved"); | |
| 332 | } | |
| 333 | }; | |
| 354 | 334 | |
| 355 | 335 | pub const Flags = packed struct { |
| 356 | 336 | /// Whether the symbol is imported at runtime. |
| ... | ... | @@ -437,6 +417,7 @@ pub const Index = u32; |
| 437 | 417 | const assert = std.debug.assert; |
| 438 | 418 | const macho = std.macho; |
| 439 | 419 | const std = @import("std"); |
| 420 | const Writer = std.io.Writer; | |
| 440 | 421 | |
| 441 | 422 | const Atom = @import("Atom.zig"); |
| 442 | 423 | const 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 | 61 | } |
| 62 | 62 | } |
| 63 | 63 | |
| 64 | pub fn format( | |
| 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 | ||
| 77 | pub fn fmt(thunk: Thunk, macho_file: *MachO) std.fmt.Formatter(format2) { | |
| 64 | pub fn fmt(thunk: Thunk, macho_file: *MachO) std.fmt.Formatter(Format, Format.default) { | |
| 78 | 65 | return .{ .data = .{ |
| 79 | 66 | .thunk = thunk, |
| 80 | 67 | .macho_file = macho_file, |
| 81 | 68 | } }; |
| 82 | 69 | } |
| 83 | 70 | |
| 84 | const FormatContext = struct { | |
| 71 | const Format = struct { | |
| 85 | 72 | thunk: Thunk, |
| 86 | 73 | macho_file: *MachO, |
| 87 | }; | |
| 88 | 74 | |
| 89 | fn format2( | |
| 90 | ctx: FormatContext, | |
| 91 | comptime unused_fmt_string: []const u8, | |
| 92 | options: std.fmt.FormatOptions, | |
| 93 | writer: anytype, | |
| 94 | ) !void { | |
| 95 | _ = options; | |
| 96 | _ = unused_fmt_string; | |
| 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 }); | |
| 75 | fn default(f: Format, w: *Writer) Writer.Error!void { | |
| 76 | const thunk = f.thunk; | |
| 77 | const macho_file = f.macho_file; | |
| 78 | try w.print("@{x} : size({x})\n", .{ thunk.value, thunk.size() }); | |
| 79 | for (thunk.symbols.keys()) |ref| { | |
| 80 | const sym = ref.getSymbol(macho_file).?; | |
| 81 | try w.print(" {f} : {s} : @{x}\n", .{ ref, sym.getName(macho_file), sym.value }); | |
| 82 | } | |
| 103 | 83 | } |
| 104 | } | |
| 84 | }; | |
| 105 | 85 | |
| 106 | 86 | const trampoline_size = 3 * @sizeOf(u32); |
| 107 | 87 | |
| ... | ... | @@ -115,6 +95,7 @@ const math = std.math; |
| 115 | 95 | const mem = std.mem; |
| 116 | 96 | const std = @import("std"); |
| 117 | 97 | const trace = @import("../../tracy.zig").trace; |
| 98 | const Writer = std.io.Writer; | |
| 118 | 99 | |
| 119 | 100 | const Allocator = mem.Allocator; |
| 120 | 101 | const 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 | 133 | for (info.records.items) |ref| { |
| 134 | 134 | const rec = ref.getUnwindRecord(macho_file); |
| 135 | 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 | 137 | rec.getAtomAddress(macho_file), |
| 138 | 138 | rec.getAtomAddress(macho_file) + rec.length, |
| 139 | 139 | atom.getName(macho_file), |
| ... | ... | @@ -202,7 +202,7 @@ pub fn generate(info: *UnwindInfo, macho_file: *MachO) !void { |
| 202 | 202 | if (i >= max_common_encodings) break; |
| 203 | 203 | if (slice[i].count < 2) continue; |
| 204 | 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 | } |
| 208 | 208 | |
| ... | ... | @@ -255,7 +255,7 @@ pub fn generate(info: *UnwindInfo, macho_file: *MachO) !void { |
| 255 | 255 | page.kind = .compressed; |
| 256 | 256 | } |
| 257 | 257 | |
| 258 | log.debug("{}", .{page.fmt(info.*)}); | |
| 258 | log.debug("{f}", .{page.fmt(info.*)}); | |
| 259 | 259 | |
| 260 | 260 | try info.pages.append(gpa, page); |
| 261 | 261 | } |
| ... | ... | @@ -455,15 +455,8 @@ pub const Encoding = extern struct { |
| 455 | 455 | return enc.enc == other.enc; |
| 456 | 456 | } |
| 457 | 457 | |
| 458 | pub fn format( | |
| 459 | enc: Encoding, | |
| 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}); | |
| 458 | pub fn format(enc: Encoding, w: *Writer) Writer.Error!void { | |
| 459 | try w.print("0x{x:0>8}", .{enc.enc}); | |
| 467 | 460 | } |
| 468 | 461 | }; |
| 469 | 462 | |
| ... | ... | @@ -517,48 +510,28 @@ pub const Record = struct { |
| 517 | 510 | return lsda.getAddress(macho_file) + rec.lsda_offset; |
| 518 | 511 | } |
| 519 | 512 | |
| 520 | pub fn format( | |
| 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) { | |
| 513 | pub fn fmt(rec: Record, macho_file: *MachO) std.fmt.Formatter(Format, Format.default) { | |
| 534 | 514 | return .{ .data = .{ |
| 535 | 515 | .rec = rec, |
| 536 | 516 | .macho_file = macho_file, |
| 537 | 517 | } }; |
| 538 | 518 | } |
| 539 | 519 | |
| 540 | const FormatContext = struct { | |
| 520 | const Format = struct { | |
| 541 | 521 | rec: Record, |
| 542 | 522 | macho_file: *MachO, |
| 543 | }; | |
| 544 | 523 | |
| 545 | fn format2( | |
| 546 | ctx: FormatContext, | |
| 547 | comptime unused_fmt_string: []const u8, | |
| 548 | options: std.fmt.FormatOptions, | |
| 549 | writer: anytype, | |
| 550 | ) !void { | |
| 551 | _ = unused_fmt_string; | |
| 552 | _ = options; | |
| 553 | const rec = ctx.rec; | |
| 554 | const macho_file = ctx.macho_file; | |
| 555 | try writer.print("{x} : len({x})", .{ | |
| 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 | } | |
| 524 | fn default(f: Format, w: *Writer) Writer.Error!void { | |
| 525 | const rec = f.rec; | |
| 526 | const macho_file = f.macho_file; | |
| 527 | try w.print("{x} : len({x})", .{ | |
| 528 | rec.enc.enc, rec.length, | |
| 529 | }); | |
| 530 | if (rec.enc.isDwarf(macho_file)) try w.print(" : fde({d})", .{rec.fde}); | |
| 531 | try w.print(" : {s}", .{rec.getAtom(macho_file).getName(macho_file)}); | |
| 532 | if (!rec.alive) try w.writeAll(" : [*]"); | |
| 533 | } | |
| 534 | }; | |
| 562 | 535 | |
| 563 | 536 | pub const Index = u32; |
| 564 | 537 | |
| ... | ... | @@ -613,45 +586,25 @@ const Page = struct { |
| 613 | 586 | return null; |
| 614 | 587 | } |
| 615 | 588 | |
| 616 | fn format( | |
| 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 { | |
| 589 | const Format = struct { | |
| 630 | 590 | page: Page, |
| 631 | 591 | info: UnwindInfo, |
| 632 | }; | |
| 633 | 592 | |
| 634 | fn format2( | |
| 635 | ctx: FormatPageContext, | |
| 636 | comptime unused_format_string: []const u8, | |
| 637 | options: std.fmt.FormatOptions, | |
| 638 | writer: anytype, | |
| 639 | ) @TypeOf(writer).Error!void { | |
| 640 | _ = options; | |
| 641 | _ = unused_format_string; | |
| 642 | try writer.writeAll("Page:\n"); | |
| 643 | try writer.print(" kind: {s}\n", .{@tagName(ctx.page.kind)}); | |
| 644 | try writer.print(" entries: {d} - {d}\n", .{ | |
| 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 }); | |
| 593 | fn default(f: Format, w: *Writer) Writer.Error!void { | |
| 594 | try w.writeAll("Page:\n"); | |
| 595 | try w.print(" kind: {s}\n", .{@tagName(f.page.kind)}); | |
| 596 | try w.print(" entries: {d} - {d}\n", .{ | |
| 597 | f.page.start, | |
| 598 | f.page.start + f.page.count, | |
| 599 | }); | |
| 600 | try w.print(" encodings (count = {d})\n", .{f.page.page_encodings_count}); | |
| 601 | for (f.page.page_encodings[0..f.page.page_encodings_count], 0..) |enc, i| { | |
| 602 | try w.print(" {d}: {f}\n", .{ f.info.common_encodings_count + i, enc }); | |
| 603 | } | |
| 651 | 604 | } |
| 652 | } | |
| 605 | }; | |
| 653 | 606 | |
| 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 | 608 | return .{ .data = .{ |
| 656 | 609 | .page = page, |
| 657 | 610 | .info = info, |
| ... | ... | @@ -720,6 +673,7 @@ const macho = std.macho; |
| 720 | 673 | const math = std.math; |
| 721 | 674 | const mem = std.mem; |
| 722 | 675 | const trace = @import("../../tracy.zig").trace; |
| 676 | const Writer = std.io.Writer; | |
| 723 | 677 | |
| 724 | 678 | const Allocator = mem.Allocator; |
| 725 | 679 | const Atom = @import("Atom.zig"); |
src/link/MachO/ZigObject.zig+34-47| ... | ... | @@ -618,7 +618,7 @@ pub fn getNavVAddr( |
| 618 | 618 | const zcu = pt.zcu; |
| 619 | 619 | const ip = &zcu.intern_pool; |
| 620 | 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 | 622 | const sym_index = if (nav.getExtern(ip)) |@"extern"| try self.getGlobalSymbol( |
| 623 | 623 | macho_file, |
| 624 | 624 | nav.name.toSlice(ip), |
| ... | ... | @@ -943,7 +943,7 @@ fn updateNavCode( |
| 943 | 943 | const ip = &zcu.intern_pool; |
| 944 | 944 | const nav = ip.getNav(nav_index); |
| 945 | 945 | |
| 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 }); | |
| 947 | 947 | |
| 948 | 948 | const target = &zcu.navFileScope(nav_index).mod.?.resolved_target.result; |
| 949 | 949 | const required_alignment = switch (pt.navAlignment(nav_index)) { |
| ... | ... | @@ -959,7 +959,7 @@ fn updateNavCode( |
| 959 | 959 | sym.out_n_sect = sect_index; |
| 960 | 960 | atom.out_n_sect = sect_index; |
| 961 | 961 | |
| 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 | 963 | defer gpa.free(sym_name); |
| 964 | 964 | sym.name = try self.addString(gpa, sym_name); |
| 965 | 965 | atom.setAlive(true); |
| ... | ... | @@ -981,7 +981,7 @@ fn updateNavCode( |
| 981 | 981 | if (need_realloc) { |
| 982 | 982 | atom.grow(macho_file) catch |err| |
| 983 | 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 | 985 | if (old_vaddr != atom.value) { |
| 986 | 986 | sym.value = 0; |
| 987 | 987 | nlist.n_value = 0; |
| ... | ... | @@ -1023,7 +1023,7 @@ fn updateTlv( |
| 1023 | 1023 | const ip = &pt.zcu.intern_pool; |
| 1024 | 1024 | const nav = ip.getNav(nav_index); |
| 1025 | 1025 | |
| 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 }); | |
| 1027 | 1027 | |
| 1028 | 1028 | // 1. Lower TLV initializer |
| 1029 | 1029 | const init_sym_index = try self.createTlvInitializer( |
| ... | ... | @@ -1351,7 +1351,7 @@ fn updateLazySymbol( |
| 1351 | 1351 | defer code_buffer.deinit(gpa); |
| 1352 | 1352 | |
| 1353 | 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 | 1355 | @tagName(lazy_sym.kind), |
| 1356 | 1356 | Type.fromInterned(lazy_sym.ty).fmt(pt), |
| 1357 | 1357 | }); |
| ... | ... | @@ -1430,7 +1430,7 @@ pub fn deleteExport( |
| 1430 | 1430 | } orelse return; |
| 1431 | 1431 | const nlist_index = metadata.@"export"(self, name.toSlice(&zcu.intern_pool)) orelse return; |
| 1432 | 1432 | |
| 1433 | log.debug("deleting export '{}'", .{name.fmt(&zcu.intern_pool)}); | |
| 1433 | log.debug("deleting export '{f}'", .{name.fmt(&zcu.intern_pool)}); | |
| 1434 | 1434 | |
| 1435 | 1435 | const nlist = &self.symtab.items(.nlist)[nlist_index.*]; |
| 1436 | 1436 | self.symtab.items(.size)[nlist_index.*] = 0; |
| ... | ... | @@ -1678,64 +1678,50 @@ pub fn asFile(self: *ZigObject) File { |
| 1678 | 1678 | return .{ .zig_object = self }; |
| 1679 | 1679 | } |
| 1680 | 1680 | |
| 1681 | pub fn fmtSymtab(self: *ZigObject, macho_file: *MachO) std.fmt.Formatter(formatSymtab) { | |
| 1681 | pub fn fmtSymtab(self: *ZigObject, macho_file: *MachO) std.fmt.Formatter(Format, Format.symtab) { | |
| 1682 | 1682 | return .{ .data = .{ |
| 1683 | 1683 | .self = self, |
| 1684 | 1684 | .macho_file = macho_file, |
| 1685 | 1685 | } }; |
| 1686 | 1686 | } |
| 1687 | 1687 | |
| 1688 | const FormatContext = struct { | |
| 1688 | const Format = struct { | |
| 1689 | 1689 | self: *ZigObject, |
| 1690 | 1690 | macho_file: *MachO, |
| 1691 | }; | |
| 1692 | 1691 | |
| 1693 | fn formatSymtab( | |
| 1694 | ctx: FormatContext, | |
| 1695 | comptime unused_fmt_string: []const u8, | |
| 1696 | options: std.fmt.FormatOptions, | |
| 1697 | writer: anytype, | |
| 1698 | ) !void { | |
| 1699 | _ = unused_fmt_string; | |
| 1700 | _ = options; | |
| 1701 | try writer.writeAll(" symbols\n"); | |
| 1702 | const self = ctx.self; | |
| 1703 | const macho_file = ctx.macho_file; | |
| 1704 | for (self.symbols.items, 0..) |sym, i| { | |
| 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)}); | |
| 1692 | fn symtab(f: Format, w: *Writer) Writer.Error!void { | |
| 1693 | try w.writeAll(" symbols\n"); | |
| 1694 | const self = f.self; | |
| 1695 | const macho_file = f.macho_file; | |
| 1696 | for (self.symbols.items, 0..) |sym, i| { | |
| 1697 | const ref = self.getSymbolRef(@intCast(i), macho_file); | |
| 1698 | if (ref.getFile(macho_file) == null) { | |
| 1699 | // TODO any better way of handling this? | |
| 1700 | try w.print(" {s} : unclaimed\n", .{sym.getName(macho_file)}); | |
| 1701 | } else { | |
| 1702 | try w.print(" {f}\n", .{ref.getSymbol(macho_file).?.fmt(macho_file)}); | |
| 1703 | } | |
| 1711 | 1704 | } |
| 1712 | 1705 | } |
| 1713 | } | |
| 1714 | 1706 | |
| 1715 | pub 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 | ||
| 1718 | pub fn fmtAtoms(self: *ZigObject, macho_file: *MachO) std.fmt.Formatter(Format, Format.atoms) { | |
| 1716 | 1719 | return .{ .data = .{ |
| 1717 | 1720 | .self = self, |
| 1718 | 1721 | .macho_file = macho_file, |
| 1719 | 1722 | } }; |
| 1720 | 1723 | } |
| 1721 | 1724 | |
| 1722 | fn 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 | ||
| 1739 | 1725 | const AvMetadata = struct { |
| 1740 | 1726 | symbol_index: Symbol.Index, |
| 1741 | 1727 | /// A list of all exports aliases of this Av. |
| ... | ... | @@ -1797,6 +1783,7 @@ const mem = std.mem; |
| 1797 | 1783 | const target_util = @import("../../target.zig"); |
| 1798 | 1784 | const trace = @import("../../tracy.zig").trace; |
| 1799 | 1785 | const std = @import("std"); |
| 1786 | const Writer = std.io.Writer; | |
| 1800 | 1787 | |
| 1801 | 1788 | const Allocator = std.mem.Allocator; |
| 1802 | 1789 | const 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 | 117 | fn markLive(atom: *Atom, macho_file: *MachO) void { |
| 118 | 118 | assert(atom.visited.load(.seq_cst)); |
| 119 | 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 | 121 | track_live_level, |
| 122 | 122 | atom.atom_index, |
| 123 | 123 | atom.getName(macho_file), |
| ... | ... | @@ -196,15 +196,8 @@ const Level = struct { |
| 196 | 196 | self.value += 1; |
| 197 | 197 | } |
| 198 | 198 | |
| 199 | pub fn format( | |
| 200 | self: *const @This(), | |
| 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); | |
| 199 | pub fn format(self: *const @This(), w: *Writer) Writer.Error!void { | |
| 200 | try w.splatByteAll(' ', self.value); | |
| 208 | 201 | } |
| 209 | 202 | }; |
| 210 | 203 | |
| ... | ... | @@ -219,6 +212,7 @@ const mem = std.mem; |
| 219 | 212 | const trace = @import("../../tracy.zig").trace; |
| 220 | 213 | const track_live_log = std.log.scoped(.dead_strip_track_live); |
| 221 | 214 | const std = @import("std"); |
| 215 | const Writer = std.io.Writer; | |
| 222 | 216 | |
| 223 | 217 | const Allocator = mem.Allocator; |
| 224 | 218 | const 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 | 654 | const macho = std.macho; |
| 655 | 655 | const mem = std.mem; |
| 656 | 656 | const testing = std.testing; |
| 657 | const trace = @import("../../../tracy.zig").trace; | |
| 658 | ||
| 659 | 657 | const Allocator = mem.Allocator; |
| 658 | const Writer = std.io.Writer; | |
| 659 | ||
| 660 | const trace = @import("../../../tracy.zig").trace; | |
| 660 | 661 | const File = @import("../file.zig").File; |
| 661 | 662 | const MachO = @import("../../MachO.zig"); |
| 662 | 663 | const Rebase = @This(); |
src/link/MachO/dyld_info/Trie.zig+2-2| ... | ... | @@ -336,9 +336,9 @@ const Edge = struct { |
| 336 | 336 | fn expectEqualHexStrings(expected: []const u8, given: []const u8) !void { |
| 337 | 337 | assert(expected.len > 0); |
| 338 | 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 | 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 | 342 | defer testing.allocator.free(given_fmt); |
| 343 | 343 | const idx = mem.indexOfDiff(u8, expected_fmt, given_fmt).?; |
| 344 | 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 | 205 | } |
| 206 | 206 | } |
| 207 | 207 | |
| 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 | 209 | log.debug(" => {x}", .{current.offset}); |
| 210 | 210 | switch (state) { |
| 211 | 211 | .start => { |
| ... | ... | @@ -447,7 +447,7 @@ pub const WeakBind = struct { |
| 447 | 447 | } |
| 448 | 448 | } |
| 449 | 449 | |
| 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 | 451 | log.debug(" => {x}", .{current.offset}); |
| 452 | 452 | switch (state) { |
| 453 | 453 | .start => { |
src/link/MachO/eh_frame.zig+26-65| ... | ... | @@ -81,46 +81,26 @@ pub const Cie = struct { |
| 81 | 81 | return true; |
| 82 | 82 | } |
| 83 | 83 | |
| 84 | pub fn format( | |
| 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) { | |
| 84 | pub fn fmt(cie: Cie, macho_file: *MachO) std.fmt.Formatter(Format, Format.default) { | |
| 98 | 85 | return .{ .data = .{ |
| 99 | 86 | .cie = cie, |
| 100 | 87 | .macho_file = macho_file, |
| 101 | 88 | } }; |
| 102 | 89 | } |
| 103 | 90 | |
| 104 | const FormatContext = struct { | |
| 91 | const Format = struct { | |
| 105 | 92 | cie: Cie, |
| 106 | 93 | macho_file: *MachO, |
| 107 | }; | |
| 108 | 94 | |
| 109 | fn format2( | |
| 110 | ctx: FormatContext, | |
| 111 | comptime unused_fmt_string: []const u8, | |
| 112 | options: std.fmt.FormatOptions, | |
| 113 | writer: anytype, | |
| 114 | ) !void { | |
| 115 | _ = unused_fmt_string; | |
| 116 | _ = options; | |
| 117 | const cie = ctx.cie; | |
| 118 | try writer.print("@{x} : size({x})", .{ | |
| 119 | cie.offset, | |
| 120 | cie.getSize(), | |
| 121 | }); | |
| 122 | if (!cie.alive) try writer.writeAll(" : [*]"); | |
| 123 | } | |
| 95 | fn default(f: Format, w: *Writer) Writer.Error!void { | |
| 96 | const cie = f.cie; | |
| 97 | try w.print("@{x} : size({x})", .{ | |
| 98 | cie.offset, | |
| 99 | cie.getSize(), | |
| 100 | }); | |
| 101 | if (!cie.alive) try w.writeAll(" : [*]"); | |
| 102 | } | |
| 103 | }; | |
| 124 | 104 | |
| 125 | 105 | pub const Index = u32; |
| 126 | 106 | |
| ... | ... | @@ -231,49 +211,29 @@ pub const Fde = struct { |
| 231 | 211 | return fde.getObject(macho_file).getAtom(fde.lsda); |
| 232 | 212 | } |
| 233 | 213 | |
| 234 | pub fn format( | |
| 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) { | |
| 214 | pub fn fmt(fde: Fde, macho_file: *MachO) std.fmt.Formatter(Format, Format.default) { | |
| 248 | 215 | return .{ .data = .{ |
| 249 | 216 | .fde = fde, |
| 250 | 217 | .macho_file = macho_file, |
| 251 | 218 | } }; |
| 252 | 219 | } |
| 253 | 220 | |
| 254 | const FormatContext = struct { | |
| 221 | const Format = struct { | |
| 255 | 222 | fde: Fde, |
| 256 | 223 | macho_file: *MachO, |
| 257 | }; | |
| 258 | 224 | |
| 259 | fn format2( | |
| 260 | ctx: FormatContext, | |
| 261 | comptime unused_fmt_string: []const u8, | |
| 262 | options: std.fmt.FormatOptions, | |
| 263 | writer: anytype, | |
| 264 | ) !void { | |
| 265 | _ = unused_fmt_string; | |
| 266 | _ = options; | |
| 267 | const fde = ctx.fde; | |
| 268 | const macho_file = ctx.macho_file; | |
| 269 | try writer.print("@{x} : size({x}) : cie({d}) : {s}", .{ | |
| 270 | fde.offset, | |
| 271 | fde.getSize(), | |
| 272 | fde.cie, | |
| 273 | fde.getAtom(macho_file).getName(macho_file), | |
| 274 | }); | |
| 275 | if (!fde.alive) try writer.writeAll(" : [*]"); | |
| 276 | } | |
| 225 | fn default(f: Format, writer: *Writer) Writer.Error!void { | |
| 226 | const fde = f.fde; | |
| 227 | const macho_file = f.macho_file; | |
| 228 | try writer.print("@{x} : size({x}) : cie({d}) : {s}", .{ | |
| 229 | fde.offset, | |
| 230 | fde.getSize(), | |
| 231 | fde.cie, | |
| 232 | fde.getAtom(macho_file).getName(macho_file), | |
| 233 | }); | |
| 234 | if (!fde.alive) try writer.writeAll(" : [*]"); | |
| 235 | } | |
| 236 | }; | |
| 277 | 237 | |
| 278 | 238 | pub const Index = u32; |
| 279 | 239 | }; |
| ... | ... | @@ -545,6 +505,7 @@ const math = std.math; |
| 545 | 505 | const mem = std.mem; |
| 546 | 506 | const std = @import("std"); |
| 547 | 507 | const trace = @import("../../tracy.zig").trace; |
| 508 | const Writer = std.io.Writer; | |
| 548 | 509 | |
| 549 | 510 | const Allocator = std.mem.Allocator; |
| 550 | 511 | const Atom = @import("Atom.zig"); |
src/link/MachO/file.zig+7-13| ... | ... | @@ -10,23 +10,16 @@ pub const File = union(enum) { |
| 10 | 10 | }; |
| 11 | 11 | } |
| 12 | 12 | |
| 13 | pub fn fmtPath(file: File) std.fmt.Formatter(formatPath) { | |
| 13 | pub fn fmtPath(file: File) std.fmt.Formatter(File, formatPath) { | |
| 14 | 14 | return .{ .data = file }; |
| 15 | 15 | } |
| 16 | 16 | |
| 17 | fn formatPath( | |
| 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; | |
| 17 | fn formatPath(file: File, w: *Writer) Writer.Error!void { | |
| 25 | 18 | switch (file) { |
| 26 | .zig_object => |zo| try writer.writeAll(zo.basename), | |
| 27 | .internal => try writer.writeAll("internal"), | |
| 28 | .object => |x| try writer.print("{}", .{x.fmtPath()}), | |
| 29 | .dylib => |dl| try writer.print("{}", .{@as(Path, dl.path)}), | |
| 19 | .zig_object => |zo| try w.writeAll(zo.basename), | |
| 20 | .internal => try w.writeAll("internal"), | |
| 21 | .object => |x| try w.print("{f}", .{x.fmtPath()}), | |
| 22 | .dylib => |dl| try w.print("{f}", .{@as(Path, dl.path)}), | |
| 30 | 23 | } |
| 31 | 24 | } |
| 32 | 25 | |
| ... | ... | @@ -371,6 +364,7 @@ const log = std.log.scoped(.link); |
| 371 | 364 | const macho = std.macho; |
| 372 | 365 | const Allocator = std.mem.Allocator; |
| 373 | 366 | const Path = std.Build.Cache.Path; |
| 367 | const Writer = std.io.Writer; | |
| 374 | 368 | |
| 375 | 369 | const trace = @import("../../tracy.zig").trace; |
| 376 | 370 | const Archive = @import("Archive.zig"); |
src/link/MachO/load_commands.zig+1| ... | ... | @@ -3,6 +3,7 @@ const assert = std.debug.assert; |
| 3 | 3 | const log = std.log.scoped(.link); |
| 4 | 4 | const macho = std.macho; |
| 5 | 5 | const mem = std.mem; |
| 6 | const Writer = std.io.Writer; | |
| 6 | 7 | |
| 7 | 8 | const Allocator = mem.Allocator; |
| 8 | 9 | const 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 | 20 | // the *only* input file over. |
| 21 | 21 | const path = positionals.items[0].path().?; |
| 22 | 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 | 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 | 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 | 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 | 30 | return; |
| 31 | 31 | } |
| 32 | 32 | |
| ... | ... | @@ -62,7 +62,7 @@ pub fn flushObject(macho_file: *MachO, comp: *Compilation, module_obj_path: ?Pat |
| 62 | 62 | allocateSegment(macho_file); |
| 63 | 63 | |
| 64 | 64 | if (build_options.enable_logging) { |
| 65 | state_log.debug("{}", .{macho_file.dumpState()}); | |
| 65 | state_log.debug("{f}", .{macho_file.dumpState()}); | |
| 66 | 66 | } |
| 67 | 67 | |
| 68 | 68 | try writeSections(macho_file); |
| ... | ... | @@ -126,7 +126,7 @@ pub fn flushStaticLib(macho_file: *MachO, comp: *Compilation, module_obj_path: ? |
| 126 | 126 | allocateSegment(macho_file); |
| 127 | 127 | |
| 128 | 128 | if (build_options.enable_logging) { |
| 129 | state_log.debug("{}", .{macho_file.dumpState()}); | |
| 129 | state_log.debug("{f}", .{macho_file.dumpState()}); | |
| 130 | 130 | } |
| 131 | 131 | |
| 132 | 132 | try writeSections(macho_file); |
| ... | ... | @@ -202,7 +202,7 @@ pub fn flushStaticLib(macho_file: *MachO, comp: *Compilation, module_obj_path: ? |
| 202 | 202 | }; |
| 203 | 203 | |
| 204 | 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 | } |
| 207 | 207 | |
| 208 | 208 | var buffer = std.ArrayList(u8).init(gpa); |
| ... | ... | @@ -784,6 +784,7 @@ const macho = std.macho; |
| 784 | 784 | const math = std.math; |
| 785 | 785 | const mem = std.mem; |
| 786 | 786 | const state_log = std.log.scoped(.link_state); |
| 787 | const Writer = std.io.Writer; | |
| 787 | 788 | |
| 788 | 789 | const Archive = @import("Archive.zig"); |
| 789 | 790 | const Atom = @import("Atom.zig"); |
src/link/MachO/synthetic.zig+70-97| ... | ... | @@ -37,34 +37,27 @@ pub const GotSection = struct { |
| 37 | 37 | } |
| 38 | 38 | } |
| 39 | 39 | |
| 40 | const FormatCtx = struct { | |
| 40 | const Format = struct { | |
| 41 | 41 | got: GotSection, |
| 42 | 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 | }; |
| 44 | 57 | |
| 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 | 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 | }; |
| 69 | 62 | |
| 70 | 63 | pub const StubsSection = struct { |
| ... | ... | @@ -128,34 +121,27 @@ pub const StubsSection = struct { |
| 128 | 121 | } |
| 129 | 122 | } |
| 130 | 123 | |
| 131 | const FormatCtx = struct { | |
| 132 | stubs: StubsSection, | |
| 133 | macho_file: *MachO, | |
| 134 | }; | |
| 135 | ||
| 136 | pub fn fmt(stubs: StubsSection, macho_file: *MachO) std.fmt.Formatter(format2) { | |
| 124 | pub fn fmt(stubs: StubsSection, macho_file: *MachO) std.fmt.Formatter(Format, Format.print) { | |
| 137 | 125 | return .{ .data = .{ .stubs = stubs, .macho_file = macho_file } }; |
| 138 | 126 | } |
| 139 | 127 | |
| 140 | pub fn format2( | |
| 141 | ctx: FormatCtx, | |
| 142 | comptime unused_fmt_string: []const u8, | |
| 143 | options: std.fmt.FormatOptions, | |
| 144 | writer: anytype, | |
| 145 | ) !void { | |
| 146 | _ = options; | |
| 147 | _ = unused_fmt_string; | |
| 148 | for (ctx.stubs.symbols.items, 0..) |ref, i| { | |
| 149 | const symbol = ref.getSymbol(ctx.macho_file).?; | |
| 150 | try writer.print(" {d}@0x{x} => {d}@0x{x} ({s})\n", .{ | |
| 151 | i, | |
| 152 | symbol.getStubsAddress(ctx.macho_file), | |
| 153 | ref, | |
| 154 | symbol.getAddress(.{}, ctx.macho_file), | |
| 155 | symbol.getName(ctx.macho_file), | |
| 156 | }); | |
| 128 | const Format = struct { | |
| 129 | stubs: StubsSection, | |
| 130 | macho_file: *MachO, | |
| 131 | ||
| 132 | pub fn print(f: Format, w: *Writer) Writer.Error!void { | |
| 133 | for (f.stubs.symbols.items, 0..) |ref, i| { | |
| 134 | const symbol = ref.getSymbol(f.macho_file).?; | |
| 135 | try w.print(" {d}@0x{x} => {f}@0x{x} ({s})\n", .{ | |
| 136 | i, | |
| 137 | symbol.getStubsAddress(f.macho_file), | |
| 138 | ref, | |
| 139 | symbol.getAddress(.{}, f.macho_file), | |
| 140 | symbol.getName(f.macho_file), | |
| 141 | }); | |
| 142 | } | |
| 157 | 143 | } |
| 158 | } | |
| 144 | }; | |
| 159 | 145 | }; |
| 160 | 146 | |
| 161 | 147 | pub const StubsHelperSection = struct { |
| ... | ... | @@ -357,34 +343,27 @@ pub const TlvPtrSection = struct { |
| 357 | 343 | } |
| 358 | 344 | } |
| 359 | 345 | |
| 360 | const FormatCtx = struct { | |
| 361 | tlv: TlvPtrSection, | |
| 362 | macho_file: *MachO, | |
| 363 | }; | |
| 364 | ||
| 365 | pub fn fmt(tlv: TlvPtrSection, macho_file: *MachO) std.fmt.Formatter(format2) { | |
| 346 | pub fn fmt(tlv: TlvPtrSection, macho_file: *MachO) std.fmt.Formatter(Format, Format.print) { | |
| 366 | 347 | return .{ .data = .{ .tlv = tlv, .macho_file = macho_file } }; |
| 367 | 348 | } |
| 368 | 349 | |
| 369 | pub fn format2( | |
| 370 | ctx: FormatCtx, | |
| 371 | comptime unused_fmt_string: []const u8, | |
| 372 | options: std.fmt.FormatOptions, | |
| 373 | writer: anytype, | |
| 374 | ) !void { | |
| 375 | _ = options; | |
| 376 | _ = unused_fmt_string; | |
| 377 | for (ctx.tlv.symbols.items, 0..) |ref, i| { | |
| 378 | const symbol = ref.getSymbol(ctx.macho_file).?; | |
| 379 | try writer.print(" {d}@0x{x} => {d}@0x{x} ({s})\n", .{ | |
| 380 | i, | |
| 381 | symbol.getTlvPtrAddress(ctx.macho_file), | |
| 382 | ref, | |
| 383 | symbol.getAddress(.{}, ctx.macho_file), | |
| 384 | symbol.getName(ctx.macho_file), | |
| 385 | }); | |
| 350 | const Format = struct { | |
| 351 | tlv: TlvPtrSection, | |
| 352 | macho_file: *MachO, | |
| 353 | ||
| 354 | pub fn print(f: Format, w: *Writer) Writer.Error!void { | |
| 355 | for (f.tlv.symbols.items, 0..) |ref, i| { | |
| 356 | const symbol = ref.getSymbol(f.macho_file).?; | |
| 357 | try w.print(" {d}@0x{x} => {f}@0x{x} ({s})\n", .{ | |
| 358 | i, | |
| 359 | symbol.getTlvPtrAddress(f.macho_file), | |
| 360 | ref, | |
| 361 | symbol.getAddress(.{}, f.macho_file), | |
| 362 | symbol.getName(f.macho_file), | |
| 363 | }); | |
| 364 | } | |
| 386 | 365 | } |
| 387 | } | |
| 366 | }; | |
| 388 | 367 | }; |
| 389 | 368 | |
| 390 | 369 | pub const ObjcStubsSection = struct { |
| ... | ... | @@ -482,34 +461,27 @@ pub const ObjcStubsSection = struct { |
| 482 | 461 | } |
| 483 | 462 | } |
| 484 | 463 | |
| 485 | const FormatCtx = struct { | |
| 486 | objc: ObjcStubsSection, | |
| 487 | macho_file: *MachO, | |
| 488 | }; | |
| 489 | ||
| 490 | pub fn fmt(objc: ObjcStubsSection, macho_file: *MachO) std.fmt.Formatter(format2) { | |
| 464 | pub fn fmt(objc: ObjcStubsSection, macho_file: *MachO) std.fmt.Formatter(Format, Format.print) { | |
| 491 | 465 | return .{ .data = .{ .objc = objc, .macho_file = macho_file } }; |
| 492 | 466 | } |
| 493 | 467 | |
| 494 | pub fn format2( | |
| 495 | ctx: FormatCtx, | |
| 496 | comptime unused_fmt_string: []const u8, | |
| 497 | options: std.fmt.FormatOptions, | |
| 498 | writer: anytype, | |
| 499 | ) !void { | |
| 500 | _ = options; | |
| 501 | _ = unused_fmt_string; | |
| 502 | for (ctx.objc.symbols.items, 0..) |ref, i| { | |
| 503 | const symbol = ref.getSymbol(ctx.macho_file).?; | |
| 504 | try writer.print(" {d}@0x{x} => {d}@0x{x} ({s})\n", .{ | |
| 505 | i, | |
| 506 | symbol.getObjcStubsAddress(ctx.macho_file), | |
| 507 | ref, | |
| 508 | symbol.getAddress(.{}, ctx.macho_file), | |
| 509 | symbol.getName(ctx.macho_file), | |
| 510 | }); | |
| 468 | const Format = struct { | |
| 469 | objc: ObjcStubsSection, | |
| 470 | macho_file: *MachO, | |
| 471 | ||
| 472 | pub fn print(f: Format, w: *Writer) Writer.Error!void { | |
| 473 | for (f.objc.symbols.items, 0..) |ref, i| { | |
| 474 | const symbol = ref.getSymbol(f.macho_file).?; | |
| 475 | try w.print(" {d}@0x{x} => {f}@0x{x} ({s})\n", .{ | |
| 476 | i, | |
| 477 | symbol.getObjcStubsAddress(f.macho_file), | |
| 478 | ref, | |
| 479 | symbol.getAddress(.{}, f.macho_file), | |
| 480 | symbol.getName(f.macho_file), | |
| 481 | }); | |
| 482 | } | |
| 511 | 483 | } |
| 512 | } | |
| 484 | }; | |
| 513 | 485 | |
| 514 | 486 | pub const Index = u32; |
| 515 | 487 | }; |
| ... | ... | @@ -625,13 +597,14 @@ pub const DataInCode = struct { |
| 625 | 597 | }; |
| 626 | 598 | }; |
| 627 | 599 | |
| 600 | const std = @import("std"); | |
| 628 | 601 | const aarch64 = @import("../aarch64.zig"); |
| 629 | 602 | const assert = std.debug.assert; |
| 630 | 603 | const macho = std.macho; |
| 631 | 604 | const math = std.math; |
| 632 | const std = @import("std"); | |
| 633 | const trace = @import("../../tracy.zig").trace; | |
| 634 | ||
| 635 | 605 | const Allocator = std.mem.Allocator; |
| 606 | const Writer = std.io.Writer; | |
| 607 | ||
| 608 | const trace = @import("../../tracy.zig").trace; | |
| 636 | 609 | const MachO = @import("../MachO.zig"); |
| 637 | 610 | const 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 | 445 | .func => return, |
| 446 | 446 | .variable => |variable| Value.fromInterned(variable.init), |
| 447 | 447 | .@"extern" => { |
| 448 | log.debug("found extern decl: {}", .{nav.name.fmt(ip)}); | |
| 448 | log.debug("found extern decl: {f}", .{nav.name.fmt(ip)}); | |
| 449 | 449 | return; |
| 450 | 450 | }, |
| 451 | 451 | else => nav_val, |
| ... | ... | @@ -675,7 +675,7 @@ pub fn flush( |
| 675 | 675 | const off = self.getAddr(text_i, .t); |
| 676 | 676 | text_i += out.code.len; |
| 677 | 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 | 679 | if (!self.sixtyfour_bit) { |
| 680 | 680 | mem.writeInt(u32, got_table[atom.got_index.? * 4 ..][0..4], @intCast(off), target.cpu.arch.endian()); |
| 681 | 681 | } else { |
| ... | ... | @@ -974,11 +974,11 @@ pub fn seeNav(self: *Plan9, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) |
| 974 | 974 | self.etext_edata_end_atom_indices[2] = atom_idx; |
| 975 | 975 | } |
| 976 | 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 | 978 | nav.name.fmt(ip), |
| 979 | 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 | 982 | return atom_idx; |
| 983 | 983 | } |
| 984 | 984 | |
| ... | ... | @@ -1043,7 +1043,7 @@ fn updateLazySymbolAtom( |
| 1043 | 1043 | defer code_buffer.deinit(gpa); |
| 1044 | 1044 | |
| 1045 | 1045 | // 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 | 1047 | @tagName(sym.kind), |
| 1048 | 1048 | Type.fromInterned(sym.ty).fmt(pt), |
| 1049 | 1049 | }); |
| ... | ... | @@ -1314,7 +1314,7 @@ pub fn getNavVAddr( |
| 1314 | 1314 | ) !u64 { |
| 1315 | 1315 | const ip = &pt.zcu.intern_pool; |
| 1316 | 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 | 1318 | if (nav.getExtern(ip) != null) { |
| 1319 | 1319 | if (nav.name.eqlSlice("etext", ip)) { |
| 1320 | 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 | 117 | } |
| 118 | 118 | |
| 119 | 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 }); | |
| 121 | 121 | |
| 122 | 122 | try self.object.updateNav(pt, nav); |
| 123 | 123 | } |
| ... | ... | @@ -203,10 +203,10 @@ pub fn flush( |
| 203 | 203 | // We need to export the list of error names somewhere so that we can pretty-print them in the |
| 204 | 204 | // executor. This is not really an important thing though, so we can just dump it in any old |
| 205 | 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 | 207 | defer error_info.deinit(); |
| 208 | 208 | |
| 209 | try error_info.appendSlice("zig_errors:"); | |
| 209 | error_info.writer.writeAll("zig_errors:") catch return error.OutOfMemory; | |
| 210 | 210 | const ip = &self.base.comp.zcu.?.intern_pool; |
| 211 | 211 | for (ip.global_error_set.getNamesFromMainThread()) |name| { |
| 212 | 212 | // Errors can contain pretty much any character - to encode them in a string we must escape |
| ... | ... | @@ -214,9 +214,9 @@ pub fn flush( |
| 214 | 214 | // name if it contains no strange characters is nice for debugging. URI encoding fits the bill. |
| 215 | 215 | // We're using : as separator, which is a reserved character. |
| 216 | 216 | |
| 217 | try error_info.append(':'); | |
| 218 | try std.Uri.Component.percentEncode( | |
| 219 | error_info.writer(), | |
| 217 | error_info.writer.writeByte(':') catch return error.OutOfMemory; | |
| 218 | std.Uri.Component.percentEncode( | |
| 219 | &error_info.writer, | |
| 220 | 220 | name.toSlice(ip), |
| 221 | 221 | struct { |
| 222 | 222 | fn isValidChar(c: u8) bool { |
| ... | ... | @@ -226,10 +226,10 @@ pub fn flush( |
| 226 | 226 | }; |
| 227 | 227 | } |
| 228 | 228 | }.isValidChar, |
| 229 | ); | |
| 229 | ) catch return error.OutOfMemory; | |
| 230 | 230 | } |
| 231 | 231 | try spv.sections.debug_strings.emit(gpa, .OpSourceExtension, .{ |
| 232 | .extension = error_info.items, | |
| 232 | .extension = error_info.getWritten(), | |
| 233 | 233 | }); |
| 234 | 234 | |
| 235 | 235 | const module = try spv.finalize(arena); |
src/link/SpirV/deduplicate.zig+1-1| ... | ... | @@ -110,7 +110,7 @@ const ModuleInfo = struct { |
| 110 | 110 | .TypeDeclaration, .ConstantCreation => { |
| 111 | 111 | const entry = try entities.getOrPut(result_id); |
| 112 | 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 | 114 | return error.DuplicateId; |
| 115 | 115 | } |
| 116 | 116 | entry.value_ptr.* = entity; |
src/link/SpirV/lower_invocation_globals.zig+9-9| ... | ... | @@ -92,7 +92,7 @@ const ModuleInfo = struct { |
| 92 | 92 | const entry_point: ResultId = @enumFromInt(inst.operands[1]); |
| 93 | 93 | const entry = try entry_points.getOrPut(entry_point); |
| 94 | 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 | 96 | return error.DuplicateId; |
| 97 | 97 | } |
| 98 | 98 | }, |
| ... | ... | @@ -103,7 +103,7 @@ const ModuleInfo = struct { |
| 103 | 103 | |
| 104 | 104 | const entry = try fn_types.getOrPut(fn_type); |
| 105 | 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 | 107 | return error.DuplicateId; |
| 108 | 108 | } |
| 109 | 109 | |
| ... | ... | @@ -135,7 +135,7 @@ const ModuleInfo = struct { |
| 135 | 135 | }, |
| 136 | 136 | .OpFunction => { |
| 137 | 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 | 139 | return error.InvalidPhysicalFormat; |
| 140 | 140 | } |
| 141 | 141 | |
| ... | ... | @@ -154,7 +154,7 @@ const ModuleInfo = struct { |
| 154 | 154 | }; |
| 155 | 155 | const entry = try functions.getOrPut(current_function); |
| 156 | 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 | 158 | return error.DuplicateId; |
| 159 | 159 | } |
| 160 | 160 | |
| ... | ... | @@ -162,7 +162,7 @@ const ModuleInfo = struct { |
| 162 | 162 | try callee_store.appendSlice(calls.keys()); |
| 163 | 163 | |
| 164 | 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 | 166 | return error.InvalidId; |
| 167 | 167 | }; |
| 168 | 168 | |
| ... | ... | @@ -187,7 +187,7 @@ const ModuleInfo = struct { |
| 187 | 187 | } |
| 188 | 188 | |
| 189 | 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 | 191 | return error.InvalidPhysicalFormat; |
| 192 | 192 | } |
| 193 | 193 | |
| ... | ... | @@ -222,7 +222,7 @@ const ModuleInfo = struct { |
| 222 | 222 | seen: *std.DynamicBitSetUnmanaged, |
| 223 | 223 | ) !void { |
| 224 | 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 | 226 | return error.InvalidId; |
| 227 | 227 | }; |
| 228 | 228 | |
| ... | ... | @@ -261,7 +261,7 @@ const ModuleInfo = struct { |
| 261 | 261 | seen: *std.DynamicBitSetUnmanaged, |
| 262 | 262 | ) !void { |
| 263 | 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 | 265 | return error.InvalidId; |
| 266 | 266 | }; |
| 267 | 267 | |
| ... | ... | @@ -276,7 +276,7 @@ const ModuleInfo = struct { |
| 276 | 276 | } |
| 277 | 277 | |
| 278 | 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 | 280 | return error.InvalidId; |
| 281 | 281 | }; |
| 282 | 282 |
src/link/SpirV/prune_unused.zig+4-4| ... | ... | @@ -128,7 +128,7 @@ const ModuleInfo = struct { |
| 128 | 128 | switch (inst.opcode) { |
| 129 | 129 | .OpFunction => { |
| 130 | 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 | 132 | return error.InvalidPhysicalFormat; |
| 133 | 133 | } |
| 134 | 134 | |
| ... | ... | @@ -145,7 +145,7 @@ const ModuleInfo = struct { |
| 145 | 145 | }; |
| 146 | 146 | const entry = try functions.getOrPut(current_function); |
| 147 | 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 | 149 | return error.DuplicateId; |
| 150 | 150 | } |
| 151 | 151 | |
| ... | ... | @@ -163,7 +163,7 @@ const ModuleInfo = struct { |
| 163 | 163 | } |
| 164 | 164 | |
| 165 | 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 | 167 | return error.InvalidPhysicalFormat; |
| 168 | 168 | } |
| 169 | 169 | |
| ... | ... | @@ -184,7 +184,7 @@ const AliveMarker = struct { |
| 184 | 184 | |
| 185 | 185 | fn markAlive(self: *AliveMarker, result_id: ResultId) BinaryModule.ParseError!void { |
| 186 | 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 | 188 | return error.InvalidId; |
| 189 | 189 | }; |
| 190 | 190 |
src/link/Wasm.zig+10-19| ... | ... | @@ -547,7 +547,7 @@ pub const SourceLocation = enum(u32) { |
| 547 | 547 | switch (sl.unpack(wasm)) { |
| 548 | 548 | .none => unreachable, |
| 549 | 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 | 551 | .source_location_index => @panic("TODO"), |
| 552 | 552 | } |
| 553 | 553 | } |
| ... | ... | @@ -579,9 +579,9 @@ pub const SourceLocation = enum(u32) { |
| 579 | 579 | .object_index => |i| { |
| 580 | 580 | const obj = i.ptr(wasm); |
| 581 | 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 | 583 | else |
| 584 | try bundle.printString("{}: {s}", .{ obj.path, msg }); | |
| 584 | try bundle.printString("{f}: {s}", .{ obj.path, msg }); | |
| 585 | 585 | }, |
| 586 | 586 | .source_location_index => @panic("TODO"), |
| 587 | 587 | }; |
| ... | ... | @@ -2126,14 +2126,7 @@ pub const FunctionType = extern struct { |
| 2126 | 2126 | wasm: *const Wasm, |
| 2127 | 2127 | ft: FunctionType, |
| 2128 | 2128 | |
| 2129 | pub fn format( | |
| 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; | |
| 2129 | pub fn format(self: Formatter, writer: *std.io.Writer) std.io.Writer.Error!void { | |
| 2137 | 2130 | const params = self.ft.params.slice(self.wasm); |
| 2138 | 2131 | const returns = self.ft.returns.slice(self.wasm); |
| 2139 | 2132 | |
| ... | ... | @@ -2912,9 +2905,7 @@ pub const Feature = packed struct(u8) { |
| 2912 | 2905 | @"=", |
| 2913 | 2906 | }; |
| 2914 | 2907 | |
| 2915 | pub fn format(feature: Feature, comptime fmt: []const u8, opt: std.fmt.FormatOptions, writer: anytype) !void { | |
| 2916 | _ = opt; | |
| 2917 | _ = fmt; | |
| 2908 | pub fn format(feature: Feature, writer: *std.io.Writer) std.io.Writer.Error!void { | |
| 2918 | 2909 | try writer.print("{s} {s}", .{ @tagName(feature.prefix), @tagName(feature.tag) }); |
| 2919 | 2910 | } |
| 2920 | 2911 | |
| ... | ... | @@ -3036,7 +3027,7 @@ fn openParseObjectReportingFailure(wasm: *Wasm, path: Path) void { |
| 3036 | 3027 | } |
| 3037 | 3028 | |
| 3038 | 3029 | fn parseObject(wasm: *Wasm, obj: link.Input.Object) !void { |
| 3039 | log.debug("parseObject {}", .{obj.path}); | |
| 3030 | log.debug("parseObject {f}", .{obj.path}); | |
| 3040 | 3031 | const gpa = wasm.base.comp.gpa; |
| 3041 | 3032 | const gc_sections = wasm.base.gc_sections; |
| 3042 | 3033 | |
| ... | ... | @@ -3060,7 +3051,7 @@ fn parseObject(wasm: *Wasm, obj: link.Input.Object) !void { |
| 3060 | 3051 | } |
| 3061 | 3052 | |
| 3062 | 3053 | fn parseArchive(wasm: *Wasm, obj: link.Input.Object) !void { |
| 3063 | log.debug("parseArchive {}", .{obj.path}); | |
| 3054 | log.debug("parseArchive {f}", .{obj.path}); | |
| 3064 | 3055 | const gpa = wasm.base.comp.gpa; |
| 3065 | 3056 | const gc_sections = wasm.base.gc_sections; |
| 3066 | 3057 | |
| ... | ... | @@ -3196,7 +3187,7 @@ pub fn updateFunc( |
| 3196 | 3187 | const is_obj = zcu.comp.config.output_mode == .Obj; |
| 3197 | 3188 | const target = &zcu.comp.root_mod.resolved_target.result; |
| 3198 | 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)}); | |
| 3200 | 3191 | |
| 3201 | 3192 | // For Wasm, we do not lower the MIR to code just yet. That lowering happens during `flush`, |
| 3202 | 3193 | // 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 | 3298 | .variable => |variable| .{ variable.init, variable.owner_nav }, |
| 3308 | 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 | 3302 | assert(!wasm.imports.contains(chased_nav_index)); |
| 3312 | 3303 | |
| 3313 | 3304 | if (nav_init != .none and !Value.fromInterned(nav_init).typeOf(zcu).hasRuntimeBits(zcu)) { |
| ... | ... | @@ -4347,7 +4338,7 @@ fn resolveFunctionSynthetic( |
| 4347 | 4338 | }); |
| 4348 | 4339 | if (import.type != correct_func_type) { |
| 4349 | 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 | 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 | 534 | wasm.memories.limits.max = @intCast(max_memory / page_size); |
| 535 | 535 | wasm.memories.limits.flags.has_max = true; |
| 536 | 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 | 539 | f.memory_layout_finished = true; |
| 540 | 540 | |
| ... | ... | @@ -1035,20 +1035,14 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { |
| 1035 | 1035 | var id: [16]u8 = undefined; |
| 1036 | 1036 | std.crypto.hash.sha3.TurboShake128(null).hash(binary_bytes.items, &id, .{}); |
| 1037 | 1037 | var uuid: [36]u8 = undefined; |
| 1038 | _ = try std.fmt.bufPrint(&uuid, "{s}-{s}-{s}-{s}-{s}", .{ | |
| 1039 | std.fmt.fmtSliceHexLower(id[0..4]), | |
| 1040 | std.fmt.fmtSliceHexLower(id[4..6]), | |
| 1041 | std.fmt.fmtSliceHexLower(id[6..8]), | |
| 1042 | std.fmt.fmtSliceHexLower(id[8..10]), | |
| 1043 | std.fmt.fmtSliceHexLower(id[10..]), | |
| 1038 | _ = try std.fmt.bufPrint(&uuid, "{x}-{x}-{x}-{x}-{x}", .{ | |
| 1039 | id[0..4], id[4..6], id[6..8], id[8..10], id[10..], | |
| 1044 | 1040 | }); |
| 1045 | 1041 | try emitBuildIdSection(gpa, binary_bytes, &uuid); |
| 1046 | 1042 | }, |
| 1047 | 1043 | .hexstring => |hs| { |
| 1048 | 1044 | var buffer: [32 * 2]u8 = undefined; |
| 1049 | const str = std.fmt.bufPrint(&buffer, "{s}", .{ | |
| 1050 | std.fmt.fmtSliceHexLower(hs.toSlice()), | |
| 1051 | }) catch unreachable; | |
| 1045 | const str = std.fmt.bufPrint(&buffer, "{x}", .{hs.toSlice()}) catch unreachable; | |
| 1052 | 1046 | try emitBuildIdSection(gpa, binary_bytes, str); |
| 1053 | 1047 | }, |
| 1054 | 1048 | else => |mode| { |
src/link/Wasm/Object.zig+7-7| ... | ... | @@ -856,7 +856,7 @@ pub fn parse( |
| 856 | 856 | start_function = @enumFromInt(functions_start + index); |
| 857 | 857 | }, |
| 858 | 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 | 860 | pos = section_end; |
| 861 | 861 | }, |
| 862 | 862 | .code => { |
| ... | ... | @@ -984,10 +984,10 @@ pub fn parse( |
| 984 | 984 | if (gop.value_ptr.type != fn_ty_index) { |
| 985 | 985 | var err = try diags.addErrorWithNotes(2); |
| 986 | 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 | 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 | 991 | continue; |
| 992 | 992 | } |
| 993 | 993 | if (gop.value_ptr.module_name != ptr.module_name.toOptional()) { |
| ... | ... | @@ -1155,11 +1155,11 @@ pub fn parse( |
| 1155 | 1155 | if (gop.value_ptr.type != ptr.type_index) { |
| 1156 | 1156 | var err = try diags.addErrorWithNotes(2); |
| 1157 | 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 | 1159 | ptr.type_index.fmt(wasm), |
| 1160 | 1160 | }); |
| 1161 | 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 | 1163 | continue; |
| 1164 | 1164 | } |
| 1165 | 1165 | if (gop.value_ptr.resolution == .unresolved or gop.value_ptr.flags.binding == .weak) { |
| ... | ... | @@ -1176,8 +1176,8 @@ pub fn parse( |
| 1176 | 1176 | } |
| 1177 | 1177 | var err = try diags.addErrorWithNotes(2); |
| 1178 | 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)}); | |
| 1180 | source_location.addNote(&err, "exported as {} here", .{gop.value_ptr.type.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 {f} here", .{gop.value_ptr.type.fmt(wasm)}); | |
| 1181 | 1181 | continue; |
| 1182 | 1182 | } else { |
| 1183 | 1183 | gop.value_ptr.* = .{ |
src/link/table_section.zig+1-8| ... | ... | @@ -39,14 +39,7 @@ pub fn TableSection(comptime Entry: type) type { |
| 39 | 39 | return self.entries.items.len; |
| 40 | 40 | } |
| 41 | 41 | |
| 42 | pub fn format( | |
| 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); | |
| 42 | pub fn format(self: Self, writer: *std.io.Writer) std.io.Writer.Error!void { | |
| 50 | 43 | try writer.writeAll("TableSection:\n"); |
| 51 | 44 | for (self.entries.items, 0..) |entry, i| { |
| 52 | 45 | try writer.print(" {d} => {}\n", .{ i, entry }); |
src/link/tapi/parse.zig+10-43| ... | ... | @@ -57,14 +57,9 @@ pub const Node = struct { |
| 57 | 57 | } |
| 58 | 58 | } |
| 59 | 59 | |
| 60 | pub fn format( | |
| 61 | self: *const Node, | |
| 62 | comptime fmt: []const u8, | |
| 63 | options: std.fmt.FormatOptions, | |
| 64 | writer: anytype, | |
| 65 | ) !void { | |
| 60 | pub fn format(self: *const Node, writer: *std.io.Writer) std.io.Writer.Error!void { | |
| 66 | 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 | } |
| 70 | 65 | |
| ... | ... | @@ -86,24 +81,17 @@ pub const Node = struct { |
| 86 | 81 | } |
| 87 | 82 | } |
| 88 | 83 | |
| 89 | pub fn format( | |
| 90 | self: *const Doc, | |
| 91 | comptime fmt: []const u8, | |
| 92 | options: std.fmt.FormatOptions, | |
| 93 | writer: anytype, | |
| 94 | ) !void { | |
| 95 | _ = options; | |
| 96 | _ = fmt; | |
| 84 | pub fn format(self: *const Doc, writer: *std.io.Writer) std.io.Writer.Error!void { | |
| 97 | 85 | if (self.directive) |id| { |
| 98 | try std.fmt.format(writer, "{{ ", .{}); | |
| 86 | try writer.print("{{ ", .{}); | |
| 99 | 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 | 90 | if (self.value) |node| { |
| 103 | try std.fmt.format(writer, "{}", .{node}); | |
| 91 | try writer.print("{}", .{node}); | |
| 104 | 92 | } |
| 105 | 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 | 121 | self.values.deinit(allocator); |
| 134 | 122 | } |
| 135 | 123 | |
| 136 | pub fn format( | |
| 137 | self: *const Map, | |
| 138 | comptime fmt: []const u8, | |
| 139 | options: std.fmt.FormatOptions, | |
| 140 | writer: anytype, | |
| 141 | ) !void { | |
| 142 | _ = options; | |
| 143 | _ = fmt; | |
| 124 | pub fn format(self: *const Map, writer: *std.io.Writer) std.io.Writer.Error!void { | |
| 144 | 125 | try std.fmt.format(writer, "{{ ", .{}); |
| 145 | 126 | for (self.values.items) |entry| { |
| 146 | 127 | const key = self.base.tree.getRaw(entry.key, entry.key); |
| ... | ... | @@ -172,14 +153,7 @@ pub const Node = struct { |
| 172 | 153 | self.values.deinit(allocator); |
| 173 | 154 | } |
| 174 | 155 | |
| 175 | pub fn format( | |
| 176 | self: *const List, | |
| 177 | comptime fmt: []const u8, | |
| 178 | options: std.fmt.FormatOptions, | |
| 179 | writer: anytype, | |
| 180 | ) !void { | |
| 181 | _ = options; | |
| 182 | _ = fmt; | |
| 156 | pub fn format(self: *const List, writer: *std.io.Writer) std.io.Writer.Error!void { | |
| 183 | 157 | try std.fmt.format(writer, "[ ", .{}); |
| 184 | 158 | for (self.values.items) |node| { |
| 185 | 159 | try std.fmt.format(writer, "{}, ", .{node}); |
| ... | ... | @@ -203,14 +177,7 @@ pub const Node = struct { |
| 203 | 177 | self.string_value.deinit(allocator); |
| 204 | 178 | } |
| 205 | 179 | |
| 206 | pub fn format( | |
| 207 | self: *const Value, | |
| 208 | comptime fmt: []const u8, | |
| 209 | options: std.fmt.FormatOptions, | |
| 210 | writer: anytype, | |
| 211 | ) !void { | |
| 212 | _ = options; | |
| 213 | _ = fmt; | |
| 180 | pub fn format(self: *const Value, writer: *std.io.Writer) std.io.Writer.Error!void { | |
| 214 | 181 | const raw = self.base.tree.getRaw(self.base.start, self.base.end); |
| 215 | 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 | 65 | |
| 66 | 66 | const fatal = std.process.fatal; |
| 67 | 67 | |
| 68 | /// This can be global since stdout is a singleton. | |
| 69 | var stdio_buffer: [4096]u8 = undefined; | |
| 70 | ||
| 68 | 71 | /// Shaming all the locations that inappropriately use an O(N) search algorithm. |
| 69 | 72 | /// Please delete this and fix the compilation errors! |
| 70 | 73 | pub const @"bad O(N)" = void; |
| ... | ... | @@ -340,11 +343,11 @@ fn mainArgs(gpa: Allocator, arena: Allocator, args: []const []const u8) !void { |
| 340 | 343 | } else if (mem.eql(u8, cmd, "targets")) { |
| 341 | 344 | dev.check(.targets_command); |
| 342 | 345 | const host = std.zig.resolveTargetQueryOrFatal(.{}); |
| 343 | const stdout = io.getStdOut().writer(); | |
| 346 | const stdout = fs.File.stdout().deprecatedWriter(); | |
| 344 | 347 | return @import("print_targets.zig").cmdTargets(arena, cmd_args, stdout, &host); |
| 345 | 348 | } else if (mem.eql(u8, cmd, "version")) { |
| 346 | 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 | 351 | // Check libc++ linkage to make sure Zig was built correctly, but only |
| 349 | 352 | // for "env" and "version" to avoid affecting the startup time for |
| 350 | 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 | 355 | } else if (mem.eql(u8, cmd, "env")) { |
| 353 | 356 | dev.check(.env_command); |
| 354 | 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 | 359 | } else if (mem.eql(u8, cmd, "reduce")) { |
| 357 | 360 | return jitCmd(gpa, arena, cmd_args, .{ |
| 358 | 361 | .cmd_name = "reduce", |
| ... | ... | @@ -360,10 +363,10 @@ fn mainArgs(gpa: Allocator, arena: Allocator, args: []const []const u8) !void { |
| 360 | 363 | }); |
| 361 | 364 | } else if (mem.eql(u8, cmd, "zen")) { |
| 362 | 365 | dev.check(.zen_command); |
| 363 | return io.getStdOut().writeAll(info_zen); | |
| 366 | return fs.File.stdout().writeAll(info_zen); | |
| 364 | 367 | } else if (mem.eql(u8, cmd, "help") or mem.eql(u8, cmd, "-h") or mem.eql(u8, cmd, "--help")) { |
| 365 | 368 | dev.check(.help_command); |
| 366 | return io.getStdOut().writeAll(usage); | |
| 369 | return fs.File.stdout().writeAll(usage); | |
| 367 | 370 | } else if (mem.eql(u8, cmd, "ast-check")) { |
| 368 | 371 | return cmdAstCheck(arena, cmd_args); |
| 369 | 372 | } else if (mem.eql(u8, cmd, "detect-cpu")) { |
| ... | ... | @@ -1038,7 +1041,7 @@ fn buildOutputType( |
| 1038 | 1041 | }; |
| 1039 | 1042 | } else if (mem.startsWith(u8, arg, "-")) { |
| 1040 | 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 | 1045 | return cleanExit(); |
| 1043 | 1046 | } else if (mem.eql(u8, arg, "--")) { |
| 1044 | 1047 | if (arg_mode == .run) { |
| ... | ... | @@ -1806,6 +1809,7 @@ fn buildOutputType( |
| 1806 | 1809 | } else manifest_file = arg; |
| 1807 | 1810 | }, |
| 1808 | 1811 | .assembly, .assembly_with_cpp, .c, .cpp, .h, .hpp, .hm, .hmm, .ll, .bc, .m, .mm => { |
| 1812 | dev.check(.c_compiler); | |
| 1809 | 1813 | try create_module.c_source_files.append(arena, .{ |
| 1810 | 1814 | // Populated after module creation. |
| 1811 | 1815 | .owner = undefined, |
| ... | ... | @@ -1816,6 +1820,7 @@ fn buildOutputType( |
| 1816 | 1820 | }); |
| 1817 | 1821 | }, |
| 1818 | 1822 | .rc => { |
| 1823 | dev.check(.win32_resource); | |
| 1819 | 1824 | try create_module.rc_source_files.append(arena, .{ |
| 1820 | 1825 | // Populated after module creation. |
| 1821 | 1826 | .owner = undefined, |
| ... | ... | @@ -2766,9 +2771,9 @@ fn buildOutputType( |
| 2766 | 2771 | } else if (mem.eql(u8, arg, "-V")) { |
| 2767 | 2772 | warn("ignoring request for supported emulations: unimplemented", .{}); |
| 2768 | 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 | 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 | 2777 | process.exit(0); |
| 2773 | 2778 | } else { |
| 2774 | 2779 | fatal("unsupported linker arg: {s}", .{arg}); |
| ... | ... | @@ -3301,6 +3306,7 @@ fn buildOutputType( |
| 3301 | 3306 | defer thread_pool.deinit(); |
| 3302 | 3307 | |
| 3303 | 3308 | for (create_module.c_source_files.items) |*src| { |
| 3309 | dev.check(.c_compiler); | |
| 3304 | 3310 | if (!mem.eql(u8, src.src_path, "-")) continue; |
| 3305 | 3311 | |
| 3306 | 3312 | const ext = src.ext orelse |
| ... | ... | @@ -3325,17 +3331,20 @@ fn buildOutputType( |
| 3325 | 3331 | // for the hashing algorithm here and in the cache are the same. |
| 3326 | 3332 | // We are providing our own cache key, because this file has nothing |
| 3327 | 3333 | // to do with the cache manifest. |
| 3328 | var hasher = Cache.Hasher.init("0123456789abcdef"); | |
| 3329 | var w = io.multiWriter(.{ f.writer(), hasher.writer() }); | |
| 3330 | var fifo = std.fifo.LinearFifo(u8, .{ .Static = 4096 }).init(); | |
| 3331 | try fifo.pump(io.getStdIn().reader(), w.writer()); | |
| 3334 | var file_writer = f.writer(&.{}); | |
| 3335 | var buffer: [1000]u8 = undefined; | |
| 3336 | var hasher = file_writer.interface.hashed(Cache.Hasher.init("0123456789abcdef"), &buffer); | |
| 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(); | |
| 3332 | 3343 | |
| 3333 | var bin_digest: Cache.BinDigest = undefined; | |
| 3334 | hasher.final(&bin_digest); | |
| 3344 | const bin_digest: Cache.BinDigest = hasher.hasher.finalResult(); | |
| 3335 | 3345 | |
| 3336 | const sub_path = try std.fmt.allocPrint(arena, "tmp" ++ sep ++ "{s}-stdin{s}", .{ | |
| 3337 | std.fmt.fmtSliceHexLower(&bin_digest), | |
| 3338 | ext.canonicalName(target), | |
| 3346 | const sub_path = try std.fmt.allocPrint(arena, "tmp" ++ sep ++ "{x}-stdin{s}", .{ | |
| 3347 | &bin_digest, ext.canonicalName(target), | |
| 3339 | 3348 | }); |
| 3340 | 3349 | try dirs.local_cache.handle.rename(dump_path, sub_path); |
| 3341 | 3350 | |
| ... | ... | @@ -3506,7 +3515,7 @@ fn buildOutputType( |
| 3506 | 3515 | if (t.arch == target.cpu.arch and t.os == target.os.tag) { |
| 3507 | 3516 | // If there's a `glibc_min`, there's also an `os_ver`. |
| 3508 | 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 | 3519 | @tagName(t.arch), |
| 3511 | 3520 | @tagName(t.os), |
| 3512 | 3521 | t.os_ver.?, |
| ... | ... | @@ -3515,7 +3524,7 @@ fn buildOutputType( |
| 3515 | 3524 | glibc_min.minor, |
| 3516 | 3525 | }); |
| 3517 | 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 | 3528 | @tagName(t.arch), |
| 3520 | 3529 | @tagName(t.os), |
| 3521 | 3530 | os_ver, |
| ... | ... | @@ -3546,15 +3555,15 @@ fn buildOutputType( |
| 3546 | 3555 | if (show_builtin) { |
| 3547 | 3556 | const builtin_opts = comp.root_mod.getBuiltinOptions(comp.config); |
| 3548 | 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 | 3560 | switch (listen) { |
| 3552 | 3561 | .none => {}, |
| 3553 | 3562 | .stdio => { |
| 3554 | 3563 | try serve( |
| 3555 | 3564 | comp, |
| 3556 | std.io.getStdIn(), | |
| 3557 | std.io.getStdOut(), | |
| 3565 | .stdin(), | |
| 3566 | .stdout(), | |
| 3558 | 3567 | test_exec_args.items, |
| 3559 | 3568 | self_exe_path, |
| 3560 | 3569 | arg_mode, |
| ... | ... | @@ -4606,7 +4615,7 @@ fn cmdTranslateC( |
| 4606 | 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 | 4617 | defer zig_file.close(); |
| 4609 | try io.getStdOut().writeFileAll(zig_file, .{}); | |
| 4618 | try fs.File.stdout().writeFileAll(zig_file, .{}); | |
| 4610 | 4619 | return cleanExit(); |
| 4611 | 4620 | } |
| 4612 | 4621 | } |
| ... | ... | @@ -4636,7 +4645,7 @@ fn cmdInit(gpa: Allocator, arena: Allocator, args: []const []const u8) !void { |
| 4636 | 4645 | if (mem.eql(u8, arg, "-s") or mem.eql(u8, arg, "--strip")) { |
| 4637 | 4646 | strip = true; |
| 4638 | 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 | 4649 | return cleanExit(); |
| 4641 | 4650 | } else { |
| 4642 | 4651 | fatal("unrecognized parameter: '{s}'", .{arg}); |
| ... | ... | @@ -5287,7 +5296,7 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !void { |
| 5287 | 5296 | const s = fs.path.sep_str; |
| 5288 | 5297 | const tmp_sub_path = "tmp" ++ s ++ results_tmp_file_nonce; |
| 5289 | 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 | 5300 | dirs.local_cache, tmp_sub_path, @errorName(err), |
| 5292 | 5301 | }); |
| 5293 | 5302 | }; |
| ... | ... | @@ -5481,8 +5490,8 @@ fn jitCmd( |
| 5481 | 5490 | defer comp.destroy(); |
| 5482 | 5491 | |
| 5483 | 5492 | if (options.server) { |
| 5484 | var server = std.zig.Server{ | |
| 5485 | .out = std.io.getStdOut(), | |
| 5493 | var server: std.zig.Server = .{ | |
| 5494 | .out = fs.File.stdout(), | |
| 5486 | 5495 | .in = undefined, // won't be receiving messages |
| 5487 | 5496 | .receive_fifo = undefined, // won't be receiving messages |
| 5488 | 5497 | }; |
| ... | ... | @@ -6015,7 +6024,7 @@ fn cmdAstCheck( |
| 6015 | 6024 | const arg = args[i]; |
| 6016 | 6025 | if (mem.startsWith(u8, arg, "-")) { |
| 6017 | 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 | 6028 | return cleanExit(); |
| 6020 | 6029 | } else if (mem.eql(u8, arg, "-t")) { |
| 6021 | 6030 | want_output_text = true; |
| ... | ... | @@ -6046,7 +6055,7 @@ fn cmdAstCheck( |
| 6046 | 6055 | break :file fs.cwd().openFile(p, .{}) catch |err| { |
| 6047 | 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 | 6059 | defer if (zig_source_path != null) f.close(); |
| 6051 | 6060 | break :s std.zig.readSourceFileToEndAlloc(arena, f, null) catch |err| { |
| 6052 | 6061 | fatal("unable to load file '{s}' for ast-check: {s}", .{ display_path, @errorName(err) }); |
| ... | ... | @@ -6065,6 +6074,8 @@ fn cmdAstCheck( |
| 6065 | 6074 | |
| 6066 | 6075 | const tree = try Ast.parse(arena, source, mode); |
| 6067 | 6076 | |
| 6077 | var stdout_writer = fs.File.stdout().writerStreaming(&stdio_buffer); | |
| 6078 | const stdout_bw = &stdout_writer.interface; | |
| 6068 | 6079 | switch (mode) { |
| 6069 | 6080 | .zig => { |
| 6070 | 6081 | const zir = try AstGen.generate(arena, tree); |
| ... | ... | @@ -6107,31 +6118,30 @@ fn cmdAstCheck( |
| 6107 | 6118 | const extra_bytes = zir.extra.len * @sizeOf(u32); |
| 6108 | 6119 | const total_bytes = @sizeOf(Zir) + instruction_bytes + extra_bytes + |
| 6109 | 6120 | zir.string_bytes.len * @sizeOf(u8); |
| 6110 | const stdout = io.getStdOut(); | |
| 6111 | const fmtIntSizeBin = std.fmt.fmtIntSizeBin; | |
| 6112 | 6121 | // zig fmt: off |
| 6113 | try stdout.writer().print( | |
| 6114 | \\# Source bytes: {} | |
| 6115 | \\# Tokens: {} ({}) | |
| 6116 | \\# AST Nodes: {} ({}) | |
| 6117 | \\# Total ZIR bytes: {} | |
| 6118 | \\# Instructions: {d} ({}) | |
| 6122 | try stdout_bw.print( | |
| 6123 | \\# Source bytes: {Bi} | |
| 6124 | \\# Tokens: {} ({Bi}) | |
| 6125 | \\# AST Nodes: {} ({Bi}) | |
| 6126 | \\# Total ZIR bytes: {Bi} | |
| 6127 | \\# Instructions: {d} ({Bi}) | |
| 6119 | 6128 | \\# String Table Bytes: {} |
| 6120 | \\# Extra Data Items: {d} ({}) | |
| 6129 | \\# Extra Data Items: {d} ({Bi}) | |
| 6121 | 6130 | \\ |
| 6122 | 6131 | , .{ |
| 6123 | fmtIntSizeBin(source.len), | |
| 6124 | tree.tokens.len, fmtIntSizeBin(token_bytes), | |
| 6125 | tree.nodes.len, fmtIntSizeBin(tree_bytes), | |
| 6126 | fmtIntSizeBin(total_bytes), | |
| 6127 | zir.instructions.len, fmtIntSizeBin(instruction_bytes), | |
| 6128 | fmtIntSizeBin(zir.string_bytes.len), | |
| 6129 | zir.extra.len, fmtIntSizeBin(extra_bytes), | |
| 6132 | source.len, | |
| 6133 | tree.tokens.len, token_bytes, | |
| 6134 | tree.nodes.len, tree_bytes, | |
| 6135 | total_bytes, | |
| 6136 | zir.instructions.len, instruction_bytes, | |
| 6137 | zir.string_bytes.len, | |
| 6138 | zir.extra.len, extra_bytes, | |
| 6130 | 6139 | }); |
| 6131 | 6140 | // zig fmt: on |
| 6132 | 6141 | } |
| 6133 | 6142 | |
| 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(); | |
| 6135 | 6145 | |
| 6136 | 6146 | if (zir.hasCompileErrors()) { |
| 6137 | 6147 | process.exit(1); |
| ... | ... | @@ -6158,7 +6168,8 @@ fn cmdAstCheck( |
| 6158 | 6168 | fatal("-t option only available in builds of zig with debug extensions", .{}); |
| 6159 | 6169 | } |
| 6160 | 6170 | |
| 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 | 6173 | return cleanExit(); |
| 6163 | 6174 | }, |
| 6164 | 6175 | } |
| ... | ... | @@ -6186,8 +6197,7 @@ fn cmdDetectCpu(args: []const []const u8) !void { |
| 6186 | 6197 | const arg = args[i]; |
| 6187 | 6198 | if (mem.startsWith(u8, arg, "-")) { |
| 6188 | 6199 | if (mem.eql(u8, arg, "-h") or mem.eql(u8, arg, "--help")) { |
| 6189 | const stdout = io.getStdOut().writer(); | |
| 6190 | try stdout.writeAll(detect_cpu_usage); | |
| 6200 | try fs.File.stdout().writeAll(detect_cpu_usage); | |
| 6191 | 6201 | return cleanExit(); |
| 6192 | 6202 | } else if (mem.eql(u8, arg, "--llvm")) { |
| 6193 | 6203 | use_llvm = true; |
| ... | ... | @@ -6279,11 +6289,11 @@ fn detectNativeCpuWithLLVM( |
| 6279 | 6289 | } |
| 6280 | 6290 | |
| 6281 | 6291 | fn printCpu(cpu: std.Target.Cpu) !void { |
| 6282 | var bw = io.bufferedWriter(io.getStdOut().writer()); | |
| 6283 | const stdout = bw.writer(); | |
| 6292 | var stdout_writer = fs.File.stdout().writerStreaming(&stdio_buffer); | |
| 6293 | const stdout_bw = &stdout_writer.interface; | |
| 6284 | 6294 | |
| 6285 | 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 | } |
| 6288 | 6298 | |
| 6289 | 6299 | const all_features = cpu.arch.allFeaturesList(); |
| ... | ... | @@ -6292,10 +6302,10 @@ fn printCpu(cpu: std.Target.Cpu) !void { |
| 6292 | 6302 | const index: std.Target.Cpu.Feature.Set.Index = @intCast(index_usize); |
| 6293 | 6303 | const is_enabled = cpu.features.isEnabled(index); |
| 6294 | 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 | } |
| 6297 | 6307 | |
| 6298 | try bw.flush(); | |
| 6308 | try stdout_bw.flush(); | |
| 6299 | 6309 | } |
| 6300 | 6310 | |
| 6301 | 6311 | fn cmdDumpLlvmInts( |
| ... | ... | @@ -6328,16 +6338,14 @@ fn cmdDumpLlvmInts( |
| 6328 | 6338 | const dl = tm.createTargetDataLayout(); |
| 6329 | 6339 | const context = llvm.Context.create(); |
| 6330 | 6340 | |
| 6331 | var bw = io.bufferedWriter(io.getStdOut().writer()); | |
| 6332 | const stdout = bw.writer(); | |
| 6333 | ||
| 6341 | var stdout_writer = fs.File.stdout().writerStreaming(&stdio_buffer); | |
| 6342 | const stdout_bw = &stdout_writer.interface; | |
| 6334 | 6343 | for ([_]u16{ 1, 8, 16, 32, 64, 128, 256 }) |bits| { |
| 6335 | 6344 | const int_type = context.intType(bits); |
| 6336 | 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 | } |
| 6339 | ||
| 6340 | try bw.flush(); | |
| 6348 | try stdout_bw.flush(); | |
| 6341 | 6349 | |
| 6342 | 6350 | return cleanExit(); |
| 6343 | 6351 | } |
| ... | ... | @@ -6359,6 +6367,8 @@ fn cmdDumpZir( |
| 6359 | 6367 | defer f.close(); |
| 6360 | 6368 | |
| 6361 | 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; | |
| 6362 | 6372 | |
| 6363 | 6373 | { |
| 6364 | 6374 | const instruction_bytes = zir.instructions.len * |
| ... | ... | @@ -6368,25 +6378,24 @@ fn cmdDumpZir( |
| 6368 | 6378 | const extra_bytes = zir.extra.len * @sizeOf(u32); |
| 6369 | 6379 | const total_bytes = @sizeOf(Zir) + instruction_bytes + extra_bytes + |
| 6370 | 6380 | zir.string_bytes.len * @sizeOf(u8); |
| 6371 | const stdout = io.getStdOut(); | |
| 6372 | const fmtIntSizeBin = std.fmt.fmtIntSizeBin; | |
| 6373 | 6381 | // zig fmt: off |
| 6374 | try stdout.writer().print( | |
| 6375 | \\# Total ZIR bytes: {} | |
| 6376 | \\# Instructions: {d} ({}) | |
| 6377 | \\# String Table Bytes: {} | |
| 6378 | \\# Extra Data Items: {d} ({}) | |
| 6382 | try stdout_bw.print( | |
| 6383 | \\# Total ZIR bytes: {Bi} | |
| 6384 | \\# Instructions: {d} ({Bi}) | |
| 6385 | \\# String Table Bytes: {Bi} | |
| 6386 | \\# Extra Data Items: {d} ({Bi}) | |
| 6379 | 6387 | \\ |
| 6380 | 6388 | , .{ |
| 6381 | fmtIntSizeBin(total_bytes), | |
| 6382 | zir.instructions.len, fmtIntSizeBin(instruction_bytes), | |
| 6383 | fmtIntSizeBin(zir.string_bytes.len), | |
| 6384 | zir.extra.len, fmtIntSizeBin(extra_bytes), | |
| 6389 | total_bytes, | |
| 6390 | zir.instructions.len, instruction_bytes, | |
| 6391 | zir.string_bytes.len, | |
| 6392 | zir.extra.len, extra_bytes, | |
| 6385 | 6393 | }); |
| 6386 | 6394 | // zig fmt: on |
| 6387 | 6395 | } |
| 6388 | 6396 | |
| 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 | } |
| 6391 | 6400 | |
| 6392 | 6401 | /// This is only enabled for debug builds. |
| ... | ... | @@ -6444,19 +6453,19 @@ fn cmdChangelist( |
| 6444 | 6453 | var inst_map: std.AutoHashMapUnmanaged(Zir.Inst.Index, Zir.Inst.Index) = .empty; |
| 6445 | 6454 | try Zcu.mapOldZirToNew(arena, old_zir, new_zir, &inst_map); |
| 6446 | 6455 | |
| 6447 | var bw = io.bufferedWriter(io.getStdOut().writer()); | |
| 6448 | const stdout = bw.writer(); | |
| 6456 | var stdout_writer = fs.File.stdout().writerStreaming(&stdio_buffer); | |
| 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 | 6460 | var it = inst_map.iterator(); |
| 6452 | 6461 | while (it.next()) |entry| { |
| 6453 | try stdout.print(" %{d} => %{d}\n", .{ | |
| 6462 | try stdout_bw.print(" %{d} => %{d}\n", .{ | |
| 6454 | 6463 | @intFromEnum(entry.key_ptr.*), |
| 6455 | 6464 | @intFromEnum(entry.value_ptr.*), |
| 6456 | 6465 | }); |
| 6457 | 6466 | } |
| 6458 | 6467 | } |
| 6459 | try bw.flush(); | |
| 6468 | try stdout_bw.flush(); | |
| 6460 | 6469 | } |
| 6461 | 6470 | |
| 6462 | 6471 | fn eatIntPrefix(arg: []const u8, base: u8) []const u8 { |
| ... | ... | @@ -6718,13 +6727,10 @@ fn accessFrameworkPath( |
| 6718 | 6727 | |
| 6719 | 6728 | for (&[_][]const u8{ ".tbd", ".dylib", "" }) |ext| { |
| 6720 | 6729 | test_path.clearRetainingCapacity(); |
| 6721 | try test_path.writer().print("{s}" ++ sep ++ "{s}.framework" ++ sep ++ "{s}{s}", .{ | |
| 6722 | framework_dir_path, | |
| 6723 | framework_name, | |
| 6724 | framework_name, | |
| 6725 | ext, | |
| 6730 | try test_path.print("{s}" ++ sep ++ "{s}.framework" ++ sep ++ "{s}{s}", .{ | |
| 6731 | framework_dir_path, framework_name, framework_name, 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 | 6734 | fs.cwd().access(test_path.items, .{}) catch |err| switch (err) { |
| 6729 | 6735 | error.FileNotFound => continue, |
| 6730 | 6736 | else => |e| fatal("unable to search for {s} framework '{s}': {s}", .{ |
| ... | ... | @@ -6794,8 +6800,7 @@ fn cmdFetch( |
| 6794 | 6800 | const arg = args[i]; |
| 6795 | 6801 | if (mem.startsWith(u8, arg, "-")) { |
| 6796 | 6802 | if (mem.eql(u8, arg, "-h") or mem.eql(u8, arg, "--help")) { |
| 6797 | const stdout = io.getStdOut().writer(); | |
| 6798 | try stdout.writeAll(usage_fetch); | |
| 6803 | try fs.File.stdout().writeAll(usage_fetch); | |
| 6799 | 6804 | return cleanExit(); |
| 6800 | 6805 | } else if (mem.eql(u8, arg, "--global-cache-dir")) { |
| 6801 | 6806 | if (i + 1 >= args.len) fatal("expected argument after '{s}'", .{arg}); |
| ... | ... | @@ -6908,7 +6913,9 @@ fn cmdFetch( |
| 6908 | 6913 | |
| 6909 | 6914 | const name = switch (save) { |
| 6910 | 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 | 6919 | return cleanExit(); |
| 6913 | 6920 | }, |
| 6914 | 6921 | .yes, .exact => |name| name: { |
| ... | ... | @@ -6944,7 +6951,7 @@ fn cmdFetch( |
| 6944 | 6951 | var saved_path_or_url = path_or_url; |
| 6945 | 6952 | |
| 6946 | 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}); | |
| 6948 | 6955 | |
| 6949 | 6956 | var uri = try std.Uri.parse(path_or_url); |
| 6950 | 6957 | |
| ... | ... | @@ -6957,7 +6964,9 @@ fn cmdFetch( |
| 6957 | 6964 | std.log.info("resolved ref '{s}' to commit {s}", .{ target_ref, latest_commit_hex }); |
| 6958 | 6965 | |
| 6959 | 6966 | // 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 | 6970 | } else { |
| 6962 | 6971 | std.log.info("resolved to commit {s}", .{latest_commit_hex}); |
| 6963 | 6972 | } |
| ... | ... | @@ -6966,23 +6975,23 @@ fn cmdFetch( |
| 6966 | 6975 | uri.fragment = .{ .raw = latest_commit_hex }; |
| 6967 | 6976 | |
| 6968 | 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 | 6979 | .no, .exact => {}, // keep the original URL |
| 6971 | 6980 | } |
| 6972 | 6981 | } |
| 6973 | 6982 | |
| 6974 | 6983 | const new_node_init = try std.fmt.allocPrint(arena, |
| 6975 | 6984 | \\.{{ |
| 6976 | \\ .url = "{}", | |
| 6977 | \\ .hash = "{}", | |
| 6985 | \\ .url = "{f}", | |
| 6986 | \\ .hash = "{f}", | |
| 6978 | 6987 | \\ }} |
| 6979 | 6988 | , .{ |
| 6980 | std.zig.fmtEscapes(saved_path_or_url), | |
| 6981 | std.zig.fmtEscapes(package_hash_slice), | |
| 6989 | std.zig.fmtString(saved_path_or_url), | |
| 6990 | std.zig.fmtString(package_hash_slice), | |
| 6982 | 6991 | }); |
| 6983 | 6992 | |
| 6984 | const new_node_text = try std.fmt.allocPrint(arena, ".{p_} = {s},\n", .{ | |
| 6985 | std.zig.fmtId(name), new_node_init, | |
| 6993 | const new_node_text = try std.fmt.allocPrint(arena, ".{f} = {s},\n", .{ | |
| 6994 | std.zig.fmtIdPU(name), new_node_init, | |
| 6986 | 6995 | }); |
| 6987 | 6996 | |
| 6988 | 6997 | const dependencies_init = try std.fmt.allocPrint(arena, ".{{\n {s} }}", .{ |
| ... | ... | @@ -7008,13 +7017,13 @@ fn cmdFetch( |
| 7008 | 7017 | |
| 7009 | 7018 | const location_replace = try std.fmt.allocPrint( |
| 7010 | 7019 | arena, |
| 7011 | "\"{}\"", | |
| 7012 | .{std.zig.fmtEscapes(saved_path_or_url)}, | |
| 7020 | "\"{f}\"", | |
| 7021 | .{std.zig.fmtString(saved_path_or_url)}, | |
| 7013 | 7022 | ); |
| 7014 | 7023 | const hash_replace = try std.fmt.allocPrint( |
| 7015 | 7024 | arena, |
| 7016 | "\"{}\"", | |
| 7017 | .{std.zig.fmtEscapes(package_hash_slice)}, | |
| 7025 | "\"{f}\"", | |
| 7026 | .{std.zig.fmtString(package_hash_slice)}, | |
| 7018 | 7027 | ); |
| 7019 | 7028 | |
| 7020 | 7029 | warn("overwriting existing dependency named '{s}'", .{name}); |
src/print_env.zig+2-2| ... | ... | @@ -4,7 +4,7 @@ const introspect = @import("introspect.zig"); |
| 4 | 4 | const Allocator = std.mem.Allocator; |
| 5 | 5 | const fatal = std.process.fatal; |
| 6 | 6 | |
| 7 | pub fn cmdEnv(arena: Allocator, args: []const []const u8, stdout: std.fs.File.Writer) !void { | |
| 7 | pub fn cmdEnv(arena: Allocator, args: []const []const u8) !void { | |
| 8 | 8 | _ = args; |
| 9 | 9 | const cwd_path = try introspect.getResolvedCwd(arena); |
| 10 | 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 | 21 | const host = try std.zig.system.resolveTargetQuery(.{}); |
| 22 | 22 | const triple = try host.zigTriple(arena); |
| 23 | 23 | |
| 24 | var bw = std.io.bufferedWriter(stdout); | |
| 24 | var bw = std.io.bufferedWriter(std.fs.File.stdout().deprecatedWriter()); | |
| 25 | 25 | const w = bw.writer(); |
| 26 | 26 | |
| 27 | 27 | var jws = std.json.writeStream(w, .{ .whitespace = .indent_1 }); |
src/print_targets.zig+1-1| ... | ... | @@ -64,7 +64,7 @@ pub fn cmdTargets( |
| 64 | 64 | { |
| 65 | 65 | var glibc_obj = try root_obj.beginTupleField("glibc", .{}); |
| 66 | 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 | 68 | defer allocator.free(tmp); |
| 69 | 69 | try glibc_obj.field(tmp, .{}); |
| 70 | 70 | } |
src/print_value.zig+34-47| ... | ... | @@ -20,15 +20,8 @@ pub const FormatContext = struct { |
| 20 | 20 | depth: u8, |
| 21 | 21 | }; |
| 22 | 22 | |
| 23 | pub fn formatSema( | |
| 24 | ctx: FormatContext, | |
| 25 | comptime fmt: []const u8, | |
| 26 | options: std.fmt.FormatOptions, | |
| 27 | writer: anytype, | |
| 28 | ) !void { | |
| 29 | _ = options; | |
| 23 | pub fn formatSema(ctx: FormatContext, writer: *std.io.Writer) std.io.Writer.Error!void { | |
| 30 | 24 | const sema = ctx.opt_sema.?; |
| 31 | comptime std.debug.assert(fmt.len == 0); | |
| 32 | 25 | return print(ctx.val, writer, ctx.depth, ctx.pt, sema) catch |err| switch (err) { |
| 33 | 26 | error.OutOfMemory => @panic("OOM"), // We're not allowed to return this from a format function |
| 34 | 27 | error.ComptimeBreak, error.ComptimeReturn => unreachable, |
| ... | ... | @@ -37,15 +30,8 @@ pub fn formatSema( |
| 37 | 30 | }; |
| 38 | 31 | } |
| 39 | 32 | |
| 40 | pub fn format( | |
| 41 | ctx: FormatContext, | |
| 42 | comptime fmt: []const u8, | |
| 43 | options: std.fmt.FormatOptions, | |
| 44 | writer: anytype, | |
| 45 | ) !void { | |
| 46 | _ = options; | |
| 33 | pub fn format(ctx: FormatContext, writer: *std.io.Writer) std.io.Writer.Error!void { | |
| 47 | 34 | std.debug.assert(ctx.opt_sema == null); |
| 48 | comptime std.debug.assert(fmt.len == 0); | |
| 49 | 35 | return print(ctx.val, writer, ctx.depth, ctx.pt, null) catch |err| switch (err) { |
| 50 | 36 | error.OutOfMemory => @panic("OOM"), // We're not allowed to return this from a format function |
| 51 | 37 | error.ComptimeBreak, error.ComptimeReturn, error.AnalysisFail => unreachable, |
| ... | ... | @@ -55,11 +41,11 @@ pub fn format( |
| 55 | 41 | |
| 56 | 42 | pub fn print( |
| 57 | 43 | val: Value, |
| 58 | writer: anytype, | |
| 44 | writer: *std.io.Writer, | |
| 59 | 45 | level: u8, |
| 60 | 46 | pt: Zcu.PerThread, |
| 61 | 47 | opt_sema: ?*Sema, |
| 62 | ) (@TypeOf(writer).Error || Zcu.CompileError)!void { | |
| 48 | ) (std.io.Writer.Error || Zcu.CompileError)!void { | |
| 63 | 49 | const zcu = pt.zcu; |
| 64 | 50 | const ip = &zcu.intern_pool; |
| 65 | 51 | switch (ip.indexToKey(val.toIntern())) { |
| ... | ... | @@ -87,35 +73,36 @@ pub fn print( |
| 87 | 73 | else => try writer.writeAll(@tagName(simple_value)), |
| 88 | 74 | }, |
| 89 | 75 | .variable => try writer.writeAll("(variable)"), |
| 90 | .@"extern" => |e| try writer.print("(extern '{}')", .{e.name.fmt(ip)}), | |
| 91 | .func => |func| try writer.print("(function '{}')", .{ip.getNav(func.owner_nav).name.fmt(ip)}), | |
| 76 | .@"extern" => |e| try writer.print("(extern '{f}')", .{e.name.fmt(ip)}), | |
| 77 | .func => |func| try writer.print("(function '{f}')", .{ip.getNav(func.owner_nav).name.fmt(ip)}), | |
| 92 | 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 | 81 | .lazy_align => |ty| if (opt_sema != null) { |
| 95 | 82 | const a = try Type.fromInterned(ty).abiAlignmentSema(pt); |
| 96 | try writer.print("{}", .{a.toByteUnits() orelse 0}); | |
| 97 | } else try writer.print("@alignOf({})", .{Type.fromInterned(ty).fmt(pt)}), | |
| 83 | try writer.print("{d}", .{a.toByteUnits() orelse 0}); | |
| 84 | } else try writer.print("@alignOf({f})", .{Type.fromInterned(ty).fmt(pt)}), | |
| 98 | 85 | .lazy_size => |ty| if (opt_sema != null) { |
| 99 | 86 | const s = try Type.fromInterned(ty).abiSizeSema(pt); |
| 100 | try writer.print("{}", .{s}); | |
| 101 | } else try writer.print("@sizeOf({})", .{Type.fromInterned(ty).fmt(pt)}), | |
| 87 | try writer.print("{d}", .{s}); | |
| 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 | 91 | err.name.fmt(ip), |
| 105 | 92 | }), |
| 106 | 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 | 95 | err_name.fmt(ip), |
| 109 | 96 | }), |
| 110 | 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 | 100 | enum_literal.fmt(ip), |
| 114 | 101 | }), |
| 115 | 102 | .enum_tag => |enum_tag| { |
| 116 | 103 | const enum_type = ip.loadEnumType(val.typeOf(zcu).toIntern()); |
| 117 | 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 | 107 | if (level == 0) { |
| 121 | 108 | return writer.writeAll("@enumFromInt(...)"); |
| ... | ... | @@ -178,7 +165,7 @@ pub fn print( |
| 178 | 165 | } |
| 179 | 166 | if (un.tag == .none) { |
| 180 | 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 | 169 | try print(Value.fromInterned(un.val), writer, level - 1, pt, opt_sema); |
| 183 | 170 | try writer.writeAll("))"); |
| 184 | 171 | } else { |
| ... | ... | @@ -197,11 +184,11 @@ fn printAggregate( |
| 197 | 184 | val: Value, |
| 198 | 185 | aggregate: InternPool.Key.Aggregate, |
| 199 | 186 | is_ref: bool, |
| 200 | writer: anytype, | |
| 187 | writer: *std.io.Writer, | |
| 201 | 188 | level: u8, |
| 202 | 189 | pt: Zcu.PerThread, |
| 203 | 190 | opt_sema: ?*Sema, |
| 204 | ) (@TypeOf(writer).Error || Zcu.CompileError)!void { | |
| 191 | ) (std.io.Writer.Error || Zcu.CompileError)!void { | |
| 205 | 192 | if (level == 0) { |
| 206 | 193 | if (is_ref) try writer.writeByte('&'); |
| 207 | 194 | return writer.writeAll(".{ ... }"); |
| ... | ... | @@ -220,7 +207,7 @@ fn printAggregate( |
| 220 | 207 | for (0..max_len) |i| { |
| 221 | 208 | if (i != 0) try writer.writeAll(", "); |
| 222 | 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 | 211 | try print(try val.fieldValue(pt, i), writer, level - 1, pt, opt_sema); |
| 225 | 212 | } |
| 226 | 213 | try writer.writeAll(" }"); |
| ... | ... | @@ -232,7 +219,7 @@ fn printAggregate( |
| 232 | 219 | const len = ty.arrayLenIncludingSentinel(zcu); |
| 233 | 220 | if (len == 0) break :string; |
| 234 | 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 | 223 | if (!is_ref) try writer.writeAll(".*"); |
| 237 | 224 | return; |
| 238 | 225 | }, |
| ... | ... | @@ -249,7 +236,7 @@ fn printAggregate( |
| 249 | 236 | const elem_val = Value.fromInterned(aggregate.storage.values()[0]); |
| 250 | 237 | if (elem_val.isUndef(zcu)) break :one_byte_str; |
| 251 | 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 | 240 | if (!is_ref) try writer.writeAll(".*"); |
| 254 | 241 | return; |
| 255 | 242 | }, |
| ... | ... | @@ -283,11 +270,11 @@ fn printPtr( |
| 283 | 270 | ptr_val: Value, |
| 284 | 271 | /// Whether to print `derivation` as an lvalue or rvalue. If `null`, the more concise option is chosen. |
| 285 | 272 | want_kind: ?PrintPtrKind, |
| 286 | writer: anytype, | |
| 273 | writer: *std.io.Writer, | |
| 287 | 274 | level: u8, |
| 288 | 275 | pt: Zcu.PerThread, |
| 289 | 276 | opt_sema: ?*Sema, |
| 290 | ) (@TypeOf(writer).Error || Zcu.CompileError)!void { | |
| 277 | ) (std.io.Writer.Error || Zcu.CompileError)!void { | |
| 291 | 278 | const ptr = switch (pt.zcu.intern_pool.indexToKey(ptr_val.toIntern())) { |
| 292 | 279 | .undef => return writer.writeAll("undefined"), |
| 293 | 280 | .ptr => |ptr| ptr, |
| ... | ... | @@ -329,7 +316,7 @@ const PrintPtrKind = enum { lvalue, rvalue }; |
| 329 | 316 | /// Returns the root derivation, which may be ignored. |
| 330 | 317 | pub fn printPtrDerivation( |
| 331 | 318 | derivation: Value.PointerDeriveStep, |
| 332 | writer: anytype, | |
| 319 | writer: *std.io.Writer, | |
| 333 | 320 | pt: Zcu.PerThread, |
| 334 | 321 | /// Whether to print `derivation` as an lvalue or rvalue. If `null`, the more concise option is chosen. |
| 335 | 322 | /// 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 | 392 | const agg_ty = (try field.parent.ptrType(pt)).childType(zcu); |
| 406 | 393 | switch (agg_ty.zigTypeTag(zcu)) { |
| 407 | 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 | 396 | } else { |
| 410 | 397 | try writer.print("[{d}]", .{field.field_idx}); |
| 411 | 398 | }, |
| 412 | 399 | .@"union" => { |
| 413 | 400 | const tag_ty = agg_ty.unionTagTypeHypothetical(zcu); |
| 414 | 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 | 404 | .pointer => switch (field.field_idx) { |
| 418 | 405 | Value.slice_ptr_index => try writer.writeAll(".ptr"), |
| ... | ... | @@ -430,12 +417,12 @@ pub fn printPtrDerivation( |
| 430 | 417 | }, |
| 431 | 418 | |
| 432 | 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 | 421 | const root = try printPtrDerivation(oac.parent.*, writer, pt, .rvalue, root_strat, ptr_depth - 1); |
| 435 | 422 | try writer.writeAll("))"); |
| 436 | 423 | break :root root; |
| 437 | 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 | 426 | const root = try printPtrDerivation(oac.parent.*, writer, pt, .rvalue, root_strat, ptr_depth - 1); |
| 440 | 427 | try writer.print(") + {d}))", .{oac.byte_offset}); |
| 441 | 428 | break :root root; |
| ... | ... | @@ -447,22 +434,22 @@ pub fn printPtrDerivation( |
| 447 | 434 | if (root_or_null == null) switch (root_strat) { |
| 448 | 435 | .str => |x| try writer.writeAll(x), |
| 449 | 436 | .print_val => |x| switch (derivation) { |
| 450 | .int => |int| try writer.print("@as({}, @ptrFromInt(0x{x}))", .{ int.ptr_ty.fmt(pt), int.addr }), | |
| 451 | .nav_ptr => |nav| try writer.print("{}", .{ip.getNav(nav).fqn.fmt(ip)}), | |
| 437 | .int => |int| try writer.print("@as({f}, @ptrFromInt(0x{x}))", .{ int.ptr_ty.fmt(pt), int.addr }), | |
| 438 | .nav_ptr => |nav| try writer.print("{f}", .{ip.getNav(nav).fqn.fmt(ip)}), | |
| 452 | 439 | .uav_ptr => |uav| { |
| 453 | 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 | 442 | try print(Value.fromInterned(uav.val), writer, x.level - 1, pt, x.opt_sema); |
| 456 | 443 | try writer.writeByte(')'); |
| 457 | 444 | }, |
| 458 | 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 | 447 | try print(info.val, writer, x.level - 1, pt, x.opt_sema); |
| 461 | 448 | try writer.writeByte(')'); |
| 462 | 449 | }, |
| 463 | 450 | .comptime_field_ptr => |val| { |
| 464 | 451 | const ty = val.typeOf(zcu); |
| 465 | try writer.print("@as({}, ", .{ty.fmt(pt)}); | |
| 452 | try writer.print("@as({f}, ", .{ty.fmt(pt)}); | |
| 466 | 453 | try print(val, writer, x.level - 1, pt, x.opt_sema); |
| 467 | 454 | try writer.writeByte(')'); |
| 468 | 455 | }, |
src/print_zir.zig+185-195| ... | ... | @@ -9,13 +9,8 @@ const Zir = std.zig.Zir; |
| 9 | 9 | const Zcu = @import("Zcu.zig"); |
| 10 | 10 | const LazySrcLoc = Zcu.LazySrcLoc; |
| 11 | 11 | |
| 12 | /// Write human-readable, debug formatted ZIR code to a file. | |
| 13 | pub fn renderAsTextToFile( | |
| 14 | gpa: Allocator, | |
| 15 | tree: ?Ast, | |
| 16 | zir: Zir, | |
| 17 | fs_file: std.fs.File, | |
| 18 | ) !void { | |
| 12 | /// Write human-readable, debug formatted ZIR code. | |
| 13 | pub fn renderAsText(gpa: Allocator, tree: ?Ast, zir: Zir, bw: *std.io.Writer) !void { | |
| 19 | 14 | var arena = std.heap.ArenaAllocator.init(gpa); |
| 20 | 15 | defer arena.deinit(); |
| 21 | 16 | |
| ... | ... | @@ -30,16 +25,13 @@ pub fn renderAsTextToFile( |
| 30 | 25 | .recurse_blocks = true, |
| 31 | 26 | }; |
| 32 | 27 | |
| 33 | var raw_stream = std.io.bufferedWriter(fs_file.writer()); | |
| 34 | const stream = raw_stream.writer(); | |
| 35 | ||
| 36 | 28 | const main_struct_inst: Zir.Inst.Index = .main_struct_inst; |
| 37 | try stream.print("%{d} ", .{@intFromEnum(main_struct_inst)}); | |
| 38 | try writer.writeInstToStream(stream, main_struct_inst); | |
| 39 | try stream.writeAll("\n"); | |
| 29 | try bw.print("%{d} ", .{@intFromEnum(main_struct_inst)}); | |
| 30 | try writer.writeInstToStream(bw, main_struct_inst); | |
| 31 | try bw.writeAll("\n"); | |
| 40 | 32 | const imports_index = zir.extra[@intFromEnum(Zir.ExtraIndex.imports)]; |
| 41 | 33 | if (imports_index != 0) { |
| 42 | try stream.writeAll("Imports:\n"); | |
| 34 | try bw.writeAll("Imports:\n"); | |
| 43 | 35 | |
| 44 | 36 | const extra = zir.extraData(Zir.Inst.Imports, imports_index); |
| 45 | 37 | var extra_index = extra.end; |
| ... | ... | @@ -49,15 +41,13 @@ pub fn renderAsTextToFile( |
| 49 | 41 | extra_index = item.end; |
| 50 | 42 | |
| 51 | 43 | const import_path = zir.nullTerminatedString(item.data.name); |
| 52 | try stream.print(" @import(\"{}\") ", .{ | |
| 53 | std.zig.fmtEscapes(import_path), | |
| 44 | try bw.print(" @import(\"{f}\") ", .{ | |
| 45 | std.zig.fmtString(import_path), | |
| 54 | 46 | }); |
| 55 | try writer.writeSrcTokAbs(stream, item.data.token); | |
| 56 | try stream.writeAll("\n"); | |
| 47 | try writer.writeSrcTokAbs(bw, item.data.token); | |
| 48 | try bw.writeAll("\n"); | |
| 57 | 49 | } |
| 58 | 50 | } |
| 59 | ||
| 60 | try raw_stream.flush(); | |
| 61 | 51 | } |
| 62 | 52 | |
| 63 | 53 | pub fn renderInstructionContext( |
| ... | ... | @@ -67,7 +57,7 @@ pub fn renderInstructionContext( |
| 67 | 57 | scope_file: *Zcu.File, |
| 68 | 58 | parent_decl_node: Ast.Node.Index, |
| 69 | 59 | indent: u32, |
| 70 | stream: anytype, | |
| 60 | bw: *std.io.Writer, | |
| 71 | 61 | ) !void { |
| 72 | 62 | var arena = std.heap.ArenaAllocator.init(gpa); |
| 73 | 63 | defer arena.deinit(); |
| ... | ... | @@ -83,13 +73,13 @@ pub fn renderInstructionContext( |
| 83 | 73 | .recurse_blocks = true, |
| 84 | 74 | }; |
| 85 | 75 | |
| 86 | try writer.writeBody(stream, block[0..block_index]); | |
| 87 | try stream.writeByteNTimes(' ', writer.indent - 2); | |
| 88 | try stream.print("> %{d} ", .{@intFromEnum(block[block_index])}); | |
| 89 | try writer.writeInstToStream(stream, block[block_index]); | |
| 90 | try stream.writeByte('\n'); | |
| 76 | try writer.writeBody(bw, block[0..block_index]); | |
| 77 | try bw.splatByteAll(' ', writer.indent - 2); | |
| 78 | try bw.print("> %{d} ", .{@intFromEnum(block[block_index])}); | |
| 79 | try writer.writeInstToStream(bw, block[block_index]); | |
| 80 | try bw.writeByte('\n'); | |
| 91 | 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 | } |
| 95 | 85 | |
| ... | ... | @@ -99,7 +89,7 @@ pub fn renderSingleInstruction( |
| 99 | 89 | scope_file: *Zcu.File, |
| 100 | 90 | parent_decl_node: Ast.Node.Index, |
| 101 | 91 | indent: u32, |
| 102 | stream: anytype, | |
| 92 | bw: *std.io.Writer, | |
| 103 | 93 | ) !void { |
| 104 | 94 | var arena = std.heap.ArenaAllocator.init(gpa); |
| 105 | 95 | defer arena.deinit(); |
| ... | ... | @@ -115,8 +105,8 @@ pub fn renderSingleInstruction( |
| 115 | 105 | .recurse_blocks = false, |
| 116 | 106 | }; |
| 117 | 107 | |
| 118 | try stream.print("%{d} ", .{@intFromEnum(inst)}); | |
| 119 | try writer.writeInstToStream(stream, inst); | |
| 108 | try bw.print("%{d} ", .{@intFromEnum(inst)}); | |
| 109 | try writer.writeInstToStream(bw, inst); | |
| 120 | 110 | } |
| 121 | 111 | |
| 122 | 112 | const Writer = struct { |
| ... | ... | @@ -186,11 +176,13 @@ const Writer = struct { |
| 186 | 176 | } |
| 187 | 177 | } = .{}, |
| 188 | 178 | |
| 179 | const Error = std.io.Writer.Error || Allocator.Error; | |
| 180 | ||
| 189 | 181 | fn writeInstToStream( |
| 190 | 182 | self: *Writer, |
| 191 | stream: anytype, | |
| 183 | stream: *std.io.Writer, | |
| 192 | 184 | inst: Zir.Inst.Index, |
| 193 | ) (@TypeOf(stream).Error || error{OutOfMemory})!void { | |
| 185 | ) Error!void { | |
| 194 | 186 | const tags = self.code.instructions.items(.tag); |
| 195 | 187 | const tag = tags[@intFromEnum(inst)]; |
| 196 | 188 | try stream.print("= {s}(", .{@tagName(tags[@intFromEnum(inst)])}); |
| ... | ... | @@ -516,7 +508,7 @@ const Writer = struct { |
| 516 | 508 | } |
| 517 | 509 | } |
| 518 | 510 | |
| 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 | 512 | const extended = self.code.instructions.items(.data)[@intFromEnum(inst)].extended; |
| 521 | 513 | try stream.print("{s}(", .{@tagName(extended.opcode)}); |
| 522 | 514 | switch (extended.opcode) { |
| ... | ... | @@ -623,13 +615,13 @@ const Writer = struct { |
| 623 | 615 | } |
| 624 | 616 | } |
| 625 | 617 | |
| 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 | 619 | try stream.writeAll(")) "); |
| 628 | 620 | const src_node: Ast.Node.Offset = @enumFromInt(@as(i32, @bitCast(extended.operand))); |
| 629 | 621 | try self.writeSrcNode(stream, src_node); |
| 630 | 622 | } |
| 631 | 623 | |
| 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 | 625 | const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].bin; |
| 634 | 626 | try self.writeInstRef(stream, inst_data.lhs); |
| 635 | 627 | try stream.print(", {d})", .{@intFromEnum(inst_data.rhs)}); |
| ... | ... | @@ -637,9 +629,9 @@ const Writer = struct { |
| 637 | 629 | |
| 638 | 630 | fn writeUnNode( |
| 639 | 631 | self: *Writer, |
| 640 | stream: anytype, | |
| 632 | stream: *std.io.Writer, | |
| 641 | 633 | inst: Zir.Inst.Index, |
| 642 | ) (@TypeOf(stream).Error || error{OutOfMemory})!void { | |
| 634 | ) Error!void { | |
| 643 | 635 | const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].un_node; |
| 644 | 636 | try self.writeInstRef(stream, inst_data.operand); |
| 645 | 637 | try stream.writeAll(") "); |
| ... | ... | @@ -648,9 +640,9 @@ const Writer = struct { |
| 648 | 640 | |
| 649 | 641 | fn writeUnTok( |
| 650 | 642 | self: *Writer, |
| 651 | stream: anytype, | |
| 643 | stream: *std.io.Writer, | |
| 652 | 644 | inst: Zir.Inst.Index, |
| 653 | ) (@TypeOf(stream).Error || error{OutOfMemory})!void { | |
| 645 | ) Error!void { | |
| 654 | 646 | const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].un_tok; |
| 655 | 647 | try self.writeInstRef(stream, inst_data.operand); |
| 656 | 648 | try stream.writeAll(") "); |
| ... | ... | @@ -659,9 +651,9 @@ const Writer = struct { |
| 659 | 651 | |
| 660 | 652 | fn writeValidateDestructure( |
| 661 | 653 | self: *Writer, |
| 662 | stream: anytype, | |
| 654 | stream: *std.io.Writer, | |
| 663 | 655 | inst: Zir.Inst.Index, |
| 664 | ) (@TypeOf(stream).Error || error{OutOfMemory})!void { | |
| 656 | ) Error!void { | |
| 665 | 657 | const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; |
| 666 | 658 | const extra = self.code.extraData(Zir.Inst.ValidateDestructure, inst_data.payload_index).data; |
| 667 | 659 | try self.writeInstRef(stream, extra.operand); |
| ... | ... | @@ -673,9 +665,9 @@ const Writer = struct { |
| 673 | 665 | |
| 674 | 666 | fn writeValidateArrayInitTy( |
| 675 | 667 | self: *Writer, |
| 676 | stream: anytype, | |
| 668 | stream: *std.io.Writer, | |
| 677 | 669 | inst: Zir.Inst.Index, |
| 678 | ) (@TypeOf(stream).Error || error{OutOfMemory})!void { | |
| 670 | ) Error!void { | |
| 679 | 671 | const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; |
| 680 | 672 | const extra = self.code.extraData(Zir.Inst.ArrayInit, inst_data.payload_index).data; |
| 681 | 673 | try self.writeInstRef(stream, extra.ty); |
| ... | ... | @@ -685,9 +677,9 @@ const Writer = struct { |
| 685 | 677 | |
| 686 | 678 | fn writeArrayTypeSentinel( |
| 687 | 679 | self: *Writer, |
| 688 | stream: anytype, | |
| 680 | stream: *std.io.Writer, | |
| 689 | 681 | inst: Zir.Inst.Index, |
| 690 | ) (@TypeOf(stream).Error || error{OutOfMemory})!void { | |
| 682 | ) Error!void { | |
| 691 | 683 | const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; |
| 692 | 684 | const extra = self.code.extraData(Zir.Inst.ArrayTypeSentinel, inst_data.payload_index).data; |
| 693 | 685 | try self.writeInstRef(stream, extra.len); |
| ... | ... | @@ -701,9 +693,9 @@ const Writer = struct { |
| 701 | 693 | |
| 702 | 694 | fn writePtrType( |
| 703 | 695 | self: *Writer, |
| 704 | stream: anytype, | |
| 696 | stream: *std.io.Writer, | |
| 705 | 697 | inst: Zir.Inst.Index, |
| 706 | ) (@TypeOf(stream).Error || error{OutOfMemory})!void { | |
| 698 | ) Error!void { | |
| 707 | 699 | const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].ptr_type; |
| 708 | 700 | const str_allowzero = if (inst_data.flags.is_allowzero) "allowzero, " else ""; |
| 709 | 701 | const str_const = if (!inst_data.flags.is_mutable) "const, " else ""; |
| ... | ... | @@ -744,12 +736,12 @@ const Writer = struct { |
| 744 | 736 | try self.writeSrcNode(stream, extra.data.src_node); |
| 745 | 737 | } |
| 746 | 738 | |
| 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 | 740 | const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].int; |
| 749 | 741 | try stream.print("{d})", .{inst_data}); |
| 750 | 742 | } |
| 751 | 743 | |
| 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 | 745 | const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].str; |
| 754 | 746 | const byte_count = inst_data.len * @sizeOf(std.math.big.Limb); |
| 755 | 747 | const limb_bytes = self.code.string_bytes[@intFromEnum(inst_data.start)..][0..byte_count]; |
| ... | ... | @@ -768,12 +760,12 @@ const Writer = struct { |
| 768 | 760 | try stream.print("{s})", .{as_string}); |
| 769 | 761 | } |
| 770 | 762 | |
| 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 | 764 | const number = self.code.instructions.items(.data)[@intFromEnum(inst)].float; |
| 773 | 765 | try stream.print("{d})", .{number}); |
| 774 | 766 | } |
| 775 | 767 | |
| 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 | 769 | const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; |
| 778 | 770 | const extra = self.code.extraData(Zir.Inst.Float128, inst_data.payload_index).data; |
| 779 | 771 | const number = extra.get(); |
| ... | ... | @@ -784,15 +776,15 @@ const Writer = struct { |
| 784 | 776 | |
| 785 | 777 | fn writeStr( |
| 786 | 778 | self: *Writer, |
| 787 | stream: anytype, | |
| 779 | stream: *std.io.Writer, | |
| 788 | 780 | inst: Zir.Inst.Index, |
| 789 | ) (@TypeOf(stream).Error || error{OutOfMemory})!void { | |
| 781 | ) Error!void { | |
| 790 | 782 | const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].str; |
| 791 | 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 | } |
| 794 | 786 | |
| 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 | 788 | const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; |
| 797 | 789 | const extra = self.code.extraData(Zir.Inst.SliceStart, inst_data.payload_index).data; |
| 798 | 790 | try self.writeInstRef(stream, extra.lhs); |
| ... | ... | @@ -802,7 +794,7 @@ const Writer = struct { |
| 802 | 794 | try self.writeSrcNode(stream, inst_data.src_node); |
| 803 | 795 | } |
| 804 | 796 | |
| 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 | 798 | const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; |
| 807 | 799 | const extra = self.code.extraData(Zir.Inst.SliceEnd, inst_data.payload_index).data; |
| 808 | 800 | try self.writeInstRef(stream, extra.lhs); |
| ... | ... | @@ -814,7 +806,7 @@ const Writer = struct { |
| 814 | 806 | try self.writeSrcNode(stream, inst_data.src_node); |
| 815 | 807 | } |
| 816 | 808 | |
| 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 | 810 | const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; |
| 819 | 811 | const extra = self.code.extraData(Zir.Inst.SliceSentinel, inst_data.payload_index).data; |
| 820 | 812 | try self.writeInstRef(stream, extra.lhs); |
| ... | ... | @@ -828,7 +820,7 @@ const Writer = struct { |
| 828 | 820 | try self.writeSrcNode(stream, inst_data.src_node); |
| 829 | 821 | } |
| 830 | 822 | |
| 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 | 824 | const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; |
| 833 | 825 | const extra = self.code.extraData(Zir.Inst.SliceLength, inst_data.payload_index).data; |
| 834 | 826 | try self.writeInstRef(stream, extra.lhs); |
| ... | ... | @@ -844,7 +836,7 @@ const Writer = struct { |
| 844 | 836 | try self.writeSrcNode(stream, inst_data.src_node); |
| 845 | 837 | } |
| 846 | 838 | |
| 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 | 840 | const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; |
| 849 | 841 | const extra = self.code.extraData(Zir.Inst.UnionInit, inst_data.payload_index).data; |
| 850 | 842 | try self.writeInstRef(stream, extra.union_type); |
| ... | ... | @@ -856,7 +848,7 @@ const Writer = struct { |
| 856 | 848 | try self.writeSrcNode(stream, inst_data.src_node); |
| 857 | 849 | } |
| 858 | 850 | |
| 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 | 852 | const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; |
| 861 | 853 | const extra = self.code.extraData(Zir.Inst.Shuffle, inst_data.payload_index).data; |
| 862 | 854 | try self.writeInstRef(stream, extra.elem_type); |
| ... | ... | @@ -870,7 +862,7 @@ const Writer = struct { |
| 870 | 862 | try self.writeSrcNode(stream, inst_data.src_node); |
| 871 | 863 | } |
| 872 | 864 | |
| 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 | 866 | const extra = self.code.extraData(Zir.Inst.Select, extended.operand).data; |
| 875 | 867 | try self.writeInstRef(stream, extra.elem_type); |
| 876 | 868 | try stream.writeAll(", "); |
| ... | ... | @@ -883,7 +875,7 @@ const Writer = struct { |
| 883 | 875 | try self.writeSrcNode(stream, extra.node); |
| 884 | 876 | } |
| 885 | 877 | |
| 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 | 879 | const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; |
| 888 | 880 | const extra = self.code.extraData(Zir.Inst.MulAdd, inst_data.payload_index).data; |
| 889 | 881 | try self.writeInstRef(stream, extra.mulend1); |
| ... | ... | @@ -895,7 +887,7 @@ const Writer = struct { |
| 895 | 887 | try self.writeSrcNode(stream, inst_data.src_node); |
| 896 | 888 | } |
| 897 | 889 | |
| 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 | 891 | const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; |
| 900 | 892 | const extra = self.code.extraData(Zir.Inst.BuiltinCall, inst_data.payload_index).data; |
| 901 | 893 | |
| ... | ... | @@ -911,7 +903,7 @@ const Writer = struct { |
| 911 | 903 | try self.writeSrcNode(stream, inst_data.src_node); |
| 912 | 904 | } |
| 913 | 905 | |
| 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 | 907 | const extra = self.code.extraData(Zir.Inst.FieldParentPtr, extended.operand).data; |
| 916 | 908 | const FlagsInt = @typeInfo(Zir.Inst.FullPtrCastFlags).@"struct".backing_integer.?; |
| 917 | 909 | const flags: Zir.Inst.FullPtrCastFlags = @bitCast(@as(FlagsInt, @truncate(extended.small))); |
| ... | ... | @@ -928,12 +920,12 @@ const Writer = struct { |
| 928 | 920 | try self.writeSrcNode(stream, extra.src_node); |
| 929 | 921 | } |
| 930 | 922 | |
| 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 | 924 | const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_tok; |
| 933 | 925 | const extra = self.code.extraData(Zir.Inst.Param, inst_data.payload_index); |
| 934 | 926 | const body = self.code.bodySlice(extra.end, extra.data.type.body_len); |
| 935 | try stream.print("\"{}\", ", .{ | |
| 936 | std.zig.fmtEscapes(self.code.nullTerminatedString(extra.data.name)), | |
| 927 | try stream.print("\"{f}\", ", .{ | |
| 928 | std.zig.fmtString(self.code.nullTerminatedString(extra.data.name)), | |
| 937 | 929 | }); |
| 938 | 930 | |
| 939 | 931 | if (extra.data.type.is_generic) try stream.writeAll("[generic] "); |
| ... | ... | @@ -943,7 +935,7 @@ const Writer = struct { |
| 943 | 935 | try self.writeSrcTok(stream, inst_data.src_tok); |
| 944 | 936 | } |
| 945 | 937 | |
| 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 | 939 | const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; |
| 948 | 940 | const extra = self.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; |
| 949 | 941 | try self.writeInstRef(stream, extra.lhs); |
| ... | ... | @@ -953,7 +945,7 @@ const Writer = struct { |
| 953 | 945 | try self.writeSrcNode(stream, inst_data.src_node); |
| 954 | 946 | } |
| 955 | 947 | |
| 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 | 949 | const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; |
| 958 | 950 | const extra = self.code.extraData(Zir.Inst.MultiOp, inst_data.payload_index); |
| 959 | 951 | const args = self.code.refSlice(extra.end, extra.data.operands_len); |
| ... | ... | @@ -966,7 +958,7 @@ const Writer = struct { |
| 966 | 958 | try self.writeSrcNode(stream, inst_data.src_node); |
| 967 | 959 | } |
| 968 | 960 | |
| 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 | 962 | const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; |
| 971 | 963 | const extra = self.code.extraData(Zir.Inst.ArrayMul, inst_data.payload_index).data; |
| 972 | 964 | try self.writeInstRef(stream, extra.res_ty); |
| ... | ... | @@ -978,13 +970,13 @@ const Writer = struct { |
| 978 | 970 | try self.writeSrcNode(stream, inst_data.src_node); |
| 979 | 971 | } |
| 980 | 972 | |
| 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 | 974 | const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].elem_val_imm; |
| 983 | 975 | try self.writeInstRef(stream, inst_data.operand); |
| 984 | 976 | try stream.print(", {d})", .{inst_data.idx}); |
| 985 | 977 | } |
| 986 | 978 | |
| 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 | 980 | const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; |
| 989 | 981 | const extra = self.code.extraData(Zir.Inst.ElemPtrImm, inst_data.payload_index).data; |
| 990 | 982 | |
| ... | ... | @@ -993,7 +985,7 @@ const Writer = struct { |
| 993 | 985 | try self.writeSrcNode(stream, inst_data.src_node); |
| 994 | 986 | } |
| 995 | 987 | |
| 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 | 989 | const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; |
| 998 | 990 | const extra = self.code.extraData(Zir.Inst.Export, inst_data.payload_index).data; |
| 999 | 991 | |
| ... | ... | @@ -1004,7 +996,7 @@ const Writer = struct { |
| 1004 | 996 | try self.writeSrcNode(stream, inst_data.src_node); |
| 1005 | 997 | } |
| 1006 | 998 | |
| 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 | 1000 | const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; |
| 1009 | 1001 | const extra = self.code.extraData(Zir.Inst.ArrayInitRefTy, inst_data.payload_index).data; |
| 1010 | 1002 | |
| ... | ... | @@ -1014,7 +1006,7 @@ const Writer = struct { |
| 1014 | 1006 | try self.writeSrcNode(stream, inst_data.src_node); |
| 1015 | 1007 | } |
| 1016 | 1008 | |
| 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 | 1010 | const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; |
| 1019 | 1011 | const extra = self.code.extraData(Zir.Inst.StructInit, inst_data.payload_index); |
| 1020 | 1012 | var field_i: u32 = 0; |
| ... | ... | @@ -1038,7 +1030,7 @@ const Writer = struct { |
| 1038 | 1030 | try self.writeSrcNode(stream, inst_data.src_node); |
| 1039 | 1031 | } |
| 1040 | 1032 | |
| 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 | 1034 | const extra = self.code.extraData(Zir.Inst.Cmpxchg, extended.operand).data; |
| 1043 | 1035 | |
| 1044 | 1036 | try self.writeInstRef(stream, extra.ptr); |
| ... | ... | @@ -1054,7 +1046,7 @@ const Writer = struct { |
| 1054 | 1046 | try self.writeSrcNode(stream, extra.node); |
| 1055 | 1047 | } |
| 1056 | 1048 | |
| 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 | 1050 | const FlagsInt = @typeInfo(Zir.Inst.FullPtrCastFlags).@"struct".backing_integer.?; |
| 1059 | 1051 | const flags: Zir.Inst.FullPtrCastFlags = @bitCast(@as(FlagsInt, @truncate(extended.small))); |
| 1060 | 1052 | const extra = self.code.extraData(Zir.Inst.BinNode, extended.operand).data; |
| ... | ... | @@ -1070,7 +1062,7 @@ const Writer = struct { |
| 1070 | 1062 | try self.writeSrcNode(stream, extra.node); |
| 1071 | 1063 | } |
| 1072 | 1064 | |
| 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 | 1066 | const FlagsInt = @typeInfo(Zir.Inst.FullPtrCastFlags).@"struct".backing_integer.?; |
| 1075 | 1067 | const flags: Zir.Inst.FullPtrCastFlags = @bitCast(@as(FlagsInt, @truncate(extended.small))); |
| 1076 | 1068 | const extra = self.code.extraData(Zir.Inst.UnNode, extended.operand).data; |
| ... | ... | @@ -1081,7 +1073,7 @@ const Writer = struct { |
| 1081 | 1073 | try self.writeSrcNode(stream, extra.node); |
| 1082 | 1074 | } |
| 1083 | 1075 | |
| 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 | 1077 | const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; |
| 1086 | 1078 | const extra = self.code.extraData(Zir.Inst.AtomicLoad, inst_data.payload_index).data; |
| 1087 | 1079 | |
| ... | ... | @@ -1094,7 +1086,7 @@ const Writer = struct { |
| 1094 | 1086 | try self.writeSrcNode(stream, inst_data.src_node); |
| 1095 | 1087 | } |
| 1096 | 1088 | |
| 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 | 1090 | const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; |
| 1099 | 1091 | const extra = self.code.extraData(Zir.Inst.AtomicStore, inst_data.payload_index).data; |
| 1100 | 1092 | |
| ... | ... | @@ -1107,7 +1099,7 @@ const Writer = struct { |
| 1107 | 1099 | try self.writeSrcNode(stream, inst_data.src_node); |
| 1108 | 1100 | } |
| 1109 | 1101 | |
| 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 | 1103 | const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; |
| 1112 | 1104 | const extra = self.code.extraData(Zir.Inst.AtomicRmw, inst_data.payload_index).data; |
| 1113 | 1105 | |
| ... | ... | @@ -1122,7 +1114,7 @@ const Writer = struct { |
| 1122 | 1114 | try self.writeSrcNode(stream, inst_data.src_node); |
| 1123 | 1115 | } |
| 1124 | 1116 | |
| 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 | 1118 | const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; |
| 1127 | 1119 | const extra = self.code.extraData(Zir.Inst.StructInitAnon, inst_data.payload_index); |
| 1128 | 1120 | var field_i: u32 = 0; |
| ... | ... | @@ -1143,7 +1135,7 @@ const Writer = struct { |
| 1143 | 1135 | try self.writeSrcNode(stream, inst_data.src_node); |
| 1144 | 1136 | } |
| 1145 | 1137 | |
| 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 | 1139 | const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; |
| 1148 | 1140 | const extra = self.code.extraData(Zir.Inst.FieldType, inst_data.payload_index).data; |
| 1149 | 1141 | try self.writeInstRef(stream, extra.container_type); |
| ... | ... | @@ -1152,7 +1144,7 @@ const Writer = struct { |
| 1152 | 1144 | try self.writeSrcNode(stream, inst_data.src_node); |
| 1153 | 1145 | } |
| 1154 | 1146 | |
| 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 | 1148 | const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; |
| 1157 | 1149 | const extra = self.code.extraData(Zir.Inst.FieldTypeRef, inst_data.payload_index).data; |
| 1158 | 1150 | try self.writeInstRef(stream, extra.container_type); |
| ... | ... | @@ -1162,7 +1154,7 @@ const Writer = struct { |
| 1162 | 1154 | try self.writeSrcNode(stream, inst_data.src_node); |
| 1163 | 1155 | } |
| 1164 | 1156 | |
| 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 | 1158 | const extra = self.code.extraData(Zir.Inst.NodeMultiOp, extended.operand); |
| 1167 | 1159 | const operands = self.code.refSlice(extra.end, extended.small); |
| 1168 | 1160 | |
| ... | ... | @@ -1176,9 +1168,9 @@ const Writer = struct { |
| 1176 | 1168 | |
| 1177 | 1169 | fn writeInstNode( |
| 1178 | 1170 | self: *Writer, |
| 1179 | stream: anytype, | |
| 1171 | stream: *std.io.Writer, | |
| 1180 | 1172 | inst: Zir.Inst.Index, |
| 1181 | ) (@TypeOf(stream).Error || error{OutOfMemory})!void { | |
| 1173 | ) Error!void { | |
| 1182 | 1174 | const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].inst_node; |
| 1183 | 1175 | try self.writeInstIndex(stream, inst_data.inst); |
| 1184 | 1176 | try stream.writeAll(") "); |
| ... | ... | @@ -1187,7 +1179,7 @@ const Writer = struct { |
| 1187 | 1179 | |
| 1188 | 1180 | fn writeAsm( |
| 1189 | 1181 | self: *Writer, |
| 1190 | stream: anytype, | |
| 1182 | stream: *std.io.Writer, | |
| 1191 | 1183 | extended: Zir.Inst.Extended.InstData, |
| 1192 | 1184 | tmpl_is_expr: bool, |
| 1193 | 1185 | ) !void { |
| ... | ... | @@ -1203,7 +1195,7 @@ const Writer = struct { |
| 1203 | 1195 | try stream.writeAll(", "); |
| 1204 | 1196 | } else { |
| 1205 | 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 | 1200 | try stream.writeAll(", "); |
| 1209 | 1201 | |
| ... | ... | @@ -1220,8 +1212,8 @@ const Writer = struct { |
| 1220 | 1212 | |
| 1221 | 1213 | const name = self.code.nullTerminatedString(output.data.name); |
| 1222 | 1214 | const constraint = self.code.nullTerminatedString(output.data.constraint); |
| 1223 | try stream.print("output({p}, \"{}\", ", .{ | |
| 1224 | std.zig.fmtId(name), std.zig.fmtEscapes(constraint), | |
| 1215 | try stream.print("output({f}, \"{f}\", ", .{ | |
| 1216 | std.zig.fmtIdP(name), std.zig.fmtString(constraint), | |
| 1225 | 1217 | }); |
| 1226 | 1218 | try self.writeFlag(stream, "->", is_type); |
| 1227 | 1219 | try self.writeInstRef(stream, output.data.operand); |
| ... | ... | @@ -1239,8 +1231,8 @@ const Writer = struct { |
| 1239 | 1231 | |
| 1240 | 1232 | const name = self.code.nullTerminatedString(input.data.name); |
| 1241 | 1233 | const constraint = self.code.nullTerminatedString(input.data.constraint); |
| 1242 | try stream.print("input({p}, \"{}\", ", .{ | |
| 1243 | std.zig.fmtId(name), std.zig.fmtEscapes(constraint), | |
| 1234 | try stream.print("input({f}, \"{f}\", ", .{ | |
| 1235 | std.zig.fmtIdP(name), std.zig.fmtString(constraint), | |
| 1244 | 1236 | }); |
| 1245 | 1237 | try self.writeInstRef(stream, input.data.operand); |
| 1246 | 1238 | try stream.writeAll(")"); |
| ... | ... | @@ -1255,7 +1247,7 @@ const Writer = struct { |
| 1255 | 1247 | const str_index = self.code.extra[extra_i]; |
| 1256 | 1248 | extra_i += 1; |
| 1257 | 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 | 1251 | if (i + 1 < clobbers_len) { |
| 1260 | 1252 | try stream.writeAll(", "); |
| 1261 | 1253 | } |
| ... | ... | @@ -1265,7 +1257,7 @@ const Writer = struct { |
| 1265 | 1257 | try self.writeSrcNode(stream, extra.data.src_node); |
| 1266 | 1258 | } |
| 1267 | 1259 | |
| 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 | 1261 | const extra = self.code.extraData(Zir.Inst.BinNode, extended.operand).data; |
| 1270 | 1262 | |
| 1271 | 1263 | try self.writeInstRef(stream, extra.lhs); |
| ... | ... | @@ -1277,7 +1269,7 @@ const Writer = struct { |
| 1277 | 1269 | |
| 1278 | 1270 | fn writeCall( |
| 1279 | 1271 | self: *Writer, |
| 1280 | stream: anytype, | |
| 1272 | stream: *std.io.Writer, | |
| 1281 | 1273 | inst: Zir.Inst.Index, |
| 1282 | 1274 | comptime kind: enum { direct, field }, |
| 1283 | 1275 | ) !void { |
| ... | ... | @@ -1299,7 +1291,7 @@ const Writer = struct { |
| 1299 | 1291 | .field => { |
| 1300 | 1292 | const field_name = self.code.nullTerminatedString(extra.data.field_name_start); |
| 1301 | 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 | 1297 | try stream.writeAll(", ["); |
| ... | ... | @@ -1311,7 +1303,7 @@ const Writer = struct { |
| 1311 | 1303 | var i: usize = 0; |
| 1312 | 1304 | var arg_start: u32 = args_len; |
| 1313 | 1305 | while (i < args_len) : (i += 1) { |
| 1314 | try stream.writeByteNTimes(' ', self.indent); | |
| 1306 | try stream.splatByteAll(' ', self.indent); | |
| 1315 | 1307 | const arg_end = self.code.extra[extra.end + i]; |
| 1316 | 1308 | defer arg_start = arg_end; |
| 1317 | 1309 | const arg_body = body[arg_start..arg_end]; |
| ... | ... | @@ -1321,14 +1313,14 @@ const Writer = struct { |
| 1321 | 1313 | } |
| 1322 | 1314 | self.indent -= 2; |
| 1323 | 1315 | if (args_len != 0) { |
| 1324 | try stream.writeByteNTimes(' ', self.indent); | |
| 1316 | try stream.splatByteAll(' ', self.indent); | |
| 1325 | 1317 | } |
| 1326 | 1318 | |
| 1327 | 1319 | try stream.writeAll("]) "); |
| 1328 | 1320 | try self.writeSrcNode(stream, inst_data.src_node); |
| 1329 | 1321 | } |
| 1330 | 1322 | |
| 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 | 1324 | const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; |
| 1333 | 1325 | const extra = self.code.extraData(Zir.Inst.Block, inst_data.payload_index); |
| 1334 | 1326 | const body = self.code.bodySlice(extra.end, extra.data.body_len); |
| ... | ... | @@ -1337,7 +1329,7 @@ const Writer = struct { |
| 1337 | 1329 | try self.writeSrcNode(stream, inst_data.src_node); |
| 1338 | 1330 | } |
| 1339 | 1331 | |
| 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 | 1333 | const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; |
| 1342 | 1334 | const extra = self.code.extraData(Zir.Inst.BlockComptime, inst_data.payload_index); |
| 1343 | 1335 | const body = self.code.bodySlice(extra.end, extra.data.body_len); |
| ... | ... | @@ -1347,7 +1339,7 @@ const Writer = struct { |
| 1347 | 1339 | try self.writeSrcNode(stream, inst_data.src_node); |
| 1348 | 1340 | } |
| 1349 | 1341 | |
| 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 | 1343 | const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; |
| 1352 | 1344 | const extra = self.code.extraData(Zir.Inst.CondBr, inst_data.payload_index); |
| 1353 | 1345 | const then_body = self.code.bodySlice(extra.end, extra.data.then_body_len); |
| ... | ... | @@ -1361,7 +1353,7 @@ const Writer = struct { |
| 1361 | 1353 | try self.writeSrcNode(stream, inst_data.src_node); |
| 1362 | 1354 | } |
| 1363 | 1355 | |
| 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 | 1357 | const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; |
| 1366 | 1358 | const extra = self.code.extraData(Zir.Inst.Try, inst_data.payload_index); |
| 1367 | 1359 | const body = self.code.bodySlice(extra.end, extra.data.body_len); |
| ... | ... | @@ -1372,7 +1364,7 @@ const Writer = struct { |
| 1372 | 1364 | try self.writeSrcNode(stream, inst_data.src_node); |
| 1373 | 1365 | } |
| 1374 | 1366 | |
| 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 | 1368 | const small: Zir.Inst.StructDecl.Small = @bitCast(extended.small); |
| 1377 | 1369 | |
| 1378 | 1370 | const extra = self.code.extraData(Zir.Inst.StructDecl, extended.operand); |
| ... | ... | @@ -1388,7 +1380,7 @@ const Writer = struct { |
| 1388 | 1380 | extra.data.fields_hash_3, |
| 1389 | 1381 | }); |
| 1390 | 1382 | |
| 1391 | try stream.print("hash({}) ", .{std.fmt.fmtSliceHexLower(&fields_hash)}); | |
| 1383 | try stream.print("hash({x}) ", .{&fields_hash}); | |
| 1392 | 1384 | |
| 1393 | 1385 | var extra_index: usize = extra.end; |
| 1394 | 1386 | |
| ... | ... | @@ -1446,7 +1438,7 @@ const Writer = struct { |
| 1446 | 1438 | try self.writeBody(stream, self.code.bodySlice(extra_index, decls_len)); |
| 1447 | 1439 | self.indent -= 2; |
| 1448 | 1440 | extra_index += decls_len; |
| 1449 | try stream.writeByteNTimes(' ', self.indent); | |
| 1441 | try stream.splatByteAll(' ', self.indent); | |
| 1450 | 1442 | try stream.writeAll("}, "); |
| 1451 | 1443 | } |
| 1452 | 1444 | |
| ... | ... | @@ -1515,11 +1507,11 @@ const Writer = struct { |
| 1515 | 1507 | self.indent += 2; |
| 1516 | 1508 | |
| 1517 | 1509 | for (fields, 0..) |field, i| { |
| 1518 | try stream.writeByteNTimes(' ', self.indent); | |
| 1510 | try stream.splatByteAll(' ', self.indent); | |
| 1519 | 1511 | try self.writeFlag(stream, "comptime ", field.is_comptime); |
| 1520 | 1512 | if (field.name != .empty) { |
| 1521 | 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 | 1515 | } else { |
| 1524 | 1516 | try stream.print("@\"{d}\": ", .{i}); |
| 1525 | 1517 | } |
| ... | ... | @@ -1558,13 +1550,13 @@ const Writer = struct { |
| 1558 | 1550 | } |
| 1559 | 1551 | |
| 1560 | 1552 | self.indent -= 2; |
| 1561 | try stream.writeByteNTimes(' ', self.indent); | |
| 1553 | try stream.splatByteAll(' ', self.indent); | |
| 1562 | 1554 | try stream.writeAll("}) "); |
| 1563 | 1555 | } |
| 1564 | 1556 | try self.writeSrcNode(stream, .zero); |
| 1565 | 1557 | } |
| 1566 | 1558 | |
| 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 | 1560 | const small = @as(Zir.Inst.UnionDecl.Small, @bitCast(extended.small)); |
| 1569 | 1561 | |
| 1570 | 1562 | const extra = self.code.extraData(Zir.Inst.UnionDecl, extended.operand); |
| ... | ... | @@ -1580,7 +1572,7 @@ const Writer = struct { |
| 1580 | 1572 | extra.data.fields_hash_3, |
| 1581 | 1573 | }); |
| 1582 | 1574 | |
| 1583 | try stream.print("hash({}) ", .{std.fmt.fmtSliceHexLower(&fields_hash)}); | |
| 1575 | try stream.print("hash({x}) ", .{&fields_hash}); | |
| 1584 | 1576 | |
| 1585 | 1577 | var extra_index: usize = extra.end; |
| 1586 | 1578 | |
| ... | ... | @@ -1630,7 +1622,7 @@ const Writer = struct { |
| 1630 | 1622 | try self.writeBody(stream, self.code.bodySlice(extra_index, decls_len)); |
| 1631 | 1623 | self.indent -= 2; |
| 1632 | 1624 | extra_index += decls_len; |
| 1633 | try stream.writeByteNTimes(' ', self.indent); | |
| 1625 | try stream.splatByteAll(' ', self.indent); | |
| 1634 | 1626 | try stream.writeAll("}"); |
| 1635 | 1627 | } |
| 1636 | 1628 | |
| ... | ... | @@ -1681,8 +1673,8 @@ const Writer = struct { |
| 1681 | 1673 | const field_name = self.code.nullTerminatedString(field_name_index); |
| 1682 | 1674 | extra_index += 1; |
| 1683 | 1675 | |
| 1684 | try stream.writeByteNTimes(' ', self.indent); | |
| 1685 | try stream.print("{p}", .{std.zig.fmtId(field_name)}); | |
| 1676 | try stream.splatByteAll(' ', self.indent); | |
| 1677 | try stream.print("{f}", .{std.zig.fmtIdP(field_name)}); | |
| 1686 | 1678 | |
| 1687 | 1679 | if (has_type) { |
| 1688 | 1680 | const field_type = @as(Zir.Inst.Ref, @enumFromInt(self.code.extra[extra_index])); |
| ... | ... | @@ -1710,12 +1702,12 @@ const Writer = struct { |
| 1710 | 1702 | } |
| 1711 | 1703 | |
| 1712 | 1704 | self.indent -= 2; |
| 1713 | try stream.writeByteNTimes(' ', self.indent); | |
| 1705 | try stream.splatByteAll(' ', self.indent); | |
| 1714 | 1706 | try stream.writeAll("}) "); |
| 1715 | 1707 | try self.writeSrcNode(stream, .zero); |
| 1716 | 1708 | } |
| 1717 | 1709 | |
| 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 | 1711 | const small = @as(Zir.Inst.EnumDecl.Small, @bitCast(extended.small)); |
| 1720 | 1712 | |
| 1721 | 1713 | const extra = self.code.extraData(Zir.Inst.EnumDecl, extended.operand); |
| ... | ... | @@ -1731,7 +1723,7 @@ const Writer = struct { |
| 1731 | 1723 | extra.data.fields_hash_3, |
| 1732 | 1724 | }); |
| 1733 | 1725 | |
| 1734 | try stream.print("hash({}) ", .{std.fmt.fmtSliceHexLower(&fields_hash)}); | |
| 1726 | try stream.print("hash({x}) ", .{&fields_hash}); | |
| 1735 | 1727 | |
| 1736 | 1728 | var extra_index: usize = extra.end; |
| 1737 | 1729 | |
| ... | ... | @@ -1779,7 +1771,7 @@ const Writer = struct { |
| 1779 | 1771 | try self.writeBody(stream, self.code.bodySlice(extra_index, decls_len)); |
| 1780 | 1772 | self.indent -= 2; |
| 1781 | 1773 | extra_index += decls_len; |
| 1782 | try stream.writeByteNTimes(' ', self.indent); | |
| 1774 | try stream.splatByteAll(' ', self.indent); | |
| 1783 | 1775 | try stream.writeAll("}, "); |
| 1784 | 1776 | } |
| 1785 | 1777 | |
| ... | ... | @@ -1815,8 +1807,8 @@ const Writer = struct { |
| 1815 | 1807 | const field_name = self.code.nullTerminatedString(@enumFromInt(self.code.extra[extra_index])); |
| 1816 | 1808 | extra_index += 1; |
| 1817 | 1809 | |
| 1818 | try stream.writeByteNTimes(' ', self.indent); | |
| 1819 | try stream.print("{p}", .{std.zig.fmtId(field_name)}); | |
| 1810 | try stream.splatByteAll(' ', self.indent); | |
| 1811 | try stream.print("{f}", .{std.zig.fmtIdP(field_name)}); | |
| 1820 | 1812 | |
| 1821 | 1813 | if (has_tag_value) { |
| 1822 | 1814 | const tag_value_ref = @as(Zir.Inst.Ref, @enumFromInt(self.code.extra[extra_index])); |
| ... | ... | @@ -1828,7 +1820,7 @@ const Writer = struct { |
| 1828 | 1820 | try stream.writeAll(",\n"); |
| 1829 | 1821 | } |
| 1830 | 1822 | self.indent -= 2; |
| 1831 | try stream.writeByteNTimes(' ', self.indent); | |
| 1823 | try stream.splatByteAll(' ', self.indent); | |
| 1832 | 1824 | try stream.writeAll("}) "); |
| 1833 | 1825 | } |
| 1834 | 1826 | try self.writeSrcNode(stream, .zero); |
| ... | ... | @@ -1836,7 +1828,7 @@ const Writer = struct { |
| 1836 | 1828 | |
| 1837 | 1829 | fn writeOpaqueDecl( |
| 1838 | 1830 | self: *Writer, |
| 1839 | stream: anytype, | |
| 1831 | stream: *std.io.Writer, | |
| 1840 | 1832 | extended: Zir.Inst.Extended.InstData, |
| 1841 | 1833 | ) !void { |
| 1842 | 1834 | const small = @as(Zir.Inst.OpaqueDecl.Small, @bitCast(extended.small)); |
| ... | ... | @@ -1872,13 +1864,13 @@ const Writer = struct { |
| 1872 | 1864 | self.indent += 2; |
| 1873 | 1865 | try self.writeBody(stream, self.code.bodySlice(extra_index, decls_len)); |
| 1874 | 1866 | self.indent -= 2; |
| 1875 | try stream.writeByteNTimes(' ', self.indent); | |
| 1867 | try stream.splatByteAll(' ', self.indent); | |
| 1876 | 1868 | try stream.writeAll("}) "); |
| 1877 | 1869 | } |
| 1878 | 1870 | try self.writeSrcNode(stream, .zero); |
| 1879 | 1871 | } |
| 1880 | 1872 | |
| 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 | 1874 | const fields_len = extended.small; |
| 1883 | 1875 | assert(fields_len != 0); |
| 1884 | 1876 | const extra = self.code.extraData(Zir.Inst.TupleDecl, extended.operand); |
| ... | ... | @@ -1906,7 +1898,7 @@ const Writer = struct { |
| 1906 | 1898 | |
| 1907 | 1899 | fn writeErrorSetDecl( |
| 1908 | 1900 | self: *Writer, |
| 1909 | stream: anytype, | |
| 1901 | stream: *std.io.Writer, | |
| 1910 | 1902 | inst: Zir.Inst.Index, |
| 1911 | 1903 | ) !void { |
| 1912 | 1904 | const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; |
| ... | ... | @@ -1920,18 +1912,18 @@ const Writer = struct { |
| 1920 | 1912 | while (extra_index < extra_index_end) : (extra_index += 1) { |
| 1921 | 1913 | const name_index: Zir.NullTerminatedString = @enumFromInt(self.code.extra[extra_index]); |
| 1922 | 1914 | const name = self.code.nullTerminatedString(name_index); |
| 1923 | try stream.writeByteNTimes(' ', self.indent); | |
| 1924 | try stream.print("{p},\n", .{std.zig.fmtId(name)}); | |
| 1915 | try stream.splatByteAll(' ', self.indent); | |
| 1916 | try stream.print("{f},\n", .{std.zig.fmtIdP(name)}); | |
| 1925 | 1917 | } |
| 1926 | 1918 | |
| 1927 | 1919 | self.indent -= 2; |
| 1928 | try stream.writeByteNTimes(' ', self.indent); | |
| 1920 | try stream.splatByteAll(' ', self.indent); | |
| 1929 | 1921 | try stream.writeAll("}) "); |
| 1930 | 1922 | |
| 1931 | 1923 | try self.writeSrcNode(stream, inst_data.src_node); |
| 1932 | 1924 | } |
| 1933 | 1925 | |
| 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 | 1927 | const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; |
| 1936 | 1928 | const extra = self.code.extraData(Zir.Inst.SwitchBlockErrUnion, inst_data.payload_index); |
| 1937 | 1929 | |
| ... | ... | @@ -1967,7 +1959,7 @@ const Writer = struct { |
| 1967 | 1959 | extra_index += body.len; |
| 1968 | 1960 | |
| 1969 | 1961 | try stream.writeAll(",\n"); |
| 1970 | try stream.writeByteNTimes(' ', self.indent); | |
| 1962 | try stream.splatByteAll(' ', self.indent); | |
| 1971 | 1963 | try stream.writeAll("non_err => "); |
| 1972 | 1964 | try self.writeBracedBody(stream, body); |
| 1973 | 1965 | } |
| ... | ... | @@ -1985,7 +1977,7 @@ const Writer = struct { |
| 1985 | 1977 | extra_index += body.len; |
| 1986 | 1978 | |
| 1987 | 1979 | try stream.writeAll(",\n"); |
| 1988 | try stream.writeByteNTimes(' ', self.indent); | |
| 1980 | try stream.splatByteAll(' ', self.indent); | |
| 1989 | 1981 | try stream.print("{s}{s}else => ", .{ capture_text, inline_text }); |
| 1990 | 1982 | try self.writeBracedBody(stream, body); |
| 1991 | 1983 | } |
| ... | ... | @@ -2002,7 +1994,7 @@ const Writer = struct { |
| 2002 | 1994 | extra_index += info.body_len; |
| 2003 | 1995 | |
| 2004 | 1996 | try stream.writeAll(",\n"); |
| 2005 | try stream.writeByteNTimes(' ', self.indent); | |
| 1997 | try stream.splatByteAll(' ', self.indent); | |
| 2006 | 1998 | switch (info.capture) { |
| 2007 | 1999 | .none => {}, |
| 2008 | 2000 | .by_val => try stream.writeAll("by_val "), |
| ... | ... | @@ -2027,7 +2019,7 @@ const Writer = struct { |
| 2027 | 2019 | extra_index += items_len; |
| 2028 | 2020 | |
| 2029 | 2021 | try stream.writeAll(",\n"); |
| 2030 | try stream.writeByteNTimes(' ', self.indent); | |
| 2022 | try stream.splatByteAll(' ', self.indent); | |
| 2031 | 2023 | switch (info.capture) { |
| 2032 | 2024 | .none => {}, |
| 2033 | 2025 | .by_val => try stream.writeAll("by_val "), |
| ... | ... | @@ -2068,7 +2060,7 @@ const Writer = struct { |
| 2068 | 2060 | try self.writeSrcNode(stream, inst_data.src_node); |
| 2069 | 2061 | } |
| 2070 | 2062 | |
| 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 | 2064 | const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; |
| 2073 | 2065 | const extra = self.code.extraData(Zir.Inst.SwitchBlock, inst_data.payload_index); |
| 2074 | 2066 | |
| ... | ... | @@ -2115,7 +2107,7 @@ const Writer = struct { |
| 2115 | 2107 | extra_index += body.len; |
| 2116 | 2108 | |
| 2117 | 2109 | try stream.writeAll(",\n"); |
| 2118 | try stream.writeByteNTimes(' ', self.indent); | |
| 2110 | try stream.splatByteAll(' ', self.indent); | |
| 2119 | 2111 | try stream.print("{s}{s}{s} => ", .{ capture_text, inline_text, prong_name }); |
| 2120 | 2112 | try self.writeBracedBody(stream, body); |
| 2121 | 2113 | } |
| ... | ... | @@ -2132,7 +2124,7 @@ const Writer = struct { |
| 2132 | 2124 | extra_index += info.body_len; |
| 2133 | 2125 | |
| 2134 | 2126 | try stream.writeAll(",\n"); |
| 2135 | try stream.writeByteNTimes(' ', self.indent); | |
| 2127 | try stream.splatByteAll(' ', self.indent); | |
| 2136 | 2128 | switch (info.capture) { |
| 2137 | 2129 | .none => {}, |
| 2138 | 2130 | .by_val => try stream.writeAll("by_val "), |
| ... | ... | @@ -2157,7 +2149,7 @@ const Writer = struct { |
| 2157 | 2149 | extra_index += items_len; |
| 2158 | 2150 | |
| 2159 | 2151 | try stream.writeAll(",\n"); |
| 2160 | try stream.writeByteNTimes(' ', self.indent); | |
| 2152 | try stream.splatByteAll(' ', self.indent); | |
| 2161 | 2153 | switch (info.capture) { |
| 2162 | 2154 | .none => {}, |
| 2163 | 2155 | .by_val => try stream.writeAll("by_val "), |
| ... | ... | @@ -2198,16 +2190,16 @@ const Writer = struct { |
| 2198 | 2190 | try self.writeSrcNode(stream, inst_data.src_node); |
| 2199 | 2191 | } |
| 2200 | 2192 | |
| 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 | 2194 | const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; |
| 2203 | 2195 | const extra = self.code.extraData(Zir.Inst.Field, inst_data.payload_index).data; |
| 2204 | 2196 | const name = self.code.nullTerminatedString(extra.field_name_start); |
| 2205 | 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 | 2199 | try self.writeSrcNode(stream, inst_data.src_node); |
| 2208 | 2200 | } |
| 2209 | 2201 | |
| 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 | 2203 | const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; |
| 2212 | 2204 | const extra = self.code.extraData(Zir.Inst.FieldNamed, inst_data.payload_index).data; |
| 2213 | 2205 | try self.writeInstRef(stream, extra.lhs); |
| ... | ... | @@ -2217,7 +2209,7 @@ const Writer = struct { |
| 2217 | 2209 | try self.writeSrcNode(stream, inst_data.src_node); |
| 2218 | 2210 | } |
| 2219 | 2211 | |
| 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 | 2213 | const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; |
| 2222 | 2214 | const extra = self.code.extraData(Zir.Inst.As, inst_data.payload_index).data; |
| 2223 | 2215 | try self.writeInstRef(stream, extra.dest_type); |
| ... | ... | @@ -2229,9 +2221,9 @@ const Writer = struct { |
| 2229 | 2221 | |
| 2230 | 2222 | fn writeNode( |
| 2231 | 2223 | self: *Writer, |
| 2232 | stream: anytype, | |
| 2224 | stream: *std.io.Writer, | |
| 2233 | 2225 | inst: Zir.Inst.Index, |
| 2234 | ) (@TypeOf(stream).Error || error{OutOfMemory})!void { | |
| 2226 | ) Error!void { | |
| 2235 | 2227 | const src_node = self.code.instructions.items(.data)[@intFromEnum(inst)].node; |
| 2236 | 2228 | try stream.writeAll(") "); |
| 2237 | 2229 | try self.writeSrcNode(stream, src_node); |
| ... | ... | @@ -2239,25 +2231,25 @@ const Writer = struct { |
| 2239 | 2231 | |
| 2240 | 2232 | fn writeStrTok( |
| 2241 | 2233 | self: *Writer, |
| 2242 | stream: anytype, | |
| 2234 | stream: *std.io.Writer, | |
| 2243 | 2235 | inst: Zir.Inst.Index, |
| 2244 | ) (@TypeOf(stream).Error || error{OutOfMemory})!void { | |
| 2236 | ) Error!void { | |
| 2245 | 2237 | const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].str_tok; |
| 2246 | 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 | 2240 | try self.writeSrcTok(stream, inst_data.src_tok); |
| 2249 | 2241 | } |
| 2250 | 2242 | |
| 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 | 2244 | const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].str_op; |
| 2253 | 2245 | const str = inst_data.getStr(self.code); |
| 2254 | 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 | } |
| 2257 | 2249 | |
| 2258 | 2250 | fn writeFunc( |
| 2259 | 2251 | self: *Writer, |
| 2260 | stream: anytype, | |
| 2252 | stream: *std.io.Writer, | |
| 2261 | 2253 | inst: Zir.Inst.Index, |
| 2262 | 2254 | inferred_error_set: bool, |
| 2263 | 2255 | ) !void { |
| ... | ... | @@ -2308,7 +2300,7 @@ const Writer = struct { |
| 2308 | 2300 | ); |
| 2309 | 2301 | } |
| 2310 | 2302 | |
| 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 | 2304 | const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; |
| 2313 | 2305 | const extra = self.code.extraData(Zir.Inst.FuncFancy, inst_data.payload_index); |
| 2314 | 2306 | |
| ... | ... | @@ -2367,7 +2359,7 @@ const Writer = struct { |
| 2367 | 2359 | ); |
| 2368 | 2360 | } |
| 2369 | 2361 | |
| 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 | 2363 | const extra = self.code.extraData(Zir.Inst.AllocExtended, extended.operand); |
| 2372 | 2364 | const small = @as(Zir.Inst.AllocExtended.Small, @bitCast(extended.small)); |
| 2373 | 2365 | |
| ... | ... | @@ -2390,7 +2382,7 @@ const Writer = struct { |
| 2390 | 2382 | try self.writeSrcNode(stream, extra.data.src_node); |
| 2391 | 2383 | } |
| 2392 | 2384 | |
| 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 | 2386 | const extra = self.code.extraData(Zir.Inst.TypeOfPeer, extended.operand); |
| 2395 | 2387 | const body = self.code.bodySlice(extra.data.body_index, extra.data.body_len); |
| 2396 | 2388 | try self.writeBracedBody(stream, body); |
| ... | ... | @@ -2403,7 +2395,7 @@ const Writer = struct { |
| 2403 | 2395 | try stream.writeAll("])"); |
| 2404 | 2396 | } |
| 2405 | 2397 | |
| 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 | 2399 | const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; |
| 2408 | 2400 | const extra = self.code.extraData(Zir.Inst.BoolBr, inst_data.payload_index); |
| 2409 | 2401 | const body = self.code.bodySlice(extra.end, extra.data.body_len); |
| ... | ... | @@ -2414,7 +2406,7 @@ const Writer = struct { |
| 2414 | 2406 | try self.writeSrcNode(stream, inst_data.src_node); |
| 2415 | 2407 | } |
| 2416 | 2408 | |
| 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 | 2410 | const int_type = self.code.instructions.items(.data)[@intFromEnum(inst)].int_type; |
| 2419 | 2411 | const prefix: u8 = switch (int_type.signedness) { |
| 2420 | 2412 | .signed => 'i', |
| ... | ... | @@ -2424,7 +2416,7 @@ const Writer = struct { |
| 2424 | 2416 | try self.writeSrcNode(stream, int_type.src_node); |
| 2425 | 2417 | } |
| 2426 | 2418 | |
| 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 | 2420 | const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].save_err_ret_index; |
| 2429 | 2421 | |
| 2430 | 2422 | try self.writeInstRef(stream, inst_data.operand); |
| ... | ... | @@ -2432,7 +2424,7 @@ const Writer = struct { |
| 2432 | 2424 | try stream.writeAll(")"); |
| 2433 | 2425 | } |
| 2434 | 2426 | |
| 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 | 2428 | const extra = self.code.extraData(Zir.Inst.RestoreErrRetIndex, extended.operand).data; |
| 2437 | 2429 | |
| 2438 | 2430 | try self.writeInstRef(stream, extra.block); |
| ... | ... | @@ -2442,7 +2434,7 @@ const Writer = struct { |
| 2442 | 2434 | try self.writeSrcNode(stream, extra.src_node); |
| 2443 | 2435 | } |
| 2444 | 2436 | |
| 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 | 2438 | const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].@"break"; |
| 2447 | 2439 | const extra = self.code.extraData(Zir.Inst.Break, inst_data.payload_index).data; |
| 2448 | 2440 | |
| ... | ... | @@ -2452,7 +2444,7 @@ const Writer = struct { |
| 2452 | 2444 | try stream.writeAll(")"); |
| 2453 | 2445 | } |
| 2454 | 2446 | |
| 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 | 2448 | const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; |
| 2457 | 2449 | |
| 2458 | 2450 | const extra = self.code.extraData(Zir.Inst.MultiOp, inst_data.payload_index); |
| ... | ... | @@ -2468,7 +2460,7 @@ const Writer = struct { |
| 2468 | 2460 | try self.writeSrcNode(stream, inst_data.src_node); |
| 2469 | 2461 | } |
| 2470 | 2462 | |
| 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 | 2464 | const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; |
| 2473 | 2465 | |
| 2474 | 2466 | const extra = self.code.extraData(Zir.Inst.MultiOp, inst_data.payload_index); |
| ... | ... | @@ -2483,7 +2475,7 @@ const Writer = struct { |
| 2483 | 2475 | try self.writeSrcNode(stream, inst_data.src_node); |
| 2484 | 2476 | } |
| 2485 | 2477 | |
| 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 | 2479 | const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; |
| 2488 | 2480 | |
| 2489 | 2481 | const extra = self.code.extraData(Zir.Inst.MultiOp, inst_data.payload_index); |
| ... | ... | @@ -2503,7 +2495,7 @@ const Writer = struct { |
| 2503 | 2495 | try self.writeSrcNode(stream, inst_data.src_node); |
| 2504 | 2496 | } |
| 2505 | 2497 | |
| 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 | 2499 | const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].@"unreachable"; |
| 2508 | 2500 | try stream.writeAll(") "); |
| 2509 | 2501 | try self.writeSrcNode(stream, inst_data.src_node); |
| ... | ... | @@ -2511,7 +2503,7 @@ const Writer = struct { |
| 2511 | 2503 | |
| 2512 | 2504 | fn writeFuncCommon( |
| 2513 | 2505 | self: *Writer, |
| 2514 | stream: anytype, | |
| 2506 | stream: *std.io.Writer, | |
| 2515 | 2507 | inferred_error_set: bool, |
| 2516 | 2508 | var_args: bool, |
| 2517 | 2509 | is_noinline: bool, |
| ... | ... | @@ -2548,19 +2540,19 @@ const Writer = struct { |
| 2548 | 2540 | try self.writeSrcNode(stream, src_node); |
| 2549 | 2541 | } |
| 2550 | 2542 | |
| 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 | 2544 | const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].dbg_stmt; |
| 2553 | 2545 | try stream.print("{d}, {d})", .{ inst_data.line + 1, inst_data.column + 1 }); |
| 2554 | 2546 | } |
| 2555 | 2547 | |
| 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 | 2549 | const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].@"defer"; |
| 2558 | 2550 | const body = self.code.bodySlice(inst_data.index, inst_data.len); |
| 2559 | 2551 | try self.writeBracedBody(stream, body); |
| 2560 | 2552 | try stream.writeByte(')'); |
| 2561 | 2553 | } |
| 2562 | 2554 | |
| 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 | 2556 | const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].defer_err_code; |
| 2565 | 2557 | const extra = self.code.extraData(Zir.Inst.DeferErrCode, inst_data.payload_index).data; |
| 2566 | 2558 | |
| ... | ... | @@ -2573,7 +2565,7 @@ const Writer = struct { |
| 2573 | 2565 | try stream.writeByte(')'); |
| 2574 | 2566 | } |
| 2575 | 2567 | |
| 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 | 2569 | const decl = self.code.getDeclaration(inst); |
| 2578 | 2570 | |
| 2579 | 2571 | const prev_parent_decl_node = self.parent_decl_node; |
| ... | ... | @@ -2594,10 +2586,8 @@ const Writer = struct { |
| 2594 | 2586 | }, |
| 2595 | 2587 | } |
| 2596 | 2588 | const src_hash = self.code.getAssociatedSrcHash(inst).?; |
| 2597 | try stream.print(" line({d}) column({d}) hash({})", .{ | |
| 2598 | decl.src_line, | |
| 2599 | decl.src_column, | |
| 2600 | std.fmt.fmtSliceHexLower(&src_hash), | |
| 2589 | try stream.print(" line({d}) column({d}) hash({x})", .{ | |
| 2590 | decl.src_line, decl.src_column, &src_hash, | |
| 2601 | 2591 | }); |
| 2602 | 2592 | |
| 2603 | 2593 | { |
| ... | ... | @@ -2631,26 +2621,26 @@ const Writer = struct { |
| 2631 | 2621 | try self.writeSrcNode(stream, .zero); |
| 2632 | 2622 | } |
| 2633 | 2623 | |
| 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 | 2625 | try stream.print("{d})) ", .{extended.small}); |
| 2636 | 2626 | const src_node: Ast.Node.Offset = @enumFromInt(@as(i32, @bitCast(extended.operand))); |
| 2637 | 2627 | try self.writeSrcNode(stream, src_node); |
| 2638 | 2628 | } |
| 2639 | 2629 | |
| 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 | 2631 | const val: Zir.Inst.BuiltinValue = @enumFromInt(extended.small); |
| 2642 | 2632 | try stream.print("{s})) ", .{@tagName(val)}); |
| 2643 | 2633 | const src_node: Ast.Node.Offset = @enumFromInt(@as(i32, @bitCast(extended.operand))); |
| 2644 | 2634 | try self.writeSrcNode(stream, src_node); |
| 2645 | 2635 | } |
| 2646 | 2636 | |
| 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 | 2638 | const op: Zir.Inst.InplaceOp = @enumFromInt(extended.small); |
| 2649 | 2639 | try self.writeInstRef(stream, @enumFromInt(extended.operand)); |
| 2650 | 2640 | try stream.print(", {s}))", .{@tagName(op)}); |
| 2651 | 2641 | } |
| 2652 | 2642 | |
| 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 | 2644 | if (ref == .none) { |
| 2655 | 2645 | return stream.writeAll(".none"); |
| 2656 | 2646 | } else if (ref.toIndex()) |i| { |
| ... | ... | @@ -2661,12 +2651,12 @@ const Writer = struct { |
| 2661 | 2651 | } |
| 2662 | 2652 | } |
| 2663 | 2653 | |
| 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 | 2655 | _ = self; |
| 2666 | 2656 | return stream.print("%{d}", .{@intFromEnum(inst)}); |
| 2667 | 2657 | } |
| 2668 | 2658 | |
| 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 | 2660 | if (captures_len == 0) { |
| 2671 | 2661 | try stream.writeAll("{}"); |
| 2672 | 2662 | return extra_index; |
| ... | ... | @@ -2686,7 +2676,7 @@ const Writer = struct { |
| 2686 | 2676 | return extra_index + 2 * captures_len; |
| 2687 | 2677 | } |
| 2688 | 2678 | |
| 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 | 2680 | switch (capture.unwrap()) { |
| 2691 | 2681 | .nested => |i| return stream.print("[{d}]", .{i}), |
| 2692 | 2682 | .instruction => |inst| return self.writeInstIndex(stream, inst), |
| ... | ... | @@ -2694,18 +2684,18 @@ const Writer = struct { |
| 2694 | 2684 | try stream.writeAll("load "); |
| 2695 | 2685 | try self.writeInstIndex(stream, ptr_inst); |
| 2696 | 2686 | }, |
| 2697 | .decl_val => |str| try stream.print("decl_val \"{}\"", .{ | |
| 2698 | std.zig.fmtEscapes(self.code.nullTerminatedString(str)), | |
| 2687 | .decl_val => |str| try stream.print("decl_val \"{f}\"", .{ | |
| 2688 | std.zig.fmtString(self.code.nullTerminatedString(str)), | |
| 2699 | 2689 | }), |
| 2700 | .decl_ref => |str| try stream.print("decl_ref \"{}\"", .{ | |
| 2701 | std.zig.fmtEscapes(self.code.nullTerminatedString(str)), | |
| 2690 | .decl_ref => |str| try stream.print("decl_ref \"{f}\"", .{ | |
| 2691 | std.zig.fmtString(self.code.nullTerminatedString(str)), | |
| 2702 | 2692 | }), |
| 2703 | 2693 | } |
| 2704 | 2694 | } |
| 2705 | 2695 | |
| 2706 | 2696 | fn writeOptionalInstRef( |
| 2707 | 2697 | self: *Writer, |
| 2708 | stream: anytype, | |
| 2698 | stream: *std.io.Writer, | |
| 2709 | 2699 | prefix: []const u8, |
| 2710 | 2700 | inst: Zir.Inst.Ref, |
| 2711 | 2701 | ) !void { |
| ... | ... | @@ -2716,7 +2706,7 @@ const Writer = struct { |
| 2716 | 2706 | |
| 2717 | 2707 | fn writeOptionalInstRefOrBody( |
| 2718 | 2708 | self: *Writer, |
| 2719 | stream: anytype, | |
| 2709 | stream: *std.io.Writer, | |
| 2720 | 2710 | prefix: []const u8, |
| 2721 | 2711 | ref: Zir.Inst.Ref, |
| 2722 | 2712 | body: []const Zir.Inst.Index, |
| ... | ... | @@ -2734,7 +2724,7 @@ const Writer = struct { |
| 2734 | 2724 | |
| 2735 | 2725 | fn writeFlag( |
| 2736 | 2726 | self: *Writer, |
| 2737 | stream: anytype, | |
| 2727 | stream: *std.io.Writer, | |
| 2738 | 2728 | name: []const u8, |
| 2739 | 2729 | flag: bool, |
| 2740 | 2730 | ) !void { |
| ... | ... | @@ -2743,7 +2733,7 @@ const Writer = struct { |
| 2743 | 2733 | try stream.writeAll(name); |
| 2744 | 2734 | } |
| 2745 | 2735 | |
| 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 | 2737 | const tree = self.tree orelse return; |
| 2748 | 2738 | const abs_node = src_node.toAbsolute(self.parent_decl_node); |
| 2749 | 2739 | const src_span = tree.nodeToSpan(abs_node); |
| ... | ... | @@ -2755,7 +2745,7 @@ const Writer = struct { |
| 2755 | 2745 | }); |
| 2756 | 2746 | } |
| 2757 | 2747 | |
| 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 | 2749 | const tree = self.tree orelse return; |
| 2760 | 2750 | const abs_tok = src_tok.toAbsolute(tree.firstToken(self.parent_decl_node)); |
| 2761 | 2751 | const span_start = tree.tokenStart(abs_tok); |
| ... | ... | @@ -2768,7 +2758,7 @@ const Writer = struct { |
| 2768 | 2758 | }); |
| 2769 | 2759 | } |
| 2770 | 2760 | |
| 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 | 2762 | const tree = self.tree orelse return; |
| 2773 | 2763 | const span_start = tree.tokenStart(src_tok); |
| 2774 | 2764 | const span_end = span_start + @as(u32, @intCast(tree.tokenSlice(src_tok).len)); |
| ... | ... | @@ -2780,15 +2770,15 @@ const Writer = struct { |
| 2780 | 2770 | }); |
| 2781 | 2771 | } |
| 2782 | 2772 | |
| 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 | 2774 | try self.writeBracedBodyConditional(stream, body, self.recurse_decls); |
| 2785 | 2775 | } |
| 2786 | 2776 | |
| 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 | 2778 | try self.writeBracedBodyConditional(stream, body, self.recurse_blocks); |
| 2789 | 2779 | } |
| 2790 | 2780 | |
| 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 | 2782 | if (body.len == 0) { |
| 2793 | 2783 | try stream.writeAll("{}"); |
| 2794 | 2784 | } else if (enabled) { |
| ... | ... | @@ -2796,7 +2786,7 @@ const Writer = struct { |
| 2796 | 2786 | self.indent += 2; |
| 2797 | 2787 | try self.writeBody(stream, body); |
| 2798 | 2788 | self.indent -= 2; |
| 2799 | try stream.writeByteNTimes(' ', self.indent); | |
| 2789 | try stream.splatByteAll(' ', self.indent); | |
| 2800 | 2790 | try stream.writeAll("}"); |
| 2801 | 2791 | } else if (body.len == 1) { |
| 2802 | 2792 | try stream.writeByte('{'); |
| ... | ... | @@ -2817,21 +2807,21 @@ const Writer = struct { |
| 2817 | 2807 | } |
| 2818 | 2808 | } |
| 2819 | 2809 | |
| 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 | 2811 | for (body) |inst| { |
| 2822 | try stream.writeByteNTimes(' ', self.indent); | |
| 2812 | try stream.splatByteAll(' ', self.indent); | |
| 2823 | 2813 | try stream.print("%{d} ", .{@intFromEnum(inst)}); |
| 2824 | 2814 | try self.writeInstToStream(stream, inst); |
| 2825 | 2815 | try stream.writeByte('\n'); |
| 2826 | 2816 | } |
| 2827 | 2817 | } |
| 2828 | 2818 | |
| 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 | 2820 | const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_tok; |
| 2831 | 2821 | const extra = self.code.extraData(Zir.Inst.Import, inst_data.payload_index).data; |
| 2832 | 2822 | try self.writeInstRef(stream, extra.res_ty); |
| 2833 | 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 | 2825 | try self.writeSrcTok(stream, inst_data.src_tok); |
| 2836 | 2826 | } |
| 2837 | 2827 | }; |
src/print_zoir.zig+22-28| ... | ... | @@ -1,13 +1,8 @@ |
| 1 | pub fn renderToFile(zoir: Zoir, arena: Allocator, f: std.fs.File) (std.fs.File.WriteError || Allocator.Error)!void { | |
| 2 | var bw = std.io.bufferedWriter(f.writer()); | |
| 3 | try renderToWriter(zoir, arena, bw.writer()); | |
| 4 | try bw.flush(); | |
| 5 | } | |
| 1 | pub const Error = error{ WriteFailed, OutOfMemory }; | |
| 6 | 2 | |
| 7 | pub fn renderToWriter(zoir: Zoir, arena: Allocator, w: anytype) (@TypeOf(w).Error || Allocator.Error)!void { | |
| 3 | pub fn renderToWriter(zoir: Zoir, arena: Allocator, w: *Writer) Error!void { | |
| 8 | 4 | assert(!zoir.hasCompileErrors()); |
| 9 | 5 | |
| 10 | const fmtIntSizeBin = std.fmt.fmtIntSizeBin; | |
| 11 | 6 | const bytes_per_node = comptime n: { |
| 12 | 7 | var n: usize = 0; |
| 13 | 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 | 18 | |
| 24 | 19 | // zig fmt: off |
| 25 | 20 | try w.print( |
| 26 | \\# Nodes: {} ({}) | |
| 27 | \\# Extra Data Items: {} ({}) | |
| 28 | \\# BigInt Limbs: {} ({}) | |
| 29 | \\# String Table Bytes: {} | |
| 30 | \\# Total ZON Bytes: {} | |
| 21 | \\# Nodes: {} ({Bi}) | |
| 22 | \\# Extra Data Items: {} ({Bi}) | |
| 23 | \\# BigInt Limbs: {} ({Bi}) | |
| 24 | \\# String Table Bytes: {Bi} | |
| 25 | \\# Total ZON Bytes: {Bi} | |
| 31 | 26 | \\ |
| 32 | 27 | , .{ |
| 33 | zoir.nodes.len, fmtIntSizeBin(node_bytes), | |
| 34 | zoir.extra.len, fmtIntSizeBin(extra_bytes), | |
| 35 | zoir.limbs.len, fmtIntSizeBin(limb_bytes), | |
| 36 | fmtIntSizeBin(string_bytes), | |
| 37 | fmtIntSizeBin(node_bytes + extra_bytes + limb_bytes + string_bytes), | |
| 28 | zoir.nodes.len, node_bytes, | |
| 29 | zoir.extra.len, extra_bytes, | |
| 30 | zoir.limbs.len, limb_bytes, | |
| 31 | string_bytes, | |
| 32 | node_bytes + extra_bytes + limb_bytes + string_bytes, | |
| 38 | 33 | }); |
| 39 | 34 | // zig fmt: on |
| 40 | 35 | var pz: PrintZon = .{ |
| 41 | .w = w.any(), | |
| 36 | .w = w, | |
| 42 | 37 | .arena = arena, |
| 43 | 38 | .zoir = zoir, |
| 44 | 39 | .indent = 0, |
| 45 | 40 | }; |
| 46 | 41 | |
| 47 | return @errorCast(pz.renderRoot()); | |
| 42 | return pz.renderRoot(); | |
| 48 | 43 | } |
| 49 | 44 | |
| 50 | 45 | const PrintZon = struct { |
| 51 | w: std.io.AnyWriter, | |
| 46 | w: *Writer, | |
| 52 | 47 | arena: Allocator, |
| 53 | 48 | zoir: Zoir, |
| 54 | 49 | indent: u32, |
| 55 | 50 | |
| 56 | fn renderRoot(pz: *PrintZon) anyerror!void { | |
| 51 | fn renderRoot(pz: *PrintZon) Error!void { | |
| 57 | 52 | try pz.renderNode(.root); |
| 58 | 53 | try pz.w.writeByte('\n'); |
| 59 | 54 | } |
| 60 | 55 | |
| 61 | fn renderNode(pz: *PrintZon, node: Zoir.Node.Index) anyerror!void { | |
| 56 | fn renderNode(pz: *PrintZon, node: Zoir.Node.Index) Error!void { | |
| 62 | 57 | const zoir = pz.zoir; |
| 63 | 58 | try pz.w.print("%{d} = ", .{@intFromEnum(node)}); |
| 64 | 59 | switch (node.get(zoir)) { |
| ... | ... | @@ -77,8 +72,8 @@ const PrintZon = struct { |
| 77 | 72 | }, |
| 78 | 73 | .float_literal => |x| try pz.w.print("float({d})", .{x}), |
| 79 | 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))}), | |
| 81 | .string_literal => |x| try pz.w.print("str(\"{}\")", .{std.zig.fmtEscapes(x)}), | |
| 75 | .enum_literal => |x| try pz.w.print("enum_literal({f})", .{std.zig.fmtIdP(x.get(zoir))}), | |
| 76 | .string_literal => |x| try pz.w.print("str(\"{f}\")", .{std.zig.fmtString(x)}), | |
| 82 | 77 | .empty_literal => try pz.w.writeAll("empty_literal(.{})"), |
| 83 | 78 | .array_literal => |vals| { |
| 84 | 79 | try pz.w.writeAll("array_literal({"); |
| ... | ... | @@ -97,7 +92,7 @@ const PrintZon = struct { |
| 97 | 92 | pz.indent += 1; |
| 98 | 93 | for (s.names, 0..s.vals.len) |name, idx| { |
| 99 | 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 | 96 | try pz.renderNode(s.vals.at(@intCast(idx))); |
| 102 | 97 | try pz.w.writeByte(','); |
| 103 | 98 | } |
| ... | ... | @@ -110,9 +105,7 @@ const PrintZon = struct { |
| 110 | 105 | |
| 111 | 106 | fn newline(pz: *PrintZon) !void { |
| 112 | 107 | try pz.w.writeByte('\n'); |
| 113 | for (0..pz.indent) |_| { | |
| 114 | try pz.w.writeByteNTimes(' ', 2); | |
| 115 | } | |
| 108 | try pz.w.splatByteAll(' ', 2 * pz.indent); | |
| 116 | 109 | } |
| 117 | 110 | }; |
| 118 | 111 | |
| ... | ... | @@ -120,3 +113,4 @@ const std = @import("std"); |
| 120 | 113 | const assert = std.debug.assert; |
| 121 | 114 | const Allocator = std.mem.Allocator; |
| 122 | 115 | const Zoir = std.zig.Zoir; |
| 116 | const Writer = std.io.Writer; |
src/register_manager.zig+3-3| ... | ... | @@ -238,7 +238,7 @@ pub fn RegisterManager( |
| 238 | 238 | if (i < count) return null; |
| 239 | 239 | |
| 240 | 240 | for (regs, insts) |reg, inst| { |
| 241 | log.debug("tryAllocReg {} for inst {?}", .{ reg, inst }); | |
| 241 | log.debug("tryAllocReg {} for inst {?f}", .{ reg, inst }); | |
| 242 | 242 | self.markRegAllocated(reg); |
| 243 | 243 | |
| 244 | 244 | if (inst) |tracked_inst| { |
| ... | ... | @@ -317,7 +317,7 @@ pub fn RegisterManager( |
| 317 | 317 | tracked_index: TrackedIndex, |
| 318 | 318 | inst: ?Air.Inst.Index, |
| 319 | 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 | 321 | if (!self.isRegIndexFree(tracked_index)) { |
| 322 | 322 | // Move the instruction that was previously there to a |
| 323 | 323 | // stack allocation. |
| ... | ... | @@ -349,7 +349,7 @@ pub fn RegisterManager( |
| 349 | 349 | tracked_index: TrackedIndex, |
| 350 | 350 | inst: ?Air.Inst.Index, |
| 351 | 351 | ) void { |
| 352 | log.debug("getRegAssumeFree {} for inst {?}", .{ regAtTrackedIndex(tracked_index), inst }); | |
| 352 | log.debug("getRegAssumeFree {} for inst {?f}", .{ regAtTrackedIndex(tracked_index), inst }); | |
| 353 | 353 | self.markRegIndexAllocated(tracked_index); |
| 354 | 354 | |
| 355 | 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 | 357 | var len: usize = undefined; |
| 358 | 358 | const bytes_ptr = asm_string.getString_bytes_begin_size(&len); |
| 359 | 359 | |
| 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 | 361 | const str_node = try Tag.string_literal.create(c.arena, str); |
| 362 | 362 | |
| 363 | 363 | const asm_node = try Tag.asm_simple.create(c.arena, str_node); |
| ... | ... | @@ -2276,7 +2276,7 @@ fn transNarrowStringLiteral( |
| 2276 | 2276 | var len: usize = undefined; |
| 2277 | 2277 | const bytes_ptr = stmt.getString_bytes_begin_size(&len); |
| 2278 | 2278 | |
| 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 | 2280 | const node = try Tag.string_literal.create(c.arena, str); |
| 2281 | 2281 | return maybeSuppressResult(c, result_used, node); |
| 2282 | 2282 | } |
| ... | ... | @@ -3338,7 +3338,7 @@ fn transPredefinedExpr(c: *Context, scope: *Scope, expr: *const clang.Predefined |
| 3338 | 3338 | |
| 3339 | 3339 | fn transCreateCharLitNode(c: *Context, narrow: bool, val: u32) TransError!Node { |
| 3340 | 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 | 3342 | else |
| 3343 | 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 | 5832 | num += c - 'A' + 10; |
| 5833 | 5833 | }, |
| 5834 | 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 | 5836 | num = 0; |
| 5837 | 5837 | if (c == '\\') |
| 5838 | 5838 | state = .escape |
| ... | ... | @@ -5858,7 +5858,7 @@ fn zigifyEscapeSequences(ctx: *Context, m: *MacroCtx) ![]const u8 { |
| 5858 | 5858 | }; |
| 5859 | 5859 | num += c - '0'; |
| 5860 | 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 | 5862 | num = 0; |
| 5863 | 5863 | count = 0; |
| 5864 | 5864 | if (c == '\\') |
| ... | ... | @@ -5872,21 +5872,21 @@ fn zigifyEscapeSequences(ctx: *Context, m: *MacroCtx) ![]const u8 { |
| 5872 | 5872 | } |
| 5873 | 5873 | } |
| 5874 | 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 | 5876 | return bytes[0..i]; |
| 5877 | 5877 | } |
| 5878 | 5878 | |
| 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 | 5880 | /// If a C string literal or char literal in a macro is not valid UTF-8, we need to escape |
| 5881 | 5881 | /// non-ASCII characters so that the Zig source we output will itself be UTF-8. |
| 5882 | 5882 | fn escapeUnprintables(ctx: *Context, m: *MacroCtx) ![]const u8 { |
| 5883 | 5883 | const zigified = try zigifyEscapeSequences(ctx, m); |
| 5884 | 5884 | if (std.unicode.utf8ValidateSlice(zigified)) return zigified; |
| 5885 | 5885 | |
| 5886 | const formatter = std.fmt.fmtSliceEscapeLower(zigified); | |
| 5887 | const encoded_size = @as(usize, @intCast(std.fmt.count("{s}", .{formatter}))); | |
| 5886 | const formatter = std.ascii.hexEscape(zigified, .lower); | |
| 5887 | const encoded_size: usize = @intCast(std.fmt.count("{f}", .{formatter})); | |
| 5888 | 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 | 5890 | error.NoSpaceLeft => unreachable, |
| 5891 | 5891 | else => |e| return e, |
| 5892 | 5892 | }; |
| ... | ... | @@ -5905,7 +5905,7 @@ fn parseCPrimaryExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node { |
| 5905 | 5905 | if (slice[0] != '\'' or slice[1] == '\\' or slice.len == 3) { |
| 5906 | 5906 | return Tag.char_literal.create(c.arena, try escapeUnprintables(c, m)); |
| 5907 | 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 | 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 | 520 | default: panic("unimplemented: fd_read special file"); |
| 521 | 521 | } |
| 522 | 522 | |
| 523 | if (fds[fd].stream == NULL) { | |
| 524 | store32_align2(res_size_ptr, 0); | |
| 525 | return wasi_errno_success; | |
| 526 | } | |
| 527 | ||
| 523 | 528 | size_t size = 0; |
| 524 | 529 | for (uint32_t i = 0; i < iovs_len; i += 1) { |
| 525 | 530 | uint32_t len = load32_align2(&iovs_ptr[i].len); |
| 526 | size_t read_size = 0; | |
| 527 | if (fds[fd].stream != NULL) | |
| 528 | read_size = fread(&m[load32_align2(&iovs_ptr[i].ptr)], 1, len, fds[fd].stream); | |
| 531 | size_t read_size = fread(&m[load32_align2(&iovs_ptr[i].ptr)], 1, len, fds[fd].stream); | |
| 529 | 532 | size += read_size; |
| 530 | 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 | 636 | } |
| 634 | 637 | |
| 635 | 638 | fpos_t pos; |
| 636 | if (fgetpos(fds[fd].stream, &pos) < 0) return wasi_errno_io; | |
| 637 | if (fseek(fds[fd].stream, offset, SEEK_SET) < 0) return wasi_errno_io; | |
| 639 | if (fds[fd].stream != NULL) { | |
| 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 | } | |
| 638 | 643 | |
| 639 | 644 | size_t size = 0; |
| 640 | 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 | 653 | if (written_size < len) break; |
| 649 | 654 | } |
| 650 | 655 | |
| 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 | } | |
| 652 | 659 | |
| 653 | 660 | if (size > 0) { |
| 654 | 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 | 971 | default: panic("unimplemented: fd_pread special file"); |
| 965 | 972 | } |
| 966 | 973 | |
| 974 | if (fds[fd].stream == NULL) { | |
| 975 | store32_align2(res_size_ptr, 0); | |
| 976 | return wasi_errno_success; | |
| 977 | } | |
| 978 | ||
| 967 | 979 | fpos_t pos; |
| 968 | 980 | if (fgetpos(fds[fd].stream, &pos) < 0) return wasi_errno_io; |
| 969 | 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 | 1032 | }; |
| 1033 | 1033 | } |
| 1034 | 1034 | |
| 1035 | test "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 | ||
| 1053 | 1035 | test "errorCast to adhoc inferred error set" { |
| 1054 | 1036 | const S = struct { |
| 1055 | 1037 | inline fn baz() !i32 { |
test/behavior/union_with_members.zig+2-2| ... | ... | @@ -10,8 +10,8 @@ const ET = union(enum) { |
| 10 | 10 | |
| 11 | 11 | pub fn print(a: *const ET, buf: []u8) anyerror!usize { |
| 12 | 12 | return switch (a.*) { |
| 13 | ET.SINT => |x| fmt.formatIntBuf(buf, x, 10, .lower, fmt.FormatOptions{}), | |
| 14 | ET.UINT => |x| fmt.formatIntBuf(buf, x, 10, .lower, fmt.FormatOptions{}), | |
| 13 | ET.SINT => |x| fmt.printInt(buf, x, 10, .lower, fmt.FormatOptions{}), | |
| 14 | ET.UINT => |x| fmt.printInt(buf, x, 10, .lower, fmt.FormatOptions{}), | |
| 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 | 2 | |
| 3 | 3 | pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace, _: ?usize) noreturn { |
| 4 | 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 | 6 | std.process.exit(0); |
| 7 | 7 | } |
| 8 | 8 | std.process.exit(1); |
test/compare_output.zig+3-286| ... | ... | @@ -17,15 +17,6 @@ pub fn addCases(cases: *tests.CompareOutputContext) void { |
| 17 | 17 | \\} |
| 18 | 18 | , "Hello, world!" ++ if (@import("builtin").os.tag == .windows) "\r\n" else "\n"); |
| 19 | 19 | |
| 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 | 20 | cases.addC("number literals", |
| 30 | 21 | \\const std = @import("std"); |
| 31 | 22 | \\const builtin = @import("builtin"); |
| ... | ... | @@ -158,24 +149,6 @@ pub fn addCases(cases: *tests.CompareOutputContext) void { |
| 158 | 149 | \\ |
| 159 | 150 | ); |
| 160 | 151 | |
| 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 | 152 | cases.addC("expose function pointer to C land", |
| 180 | 153 | \\const c = @cImport(@cInclude("stdlib.h")); |
| 181 | 154 | \\ |
| ... | ... | @@ -236,267 +209,11 @@ pub fn addCases(cases: *tests.CompareOutputContext) void { |
| 236 | 209 | \\} |
| 237 | 210 | , "3.25\n3\n3.00\n-0.40\n"); |
| 238 | 211 | |
| 239 | cases.add("same named methods in incomplete struct", | |
| 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 | |
| 212 | cases.add("valid carriage return example", "const std = @import(\"std\");\r\n" ++ // Testing CRLF line endings are valid | |
| 497 | 213 | "\r\n" ++ |
| 498 | 214 | "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 | 217 | " stdout.print(\\\\A Multiline\r\n" ++ // testing CRLF at end of multiline string line is valid and normalises to \n in the output |
| 501 | 218 | " \\\\String\r\n" ++ |
| 502 | 219 | " , .{}) catch unreachable;\r\n" ++ |
test/incremental/add_decl+7-7| ... | ... | @@ -6,7 +6,7 @@ |
| 6 | 6 | #file=main.zig |
| 7 | 7 | const std = @import("std"); |
| 8 | 8 | pub fn main() !void { |
| 9 | try std.io.getStdOut().writeAll(foo); | |
| 9 | try std.fs.File.stdout().writeAll(foo); | |
| 10 | 10 | } |
| 11 | 11 | const foo = "good morning\n"; |
| 12 | 12 | #expect_stdout="good morning\n" |
| ... | ... | @@ -15,7 +15,7 @@ const foo = "good morning\n"; |
| 15 | 15 | #file=main.zig |
| 16 | 16 | const std = @import("std"); |
| 17 | 17 | pub fn main() !void { |
| 18 | try std.io.getStdOut().writeAll(foo); | |
| 18 | try std.fs.File.stdout().writeAll(foo); | |
| 19 | 19 | } |
| 20 | 20 | const foo = "good morning\n"; |
| 21 | 21 | const bar = "good evening\n"; |
| ... | ... | @@ -25,7 +25,7 @@ const bar = "good evening\n"; |
| 25 | 25 | #file=main.zig |
| 26 | 26 | const std = @import("std"); |
| 27 | 27 | pub fn main() !void { |
| 28 | try std.io.getStdOut().writeAll(bar); | |
| 28 | try std.fs.File.stdout().writeAll(bar); | |
| 29 | 29 | } |
| 30 | 30 | const foo = "good morning\n"; |
| 31 | 31 | const bar = "good evening\n"; |
| ... | ... | @@ -35,17 +35,17 @@ const bar = "good evening\n"; |
| 35 | 35 | #file=main.zig |
| 36 | 36 | const std = @import("std"); |
| 37 | 37 | pub fn main() !void { |
| 38 | try std.io.getStdOut().writeAll(qux); | |
| 38 | try std.fs.File.stdout().writeAll(qux); | |
| 39 | 39 | } |
| 40 | 40 | const foo = "good morning\n"; |
| 41 | 41 | const 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' | |
| 43 | 43 | |
| 44 | 44 | #update=add missing declaration |
| 45 | 45 | #file=main.zig |
| 46 | 46 | const std = @import("std"); |
| 47 | 47 | pub fn main() !void { |
| 48 | try std.io.getStdOut().writeAll(qux); | |
| 48 | try std.fs.File.stdout().writeAll(qux); | |
| 49 | 49 | } |
| 50 | 50 | const foo = "good morning\n"; |
| 51 | 51 | const bar = "good evening\n"; |
| ... | ... | @@ -56,7 +56,7 @@ const qux = "good night\n"; |
| 56 | 56 | #file=main.zig |
| 57 | 57 | const std = @import("std"); |
| 58 | 58 | pub fn main() !void { |
| 59 | try std.io.getStdOut().writeAll(qux); | |
| 59 | try std.fs.File.stdout().writeAll(qux); | |
| 60 | 60 | } |
| 61 | 61 | const qux = "good night\n"; |
| 62 | 62 | #expect_stdout="good night\n" |
test/incremental/add_decl_namespaced+7-7| ... | ... | @@ -6,7 +6,7 @@ |
| 6 | 6 | #file=main.zig |
| 7 | 7 | const std = @import("std"); |
| 8 | 8 | pub fn main() !void { |
| 9 | try std.io.getStdOut().writeAll(@This().foo); | |
| 9 | try std.fs.File.stdout().writeAll(@This().foo); | |
| 10 | 10 | } |
| 11 | 11 | const foo = "good morning\n"; |
| 12 | 12 | #expect_stdout="good morning\n" |
| ... | ... | @@ -15,7 +15,7 @@ const foo = "good morning\n"; |
| 15 | 15 | #file=main.zig |
| 16 | 16 | const std = @import("std"); |
| 17 | 17 | pub fn main() !void { |
| 18 | try std.io.getStdOut().writeAll(@This().foo); | |
| 18 | try std.fs.File.stdout().writeAll(@This().foo); | |
| 19 | 19 | } |
| 20 | 20 | const foo = "good morning\n"; |
| 21 | 21 | const bar = "good evening\n"; |
| ... | ... | @@ -25,7 +25,7 @@ const bar = "good evening\n"; |
| 25 | 25 | #file=main.zig |
| 26 | 26 | const std = @import("std"); |
| 27 | 27 | pub fn main() !void { |
| 28 | try std.io.getStdOut().writeAll(@This().bar); | |
| 28 | try std.fs.File.stdout().writeAll(@This().bar); | |
| 29 | 29 | } |
| 30 | 30 | const foo = "good morning\n"; |
| 31 | 31 | const bar = "good evening\n"; |
| ... | ... | @@ -35,18 +35,18 @@ const bar = "good evening\n"; |
| 35 | 35 | #file=main.zig |
| 36 | 36 | const std = @import("std"); |
| 37 | 37 | pub fn main() !void { |
| 38 | try std.io.getStdOut().writeAll(@This().qux); | |
| 38 | try std.fs.File.stdout().writeAll(@This().qux); | |
| 39 | 39 | } |
| 40 | 40 | const foo = "good morning\n"; |
| 41 | 41 | const 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 | 43 | #expect_error=main.zig:1:1: note: struct declared here |
| 44 | 44 | |
| 45 | 45 | #update=add missing declaration |
| 46 | 46 | #file=main.zig |
| 47 | 47 | const std = @import("std"); |
| 48 | 48 | pub fn main() !void { |
| 49 | try std.io.getStdOut().writeAll(@This().qux); | |
| 49 | try std.fs.File.stdout().writeAll(@This().qux); | |
| 50 | 50 | } |
| 51 | 51 | const foo = "good morning\n"; |
| 52 | 52 | const bar = "good evening\n"; |
| ... | ... | @@ -57,7 +57,7 @@ const qux = "good night\n"; |
| 57 | 57 | #file=main.zig |
| 58 | 58 | const std = @import("std"); |
| 59 | 59 | pub fn main() !void { |
| 60 | try std.io.getStdOut().writeAll(@This().qux); | |
| 60 | try std.fs.File.stdout().writeAll(@This().qux); | |
| 61 | 61 | } |
| 62 | 62 | const qux = "good night\n"; |
| 63 | 63 | #expect_stdout="good night\n" |
test/incremental/bad_import+2-2| ... | ... | @@ -7,7 +7,7 @@ |
| 7 | 7 | #file=main.zig |
| 8 | 8 | pub fn main() !void { |
| 9 | 9 | _ = @import("foo.zig"); |
| 10 | try std.io.getStdOut().writeAll("success\n"); | |
| 10 | try std.fs.File.stdout().writeAll("success\n"); | |
| 11 | 11 | } |
| 12 | 12 | const std = @import("std"); |
| 13 | 13 | #file=foo.zig |
| ... | ... | @@ -29,7 +29,7 @@ comptime { |
| 29 | 29 | #file=main.zig |
| 30 | 30 | pub fn main() !void { |
| 31 | 31 | //_ = @import("foo.zig"); |
| 32 | try std.io.getStdOut().writeAll("success\n"); | |
| 32 | try std.fs.File.stdout().writeAll("success\n"); | |
| 33 | 33 | } |
| 34 | 34 | const std = @import("std"); |
| 35 | 35 | #expect_stdout="success\n" |
test/incremental/change_embed_file+3-3| ... | ... | @@ -7,7 +7,7 @@ |
| 7 | 7 | const std = @import("std"); |
| 8 | 8 | const string = @embedFile("string.txt"); |
| 9 | 9 | pub fn main() !void { |
| 10 | try std.io.getStdOut().writeAll(string); | |
| 10 | try std.fs.File.stdout().writeAll(string); | |
| 11 | 11 | } |
| 12 | 12 | #file=string.txt |
| 13 | 13 | Hello, World! |
| ... | ... | @@ -27,7 +27,7 @@ Hello again, World! |
| 27 | 27 | const std = @import("std"); |
| 28 | 28 | const string = @embedFile("string.txt"); |
| 29 | 29 | pub 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 | 32 | #expect_stdout="a hardcoded string\n" |
| 33 | 33 | |
| ... | ... | @@ -36,7 +36,7 @@ pub fn main() !void { |
| 36 | 36 | const std = @import("std"); |
| 37 | 37 | const string = @embedFile("string.txt"); |
| 38 | 38 | pub fn main() !void { |
| 39 | try std.io.getStdOut().writeAll(string); | |
| 39 | try std.fs.File.stdout().writeAll(string); | |
| 40 | 40 | } |
| 41 | 41 | #expect_error=main.zig:2:27: error: unable to open 'string.txt': FileNotFound |
| 42 | 42 |
test/incremental/change_enum_tag_type+6-3| ... | ... | @@ -14,7 +14,8 @@ const Foo = enum(Tag) { |
| 14 | 14 | pub fn main() !void { |
| 15 | 15 | var val: Foo = undefined; |
| 16 | 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 | } |
| 19 | 20 | const std = @import("std"); |
| 20 | 21 | #expect_stdout="a\n" |
| ... | ... | @@ -31,7 +32,8 @@ const Foo = enum(Tag) { |
| 31 | 32 | pub fn main() !void { |
| 32 | 33 | var val: Foo = undefined; |
| 33 | 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 | } |
| 36 | 38 | comptime { |
| 37 | 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 | 55 | pub fn main() !void { |
| 54 | 56 | var val: Foo = undefined; |
| 55 | 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 | } |
| 58 | 61 | const std = @import("std"); |
| 59 | 62 | #expect_stdout="a\n" |
test/incremental/change_exports+12-6| ... | ... | @@ -16,7 +16,8 @@ pub fn main() !void { |
| 16 | 16 | extern const bar: u32; |
| 17 | 17 | }; |
| 18 | 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 | } |
| 21 | 22 | const std = @import("std"); |
| 22 | 23 | #expect_stdout="123\n" |
| ... | ... | @@ -37,7 +38,8 @@ pub fn main() !void { |
| 37 | 38 | extern const other: u32; |
| 38 | 39 | }; |
| 39 | 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 | } |
| 42 | 44 | const std = @import("std"); |
| 43 | 45 | #expect_error=main.zig:6:5: error: exported symbol collision: foo |
| ... | ... | @@ -59,7 +61,8 @@ pub fn main() !void { |
| 59 | 61 | extern const other: u32; |
| 60 | 62 | }; |
| 61 | 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 | } |
| 64 | 67 | const std = @import("std"); |
| 65 | 68 | #expect_stdout="123 456\n" |
| ... | ... | @@ -83,7 +86,8 @@ pub fn main() !void { |
| 83 | 86 | extern const other: u32; |
| 84 | 87 | }; |
| 85 | 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 | } |
| 88 | 92 | const std = @import("std"); |
| 89 | 93 | #expect_stdout="123 456\n" |
| ... | ... | @@ -128,7 +132,8 @@ pub fn main() !void { |
| 128 | 132 | extern const other: u32; |
| 129 | 133 | }; |
| 130 | 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 | } |
| 133 | 138 | const std = @import("std"); |
| 134 | 139 | #expect_stdout="123 456\n" |
| ... | ... | @@ -152,7 +157,8 @@ pub fn main() !void { |
| 152 | 157 | extern const other: u32; |
| 153 | 158 | }; |
| 154 | 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 | } |
| 157 | 163 | const std = @import("std"); |
| 158 | 164 | #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 | try foo(123); |
| 8 | 8 | } |
| 9 | 9 | fn 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 | } |
| 12 | 13 | const std = @import("std"); |
| 13 | 14 | #expect_stdout="123\n" |
| ... | ... | @@ -18,7 +19,8 @@ pub fn main() !void { |
| 18 | 19 | try foo(123); |
| 19 | 20 | } |
| 20 | 21 | fn 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 | } |
| 23 | 25 | const std = @import("std"); |
| 24 | 26 | #expect_stdout="123\n" |
| ... | ... | @@ -29,7 +31,8 @@ pub fn main() !void { |
| 29 | 31 | try foo(-42); |
| 30 | 32 | } |
| 31 | 33 | fn 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 | } |
| 34 | 37 | const std = @import("std"); |
| 35 | 38 | #expect_stdout="-42\n" |
test/incremental/change_generic_line_number+2-2| ... | ... | @@ -6,7 +6,7 @@ const std = @import("std"); |
| 6 | 6 | fn Printer(message: []const u8) type { |
| 7 | 7 | return struct { |
| 8 | 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 | 22 | fn Printer(message: []const u8) type { |
| 23 | 23 | return struct { |
| 24 | 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 | 4 | #file=main.zig |
| 5 | 5 | const std = @import("std"); |
| 6 | 6 | pub fn main() !void { |
| 7 | try std.io.getStdOut().writeAll("foo\n"); | |
| 7 | try std.fs.File.stdout().writeAll("foo\n"); | |
| 8 | 8 | } |
| 9 | 9 | #expect_stdout="foo\n" |
| 10 | 10 | #update=change line number |
| ... | ... | @@ -12,6 +12,6 @@ pub fn main() !void { |
| 12 | 12 | const std = @import("std"); |
| 13 | 13 | |
| 14 | 14 | pub fn main() !void { |
| 15 | try std.io.getStdOut().writeAll("foo\n"); | |
| 15 | try std.fs.File.stdout().writeAll("foo\n"); | |
| 16 | 16 | } |
| 17 | 17 | #expect_stdout="foo\n" |
test/incremental/change_panic_handler+6-3| ... | ... | @@ -11,7 +11,8 @@ pub fn main() !u8 { |
| 11 | 11 | } |
| 12 | 12 | pub const panic = std.debug.FullPanic(myPanic); |
| 13 | 13 | fn 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 | 16 | std.process.exit(0); |
| 16 | 17 | } |
| 17 | 18 | const std = @import("std"); |
| ... | ... | @@ -27,7 +28,8 @@ pub fn main() !u8 { |
| 27 | 28 | } |
| 28 | 29 | pub const panic = std.debug.FullPanic(myPanic); |
| 29 | 30 | fn 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 | 33 | std.process.exit(0); |
| 32 | 34 | } |
| 33 | 35 | const std = @import("std"); |
| ... | ... | @@ -43,7 +45,8 @@ pub fn main() !u8 { |
| 43 | 45 | } |
| 44 | 46 | pub const panic = std.debug.FullPanic(myPanicNew); |
| 45 | 47 | fn 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 | 50 | std.process.exit(0); |
| 48 | 51 | } |
| 49 | 52 | const std = @import("std"); |
test/incremental/change_panic_handler_explicit+6-3| ... | ... | @@ -41,7 +41,8 @@ pub const panic = struct { |
| 41 | 41 | pub const noreturnReturned = no_panic.noreturnReturned; |
| 42 | 42 | }; |
| 43 | 43 | fn 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 | 46 | std.process.exit(0); |
| 46 | 47 | } |
| 47 | 48 | const std = @import("std"); |
| ... | ... | @@ -87,7 +88,8 @@ pub const panic = struct { |
| 87 | 88 | pub const noreturnReturned = no_panic.noreturnReturned; |
| 88 | 89 | }; |
| 89 | 90 | fn 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 | 93 | std.process.exit(0); |
| 92 | 94 | } |
| 93 | 95 | const std = @import("std"); |
| ... | ... | @@ -133,7 +135,8 @@ pub const panic = struct { |
| 133 | 135 | pub const noreturnReturned = no_panic.noreturnReturned; |
| 134 | 136 | }; |
| 135 | 137 | fn 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 | 140 | std.process.exit(0); |
| 138 | 141 | } |
| 139 | 142 | const std = @import("std"); |
test/incremental/change_shift_op+4-2| ... | ... | @@ -8,7 +8,8 @@ pub fn main() !void { |
| 8 | 8 | try foo(0x1300); |
| 9 | 9 | } |
| 10 | 10 | fn 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 | } |
| 13 | 14 | const std = @import("std"); |
| 14 | 15 | #expect_stdout="0x3000\n" |
| ... | ... | @@ -18,7 +19,8 @@ pub fn main() !void { |
| 18 | 19 | try foo(0x1300); |
| 19 | 20 | } |
| 20 | 21 | fn 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 | } |
| 23 | 25 | const std = @import("std"); |
| 24 | 26 | #expect_stdout="0x130\n" |
test/incremental/change_struct_same_fields+6-3| ... | ... | @@ -10,7 +10,8 @@ pub fn main() !void { |
| 10 | 10 | try foo(&val); |
| 11 | 11 | } |
| 12 | 12 | fn 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 | 15 | "{d} {d}\n", |
| 15 | 16 | .{ val.x, val.y }, |
| 16 | 17 | ); |
| ... | ... | @@ -26,7 +27,8 @@ pub fn main() !void { |
| 26 | 27 | try foo(&val); |
| 27 | 28 | } |
| 28 | 29 | fn 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 | 32 | "{d} {d}\n", |
| 31 | 33 | .{ val.x, val.y }, |
| 32 | 34 | ); |
| ... | ... | @@ -42,7 +44,8 @@ pub fn main() !void { |
| 42 | 44 | try foo(&val); |
| 43 | 45 | } |
| 44 | 46 | fn 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 | 49 | "{d} {d}\n", |
| 47 | 50 | .{ val.x, val.y }, |
| 48 | 51 | ); |
test/incremental/change_zon_file+3-3| ... | ... | @@ -7,7 +7,7 @@ |
| 7 | 7 | const std = @import("std"); |
| 8 | 8 | const message: []const u8 = @import("message.zon"); |
| 9 | 9 | pub fn main() !void { |
| 10 | try std.io.getStdOut().writeAll(message); | |
| 10 | try std.fs.File.stdout().writeAll(message); | |
| 11 | 11 | } |
| 12 | 12 | #file=message.zon |
| 13 | 13 | "Hello, World!\n" |
| ... | ... | @@ -28,7 +28,7 @@ pub fn main() !void { |
| 28 | 28 | const std = @import("std"); |
| 29 | 29 | const message: []const u8 = @import("message.zon"); |
| 30 | 30 | pub 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 | 33 | #expect_error=message.zon:1:1: error: unable to load 'message.zon': FileNotFound |
| 34 | 34 | #expect_error=main.zig:2:37: note: file imported here |
| ... | ... | @@ -43,6 +43,6 @@ pub fn main() !void { |
| 43 | 43 | const std = @import("std"); |
| 44 | 44 | const message: []const u8 = @import("message.zon"); |
| 45 | 45 | pub fn main() !void { |
| 46 | try std.io.getStdOut().writeAll(message); | |
| 46 | try std.fs.File.stdout().writeAll(message); | |
| 47 | 47 | } |
| 48 | 48 | #expect_stdout="We're back, World!\n" |
test/incremental/change_zon_file_no_result_type+1-1| ... | ... | @@ -6,7 +6,7 @@ |
| 6 | 6 | #file=main.zig |
| 7 | 7 | const std = @import("std"); |
| 8 | 8 | pub 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 | 11 | #file=foo.zon |
| 12 | 12 | .{ |
test/incremental/compile_log+3-3| ... | ... | @@ -7,7 +7,7 @@ |
| 7 | 7 | #file=main.zig |
| 8 | 8 | const std = @import("std"); |
| 9 | 9 | pub 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 | 12 | #expect_stdout="Hello, World!\n" |
| 13 | 13 | |
| ... | ... | @@ -15,7 +15,7 @@ pub fn main() !void { |
| 15 | 15 | #file=main.zig |
| 16 | 16 | const std = @import("std"); |
| 17 | 17 | pub fn main() !void { |
| 18 | try std.io.getStdOut().writeAll("Hello, World!\n"); | |
| 18 | try std.fs.File.stdout().writeAll("Hello, World!\n"); | |
| 19 | 19 | @compileLog("this is a log"); |
| 20 | 20 | } |
| 21 | 21 | #expect_error=main.zig:4:5: error: found compile log statement |
| ... | ... | @@ -25,6 +25,6 @@ pub fn main() !void { |
| 25 | 25 | #file=main.zig |
| 26 | 26 | const std = @import("std"); |
| 27 | 27 | pub 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 | 30 | #expect_stdout="Hello, World!\n" |
test/incremental/fix_astgen_failure+5-5| ... | ... | @@ -9,28 +9,28 @@ pub fn main() !void { |
| 9 | 9 | } |
| 10 | 10 | #file=foo.zig |
| 11 | 11 | pub 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 | 14 | #expect_error=foo.zig:2:9: error: use of undeclared identifier 'std' |
| 15 | 15 | #update=fix the error |
| 16 | 16 | #file=foo.zig |
| 17 | 17 | const std = @import("std"); |
| 18 | 18 | pub 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 | 21 | #expect_stdout="Hello, World!\n" |
| 22 | 22 | #update=add new error |
| 23 | 23 | #file=foo.zig |
| 24 | 24 | const std = @import("std"); |
| 25 | 25 | pub 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 | 29 | #update=fix the new error |
| 30 | 30 | #file=foo.zig |
| 31 | 31 | const std = @import("std"); |
| 32 | 32 | const hello_str = "Hello, World! Again!\n"; |
| 33 | 33 | pub fn hello() !void { |
| 34 | try std.io.getStdOut().writeAll(hello_str); | |
| 34 | try std.fs.File.stdout().writeAll(hello_str); | |
| 35 | 35 | } |
| 36 | 36 | #expect_stdout="Hello, World! Again!\n" |
test/incremental/function_becomes_inline+3-3| ... | ... | @@ -7,7 +7,7 @@ pub fn main() !void { |
| 7 | 7 | try foo(); |
| 8 | 8 | } |
| 9 | 9 | fn foo() !void { |
| 10 | try std.io.getStdOut().writer().writeAll("Hello, World!\n"); | |
| 10 | try std.fs.File.stdout().writeAll("Hello, World!\n"); | |
| 11 | 11 | } |
| 12 | 12 | const std = @import("std"); |
| 13 | 13 | #expect_stdout="Hello, World!\n" |
| ... | ... | @@ -18,7 +18,7 @@ pub fn main() !void { |
| 18 | 18 | try foo(); |
| 19 | 19 | } |
| 20 | 20 | inline 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 | } |
| 23 | 23 | const std = @import("std"); |
| 24 | 24 | #expect_stdout="Hello, World!\n" |
| ... | ... | @@ -29,7 +29,7 @@ pub fn main() !void { |
| 29 | 29 | try foo(); |
| 30 | 30 | } |
| 31 | 31 | inline 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 | } |
| 34 | 34 | const std = @import("std"); |
| 35 | 35 | #expect_stdout="Hello, `inline` World!\n" |
test/incremental/hello+2-2| ... | ... | @@ -6,13 +6,13 @@ |
| 6 | 6 | #file=main.zig |
| 7 | 7 | const std = @import("std"); |
| 8 | 8 | pub 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 | 11 | #expect_stdout="good morning\n" |
| 12 | 12 | #update=change the string |
| 13 | 13 | #file=main.zig |
| 14 | 14 | const std = @import("std"); |
| 15 | 15 | pub fn main() !void { |
| 16 | try std.io.getStdOut().writeAll("おはようございます\n"); | |
| 16 | try std.fs.File.stdout().writeAll("おはようございます\n"); | |
| 17 | 17 | } |
| 18 | 18 | #expect_stdout="おはようございます\n" |
test/incremental/make_decl_pub+2-2| ... | ... | @@ -11,7 +11,7 @@ pub fn main() !void { |
| 11 | 11 | #file=foo.zig |
| 12 | 12 | const std = @import("std"); |
| 13 | 13 | fn hello() !void { |
| 14 | try std.io.getStdOut().writeAll("Hello, World!\n"); | |
| 14 | try std.fs.File.stdout().writeAll("Hello, World!\n"); | |
| 15 | 15 | } |
| 16 | 16 | #expect_error=main.zig:3:12: error: 'hello' is not marked 'pub' |
| 17 | 17 | #expect_error=foo.zig:2:1: note: declared here |
| ... | ... | @@ -20,6 +20,6 @@ fn hello() !void { |
| 20 | 20 | #file=foo.zig |
| 21 | 21 | const std = @import("std"); |
| 22 | 22 | pub 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 | 25 | #expect_stdout="Hello, World!\n" |
test/incremental/modify_inline_fn+2-2| ... | ... | @@ -7,7 +7,7 @@ |
| 7 | 7 | const std = @import("std"); |
| 8 | 8 | pub fn main() !void { |
| 9 | 9 | const str = getStr(); |
| 10 | try std.io.getStdOut().writeAll(str); | |
| 10 | try std.fs.File.stdout().writeAll(str); | |
| 11 | 11 | } |
| 12 | 12 | inline fn getStr() []const u8 { |
| 13 | 13 | return "foo\n"; |
| ... | ... | @@ -18,7 +18,7 @@ inline fn getStr() []const u8 { |
| 18 | 18 | const std = @import("std"); |
| 19 | 19 | pub fn main() !void { |
| 20 | 20 | const str = getStr(); |
| 21 | try std.io.getStdOut().writeAll(str); | |
| 21 | try std.fs.File.stdout().writeAll(str); | |
| 22 | 22 | } |
| 23 | 23 | inline fn getStr() []const u8 { |
| 24 | 24 | return "bar\n"; |
test/incremental/move_src+6-4| ... | ... | @@ -6,7 +6,8 @@ |
| 6 | 6 | #file=main.zig |
| 7 | 7 | const std = @import("std"); |
| 8 | 8 | pub 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 | } |
| 11 | 12 | fn foo() u32 { |
| 12 | 13 | return @src().line; |
| ... | ... | @@ -14,13 +15,14 @@ fn foo() u32 { |
| 14 | 15 | fn bar() u32 { |
| 15 | 16 | return 123; |
| 16 | 17 | } |
| 17 | #expect_stdout="6 123\n" | |
| 18 | #expect_stdout="7 123\n" | |
| 18 | 19 | |
| 19 | 20 | #update=add newline |
| 20 | 21 | #file=main.zig |
| 21 | 22 | const std = @import("std"); |
| 22 | 23 | pub 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 | } |
| 25 | 27 | |
| 26 | 28 | fn foo() u32 { |
| ... | ... | @@ -29,4 +31,4 @@ fn foo() u32 { |
| 29 | 31 | fn bar() u32 { |
| 30 | 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 | const std = @import("std"); |
| 8 | 8 | var some_enum: enum { first, second } = .first; |
| 9 | 9 | pub 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 | 12 | #expect_stdout="first" |
| 13 | 13 | #update=no change |
| ... | ... | @@ -15,6 +15,6 @@ pub fn main() !void { |
| 15 | 15 | const std = @import("std"); |
| 16 | 16 | var some_enum: enum { first, second } = .first; |
| 17 | 17 | pub 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 | 20 | #expect_stdout="first" |
test/incremental/recursive_function_becomes_non_recursive+2-2| ... | ... | @@ -8,7 +8,7 @@ pub fn main() !void { |
| 8 | 8 | try foo(false); |
| 9 | 9 | } |
| 10 | 10 | fn foo(recurse: bool) !void { |
| 11 | const stdout = std.io.getStdOut().writer(); | |
| 11 | const stdout = std.fs.File.stdout(); | |
| 12 | 12 | if (recurse) return foo(true); |
| 13 | 13 | try stdout.writeAll("non-recursive path\n"); |
| 14 | 14 | } |
| ... | ... | @@ -21,7 +21,7 @@ pub fn main() !void { |
| 21 | 21 | try foo(true); |
| 22 | 22 | } |
| 23 | 23 | fn foo(recurse: bool) !void { |
| 24 | const stdout = std.io.getStdOut().writer(); | |
| 24 | const stdout = std.fs.File.stdout(); | |
| 25 | 25 | if (recurse) return stdout.writeAll("x==1\n"); |
| 26 | 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 | 9 | bar = 2, |
| 10 | 10 | }; |
| 11 | 11 | pub 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 | } |
| 14 | 15 | const std = @import("std"); |
| 15 | 16 | #expect_stdout="1\n" |
| ... | ... | @@ -20,8 +21,9 @@ const MyEnum = enum(u8) { |
| 20 | 21 | bar = 2, |
| 21 | 22 | }; |
| 22 | 23 | pub 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 | } |
| 25 | 27 | const 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 | 29 | #expect_error=main.zig:1:16: note: enum declared here |
test/incremental/unreferenced_error+4-4| ... | ... | @@ -6,7 +6,7 @@ |
| 6 | 6 | #file=main.zig |
| 7 | 7 | const std = @import("std"); |
| 8 | 8 | pub fn main() !void { |
| 9 | try std.io.getStdOut().writeAll(a); | |
| 9 | try std.fs.File.stdout().writeAll(a); | |
| 10 | 10 | } |
| 11 | 11 | const a = "Hello, World!\n"; |
| 12 | 12 | #expect_stdout="Hello, World!\n" |
| ... | ... | @@ -15,7 +15,7 @@ const a = "Hello, World!\n"; |
| 15 | 15 | #file=main.zig |
| 16 | 16 | const std = @import("std"); |
| 17 | 17 | pub fn main() !void { |
| 18 | try std.io.getStdOut().writeAll(a); | |
| 18 | try std.fs.File.stdout().writeAll(a); | |
| 19 | 19 | } |
| 20 | 20 | const a = @compileError("bad a"); |
| 21 | 21 | #expect_error=main.zig:5:11: error: bad a |
| ... | ... | @@ -24,7 +24,7 @@ const a = @compileError("bad a"); |
| 24 | 24 | #file=main.zig |
| 25 | 25 | const std = @import("std"); |
| 26 | 26 | pub fn main() !void { |
| 27 | try std.io.getStdOut().writeAll(b); | |
| 27 | try std.fs.File.stdout().writeAll(b); | |
| 28 | 28 | } |
| 29 | 29 | const a = @compileError("bad a"); |
| 30 | 30 | const b = "Hi there!\n"; |
| ... | ... | @@ -34,7 +34,7 @@ const b = "Hi there!\n"; |
| 34 | 34 | #file=main.zig |
| 35 | 35 | const std = @import("std"); |
| 36 | 36 | pub fn main() !void { |
| 37 | try std.io.getStdOut().writeAll(a); | |
| 37 | try std.fs.File.stdout().writeAll(a); | |
| 38 | 38 | } |
| 39 | 39 | const a = "Back to a\n"; |
| 40 | 40 | const b = @compileError("bad b"); |
test/link/bss/main.zig+4-1| ... | ... | @@ -4,8 +4,11 @@ const std = @import("std"); |
| 4 | 4 | var buffer: [0x1000000]u64 = [1]u64{0} ** 0x1000000; |
| 5 | 5 | |
| 6 | 6 | pub fn main() anyerror!void { |
| 7 | var stdout_writer = std.fs.File.stdout().writerStreaming(&.{}); | |
| 8 | ||
| 7 | 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 | 12 | // workaround the dreaded decl_val |
| 10 | 13 | (&buffer)[0], |
| 11 | 14 | (&buffer)[0x10], |
test/link/elf.zig+4-4| ... | ... | @@ -1315,8 +1315,8 @@ fn testGcSectionsZig(b: *Build, opts: Options) *Step { |
| 1315 | 1315 | \\extern var live_var2: i32; |
| 1316 | 1316 | \\extern fn live_fn2() void; |
| 1317 | 1317 | \\pub fn main() void { |
| 1318 | \\ const stdout = std.io.getStdOut(); | |
| 1319 | \\ stdout.writer().print("{d} {d}\n", .{ live_var1, live_var2 }) catch unreachable; | |
| 1318 | \\ var stdout_writer = std.fs.File.stdout().writerStreaming(&.{}); | |
| 1319 | \\ stdout_writer.interface.print("{d} {d}\n", .{ live_var1, live_var2 }) catch @panic("fail"); | |
| 1320 | 1320 | \\ live_fn2(); |
| 1321 | 1321 | \\} |
| 1322 | 1322 | , |
| ... | ... | @@ -1357,8 +1357,8 @@ fn testGcSectionsZig(b: *Build, opts: Options) *Step { |
| 1357 | 1357 | \\extern var live_var2: i32; |
| 1358 | 1358 | \\extern fn live_fn2() void; |
| 1359 | 1359 | \\pub fn main() void { |
| 1360 | \\ const stdout = std.io.getStdOut(); | |
| 1361 | \\ stdout.writer().print("{d} {d}\n", .{ live_var1, live_var2 }) catch unreachable; | |
| 1360 | \\ var stdout_writer = std.fs.File.stdout().writerStreaming(&.{}); | |
| 1361 | \\ stdout_writer.interface.print("{d} {d}\n", .{ live_var1, live_var2 }) catch @panic("fail"); | |
| 1362 | 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 | 710 | const exe = addExecutable(b, opts, .{ .name = "main", .zig_source_bytes = |
| 711 | 711 | \\const std = @import("std"); |
| 712 | 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 | }); |
| 716 | 716 | |
| ... | ... | @@ -2365,10 +2365,11 @@ fn testTlsZig(b: *Build, opts: Options) *Step { |
| 2365 | 2365 | \\threadlocal var x: i32 = 0; |
| 2366 | 2366 | \\threadlocal var y: i32 = -1; |
| 2367 | 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 | 2370 | \\ x -= 1; |
| 2370 | 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 | }); |
| 2374 | 2375 |
test/link/wasm/extern/main.zig+2-2| ... | ... | @@ -3,6 +3,6 @@ const std = @import("std"); |
| 3 | 3 | extern const foo: u32; |
| 4 | 4 | |
| 5 | 5 | pub fn main() void { |
| 6 | const std_out = std.io.getStdOut(); | |
| 7 | std_out.writer().print("Result: {d}", .{foo}) catch {}; | |
| 6 | var stdout_writer = std.fs.File.stdout().writerStreaming(&.{}); | |
| 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 | 84 | break :got_result try buf.toOwnedSlice(); |
| 85 | 85 | }; |
| 86 | 86 | |
| 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 | 27 | } |
| 28 | 28 | |
| 29 | 29 | // 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"); | |
| 31 | 31 | |
| 32 | 32 | // test stdin pipe from parent |
| 33 | 33 | const hello_stdin = "hello from stdin"; |
| 34 | 34 | var buf: [hello_stdin.len]u8 = undefined; |
| 35 | const stdin = std.io.getStdIn().reader(); | |
| 35 | const stdin: std.fs.File = .stdin(); | |
| 36 | 36 | const n = try stdin.readAll(&buf); |
| 37 | 37 | if (!std.mem.eql(u8, buf[0..n], hello_stdin)) { |
| 38 | 38 | testError("stdin: '{s}'; want '{s}'", .{ buf[0..n], hello_stdin }); |
| ... | ... | @@ -40,7 +40,8 @@ fn run(allocator: std.mem.Allocator) !void { |
| 40 | 40 | } |
| 41 | 41 | |
| 42 | 42 | fn 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 | 45 | stderr.print("CHILD TEST ERROR: ", .{}) catch {}; |
| 45 | 46 | stderr.print(fmt, args) catch {}; |
| 46 | 47 | if (fmt[fmt.len - 1] != '\n') { |
test/standalone/child_process/main.zig+4-3| ... | ... | @@ -19,13 +19,13 @@ pub fn main() !void { |
| 19 | 19 | child.stderr_behavior = .Inherit; |
| 20 | 20 | try child.spawn(); |
| 21 | 21 | const child_stdin = child.stdin.?; |
| 22 | try child_stdin.writer().writeAll("hello from stdin"); // verified in child | |
| 22 | try child_stdin.writeAll("hello from stdin"); // verified in child | |
| 23 | 23 | child_stdin.close(); |
| 24 | 24 | child.stdin = null; |
| 25 | 25 | |
| 26 | 26 | const hello_stdout = "hello from stdout"; |
| 27 | 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 | 29 | if (!std.mem.eql(u8, buf[0..n], hello_stdout)) { |
| 30 | 30 | testError("child stdout: '{s}'; want '{s}'", .{ buf[0..n], hello_stdout }); |
| 31 | 31 | } |
| ... | ... | @@ -45,7 +45,8 @@ pub fn main() !void { |
| 45 | 45 | var parent_test_error = false; |
| 46 | 46 | |
| 47 | 47 | fn 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 | 50 | stderr.print("PARENT TEST ERROR: ", .{}) catch {}; |
| 50 | 51 | stderr.print(fmt, args) catch {}; |
| 51 | 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 | 10 | dir_name, .{}); |
| 11 | 11 | const file_name = args.next().?; |
| 12 | 12 | const file = try dir.createFile(file_name, .{}); |
| 13 | try file.writer().print( | |
| 13 | try file.deprecatedWriter().print( | |
| 14 | 14 | \\{s} |
| 15 | 15 | \\{s} |
| 16 | 16 | \\Hello, world! |
test/standalone/sigpipe/breakpipe.zig+1-1| ... | ... | @@ -10,7 +10,7 @@ pub fn main() !void { |
| 10 | 10 | std.posix.close(pipe[0]); |
| 11 | 11 | _ = std.posix.write(pipe[1], "a") catch |err| switch (err) { |
| 12 | 12 | error.BrokenPipe => { |
| 13 | try std.io.getStdOut().writer().writeAll("BrokenPipe\n"); | |
| 13 | try std.fs.File.stdout().writeAll("BrokenPipe\n"); | |
| 14 | 14 | std.posix.exit(123); |
| 15 | 15 | }, |
| 16 | 16 | else => |e| return e, |
test/standalone/simple/brace_expansion.zig deleted-292| ... | ... | @@ -1,292 +0,0 @@ |
| 1 | const std = @import("std"); | |
| 2 | const io = std.io; | |
| 3 | const mem = std.mem; | |
| 4 | const debug = std.debug; | |
| 5 | const assert = debug.assert; | |
| 6 | const testing = std.testing; | |
| 7 | const ArrayList = std.ArrayList; | |
| 8 | const maxInt = std.math.maxInt; | |
| 9 | ||
| 10 | const Token = union(enum) { | |
| 11 | Word: []const u8, | |
| 12 | OpenBrace, | |
| 13 | CloseBrace, | |
| 14 | Comma, | |
| 15 | Eof, | |
| 16 | }; | |
| 17 | ||
| 18 | var gpa: std.heap.GeneralPurposeAllocator(.{}) = .init; | |
| 19 | var global_allocator = gpa.allocator(); | |
| 20 | ||
| 21 | fn 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 | ||
| 68 | const 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 | ||
| 91 | const ParseError = error{ | |
| 92 | InvalidInput, | |
| 93 | OutOfMemory, | |
| 94 | }; | |
| 95 | ||
| 96 | fn 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 | ||
| 137 | fn 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 | ||
| 170 | const ExpandNodeError = error{OutOfMemory}; | |
| 171 | ||
| 172 | fn 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 | ||
| 226 | pub 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 | ||
| 241 | test "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 | ||
| 255 | fn 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 | ||
| 262 | test "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 | ||
| 285 | fn 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 | 109 | //.{ |
| 110 | 110 | // .src_path = "issue_9693/main.zig", |
| 111 | 111 | //}, |
| 112 | .{ | |
| 113 | .src_path = "brace_expansion.zig", | |
| 114 | .is_test = true, | |
| 115 | }, | |
| 116 | 112 | .{ |
| 117 | 113 | .src_path = "issue_7030.zig", |
| 118 | 114 | .target = .{ |
test/standalone/simple/cat/main.zig+10-10| ... | ... | @@ -1,42 +1,42 @@ |
| 1 | 1 | const std = @import("std"); |
| 2 | 2 | const io = std.io; |
| 3 | const process = std.process; | |
| 4 | 3 | const fs = std.fs; |
| 5 | 4 | const mem = std.mem; |
| 6 | 5 | const warn = std.log.warn; |
| 6 | const fatal = std.process.fatal; | |
| 7 | 7 | |
| 8 | 8 | pub fn main() !void { |
| 9 | 9 | var arena_instance = std.heap.ArenaAllocator.init(std.heap.page_allocator); |
| 10 | 10 | defer arena_instance.deinit(); |
| 11 | 11 | const arena = arena_instance.allocator(); |
| 12 | 12 | |
| 13 | const args = try process.argsAlloc(arena); | |
| 13 | const args = try std.process.argsAlloc(arena); | |
| 14 | 14 | |
| 15 | 15 | const exe = args[0]; |
| 16 | 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(&.{}); | |
| 18 | 20 | |
| 19 | 21 | const cwd = fs.cwd(); |
| 20 | 22 | |
| 21 | 23 | for (args[1..]) |arg| { |
| 22 | 24 | if (mem.eql(u8, arg, "-")) { |
| 23 | 25 | catted_anything = true; |
| 24 | try stdout_file.writeFileAll(io.getStdIn(), .{}); | |
| 26 | _ = try stdout.sendFileAll(&stdin_reader, .unlimited); | |
| 25 | 27 | } else if (mem.startsWith(u8, arg, "-")) { |
| 26 | 28 | return usage(exe); |
| 27 | 29 | } else { |
| 28 | const file = cwd.openFile(arg, .{}) catch |err| { | |
| 29 | warn("Unable to open file: {s}\n", .{@errorName(err)}); | |
| 30 | return err; | |
| 31 | }; | |
| 30 | const file = cwd.openFile(arg, .{}) catch |err| fatal("unable to open file: {t}\n", .{err}); | |
| 32 | 31 | defer file.close(); |
| 33 | 32 | |
| 34 | 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 | 38 | if (!catted_anything) { |
| 39 | try stdout_file.writeFileAll(io.getStdIn(), .{}); | |
| 39 | _ = try stdout.sendFileAll(&stdin_reader, .unlimited); | |
| 40 | 40 | } |
| 41 | 41 | } |
| 42 | 42 |
test/standalone/simple/guess_number/main.zig+11-13| ... | ... | @@ -1,37 +1,35 @@ |
| 1 | 1 | const builtin = @import("builtin"); |
| 2 | 2 | const std = @import("std"); |
| 3 | const io = std.io; | |
| 4 | const fmt = std.fmt; | |
| 5 | 3 | |
| 6 | 4 | pub fn main() !void { |
| 7 | const stdout = io.getStdOut().writer(); | |
| 8 | const stdin = io.getStdIn(); | |
| 5 | var stdout_writer = std.fs.File.stdout().writerStreaming(&.{}); | |
| 6 | const out = &stdout_writer.interface; | |
| 7 | const stdin: std.fs.File = .stdin(); | |
| 9 | 8 | |
| 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"); | |
| 11 | 10 | |
| 12 | 11 | const answer = std.crypto.random.intRangeLessThan(u8, 0, 100) + 1; |
| 13 | 12 | |
| 14 | 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 | 15 | var line_buf: [20]u8 = undefined; |
| 17 | ||
| 18 | 16 | const amt = try stdin.read(&line_buf); |
| 19 | 17 | if (amt == line_buf.len) { |
| 20 | try stdout.print("Input too long.\n", .{}); | |
| 18 | try out.writeAll("Input too long.\n"); | |
| 21 | 19 | continue; |
| 22 | 20 | } |
| 23 | 21 | const line = std.mem.trimEnd(u8, line_buf[0..amt], "\r\n"); |
| 24 | 22 | |
| 25 | const guess = fmt.parseUnsigned(u8, line, 10) catch { | |
| 26 | try stdout.print("Invalid number.\n", .{}); | |
| 23 | const guess = std.fmt.parseUnsigned(u8, line, 10) catch { | |
| 24 | try out.writeAll("Invalid number.\n"); | |
| 27 | 25 | continue; |
| 28 | 26 | }; |
| 29 | 27 | if (guess > answer) { |
| 30 | try stdout.print("Guess lower.\n", .{}); | |
| 28 | try out.writeAll("Guess lower.\n"); | |
| 31 | 29 | } else if (guess < answer) { |
| 32 | try stdout.print("Guess higher.\n", .{}); | |
| 30 | try out.writeAll("Guess higher.\n"); | |
| 33 | 31 | } else { |
| 34 | try stdout.print("You win!\n", .{}); | |
| 32 | try out.writeAll("You win!\n"); | |
| 35 | 33 | return; |
| 36 | 34 | } |
| 37 | 35 | } |
test/standalone/simple/hello_world/hello.zig+1-1| ... | ... | @@ -1,5 +1,5 @@ |
| 1 | 1 | const std = @import("std"); |
| 2 | 2 | |
| 3 | 3 | pub 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 | const Big = @Type(.{ .@"enum" = .{ |
| 7 | 7 | .tag_type = u16, |
| 8 | 8 | .fields = make_fields: { |
| 9 | @setEvalBranchQuota(500000); | |
| 9 | 10 | var fields: [1001]std.builtin.Type.EnumField = undefined; |
| 10 | 11 | for (&fields, 0..) |*field, i| { |
| 11 | 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 | 58 | std.debug.print(">>> found discrepancy <<<\n", .{}); |
| 59 | 59 | const cmd_line_wtf8 = try std.unicode.wtf16LeToWtf8Alloc(allocator, cmd_line_w); |
| 60 | 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)}); | |
| 62 | 62 | |
| 63 | 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 | 27 | wtf8_buf.clearRetainingCapacity(); |
| 28 | 28 | try std.unicode.wtf16LeToWtf8ArrayList(&wtf8_buf, std.mem.span(expected_arg)); |
| 29 | 29 | if (!std.mem.eql(u8, wtf8_buf.items, arg_wtf8)) { |
| 30 | std.debug.print("{}: expected: \"{}\"\n", .{ i, std.zig.fmtEscapes(wtf8_buf.items) }); | |
| 31 | std.debug.print("{}: actual: \"{}\"\n", .{ i, std.zig.fmtEscapes(arg_wtf8) }); | |
| 30 | std.debug.print("{}: expected: \"{f}\"\n", .{ i, std.zig.fmtString(wtf8_buf.items) }); | |
| 31 | std.debug.print("{}: actual: \"{f}\"\n", .{ i, std.zig.fmtString(arg_wtf8) }); | |
| 32 | 32 | eql = false; |
| 33 | 33 | } |
| 34 | 34 | } |
| ... | ... | @@ -36,22 +36,22 @@ fn testArgv(expected_args: []const [*:0]const u16) !void { |
| 36 | 36 | for (expected_args[min_len..], min_len..) |arg, i| { |
| 37 | 37 | wtf8_buf.clearRetainingCapacity(); |
| 38 | 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 | 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 | 44 | const peb = std.os.windows.peb(); |
| 45 | 45 | const lpCmdLine: [*:0]u16 = @ptrCast(peb.ProcessParameters.CommandLine.Buffer); |
| 46 | 46 | wtf8_buf.clearRetainingCapacity(); |
| 47 | 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 | 49 | std.debug.print("expected argv:\n", .{}); |
| 50 | 50 | std.debug.print("&.{{\n", .{}); |
| 51 | 51 | for (expected_args) |arg| { |
| 52 | 52 | wtf8_buf.clearRetainingCapacity(); |
| 53 | 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 | 56 | std.debug.print("}}\n", .{}); |
| 57 | 57 | return error.ArgvMismatch; |
test/standalone/windows_bat_args/echo-args.zig+2-1| ... | ... | @@ -5,7 +5,8 @@ pub fn main() !void { |
| 5 | 5 | defer arena_state.deinit(); |
| 6 | 6 | const arena = arena_state.allocator(); |
| 7 | 7 | |
| 8 | const stdout = std.io.getStdOut().writer(); | |
| 8 | var stdout_writer = std.fs.File.stdout().writerStreaming(&.{}); | |
| 9 | const stdout = &stdout_writer.interface; | |
| 9 | 10 | var args = try std.process.argsAlloc(arena); |
| 10 | 11 | for (args[1..], 1..) |arg, i| { |
| 11 | 12 | try stdout.writeAll(arg); |
test/standalone/windows_spawn/hello.zig+2-1| ... | ... | @@ -1,6 +1,7 @@ |
| 1 | 1 | const std = @import("std"); |
| 2 | 2 | |
| 3 | 3 | pub 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 | 6 | try stdout.writeAll("hello from exe\n"); |
| 6 | 7 | } |
test/tests.zig+11-9| ... | ... | @@ -918,14 +918,16 @@ const test_targets = blk: { |
| 918 | 918 | .link_libc = true, |
| 919 | 919 | }, |
| 920 | 920 | |
| 921 | .{ | |
| 922 | .target = std.Target.Query.parse(.{ | |
| 923 | .arch_os_abi = "riscv64-linux-none", | |
| 924 | .cpu_features = "baseline+v+zbb", | |
| 925 | }) catch unreachable, | |
| 926 | .use_llvm = false, | |
| 927 | .use_lld = false, | |
| 928 | }, | |
| 921 | // TODO implement codegen airFieldParentPtr | |
| 922 | // TODO implement airMemmove for riscv64 | |
| 923 | //.{ | |
| 924 | // .target = std.Target.Query.parse(.{ | |
| 925 | // .arch_os_abi = "riscv64-linux-none", | |
| 926 | // .cpu_features = "baseline+v+zbb", | |
| 927 | // }) catch unreachable, | |
| 928 | // .use_llvm = false, | |
| 929 | // .use_lld = false, | |
| 930 | //}, | |
| 929 | 931 | .{ |
| 930 | 932 | .target = .{ |
| 931 | 933 | .cpu_arch = .riscv64, |
| ... | ... | @@ -2753,7 +2755,7 @@ pub fn addIncrementalTests(b: *std.Build, test_step: *Step) !void { |
| 2753 | 2755 | |
| 2754 | 2756 | run.addArg(b.graph.zig_exe); |
| 2755 | 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}) }); | |
| 2757 | 2759 | |
| 2758 | 2760 | run.addCheck(.{ .expect_term = .{ .Exited = 0 } }); |
| 2759 | 2761 |
tools/docgen.zig+4-5| ... | ... | @@ -43,8 +43,7 @@ pub fn main() !void { |
| 43 | 43 | while (args_it.next()) |arg| { |
| 44 | 44 | if (mem.startsWith(u8, arg, "-")) { |
| 45 | 45 | if (mem.eql(u8, arg, "-h") or mem.eql(u8, arg, "--help")) { |
| 46 | const stdout = io.getStdOut().writer(); | |
| 47 | try stdout.writeAll(usage); | |
| 46 | try fs.File.stdout().writeAll(usage); | |
| 48 | 47 | process.exit(0); |
| 49 | 48 | } else if (mem.eql(u8, arg, "--code-dir")) { |
| 50 | 49 | if (args_it.next()) |param| { |
| ... | ... | @@ -76,9 +75,9 @@ pub fn main() !void { |
| 76 | 75 | var code_dir = try fs.cwd().openDir(code_dir_path, .{}); |
| 77 | 76 | defer code_dir.close(); |
| 78 | 77 | |
| 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); | |
| 80 | 79 | |
| 81 | var buffered_writer = io.bufferedWriter(out_file.writer()); | |
| 80 | var buffered_writer = io.bufferedWriter(out_file.deprecatedWriter()); | |
| 82 | 81 | |
| 83 | 82 | var tokenizer = Tokenizer.init(input_path, input_file_bytes); |
| 84 | 83 | var toc = try genToc(arena, &tokenizer); |
| ... | ... | @@ -426,7 +425,7 @@ fn genToc(allocator: Allocator, tokenizer: *Tokenizer) !Toc { |
| 426 | 425 | try toc.writeByte('\n'); |
| 427 | 426 | try toc.writeByteNTimes(' ', header_stack_size * 4); |
| 428 | 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 | 429 | } else { |
| 431 | 430 | try toc.writeAll("<ul>\n"); |
| 432 | 431 | } |
tools/doctest.zig+2-2| ... | ... | @@ -44,7 +44,7 @@ pub fn main() !void { |
| 44 | 44 | while (args_it.next()) |arg| { |
| 45 | 45 | if (mem.startsWith(u8, arg, "-")) { |
| 46 | 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 | 48 | process.exit(0); |
| 49 | 49 | } else if (mem.eql(u8, arg, "-i")) { |
| 50 | 50 | opt_input = args_it.next() orelse fatal("expected parameter after -i", .{}); |
| ... | ... | @@ -85,7 +85,7 @@ pub fn main() !void { |
| 85 | 85 | var out_file = try fs.cwd().createFile(output_path, .{}); |
| 86 | 86 | defer out_file.close(); |
| 87 | 87 | |
| 88 | var bw = std.io.bufferedWriter(out_file.writer()); | |
| 88 | var bw = std.io.bufferedWriter(out_file.deprecatedWriter()); | |
| 89 | 89 | const out = bw.writer(); |
| 90 | 90 | |
| 91 | 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 | 48 | fatal("failed to load coverage file {}: {s}", .{ cov_path, @errorName(err) }); |
| 49 | 49 | }; |
| 50 | 50 | |
| 51 | var bw = std.io.bufferedWriter(std.io.getStdOut().writer()); | |
| 52 | const stdout = bw.writer(); | |
| 51 | var stdout_buffer: [4000]u8 = undefined; | |
| 52 | var stdout_writer = std.fs.File.stdout().writerStreaming(&stdout_buffer); | |
| 53 | const stdout = &stdout_writer.interface; | |
| 53 | 54 | |
| 54 | 55 | const header: *SeenPcsHeader = @ptrCast(cov_bytes); |
| 55 | 56 | try stdout.print("{any}\n", .{header.*}); |
| ... | ... | @@ -83,5 +84,5 @@ pub fn main() !void { |
| 83 | 84 | }); |
| 84 | 85 | } |
| 85 | 86 | |
| 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 | 5 | const process = std.process; |
| 6 | 6 | const assert = std.debug.assert; |
| 7 | 7 | const tmpDir = std.testing.tmpDir; |
| 8 | const fatal = std.process.fatal; | |
| 9 | const info = std.log.info; | |
| 8 | 10 | |
| 9 | 11 | const Allocator = mem.Allocator; |
| 10 | 12 | const OsTag = std.Target.Os.Tag; |
| ... | ... | @@ -245,19 +247,6 @@ const ArgsIterator = struct { |
| 245 | 247 | } |
| 246 | 248 | }; |
| 247 | 249 | |
| 248 | fn 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 | ||
| 253 | fn 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 | ||
| 261 | 250 | const Version = struct { |
| 262 | 251 | major: u16, |
| 263 | 252 | minor: u8, |
tools/gen_macos_headers_c.zig+9-17| ... | ... | @@ -1,5 +1,7 @@ |
| 1 | 1 | const std = @import("std"); |
| 2 | 2 | const assert = std.debug.assert; |
| 3 | const info = std.log.info; | |
| 4 | const fatal = std.process.fatal; | |
| 3 | 5 | |
| 4 | 6 | const Allocator = std.mem.Allocator; |
| 5 | 7 | |
| ... | ... | @@ -13,19 +15,6 @@ const usage = |
| 13 | 15 | \\-h, --help Print this help and exit |
| 14 | 16 | ; |
| 15 | 17 | |
| 16 | fn 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 | ||
| 21 | fn 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 | ||
| 29 | 18 | pub fn main() anyerror!void { |
| 30 | 19 | var arena_allocator = std.heap.ArenaAllocator.init(gpa); |
| 31 | 20 | defer arena_allocator.deinit(); |
| ... | ... | @@ -58,16 +47,19 @@ pub fn main() anyerror!void { |
| 58 | 47 | |
| 59 | 48 | std.mem.sort([]const u8, paths.items, {}, SortFn.lessThan); |
| 60 | 49 | |
| 61 | const stdout = std.io.getStdOut().writer(); | |
| 62 | try stdout.writeAll("#define _XOPEN_SOURCE\n"); | |
| 50 | var buffer: [2000]u8 = undefined; | |
| 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 | 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 | 58 | \\int main(int argc, char **argv) { |
| 68 | 59 | \\ return 0; |
| 69 | 60 | \\} |
| 70 | 61 | ); |
| 62 | try w.flush(); | |
| 71 | 63 | } |
| 72 | 64 | |
| 73 | 65 | fn findHeaders( |
tools/gen_outline_atomics.zig+4-3| ... | ... | @@ -17,8 +17,9 @@ pub fn main() !void { |
| 17 | 17 | |
| 18 | 18 | //const args = try std.process.argsAlloc(arena); |
| 19 | 19 | |
| 20 | var bw = std.io.bufferedWriter(std.io.getStdOut().writer()); | |
| 21 | const w = bw.writer(); | |
| 20 | var stdout_buffer: [2000]u8 = undefined; | |
| 21 | var stdout_writer = std.fs.File.stdout().writerStreaming(&stdout_buffer); | |
| 22 | const w = &stdout_writer.interface; | |
| 22 | 23 | |
| 23 | 24 | try w.writeAll( |
| 24 | 25 | \\//! This file is generated by tools/gen_outline_atomics.zig. |
| ... | ... | @@ -57,7 +58,7 @@ pub fn main() !void { |
| 57 | 58 | |
| 58 | 59 | try w.writeAll(footer.items); |
| 59 | 60 | try w.writeAll("}\n"); |
| 60 | try bw.flush(); | |
| 61 | try w.flush(); | |
| 61 | 62 | } |
| 62 | 63 | |
| 63 | 64 | fn writeFunction( |
tools/gen_spirv_spec.zig+9-12| ... | ... | @@ -91,9 +91,10 @@ pub fn main() !void { |
| 91 | 91 | |
| 92 | 92 | try readExtRegistry(&exts, a, std.fs.cwd(), args[2]); |
| 93 | 93 | |
| 94 | var bw = std.io.bufferedWriter(std.io.getStdOut().writer()); | |
| 95 | try render(bw.writer(), a, core_spec, exts.items); | |
| 96 | try bw.flush(); | |
| 94 | var buffer: [4000]u8 = undefined; | |
| 95 | var w = std.fs.File.stdout().writerStreaming(&buffer); | |
| 96 | try render(&w, a, core_spec, exts.items); | |
| 97 | try w.flush(); | |
| 97 | 98 | } |
| 98 | 99 | |
| 99 | 100 | fn 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 | 167 | } |
| 167 | 168 | } |
| 168 | 169 | |
| 169 | fn render(writer: anytype, a: Allocator, registry: CoreRegistry, extensions: []const Extension) !void { | |
| 170 | fn render(writer: *std.io.Writer, a: Allocator, registry: CoreRegistry, extensions: []const Extension) !void { | |
| 170 | 171 | try writer.writeAll( |
| 171 | 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 | 189 | \\ none, |
| 189 | 190 | \\ _, |
| 190 | 191 | \\ |
| 191 | \\ pub fn format( | |
| 192 | \\ self: IdResult, | |
| 193 | \\ comptime _: []const u8, | |
| 194 | \\ _: std.fmt.FormatOptions, | |
| 195 | \\ writer: anytype, | |
| 196 | \\ ) @TypeOf(writer).Error!void { | |
| 192 | \\ pub fn format(self: IdResult, writer: *std.io.Writer) std.io.Writer.Error!void { | |
| 197 | 193 | \\ switch (self) { |
| 198 | 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 | 895 | } |
| 900 | 896 | |
| 901 | 897 | fn usageAndExit(arg0: []const u8, code: u8) noreturn { |
| 902 | std.io.getStdErr().writer().print( | |
| 898 | const stderr = std.debug.lockStderrWriter(&.{}); | |
| 899 | stderr.print( | |
| 903 | 900 | \\Usage: {s} <SPIRV-Headers repository path> <path/to/zig/src/codegen/spirv/extinst.zig.grammar.json> |
| 904 | 901 | \\ |
| 905 | 902 | \\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 | 333 | } |
| 334 | 334 | } |
| 335 | 335 | |
| 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 | 339 | try stdout.writeAll( |
| 338 | 340 | \\#ifdef PTR64 |
| 339 | 341 | \\#define WEAK64 .weak |
| ... | ... | @@ -533,6 +535,8 @@ pub fn main() !void { |
| 533 | 535 | .all => {}, |
| 534 | 536 | .single, .multi, .family, .time32 => try stdout.writeAll("#endif\n"), |
| 535 | 537 | } |
| 538 | ||
| 539 | try stdout.flush(); | |
| 536 | 540 | } |
| 537 | 541 | |
| 538 | 542 | fn 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 | 6 | var gpa: std.heap.GeneralPurposeAllocator(.{}) = .init; |
| 7 | 7 | var allocator = gpa.allocator(); |
| 8 | 8 | |
| 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 | 12 | try output.writeAll( |
| 11 | 13 | \\// This file was generated by _generate_JSONTestSuite.zig |
| 12 | 14 | \\// These test cases are sourced from: https://github.com/nst/JSONTestSuite |
| ... | ... | @@ -44,6 +46,8 @@ pub fn main() !void { |
| 44 | 46 | try writeString(output, contents); |
| 45 | 47 | try output.writeAll(");\n}\n"); |
| 46 | 48 | } |
| 49 | ||
| 50 | try output.flush(); | |
| 47 | 51 | } |
| 48 | 52 | |
| 49 | 53 | const 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 | 42 | const query = try std.Target.Query.parse(.{ .arch_os_abi = args[1] }); |
| 43 | 43 | const target = try std.zig.system.resolveTargetQuery(query); |
| 44 | 44 | |
| 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 | 48 | inline for (@typeInfo(std.Target.CType).@"enum".fields) |field| { |
| 47 | 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 | 51 | cName(c_type), |
| 50 | 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 | 55 | cName(c_type), |
| 54 | 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 | 59 | cName(c_type), |
| 58 | 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 | 666 | const allocator = arena.allocator(); |
| 667 | 667 | |
| 668 | 668 | const args = try std.process.argsAlloc(allocator); |
| 669 | if (args.len < 3 or mem.eql(u8, args[1], "--help")) | |
| 670 | usageAndExit(std.io.getStdErr(), args[0], 1); | |
| 669 | if (args.len < 3 or mem.eql(u8, args[1], "--help")) { | |
| 670 | usage(std.debug.lockStderrWriter(&.{}), args[0]) catch std.process.exit(2); | |
| 671 | std.process.exit(1); | |
| 672 | } | |
| 671 | 673 | const zig_exe = args[1]; |
| 672 | 674 | const linux_path = args[2]; |
| 673 | 675 | |
| 674 | var buf_out = std.io.bufferedWriter(std.io.getStdOut().writer()); | |
| 675 | const writer = buf_out.writer(); | |
| 676 | var stdout_buffer: [2000]u8 = undefined; | |
| 677 | var stdout_writer = std.fs.File.stdout().writerStreaming(&stdout_buffer); | |
| 678 | const writer = &stdout_writer.interface; | |
| 676 | 679 | |
| 677 | 680 | var linux_dir = try std.fs.cwd().openDir(linux_path, .{}); |
| 678 | 681 | defer linux_dir.close(); |
| ... | ... | @@ -714,17 +717,16 @@ pub fn main() !void { |
| 714 | 717 | } |
| 715 | 718 | } |
| 716 | 719 | |
| 717 | try buf_out.flush(); | |
| 720 | try writer.flush(); | |
| 718 | 721 | } |
| 719 | 722 | |
| 720 | fn usageAndExit(file: fs.File, arg0: []const u8, code: u8) noreturn { | |
| 721 | file.writer().print( | |
| 723 | fn usage(w: *std.io.Writer, arg0: []const u8) std.io.Writer.Error!void { | |
| 724 | try w.print( | |
| 722 | 725 | \\Usage: {s} /path/to/zig /path/to/linux |
| 723 | 726 | \\Alternative Usage: zig run /path/to/git/zig/tools/generate_linux_syscalls.zig -- /path/to/zig /path/to/linux |
| 724 | 727 | \\ |
| 725 | 728 | \\Generates the list of Linux syscalls for each supported cpu arch, using the Linux development tree. |
| 726 | 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); | |
| 729 | std.process.exit(code); | |
| 731 | , .{arg0}); | |
| 730 | 732 | } |
tools/update_clang_options.zig+22-20| ... | ... | @@ -634,25 +634,25 @@ pub fn main() anyerror!void { |
| 634 | 634 | const allocator = arena.allocator(); |
| 635 | 635 | const args = try std.process.argsAlloc(allocator); |
| 636 | 636 | |
| 637 | if (args.len <= 1) { | |
| 638 | usageAndExit(std.io.getStdErr(), args[0], 1); | |
| 639 | } | |
| 637 | var stdout_buffer: [4000]u8 = undefined; | |
| 638 | var stdout_writer = fs.stdout().writerStreaming(&stdout_buffer); | |
| 639 | const stdout = &stdout_writer.interface; | |
| 640 | ||
| 641 | if (args.len <= 1) printUsageAndExit(args[0]); | |
| 642 | ||
| 640 | 643 | if (std.mem.eql(u8, args[1], "--help")) { |
| 641 | usageAndExit(std.io.getStdOut(), args[0], 0); | |
| 642 | } | |
| 643 | if (args.len < 3) { | |
| 644 | usageAndExit(std.io.getStdErr(), args[0], 1); | |
| 644 | printUsage(stdout, args[0]) catch std.process.exit(2); | |
| 645 | stdout.flush() catch std.process.exit(2); | |
| 646 | std.process.exit(0); | |
| 645 | 647 | } |
| 646 | 648 | |
| 649 | if (args.len < 3) printUsageAndExit(args[0]); | |
| 650 | ||
| 647 | 651 | const llvm_tblgen_exe = args[1]; |
| 648 | if (std.mem.startsWith(u8, llvm_tblgen_exe, "-")) { | |
| 649 | usageAndExit(std.io.getStdErr(), args[0], 1); | |
| 650 | } | |
| 652 | if (std.mem.startsWith(u8, llvm_tblgen_exe, "-")) printUsageAndExit(args[0]); | |
| 651 | 653 | |
| 652 | 654 | const llvm_src_root = args[2]; |
| 653 | if (std.mem.startsWith(u8, llvm_src_root, "-")) { | |
| 654 | usageAndExit(std.io.getStdErr(), args[0], 1); | |
| 655 | } | |
| 655 | if (std.mem.startsWith(u8, llvm_src_root, "-")) printUsageAndExit(args[0]); | |
| 656 | 656 | |
| 657 | 657 | var llvm_to_zig_cpu_features = std.StringHashMap([]const u8).init(allocator); |
| 658 | 658 | |
| ... | ... | @@ -719,8 +719,6 @@ pub fn main() anyerror!void { |
| 719 | 719 | // "W" and "Wl,". So we sort this list in order of descending priority. |
| 720 | 720 | std.mem.sort(*json.ObjectMap, all_objects.items, {}, objectLessThan); |
| 721 | 721 | |
| 722 | var buffered_stdout = std.io.bufferedWriter(std.io.getStdOut().writer()); | |
| 723 | const stdout = buffered_stdout.writer(); | |
| 724 | 722 | try stdout.writeAll( |
| 725 | 723 | \\// This file is generated by tools/update_clang_options.zig. |
| 726 | 724 | \\// zig fmt: off |
| ... | ... | @@ -815,7 +813,7 @@ pub fn main() anyerror!void { |
| 815 | 813 | \\ |
| 816 | 814 | ); |
| 817 | 815 | |
| 818 | try buffered_stdout.flush(); | |
| 816 | try stdout.flush(); | |
| 819 | 817 | } |
| 820 | 818 | |
| 821 | 819 | // 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 | 964 | return std.mem.lessThan(u8, a_key, b_key); |
| 967 | 965 | } |
| 968 | 966 | |
| 969 | fn usageAndExit(file: fs.File, arg0: []const u8, code: u8) noreturn { | |
| 970 | file.writer().print( | |
| 967 | fn printUsageAndExit(arg0: []const u8) noreturn { | |
| 968 | printUsage(std.debug.lockStderrWriter(&.{}), arg0) catch std.process.exit(2); | |
| 969 | std.process.exit(1); | |
| 970 | } | |
| 971 | ||
| 972 | fn printUsage(w: *std.io.Writer, arg0: []const u8) std.io.Writer.Error!void { | |
| 973 | try w.print( | |
| 971 | 974 | \\Usage: {s} /path/to/llvm-tblgen /path/to/git/llvm/llvm-project |
| 972 | 975 | \\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 | 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); | |
| 977 | std.process.exit(code); | |
| 979 | , .{arg0}); | |
| 978 | 980 | } |
tools/update_cpu_features.zig+2-2| ... | ... | @@ -2082,8 +2082,8 @@ fn processOneTarget(job: Job) void { |
| 2082 | 2082 | } |
| 2083 | 2083 | |
| 2084 | 2084 | fn usageAndExit(arg0: []const u8, code: u8) noreturn { |
| 2085 | const stderr = std.io.getStdErr(); | |
| 2086 | stderr.writer().print( | |
| 2085 | const stderr = std.debug.lockStderrWriter(&.{}); | |
| 2086 | stderr.print( | |
| 2087 | 2087 | \\Usage: {s} /path/to/llvm-tblgen /path/git/llvm-project /path/git/zig [zig_name filter] |
| 2088 | 2088 | \\ |
| 2089 | 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 | 11 | const arena = arena_state.allocator(); |
| 12 | 12 | |
| 13 | 13 | const args = try std.process.argsAlloc(arena); |
| 14 | if (args.len <= 1) { | |
| 15 | usageAndExit(std.io.getStdErr(), args[0], 1); | |
| 16 | } | |
| 14 | if (args.len <= 1) printUsageAndExit(args[0]); | |
| 17 | 15 | |
| 18 | 16 | const zig_src_root = args[1]; |
| 19 | if (mem.startsWith(u8, zig_src_root, "-")) { | |
| 20 | usageAndExit(std.io.getStdErr(), args[0], 1); | |
| 21 | } | |
| 17 | if (mem.startsWith(u8, zig_src_root, "-")) printUsageAndExit(args[0]); | |
| 22 | 18 | |
| 23 | 19 | var zig_src_dir = try fs.cwd().openDir(zig_src_root, .{}); |
| 24 | 20 | defer zig_src_dir.close(); |
| ... | ... | @@ -193,10 +189,14 @@ pub fn main() anyerror!void { |
| 193 | 189 | } |
| 194 | 190 | } |
| 195 | 191 | |
| 196 | fn usageAndExit(file: fs.File, arg0: []const u8, code: u8) noreturn { | |
| 197 | file.writer().print( | |
| 192 | fn printUsageAndExit(arg0: []const u8) noreturn { | |
| 193 | printUsage(std.debug.lockStderrWriter(&.{}), arg0) catch std.process.exit(2); | |
| 194 | std.process.exit(1); | |
| 195 | } | |
| 196 | ||
| 197 | fn printUsage(w: *std.io.Writer, arg0: []const u8) std.io.Writer.Error!void { | |
| 198 | return w.print( | |
| 198 | 199 | \\Usage: {s} /path/git/zig |
| 199 | 200 | \\ |
| 200 | , .{arg0}) catch std.process.exit(1); | |
| 201 | std.process.exit(code); | |
| 201 | , .{arg0}); | |
| 202 | 202 | } |