authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-07-06 15:51:44-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-07-07 22:43:53-07:00
log7e2a26c0c441a902968726442114e3590820433b
tree90035e47e0208afa7d1bcd3484e30d22d2a24f4e
parent5378fdb153bc76990105e3640e7725e434e8cdee

std.io.Writer.printValue: rework logic

Alignment and fill options only apply to numbers. Rework the implementation to mainly branch on the format string rather than the type information. This is more straightforward to maintain and more straightforward for comptime evaluation. Enums support being printed as decimal, hexadecimal, octal, and binary. `formatInteger` is another possible format method that is unconditionally called when the value type is struct and one of the integer-printing format specifiers are used.

29 files changed, 636 insertions(+), 452 deletions(-)

lib/compiler/aro/aro/Diagnostics.zig+2-2
...@@ -461,10 +461,10 @@ pub fn renderMessage(comp: *Compilation, m: anytype, msg: Message) void {...@@ -461,10 +461,10 @@ pub fn renderMessage(comp: *Compilation, m: anytype, msg: Message) void {
461 try writer.writeByte(@intCast(codepoint));461 try writer.writeByte(@intCast(codepoint));
462 } else if (codepoint < 0xFFFF) {462 } else if (codepoint < 0xFFFF) {
463 try writer.writeAll("\\u");463 try writer.writeAll("\\u");
464 try writer.printIntOptions(codepoint, 16, .upper, .{ .fill = '0', .width = 4 });464 try writer.printInt(codepoint, 16, .upper, .{ .fill = '0', .width = 4 });
465 } else {465 } else {
466 try writer.writeAll("\\U");466 try writer.writeAll("\\U");
467 try writer.printIntOptions(codepoint, 16, .upper, .{ .fill = '0', .width = 8 });467 try writer.printInt(codepoint, 16, .upper, .{ .fill = '0', .width = 8 });
468 }468 }
469 }469 }
470 }470 }
lib/compiler/aro/aro/Preprocessor.zig+1-1
...@@ -3262,7 +3262,7 @@ fn printLinemarker(...@@ -3262,7 +3262,7 @@ fn printLinemarker(
3262 // containing the same bytes as the input regardless of encoding.3262 // containing the same bytes as the input regardless of encoding.
3263 else => {3263 else => {
3264 try w.writeAll("\\x");3264 try w.writeAll("\\x");
3265 // TODO try w.printIntOptions(byte, 16, .lower, .{ .width = 2, .fill = '0' });3265 // TODO try w.printInt(byte, 16, .lower, .{ .width = 2, .fill = '0' });
3266 try w.print("{x:0>2}", .{byte});3266 try w.print("{x:0>2}", .{byte});
3267 },3267 },
3268 };3268 };
lib/compiler/aro/aro/Value.zig+1-2
...@@ -961,8 +961,7 @@ pub fn print(v: Value, ty: Type, comp: *const Compilation, w: anytype) @TypeOf(w...@@ -961,8 +961,7 @@ pub fn print(v: Value, ty: Type, comp: *const Compilation, w: anytype) @TypeOf(w
961 switch (key) {961 switch (key) {
962 .null => return w.writeAll("nullptr_t"),962 .null => return w.writeAll("nullptr_t"),
963 .int => |repr| switch (repr) {963 .int => |repr| switch (repr) {
964 inline .u64, .i64 => |x| return w.print("{d}", .{x}),964 inline .u64, .i64, .big_int => |x| return w.print("{d}", .{x}),
965 .big_int => |x| return w.print("{fd}", .{x}),
966 },965 },
967 .float => |repr| switch (repr) {966 .float => |repr| switch (repr) {
968 .f16 => |x| return w.print("{d}", .{@round(@as(f64, @floatCast(x)) * 1000) / 1000}),967 .f16 => |x| return w.print("{d}", .{@round(@as(f64, @floatCast(x)) * 1000) / 1000}),
lib/std/Build/Step/CheckObject.zig+4-7
...@@ -230,12 +230,7 @@ const ComputeCompareExpected = struct {...@@ -230,12 +230,7 @@ const ComputeCompareExpected = struct {
230 literal: u64,230 literal: u64,
231 },231 },
232232
233 pub fn format(233 pub fn format(value: ComputeCompareExpected, bw: *Writer) Writer.Error!void {
234 value: ComputeCompareExpected,
235 bw: *Writer,
236 comptime fmt: []const u8,
237 ) !void {
238 if (fmt.len != 0) std.fmt.invalidFmtError(fmt, value);
239 try bw.print("{s} ", .{@tagName(value.op)});234 try bw.print("{s} ", .{@tagName(value.op)});
240 switch (value.value) {235 switch (value.value) {
241 .variable => |name| try bw.writeAll(name),236 .variable => |name| try bw.writeAll(name),
...@@ -571,7 +566,9 @@ fn make(step: *Step, make_options: Step.MakeOptions) !void {...@@ -571,7 +566,9 @@ fn make(step: *Step, make_options: Step.MakeOptions) !void {
571 null,566 null,
572 .of(u64),567 .of(u64),
573 null,568 null,
574 ) catch |err| return step.fail("unable to read '{f'}': {s}", .{ src_path, @errorName(err) });569 ) catch |err| return step.fail("unable to read '{f}': {s}", .{
570 std.fmt.alt(src_path, .formatEscapeChar), @errorName(err),
571 });
575572
576 var vars: std.StringHashMap(u64) = .init(gpa);573 var vars: std.StringHashMap(u64) = .init(gpa);
577 for (check_object.checks.items) |chk| {574 for (check_object.checks.items) |chk| {
lib/std/Target.zig+7-18
...@@ -301,24 +301,13 @@ pub const Os = struct {...@@ -301,24 +301,13 @@ pub const Os = struct {
301301
302 /// This function is defined to serialize a Zig source code representation of this302 /// This function is defined to serialize a Zig source code representation of this
303 /// type, that, when parsed, will deserialize into the same data.303 /// type, that, when parsed, will deserialize into the same data.
304 pub fn format(ver: WindowsVersion, w: *std.io.Writer, comptime f: []const u8) std.io.Writer.Error!void {304 pub fn format(wv: WindowsVersion, w: *std.io.Writer) std.io.Writer.Error!void {
305 const maybe_name = std.enums.tagName(WindowsVersion, ver);305 if (std.enums.tagName(WindowsVersion, wv)) |name| {
306 if (comptime std.mem.eql(u8, f, "s")) {306 var vecs: [2][]const u8 = .{ ".", name };
307 if (maybe_name) |name|307 return w.writeVecAll(&vecs);
308 try w.print(".{s}", .{name})308 } else {
309 else309 return w.print("@enumFromInt(0x{X:0>8})", .{wv});
310 try w.print(".{d}", .{@intFromEnum(ver)});310 }
311 } else if (comptime std.mem.eql(u8, f, "c")) {
312 if (maybe_name) |name|
313 try w.print(".{s}", .{name})
314 else
315 try w.print("@enumFromInt(0x{X:0>8})", .{@intFromEnum(ver)});
316 } else if (f.len == 0) {
317 if (maybe_name) |name|
318 try w.print("WindowsVersion.{s}", .{name})
319 else
320 try w.print("WindowsVersion(0x{X:0>8})", .{@intFromEnum(ver)});
321 } else std.fmt.invalidFmtError(f, ver);
322 }311 }
323 };312 };
324313
lib/std/Uri.zig+14
...@@ -240,6 +240,10 @@ pub fn parseAfterScheme(scheme: []const u8, text: []const u8) ParseError!Uri {...@@ -240,6 +240,10 @@ pub fn parseAfterScheme(scheme: []const u8, text: []const u8) ParseError!Uri {
240 return uri;240 return uri;
241}241}
242242
243pub fn format(uri: *const Uri, writer: *std.io.Writer) std.io.Writer.Error!void {
244 return writeToStream(uri, writer, .all);
245}
246
243pub fn writeToStream(uri: *const Uri, writer: *std.io.Writer, flags: Format.Flags) std.io.Writer.Error!void {247pub fn writeToStream(uri: *const Uri, writer: *std.io.Writer, flags: Format.Flags) std.io.Writer.Error!void {
244 if (flags.scheme) {248 if (flags.scheme) {
245 try writer.print("{s}:", .{uri.scheme});249 try writer.print("{s}:", .{uri.scheme});
...@@ -302,6 +306,16 @@ pub const Format = struct {...@@ -302,6 +306,16 @@ pub const Format = struct {
302 fragment: bool = false,306 fragment: bool = false,
303 /// When true, include the port part of the URI. Ignored when `port` is null.307 /// When true, include the port part of the URI. Ignored when `port` is null.
304 port: bool = true,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 };
305 };319 };
306320
307 pub fn default(f: Format, writer: *std.io.Writer) std.io.Writer.Error!void {321 pub fn default(f: Format, writer: *std.io.Writer) std.io.Writer.Error!void {
lib/std/fmt.zig+40-62
...@@ -53,16 +53,20 @@ pub const Options = struct {...@@ -53,16 +53,20 @@ pub const Options = struct {
53/// - when using a field name, you are required to enclose the field name (an identifier) in square53/// - when using a field name, you are required to enclose the field name (an identifier) in square
54/// brackets, e.g. {[score]...} as opposed to the numeric index form which can be written e.g. {2...}54/// brackets, e.g. {[score]...} as opposed to the numeric index form which can be written e.g. {2...}
55/// - *specifier* is a type-dependent formatting option that determines how a type should formatted (see below)55/// - *specifier* is a type-dependent formatting option that determines how a type should formatted (see below)
56/// - *fill* is a single byte which is used to pad the formatted text56/// - *fill* is a single byte which is used to pad formatted numbers.
57/// - *alignment* is one of the three bytes '<', '^', or '>' to make the text left-, center-, or right-aligned, respectively57/// - *alignment* is one of the three bytes '<', '^', or '>' to make numbers
58/// - *width* is the total width of the field in bytes. This is generally only58/// left, center, or right-aligned, respectively.
59/// useful for ASCII text, such as numbers.59/// - *width* is the total width of the field in bytes. This only applies to number formatting.
60/// - *precision* specifies how many decimals a formatted number should have60/// - *precision* specifies how many decimals a formatted number should have.
61///61///
62/// Note that most of the parameters are optional and may be omitted. Also you can leave out separators like `:` and `.` when62/// Note that most of the parameters are optional and may be omitted. Also you
63/// all parameters after the separator are omitted.63/// can leave out separators like `:` and `.` when all parameters after the
64/// Only exception is the *fill* parameter. If a non-zero *fill* character is required at the same time as *width* is specified,64/// separator are omitted.
65/// one has to specify *alignment* as well, as otherwise the digit following `:` is interpreted as *width*, not *fill*.65///
66/// Only exception is the *fill* parameter. If a non-zero *fill* character is
67/// required at the same time as *width* is specified, one has to specify
68/// *alignment* as well, as otherwise the digit following `:` is interpreted as
69/// *width*, not *fill*.
66///70///
67/// The *specifier* has several options for types:71/// The *specifier* has several options for types:
68/// - `x` and `X`: output numeric value in hexadecimal notation, or string in hexadecimal bytes72/// - `x` and `X`: output numeric value in hexadecimal notation, or string in hexadecimal bytes
...@@ -405,9 +409,9 @@ pub const ArgState = struct {...@@ -405,9 +409,9 @@ pub const ArgState = struct {
405/// Asserts the rendered integer value fits in `buffer`.409/// Asserts the rendered integer value fits in `buffer`.
406/// Returns the end index within `buffer`.410/// Returns the end index within `buffer`.
407pub fn printInt(buffer: []u8, value: anytype, base: u8, case: Case, options: Options) usize {411pub fn printInt(buffer: []u8, value: anytype, base: u8, case: Case, options: Options) usize {
408 var bw: Writer = .fixed(buffer);412 var w: Writer = .fixed(buffer);
409 bw.printIntOptions(value, base, case, options) catch unreachable;413 w.printInt(value, base, case, options) catch unreachable;
410 return bw.end;414 return w.end;
411}415}
412416
413/// Converts values in the range [0, 100) to a base 10 string.417/// Converts values in the range [0, 100) to a base 10 string.
...@@ -956,35 +960,23 @@ fn expectArrayFmt(expected: []const u8, comptime template: []const u8, comptime...@@ -956,35 +960,23 @@ fn expectArrayFmt(expected: []const u8, comptime template: []const u8, comptime
956}960}
957961
958test "array" {962test "array" {
959 {963 const value: [3]u8 = "abc".*;
960 const value: [3]u8 = "abc".*;964 try expectArrayFmt("array: abc\n", "array: {s}\n", value);
961 try expectArrayFmt("array: abc\n", "array: {s}\n", value);965 try expectArrayFmt("array: 616263\n", "array: {x}\n", value);
962 try expectArrayFmt("array: { 97, 98, 99 }\n", "array: {d}\n", value);966 try expectArrayFmt("array: { 97, 98, 99 }\n", "array: {any}\n", value);
963 try expectArrayFmt("array: 616263\n", "array: {x}\n", value);
964 try expectArrayFmt("array: { 97, 98, 99 }\n", "array: {any}\n", value);
965
966 var buf: [100]u8 = undefined;
967 try expectFmt(
968 try bufPrint(buf[0..], "array: [3]u8@{x}\n", .{@intFromPtr(&value)}),
969 "array: {*}\n",
970 .{&value},
971 );
972 }
973967
974 {968 var buf: [100]u8 = undefined;
975 const value = [2][3]u8{ "abc".*, "def".* };969 try expectFmt(
976970 try bufPrint(buf[0..], "array: [3]u8@{x}\n", .{@intFromPtr(&value)}),
977 try expectArrayFmt("array: { abc, def }\n", "array: {s}\n", value);971 "array: {*}\n",
978 try expectArrayFmt("array: { { 97, 98, 99 }, { 100, 101, 102 } }\n", "array: {d}\n", value);972 .{&value},
979 try expectArrayFmt("array: { 616263, 646566 }\n", "array: {x}\n", value);973 );
980 }
981}974}
982975
983test "slice" {976test "slice" {
984 {977 {
985 const value: []const u8 = "abc";978 const value: []const u8 = "abc";
986 try expectFmt("slice: abc\n", "slice: {s}\n", .{value});979 try expectFmt("slice: abc\n", "slice: {s}\n", .{value});
987 try expectFmt("slice: { 97, 98, 99 }\n", "slice: {d}\n", .{value});
988 try expectFmt("slice: 616263\n", "slice: {x}\n", .{value});980 try expectFmt("slice: 616263\n", "slice: {x}\n", .{value});
989 try expectFmt("slice: { 97, 98, 99 }\n", "slice: {any}\n", .{value});981 try expectFmt("slice: { 97, 98, 99 }\n", "slice: {any}\n", .{value});
990 }982 }
...@@ -999,17 +991,12 @@ test "slice" {...@@ -999,17 +991,12 @@ test "slice" {
999 try expectFmt("buf: \x00hello\x00\n", "buf: {s}\n", .{null_term_slice});991 try expectFmt("buf: \x00hello\x00\n", "buf: {s}\n", .{null_term_slice});
1000 }992 }
1001993
1002 try expectFmt("buf: Test\n", "buf: {s:5}\n", .{"Test"});
1003 try expectFmt("buf: Test\n Other text", "buf: {s}\n Other text", .{"Test"});994 try expectFmt("buf: Test\n Other text", "buf: {s}\n Other text", .{"Test"});
1004995
1005 {996 {
1006 var int_slice = [_]u32{ 1, 4096, 391891, 1111111111 };997 var int_slice = [_]u32{ 1, 4096, 391891, 1111111111 };
1007 var runtime_zero: usize = 0;998 const input: []const u32 = &int_slice;
1008 _ = &runtime_zero;999 try expectFmt("int: { 1, 4096, 391891, 1111111111 }", "int: {any}", .{input});
1009 try expectFmt("int: { 1, 4096, 391891, 1111111111 }", "int: {any}", .{int_slice[runtime_zero..]});
1010 try expectFmt("int: { 1, 4096, 391891, 1111111111 }", "int: {d}", .{int_slice[runtime_zero..]});
1011 try expectFmt("int: { 1, 1000, 5fad3, 423a35c7 }", "int: {x}", .{int_slice[runtime_zero..]});
1012 try expectFmt("int: { 00001, 01000, 5fad3, 423a35c7 }", "int: {x:0>5}", .{int_slice[runtime_zero..]});
1013 }1000 }
1014 {1001 {
1015 const S1 = struct {1002 const S1 = struct {
...@@ -1054,11 +1041,6 @@ test "cstr" {...@@ -1054,11 +1041,6 @@ test "cstr" {
1054 "cstr: {s}\n",1041 "cstr: {s}\n",
1055 .{@as([*c]const u8, @ptrCast("Test C"))},1042 .{@as([*c]const u8, @ptrCast("Test C"))},
1056 );1043 );
1057 try expectFmt(
1058 "cstr: Test C\n",
1059 "cstr: {s:10}\n",
1060 .{@as([*c]const u8, @ptrCast("Test C"))},
1061 );
1062}1044}
10631045
1064test "struct" {1046test "struct" {
...@@ -1428,16 +1410,12 @@ test "enum-literal" {...@@ -1428,16 +1410,12 @@ test "enum-literal" {
14281410
1429test "padding" {1411test "padding" {
1430 try expectFmt("Simple", "{s}", .{"Simple"});1412 try expectFmt("Simple", "{s}", .{"Simple"});
1431 try expectFmt(" true", "{:10}", .{true});1413 try expectFmt(" 1234", "{:10}", .{1234});
1432 try expectFmt(" true", "{:>10}", .{true});1414 try expectFmt(" 1234", "{:>10}", .{1234});
1433 try expectFmt("======true", "{:=>10}", .{true});1415 try expectFmt("======1234", "{:=>10}", .{1234});
1434 try expectFmt("true======", "{:=<10}", .{true});1416 try expectFmt("1234======", "{:=<10}", .{1234});
1435 try expectFmt(" true ", "{:^10}", .{true});1417 try expectFmt(" 1234 ", "{:^10}", .{1234});
1436 try expectFmt("===true===", "{:=^10}", .{true});1418 try expectFmt("===1234===", "{:=^10}", .{1234});
1437 try expectFmt(" Minimum width", "{s:18} width", .{"Minimum"});
1438 try expectFmt("==================Filled", "{s:=>24}", .{"Filled"});
1439 try expectFmt(" Centered ", "{s:^24}", .{"Centered"});
1440 try expectFmt("-", "{s:-^1}", .{""});
1441 try expectFmt("====a", "{c:=>5}", .{'a'});1419 try expectFmt("====a", "{c:=>5}", .{'a'});
1442 try expectFmt("==a==", "{c:=^5}", .{'a'});1420 try expectFmt("==a==", "{c:=^5}", .{'a'});
1443 try expectFmt("a====", "{c:=<5}", .{'a'});1421 try expectFmt("a====", "{c:=<5}", .{'a'});
...@@ -1485,17 +1463,17 @@ test "named arguments" {...@@ -1485,17 +1463,17 @@ test "named arguments" {
14851463
1486test "runtime width specifier" {1464test "runtime width specifier" {
1487 const width: usize = 9;1465 const width: usize = 9;
1488 try expectFmt("~~hello~~", "{s:~^[1]}", .{ "hello", width });1466 try expectFmt("~~12345~~", "{d:~^[1]}", .{ 12345, width });
1489 try expectFmt("~~hello~~", "{s:~^[width]}", .{ .string = "hello", .width = width });1467 try expectFmt("~~12345~~", "{d:~^[width]}", .{ .string = 12345, .width = width });
1490 try expectFmt(" hello", "{s:[1]}", .{ "hello", width });1468 try expectFmt(" 12345", "{d:[1]}", .{ 12345, width });
1491 try expectFmt("42 hello", "{d} {s:[2]}", .{ 42, "hello", width });1469 try expectFmt("42 12345", "{d} {d:[2]}", .{ 42, 12345, width });
1492}1470}
14931471
1494test "runtime precision specifier" {1472test "runtime precision specifier" {
1495 const number: f32 = 3.1415;1473 const number: f32 = 3.1415;
1496 const precision: usize = 2;1474 const precision: usize = 2;
1497 try expectFmt("3.14e0", "{:1.[1]}", .{ number, precision });1475 try expectFmt("3.14e0", "{e:1.[1]}", .{ number, precision });
1498 try expectFmt("3.14e0", "{:1.[precision]}", .{ .number = number, .precision = precision });1476 try expectFmt("3.14e0", "{e:1.[precision]}", .{ .number = number, .precision = precision });
1499}1477}
15001478
1501test "recursive format function" {1479test "recursive format function" {
lib/std/io/Writer.zig+284-207
...@@ -777,15 +777,15 @@ pub fn printAddress(w: *Writer, value: anytype) Error!void {...@@ -777,15 +777,15 @@ pub fn printAddress(w: *Writer, value: anytype) Error!void {
777 .pointer => |info| {777 .pointer => |info| {
778 try w.writeAll(@typeName(info.child) ++ "@");778 try w.writeAll(@typeName(info.child) ++ "@");
779 if (info.size == .slice)779 if (info.size == .slice)
780 try w.printIntOptions(@intFromPtr(value.ptr), 16, .lower, .{})780 try w.printInt(@intFromPtr(value.ptr), 16, .lower, .{})
781 else781 else
782 try w.printIntOptions(@intFromPtr(value), 16, .lower, .{});782 try w.printInt(@intFromPtr(value), 16, .lower, .{});
783 return;783 return;
784 },784 },
785 .optional => |info| {785 .optional => |info| {
786 if (@typeInfo(info.child) == .pointer) {786 if (@typeInfo(info.child) == .pointer) {
787 try w.writeAll(@typeName(info.child) ++ "@");787 try w.writeAll(@typeName(info.child) ++ "@");
788 try w.printIntOptions(@intFromPtr(value), 16, .lower, .{});788 try w.printInt(@intFromPtr(value), 16, .lower, .{});
789 return;789 return;
790 }790 }
791 },791 },
...@@ -804,11 +804,147 @@ pub fn printValue(...@@ -804,11 +804,147 @@ pub fn printValue(
804) Error!void {804) Error!void {
805 const T = @TypeOf(value);805 const T = @TypeOf(value);
806806
807 if (fmt.len == 1) switch (fmt[0]) {807 switch (fmt.len) {
808 '*' => return w.printAddress(value),808 1 => switch (fmt[0]) {
809 'f' => return value.format(w),809 '*' => return w.printAddress(value),
810 'f' => return value.format(w),
811 'd' => switch (@typeInfo(T)) {
812 .float, .comptime_float => return printFloat(w, value, .decimal, options),
813 .int, .comptime_int => return printInt(w, value, 10, .lower, options),
814 .@"struct" => return value.formatInteger(w, 10, .lower),
815 .@"enum" => return printInt(w, @intFromEnum(value), 10, .lower, options),
816 .vector => return printVector(w, fmt, options, value, max_depth),
817 else => invalidFmtError(fmt, value),
818 },
819 'c' => return w.printAsciiChar(value, options),
820 'u' => return w.printUnicodeCodepoint(value),
821 'b' => switch (@typeInfo(T)) {
822 .int, .comptime_int => return printInt(w, value, 2, .lower, options),
823 .@"enum" => return printInt(w, @intFromEnum(value), 2, .lower, options),
824 .@"struct" => return value.formatInteger(w, 2, .lower),
825 .vector => return printVector(w, fmt, options, value, max_depth),
826 else => invalidFmtError(fmt, value),
827 },
828 'o' => switch (@typeInfo(T)) {
829 .int, .comptime_int => return printInt(w, value, 8, .lower, options),
830 .@"enum" => return printInt(w, @intFromEnum(value), 8, .lower, options),
831 .@"struct" => return value.formatInteger(w, 8, .lower),
832 .vector => return printVector(w, fmt, options, value, max_depth),
833 else => invalidFmtError(fmt, value),
834 },
835 'x' => switch (@typeInfo(T)) {
836 .float, .comptime_float => return printFloatHexOptions(w, value, .lower, options),
837 .int, .comptime_int => return printInt(w, value, 16, .lower, options),
838 .@"enum" => return printInt(w, @intFromEnum(value), 16, .lower, options),
839 .@"struct" => return value.formatInteger(w, 16, .lower),
840 .pointer => |info| switch (info.size) {
841 .one, .slice => {
842 const slice: []const u8 = value;
843 return printHex(w, slice, .lower);
844 },
845 .many, .c => {
846 const slice: [:0]const u8 = std.mem.span(value);
847 return printHex(w, slice, .lower);
848 },
849 },
850 .array => {
851 const slice: []const u8 = &value;
852 return printHex(w, slice, .lower);
853 },
854 .vector => return printVector(w, fmt, options, value, max_depth),
855 else => invalidFmtError(fmt, value),
856 },
857 'X' => switch (@typeInfo(T)) {
858 .float, .comptime_float => return printFloatHexOptions(w, value, .lower, options),
859 .int, .comptime_int => return printInt(w, value, 16, .upper, options),
860 .@"enum" => return printInt(w, @intFromEnum(value), 16, .upper, options),
861 .@"struct" => return value.formatInteger(w, 16, .upper),
862 .pointer => |info| switch (info.size) {
863 .one, .slice => {
864 const slice: []const u8 = value;
865 return printHex(w, slice, .upper);
866 },
867 .many, .c => {
868 const slice: [:0]const u8 = std.mem.span(value);
869 return printHex(w, slice, .upper);
870 },
871 },
872 .array => {
873 const slice: []const u8 = &value;
874 return printHex(w, slice, .upper);
875 },
876 .vector => return printVector(w, fmt, options, value, max_depth),
877 else => invalidFmtError(fmt, value),
878 },
879 's' => switch (@typeInfo(T)) {
880 .pointer => |info| switch (info.size) {
881 .one, .slice => {
882 const slice: []const u8 = value;
883 return w.writeAll(slice);
884 },
885 .many, .c => {
886 const slice: [:0]const u8 = std.mem.span(value);
887 return w.writeAll(slice);
888 },
889 },
890 .array => {
891 const slice: []const u8 = &value;
892 return w.writeAll(slice);
893 },
894 else => invalidFmtError(fmt, value),
895 },
896 'B' => switch (@typeInfo(T)) {
897 .int, .comptime_int => return w.printByteSize(value, .decimal, options),
898 .@"struct" => return value.formatByteSize(w, .decimal),
899 else => invalidFmtError(fmt, value),
900 },
901 'D' => switch (@typeInfo(T)) {
902 .int, .comptime_int => return w.printDuration(value, options),
903 .@"struct" => return value.formatDuration(w),
904 else => invalidFmtError(fmt, value),
905 },
906 'e' => switch (@typeInfo(T)) {
907 .float, .comptime_float => return printFloat(w, value, .scientific, options),
908 .@"struct" => return value.formatFloat(w, .scientific),
909 else => invalidFmtError(fmt, value),
910 },
911 't' => switch (@typeInfo(T)) {
912 .error_set => return w.writeAll(@errorName(value)),
913 .@"enum", .@"union" => return w.writeAll(@tagName(value)),
914 else => invalidFmtError(fmt, value),
915 },
916 else => {},
917 },
918 2 => switch (fmt[0]) {
919 'B' => switch (fmt[1]) {
920 'i' => switch (@typeInfo(T)) {
921 .int, .comptime_int => return w.printByteSize(value, .binary, options),
922 .@"struct" => return value.formatByteSize(w, .binary),
923 else => invalidFmtError(fmt, value),
924 },
925 else => {},
926 },
927 else => {},
928 },
929 3 => if (fmt[0] == 'b' and fmt[1] == '6' and fmt[2] == '4') switch (@typeInfo(T)) {
930 .pointer => |info| switch (info.size) {
931 .one, .slice => {
932 const slice: []const u8 = value;
933 return w.printBase64(slice);
934 },
935 .many, .c => {
936 const slice: [:0]const u8 = std.mem.span(value);
937 return w.printBase64(slice);
938 },
939 },
940 .array => {
941 const slice: []const u8 = &value;
942 return w.printBase64(slice);
943 },
944 else => invalidFmtError(fmt, value),
945 },
810 else => {},946 else => {},
811 };947 }
812948
813 const is_any = comptime std.mem.eql(u8, fmt, ANY);949 const is_any = comptime std.mem.eql(u8, fmt, ANY);
814 if (!is_any and std.meta.hasMethod(T, "format") and fmt.len == 0) {950 if (!is_any and std.meta.hasMethod(T, "format") and fmt.len == 0) {
...@@ -817,15 +953,21 @@ pub fn printValue(...@@ -817,15 +953,21 @@ pub fn printValue(
817 }953 }
818954
819 switch (@typeInfo(T)) {955 switch (@typeInfo(T)) {
820 .float, .comptime_float => return w.printFloat(if (is_any) "d" else fmt, options, value),956 .float, .comptime_float => {
821 .int, .comptime_int => return w.printInt(if (is_any) "d" else fmt, options, value),957 if (!is_any and fmt.len != 0) invalidFmtError(fmt, value);
958 return printFloat(w, value, .decimal, options);
959 },
960 .int, .comptime_int => {
961 if (!is_any and fmt.len != 0) invalidFmtError(fmt, value);
962 return printInt(w, value, 10, .lower, options);
963 },
822 .bool => {964 .bool => {
823 if (!is_any and fmt.len != 0) invalidFmtError(fmt, value);965 if (!is_any and fmt.len != 0) invalidFmtError(fmt, value);
824 return w.alignBufferOptions(if (value) "true" else "false", options);966 return w.writeAll(if (value) "true" else "false");
825 },967 },
826 .void => {968 .void => {
827 if (!is_any and fmt.len != 0) invalidFmtError(fmt, value);969 if (!is_any and fmt.len != 0) invalidFmtError(fmt, value);
828 return w.alignBufferOptions("void", options);970 return w.writeAll("void");
829 },971 },
830 .optional => {972 .optional => {
831 const remaining_fmt = comptime if (fmt.len > 0 and fmt[0] == '?')973 const remaining_fmt = comptime if (fmt.len > 0 and fmt[0] == '?')
...@@ -854,40 +996,18 @@ pub fn printValue(...@@ -854,40 +996,18 @@ pub fn printValue(
854 }996 }
855 },997 },
856 .error_set => {998 .error_set => {
857 if (fmt.len == 1 and fmt[0] == 't') return w.writeAll(@errorName(value));
858 if (!is_any and fmt.len != 0) invalidFmtError(fmt, value);999 if (!is_any and fmt.len != 0) invalidFmtError(fmt, value);
859 try printErrorSet(w, value);1000 return printErrorSet(w, value);
860 },1001 },
861 .@"enum" => {1002 .@"enum" => |info| {
862 if (fmt.len == 1 and fmt[0] == 't') {1003 if (!is_any and fmt.len != 0) invalidFmtError(fmt, value);
863 try w.writeAll(@tagName(value));1004 if (info.is_exhaustive) {
864 return;1005 return printEnumExhaustive(w, value);
865 }1006 } else {
866 if (!is_any) {1007 return printEnumNonexhaustive(w, value);
867 if (fmt.len != 0) return printValue(w, fmt, options, @intFromEnum(value), max_depth);
868 return printValue(w, ANY, options, value, max_depth);
869 }
870 const enum_info = @typeInfo(T).@"enum";
871 if (enum_info.is_exhaustive) {
872 var vecs: [2][]const u8 = .{ ".", @tagName(value) };
873 try w.writeVecAll(&vecs);
874 return;
875 }
876 if (std.enums.tagName(T, value)) |tag_name| {
877 var vecs: [2][]const u8 = .{ ".", tag_name };
878 try w.writeVecAll(&vecs);
879 return;
880 }1008 }
881 try w.writeAll("@enumFromInt(");
882 try w.printValue(ANY, options, @intFromEnum(value), max_depth);
883 try w.writeByte(')');
884 return;
885 },1009 },
886 .@"union" => |info| {1010 .@"union" => |info| {
887 if (fmt.len == 1 and fmt[0] == 't') {
888 try w.writeAll(@tagName(value));
889 return;
890 }
891 if (!is_any) {1011 if (!is_any) {
892 if (fmt.len != 0) invalidFmtError(fmt, value);1012 if (fmt.len != 0) invalidFmtError(fmt, value);
893 return printValue(w, ANY, options, value, max_depth);1013 return printValue(w, ANY, options, value, max_depth);
...@@ -971,38 +1091,18 @@ pub fn printValue(...@@ -971,38 +1091,18 @@ pub fn printValue(
971 else => {1091 else => {
972 var buffers: [2][]const u8 = .{ @typeName(ptr_info.child), "@" };1092 var buffers: [2][]const u8 = .{ @typeName(ptr_info.child), "@" };
973 try w.writeVecAll(&buffers);1093 try w.writeVecAll(&buffers);
974 try w.printIntOptions(@intFromPtr(value), 16, .lower, options);1094 try w.printInt(@intFromPtr(value), 16, .lower, options);
975 return;1095 return;
976 },1096 },
977 },1097 },
978 .many, .c => {1098 .many, .c => {
979 if (ptr_info.sentinel() != null)1099 if (!is_any) @compileError("cannot format pointer without a specifier (i.e. {s} or {*})");
980 return w.printValue(fmt, options, std.mem.span(value), max_depth);
981 if (fmt.len == 1 and fmt[0] == 's' and ptr_info.child == u8)
982 return w.alignBufferOptions(std.mem.span(value), options);
983 if (!is_any and fmt.len == 0)
984 @compileError("cannot format pointer without a specifier (i.e. {s} or {*})");
985 if (!is_any and fmt.len != 0)
986 invalidFmtError(fmt, value);
987 try w.printAddress(value);1100 try w.printAddress(value);
988 },1101 },
989 .slice => {1102 .slice => {
990 if (!is_any and fmt.len == 0)1103 if (!is_any)
991 @compileError("cannot format slice without a specifier (i.e. {s}, {x}, {b64}, or {any})");1104 @compileError("cannot format slice without a specifier (i.e. {s}, {x}, {b64}, or {any})");
992 if (max_depth == 0)1105 if (max_depth == 0) return w.writeAll("{ ... }");
993 return w.writeAll("{ ... }");
994 if (ptr_info.child == u8) switch (fmt.len) {
995 1 => switch (fmt[0]) {
996 's' => return w.alignBufferOptions(value, options),
997 'x' => return w.printHex(value, .lower),
998 'X' => return w.printHex(value, .upper),
999 else => {},
1000 },
1001 3 => if (fmt[0] == 'b' and fmt[1] == '6' and fmt[2] == '4') {
1002 return w.printBase64(value);
1003 },
1004 else => {},
1005 };
1006 try w.writeAll("{ ");1106 try w.writeAll("{ ");
1007 for (value, 0..) |elem, i| {1107 for (value, 0..) |elem, i| {
1008 try w.printValue(fmt, options, elem, max_depth - 1);1108 try w.printValue(fmt, options, elem, max_depth - 1);
...@@ -1013,21 +1113,9 @@ pub fn printValue(...@@ -1013,21 +1113,9 @@ pub fn printValue(
1013 try w.writeAll(" }");1113 try w.writeAll(" }");
1014 },1114 },
1015 },1115 },
1016 .array => |info| {1116 .array => {
1017 if (fmt.len == 0)1117 if (!is_any) @compileError("cannot format array without a specifier (i.e. {s} or {any})");
1018 @compileError("cannot format array without a specifier (i.e. {s} or {any})");1118 if (max_depth == 0) return w.writeAll("{ ... }");
1019 if (max_depth == 0) {
1020 return w.writeAll("{ ... }");
1021 }
1022 if (info.child == u8) {
1023 if (fmt[0] == 's') {
1024 return w.alignBufferOptions(&value, options);
1025 } else if (fmt[0] == 'x') {
1026 return w.printHex(&value, .lower);
1027 } else if (fmt[0] == 'X') {
1028 return w.printHex(&value, .upper);
1029 }
1030 }
1031 try w.writeAll("{ ");1119 try w.writeAll("{ ");
1032 for (value, 0..) |elem, i| {1120 for (value, 0..) |elem, i| {
1033 try w.printValue(fmt, options, elem, max_depth - 1);1121 try w.printValue(fmt, options, elem, max_depth - 1);
...@@ -1037,33 +1125,23 @@ pub fn printValue(...@@ -1037,33 +1125,23 @@ pub fn printValue(
1037 }1125 }
1038 try w.writeAll(" }");1126 try w.writeAll(" }");
1039 },1127 },
1040 .vector => |info| {1128 .vector => {
1041 if (max_depth == 0) {1129 if (!is_any and fmt.len != 0) invalidFmtError(fmt, value);
1042 return w.writeAll("{ ... }");1130 return printVector(w, fmt, options, value, max_depth);
1043 }
1044 try w.writeAll("{ ");
1045 var i: usize = 0;
1046 while (i < info.len) : (i += 1) {
1047 try w.printValue(fmt, options, value[i], max_depth - 1);
1048 if (i < info.len - 1) {
1049 try w.writeAll(", ");
1050 }
1051 }
1052 try w.writeAll(" }");
1053 },1131 },
1054 .@"fn" => @compileError("unable to format function body type, use '*const " ++ @typeName(T) ++ "' for a function pointer type"),1132 .@"fn" => @compileError("unable to format function body type, use '*const " ++ @typeName(T) ++ "' for a function pointer type"),
1055 .type => {1133 .type => {
1056 if (!is_any and fmt.len != 0) invalidFmtError(fmt, value);1134 if (!is_any and fmt.len != 0) invalidFmtError(fmt, value);
1057 return w.alignBufferOptions(@typeName(value), options);1135 return w.writeAll(@typeName(value));
1058 },1136 },
1059 .enum_literal => {1137 .enum_literal => {
1060 if (!is_any and fmt.len != 0) invalidFmtError(fmt, value);1138 if (!is_any and fmt.len != 0) invalidFmtError(fmt, value);
1061 const buffer = [_]u8{'.'} ++ @tagName(value);1139 var vecs: [2][]const u8 = .{ ".", @tagName(value) };
1062 return w.alignBufferOptions(buffer, options);1140 return w.writeVecAll(&vecs);
1063 },1141 },
1064 .null => {1142 .null => {
1065 if (!is_any and fmt.len != 0) invalidFmtError(fmt, value);1143 if (!is_any and fmt.len != 0) invalidFmtError(fmt, value);
1066 return w.alignBufferOptions("null", options);1144 return w.writeAll("null");
1067 },1145 },
1068 else => @compileError("unable to format type '" ++ @typeName(T) ++ "'"),1146 else => @compileError("unable to format type '" ++ @typeName(T) ++ "'"),
1069 }1147 }
...@@ -1074,75 +1152,68 @@ fn printErrorSet(w: *Writer, error_set: anyerror) Error!void {...@@ -1074,75 +1152,68 @@ fn printErrorSet(w: *Writer, error_set: anyerror) Error!void {
1074 try w.writeVecAll(&vecs);1152 try w.writeVecAll(&vecs);
1075}1153}
10761154
1077pub fn printInt(1155fn printEnumExhaustive(w: *Writer, value: anytype) Error!void {
1156 var vecs: [2][]const u8 = .{ ".", @tagName(value) };
1157 try w.writeVecAll(&vecs);
1158}
1159
1160fn printEnumNonexhaustive(w: *Writer, value: anytype) Error!void {
1161 if (std.enums.tagName(@TypeOf(value), value)) |tag_name| {
1162 var vecs: [2][]const u8 = .{ ".", tag_name };
1163 try w.writeVecAll(&vecs);
1164 return;
1165 }
1166 try w.writeAll("@enumFromInt(");
1167 try w.printInt(@intFromEnum(value), 10, .lower, .{});
1168 try w.writeByte(')');
1169}
1170
1171pub fn printVector(
1078 w: *Writer,1172 w: *Writer,
1079 comptime fmt: []const u8,1173 comptime fmt: []const u8,
1080 options: std.fmt.Options,1174 options: std.fmt.Options,
1081 value: anytype,1175 value: anytype,
1176 max_depth: usize,
1082) Error!void {1177) Error!void {
1083 const int_value = if (@TypeOf(value) == comptime_int) blk: {1178 const len = @typeInfo(@TypeOf(value)).vector.len;
1084 const Int = std.math.IntFittingRange(value, value);1179 if (max_depth == 0) return w.writeAll("{ ... }");
1085 break :blk @as(Int, value);1180 try w.writeAll("{ ");
1086 } else value;1181 inline for (0..len) |i| {
10871182 try w.printValue(fmt, options, value[i], max_depth - 1);
1088 switch (fmt.len) {1183 if (i < len - 1) try w.writeAll(", ");
1089 0 => return w.printIntOptions(int_value, 10, .lower, options),
1090 1 => switch (fmt[0]) {
1091 'd' => return w.printIntOptions(int_value, 10, .lower, options),
1092 'c' => {
1093 if (@typeInfo(@TypeOf(int_value)).int.bits <= 8) {
1094 return w.printAsciiChar(@as(u8, int_value), options);
1095 } else {
1096 @compileError("cannot print integer that is larger than 8 bits as an ASCII character");
1097 }
1098 },
1099 'u' => {
1100 if (@typeInfo(@TypeOf(int_value)).int.bits <= 21) {
1101 return w.printUnicodeCodepoint(@as(u21, int_value), options);
1102 } else {
1103 @compileError("cannot print integer that is larger than 21 bits as an UTF-8 sequence");
1104 }
1105 },
1106 'b' => return w.printIntOptions(int_value, 2, .lower, options),
1107 'x' => return w.printIntOptions(int_value, 16, .lower, options),
1108 'X' => return w.printIntOptions(int_value, 16, .upper, options),
1109 'o' => return w.printIntOptions(int_value, 8, .lower, options),
1110 'B' => return w.printByteSize(int_value, .decimal, options),
1111 'D' => return w.printDuration(int_value, options),
1112 else => invalidFmtError(fmt, value),
1113 },
1114 2 => {
1115 if (fmt[0] == 'B' and fmt[1] == 'i') {
1116 return w.printByteSize(int_value, .binary, options);
1117 } else {
1118 invalidFmtError(fmt, value);
1119 }
1120 },
1121 else => invalidFmtError(fmt, value),
1122 }1184 }
1123 comptime unreachable;1185 try w.writeAll(" }");
1124}
1125
1126pub fn printAsciiChar(w: *Writer, c: u8, options: std.fmt.Options) Error!void {
1127 return w.alignBufferOptions(@as(*const [1]u8, &c), options);
1128}1186}
11291187
1130pub fn printAscii(w: *Writer, bytes: []const u8, options: std.fmt.Options) Error!void {1188// A wrapper around `printIntAny` to avoid the generic explosion of this
1131 return w.alignBufferOptions(bytes, options);1189// function by funneling smaller integer types through `isize` and `usize`.
1132}1190pub inline fn printInt(
11331191 w: *Writer,
1134pub fn printUnicodeCodepoint(w: *Writer, c: u21, options: std.fmt.Options) Error!void {1192 value: anytype,
1135 var buf: [4]u8 = undefined;1193 base: u8,
1136 const len = std.unicode.utf8Encode(c, &buf) catch |err| switch (err) {1194 case: std.fmt.Case,
1137 error.Utf8CannotEncodeSurrogateHalf, error.CodepointTooLarge => l: {1195 options: std.fmt.Options,
1138 buf[0..3].* = std.unicode.replacement_character_utf8;1196) Error!void {
1139 break :l 3;1197 switch (@TypeOf(value)) {
1198 isize, usize => {},
1199 comptime_int => {
1200 if (comptime std.math.cast(usize, value)) |x| return printIntAny(w, x, base, case, options);
1201 if (comptime std.math.cast(isize, value)) |x| return printIntAny(w, x, base, case, options);
1202 const Int = std.math.IntFittingRange(value, value);
1203 return printIntAny(w, @as(Int, value), base, case, options);
1140 },1204 },
1141 };1205 else => switch (@typeInfo(@TypeOf(value)).int.signedness) {
1142 return w.alignBufferOptions(buf[0..len], options);1206 .signed => if (std.math.cast(isize, value)) |x| return printIntAny(w, x, base, case, options),
1207 .unsigned => if (std.math.cast(usize, value)) |x| return printIntAny(w, x, base, case, options),
1208 },
1209 }
1210 return printIntAny(w, value, base, case, options);
1143}1211}
11441212
1145pub fn printIntOptions(1213/// In general, prefer `printInt` to avoid generic explosion. However this
1214/// function may be used when optimal codegen for a particular integer type is
1215/// desired.
1216pub fn printIntAny(
1146 w: *Writer,1217 w: *Writer,
1147 value: anytype,1218 value: anytype,
1148 base: u8,1219 base: u8,
...@@ -1150,20 +1221,14 @@ pub fn printIntOptions(...@@ -1150,20 +1221,14 @@ pub fn printIntOptions(
1150 options: std.fmt.Options,1221 options: std.fmt.Options,
1151) Error!void {1222) Error!void {
1152 assert(base >= 2);1223 assert(base >= 2);
11531224 const value_info = @typeInfo(@TypeOf(value)).int;
1154 const int_value = if (@TypeOf(value) == comptime_int) blk: {
1155 const Int = std.math.IntFittingRange(value, value);
1156 break :blk @as(Int, value);
1157 } else value;
1158
1159 const value_info = @typeInfo(@TypeOf(int_value)).int;
11601225
1161 // The type must have the same size as `base` or be wider in order for the1226 // The type must have the same size as `base` or be wider in order for the
1162 // division to work1227 // division to work
1163 const min_int_bits = comptime @max(value_info.bits, 8);1228 const min_int_bits = comptime @max(value_info.bits, 8);
1164 const MinInt = std.meta.Int(.unsigned, min_int_bits);1229 const MinInt = std.meta.Int(.unsigned, min_int_bits);
11651230
1166 const abs_value = @abs(int_value);1231 const abs_value = @abs(value);
1167 // The worst case in terms of space needed is base 2, plus 1 for the sign1232 // The worst case in terms of space needed is base 2, plus 1 for the sign
1168 var buf: [1 + @max(@as(comptime_int, value_info.bits), 1)]u8 = undefined;1233 var buf: [1 + @max(@as(comptime_int, value_info.bits), 1)]u8 = undefined;
11691234
...@@ -1210,38 +1275,49 @@ pub fn printIntOptions(...@@ -1210,38 +1275,49 @@ pub fn printIntOptions(
1210 return w.alignBufferOptions(buf[index..], options);1275 return w.alignBufferOptions(buf[index..], options);
1211}1276}
12121277
1278pub fn printAsciiChar(w: *Writer, c: u8, options: std.fmt.Options) Error!void {
1279 return w.alignBufferOptions(@as(*const [1]u8, &c), options);
1280}
1281
1282pub fn printAscii(w: *Writer, bytes: []const u8, options: std.fmt.Options) Error!void {
1283 return w.alignBufferOptions(bytes, options);
1284}
1285
1286pub fn printUnicodeCodepoint(w: *Writer, c: u21) Error!void {
1287 var buf: [4]u8 = undefined;
1288 const len = std.unicode.utf8Encode(c, &buf) catch |err| switch (err) {
1289 error.Utf8CannotEncodeSurrogateHalf, error.CodepointTooLarge => l: {
1290 buf[0..3].* = std.unicode.replacement_character_utf8;
1291 break :l 3;
1292 },
1293 };
1294 return w.writeAll(buf[0..len]);
1295}
1296
1213pub fn printFloat(1297pub fn printFloat(
1214 w: *Writer,1298 w: *Writer,
1215 comptime fmt: []const u8,
1216 options: std.fmt.Options,
1217 value: anytype,1299 value: anytype,
1300 mode: std.fmt.float.Mode,
1301 options: std.fmt.Options,
1218) Error!void {1302) Error!void {
1219 var buf: [std.fmt.float.bufferSize(.decimal, f64)]u8 = undefined;1303 var buf: [std.fmt.float.bufferSize(.decimal, f64)]u8 = undefined;
1304 const s = std.fmt.float.render(&buf, value, .{
1305 .mode = mode,
1306 .precision = options.precision,
1307 }) catch |err| switch (err) {
1308 error.BufferTooSmall => "(float)",
1309 };
1310 return w.alignBufferOptions(s, options);
1311}
12201312
1221 if (fmt.len > 1) invalidFmtError(fmt, value);1313pub fn printFloatHexOptions(w: *Writer, value: anytype, case: std.fmt.Case, options: std.fmt.Options) Error!void {
1222 switch (if (fmt.len == 0) 'e' else fmt[0]) {1314 var buf: [50]u8 = undefined; // for aligning
1223 'e' => {1315 var sub_writer: Writer = .fixed(&buf);
1224 const s = std.fmt.float.render(&buf, value, .{ .mode = .scientific, .precision = options.precision }) catch |err| switch (err) {1316 printFloatHex(&sub_writer, value, case, options.precision) catch unreachable; // buf is large enough
1225 error.BufferTooSmall => "(float)",1317 return w.alignBufferOptions(sub_writer.buffered(), options);
1226 };
1227 return w.alignBufferOptions(s, options);
1228 },
1229 'd' => {
1230 const s = std.fmt.float.render(&buf, value, .{ .mode = .decimal, .precision = options.precision }) catch |err| switch (err) {
1231 error.BufferTooSmall => "(float)",
1232 };
1233 return w.alignBufferOptions(s, options);
1234 },
1235 'x' => {
1236 var sub_bw: Writer = .fixed(&buf);
1237 sub_bw.printFloatHexadecimal(value, options.precision) catch unreachable;
1238 return w.alignBufferOptions(sub_bw.buffered(), options);
1239 },
1240 else => invalidFmtError(fmt, value),
1241 }
1242}1318}
12431319
1244pub fn printFloatHexadecimal(w: *Writer, value: anytype, opt_precision: ?usize) Error!void {1320pub fn printFloatHex(w: *Writer, value: anytype, case: std.fmt.Case, opt_precision: ?usize) Error!void {
1245 if (std.math.signbit(value)) try w.writeByte('-');1321 if (std.math.signbit(value)) try w.writeByte('-');
1246 if (std.math.isNan(value)) return w.writeAll("nan");1322 if (std.math.isNan(value)) return w.writeAll("nan");
1247 if (std.math.isInf(value)) return w.writeAll("inf");1323 if (std.math.isInf(value)) return w.writeAll("inf");
...@@ -1320,7 +1396,7 @@ pub fn printFloatHexadecimal(w: *Writer, value: anytype, opt_precision: ?usize)...@@ -1320,7 +1396,7 @@ pub fn printFloatHexadecimal(w: *Writer, value: anytype, opt_precision: ?usize)
13201396
1321 // +1 for the decimal part.1397 // +1 for the decimal part.
1322 var buf: [1 + mantissa_digits]u8 = undefined;1398 var buf: [1 + mantissa_digits]u8 = undefined;
1323 assert(std.fmt.printInt(&buf, mantissa, 16, .lower, .{ .fill = '0', .width = 1 + mantissa_digits }) == buf.len);1399 assert(std.fmt.printInt(&buf, mantissa, 16, case, .{ .fill = '0', .width = 1 + mantissa_digits }) == buf.len);
13241400
1325 try w.writeAll("0x");1401 try w.writeAll("0x");
1326 try w.writeByte(buf[0]);1402 try w.writeByte(buf[0]);
...@@ -1337,7 +1413,7 @@ pub fn printFloatHexadecimal(w: *Writer, value: anytype, opt_precision: ?usize)...@@ -1337,7 +1413,7 @@ pub fn printFloatHexadecimal(w: *Writer, value: anytype, opt_precision: ?usize)
1337 try w.splatByteAll('0', precision - trimmed.len);1413 try w.splatByteAll('0', precision - trimmed.len);
1338 };1414 };
1339 try w.writeAll("p");1415 try w.writeAll("p");
1340 try w.printIntOptions(exponent - exponent_bias, 10, .lower, .{});1416 try w.printInt(exponent - exponent_bias, 10, case, .{});
1341}1417}
13421418
1343pub const ByteSizeUnits = enum {1419pub const ByteSizeUnits = enum {
...@@ -1433,7 +1509,7 @@ pub fn printDurationUnsigned(w: *Writer, ns: u64) Error!void {...@@ -1433,7 +1509,7 @@ pub fn printDurationUnsigned(w: *Writer, ns: u64) Error!void {
1433 }) |unit| {1509 }) |unit| {
1434 if (ns_remaining >= unit.ns) {1510 if (ns_remaining >= unit.ns) {
1435 const units = ns_remaining / unit.ns;1511 const units = ns_remaining / unit.ns;
1436 try w.printIntOptions(units, 10, .lower, .{});1512 try w.printInt(units, 10, .lower, .{});
1437 try w.writeByte(unit.sep);1513 try w.writeByte(unit.sep);
1438 ns_remaining -= units * unit.ns;1514 ns_remaining -= units * unit.ns;
1439 if (ns_remaining == 0) return;1515 if (ns_remaining == 0) return;
...@@ -1447,13 +1523,13 @@ pub fn printDurationUnsigned(w: *Writer, ns: u64) Error!void {...@@ -1447,13 +1523,13 @@ pub fn printDurationUnsigned(w: *Writer, ns: u64) Error!void {
1447 }) |unit| {1523 }) |unit| {
1448 const kunits = ns_remaining * 1000 / unit.ns;1524 const kunits = ns_remaining * 1000 / unit.ns;
1449 if (kunits >= 1000) {1525 if (kunits >= 1000) {
1450 try w.printIntOptions(kunits / 1000, 10, .lower, .{});1526 try w.printInt(kunits / 1000, 10, .lower, .{});
1451 const frac = kunits % 1000;1527 const frac = kunits % 1000;
1452 if (frac > 0) {1528 if (frac > 0) {
1453 // Write up to 3 decimal places1529 // Write up to 3 decimal places
1454 var decimal_buf = [_]u8{ '.', 0, 0, 0 };1530 var decimal_buf = [_]u8{ '.', 0, 0, 0 };
1455 var inner: Writer = .fixed(decimal_buf[1..]);1531 var inner: Writer = .fixed(decimal_buf[1..]);
1456 inner.printIntOptions(frac, 10, .lower, .{ .fill = '0', .width = 3 }) catch unreachable;1532 inner.printInt(frac, 10, .lower, .{ .fill = '0', .width = 3 }) catch unreachable;
1457 var end: usize = 4;1533 var end: usize = 4;
1458 while (end > 1) : (end -= 1) {1534 while (end > 1) : (end -= 1) {
1459 if (decimal_buf[end - 1] != '0') break;1535 if (decimal_buf[end - 1] != '0') break;
...@@ -1464,7 +1540,7 @@ pub fn printDurationUnsigned(w: *Writer, ns: u64) Error!void {...@@ -1464,7 +1540,7 @@ pub fn printDurationUnsigned(w: *Writer, ns: u64) Error!void {
1464 }1540 }
1465 }1541 }
14661542
1467 try w.printIntOptions(ns_remaining, 10, .lower, .{});1543 try w.printInt(ns_remaining, 10, .lower, .{});
1468 try w.writeAll("ns");1544 try w.writeAll("ns");
1469}1545}
14701546
...@@ -1474,12 +1550,18 @@ pub fn printDurationUnsigned(w: *Writer, ns: u64) Error!void {...@@ -1474,12 +1550,18 @@ pub fn printDurationUnsigned(w: *Writer, ns: u64) Error!void {
1474pub fn printDuration(w: *Writer, nanoseconds: anytype, options: std.fmt.Options) Error!void {1550pub fn printDuration(w: *Writer, nanoseconds: anytype, options: std.fmt.Options) Error!void {
1475 // worst case: "-XXXyXXwXXdXXhXXmXX.XXXs".len = 241551 // worst case: "-XXXyXXwXXdXXhXXmXX.XXXs".len = 24
1476 var buf: [24]u8 = undefined;1552 var buf: [24]u8 = undefined;
1477 var sub_bw: Writer = .fixed(&buf);1553 var sub_writer: Writer = .fixed(&buf);
1478 switch (@typeInfo(@TypeOf(nanoseconds)).int.signedness) {1554 if (@TypeOf(nanoseconds) == comptime_int) {
1479 .signed => sub_bw.printDurationSigned(nanoseconds) catch unreachable,1555 if (nanoseconds >= 0) {
1480 .unsigned => sub_bw.printDurationUnsigned(nanoseconds) catch unreachable,1556 sub_writer.printDurationUnsigned(nanoseconds) catch unreachable;
1557 } else {
1558 sub_writer.printDurationSigned(nanoseconds) catch unreachable;
1559 }
1560 } else switch (@typeInfo(@TypeOf(nanoseconds)).int.signedness) {
1561 .signed => sub_writer.printDurationSigned(nanoseconds) catch unreachable,
1562 .unsigned => sub_writer.printDurationUnsigned(nanoseconds) catch unreachable,
1481 }1563 }
1482 return w.alignBufferOptions(sub_bw.buffered(), options);1564 return w.alignBufferOptions(sub_writer.buffered(), options);
1483}1565}
14841566
1485pub fn printHex(w: *Writer, bytes: []const u8, case: std.fmt.Case) Error!void {1567pub fn printHex(w: *Writer, bytes: []const u8, case: std.fmt.Case) Error!void {
...@@ -1749,7 +1831,7 @@ fn testDurationCaseSigned(expected: []const u8, input: i64) !void {...@@ -1749,7 +1831,7 @@ fn testDurationCaseSigned(expected: []const u8, input: i64) !void {
1749 try testing.expectEqualStrings(expected, w.buffered());1831 try testing.expectEqualStrings(expected, w.buffered());
1750}1832}
17511833
1752test printIntOptions {1834test printInt {
1753 try testPrintIntCase("-1", @as(i1, -1), 10, .lower, .{});1835 try testPrintIntCase("-1", @as(i1, -1), 10, .lower, .{});
17541836
1755 try testPrintIntCase("-101111000110000101001110", @as(i32, -12345678), 2, .lower, .{});1837 try testPrintIntCase("-101111000110000101001110", @as(i32, -12345678), 2, .lower, .{});
...@@ -1765,27 +1847,22 @@ test printIntOptions {...@@ -1765,27 +1847,22 @@ test printIntOptions {
17651847
1766 try testPrintIntCase("+42", @as(i32, 42), 10, .lower, .{ .width = 3 });1848 try testPrintIntCase("+42", @as(i32, 42), 10, .lower, .{ .width = 3 });
1767 try testPrintIntCase("-42", @as(i32, -42), 10, .lower, .{ .width = 3 });1849 try testPrintIntCase("-42", @as(i32, -42), 10, .lower, .{ .width = 3 });
1768}
17691850
1770test "printInt with comptime_int" {1851 try testPrintIntCase("123456789123456789", @as(comptime_int, 123456789123456789), 10, .lower, .{});
1771 var buf: [20]u8 = undefined;
1772 var w: Writer = .fixed(&buf);
1773 try w.printInt("", .{}, @as(comptime_int, 123456789123456789));
1774 try std.testing.expectEqualStrings("123456789123456789", w.buffered());
1775}1852}
17761853
1777test "printFloat with comptime_float" {1854test "printFloat with comptime_float" {
1778 var buf: [20]u8 = undefined;1855 var buf: [20]u8 = undefined;
1779 var w: Writer = .fixed(&buf);1856 var w: Writer = .fixed(&buf);
1780 try w.printFloat("", .{}, @as(comptime_float, 1.0));1857 try w.printFloat(@as(comptime_float, 1.0), .scientific, .{});
1781 try std.testing.expectEqualStrings(w.buffered(), "1e0");1858 try std.testing.expectEqualStrings(w.buffered(), "1e0");
1782 try std.testing.expectFmt("1e0", "{}", .{1.0});1859 try std.testing.expectFmt("1", "{}", .{1.0});
1783}1860}
17841861
1785fn testPrintIntCase(expected: []const u8, value: anytype, base: u8, case: std.fmt.Case, options: std.fmt.Options) !void {1862fn testPrintIntCase(expected: []const u8, value: anytype, base: u8, case: std.fmt.Case, options: std.fmt.Options) !void {
1786 var buffer: [100]u8 = undefined;1863 var buffer: [100]u8 = undefined;
1787 var w: Writer = .fixed(&buffer);1864 var w: Writer = .fixed(&buffer);
1788 try w.printIntOptions(value, base, case, options);1865 try w.printInt(value, base, case, options);
1789 try testing.expectEqualStrings(expected, w.buffered());1866 try testing.expectEqualStrings(expected, w.buffered());
1790}1867}
17911868
lib/std/json/dynamic_test.zig+2-2
...@@ -254,7 +254,7 @@ test "Value.jsonStringify" {...@@ -254,7 +254,7 @@ test "Value.jsonStringify" {
254 \\ true,254 \\ true,
255 \\ 42,255 \\ 42,
256 \\ 43,256 \\ 43,
257 \\ 4.2e1,257 \\ 42,
258 \\ "weeee",258 \\ "weeee",
259 \\ [259 \\ [
260 \\ 1,260 \\ 1,
...@@ -266,7 +266,7 @@ test "Value.jsonStringify" {...@@ -266,7 +266,7 @@ test "Value.jsonStringify" {
266 \\ }266 \\ }
267 \\]267 \\]
268 ;268 ;
269 try testing.expectEqualSlices(u8, expected, fbs.getWritten());269 try testing.expectEqualStrings(expected, fbs.getWritten());
270}270}
271271
272test "parseFromValue(std.json.Value,...)" {272test "parseFromValue(std.json.Value,...)" {
lib/std/json/stringify.zig-1
...@@ -469,7 +469,6 @@ pub fn WriteStream(...@@ -469,7 +469,6 @@ pub fn WriteStream(
469 /// * When option `emit_nonportable_numbers_as_strings` is true, if the value is outside the range `+-1<<53` (the precise integer range of f64), it is rendered as a JSON string in base 10. Otherwise, it is rendered as JSON number.469 /// * When option `emit_nonportable_numbers_as_strings` is true, if the value is outside the range `+-1<<53` (the precise integer range of f64), it is rendered as a JSON string in base 10. Otherwise, it is rendered as JSON number.
470 /// * Zig floats -> JSON number or string.470 /// * Zig floats -> JSON number or string.
471 /// * If the value cannot be precisely represented by an f64, it is rendered as a JSON string. Otherwise, it is rendered as JSON number.471 /// * If the value cannot be precisely represented by an f64, it is rendered as a JSON string. Otherwise, it is rendered as JSON number.
472 /// * TODO: Float rendering will likely change in the future, e.g. to remove the unnecessary "e+00".
473 /// * Zig `[]const u8`, `[]u8`, `*[N]u8`, `@Vector(N, u8)`, and similar -> JSON string.472 /// * Zig `[]const u8`, `[]u8`, `*[N]u8`, `@Vector(N, u8)`, and similar -> JSON string.
474 /// * See `StringifyOptions.emit_strings_as_arrays`.473 /// * See `StringifyOptions.emit_strings_as_arrays`.
475 /// * If the content is not valid UTF-8, rendered as an array of numbers instead.474 /// * If the content is not valid UTF-8, rendered as an array of numbers instead.
lib/std/json/stringify_test.zig+6-6
...@@ -74,16 +74,16 @@ fn testBasicWriteStream(w: anytype, slice_stream: anytype) !void {...@@ -74,16 +74,16 @@ fn testBasicWriteStream(w: anytype, slice_stream: anytype) !void {
74 \\{74 \\{
75 \\ "object": {75 \\ "object": {
76 \\ "one": 1,76 \\ "one": 1,
77 \\ "two": 2e077 \\ "two": 2
78 \\ },78 \\ },
79 \\ "string": "This is a string",79 \\ "string": "This is a string",
80 \\ "array": [80 \\ "array": [
81 \\ "Another string",81 \\ "Another string",
82 \\ 1,82 \\ 1,
83 \\ 3.5e083 \\ 3.5
84 \\ ],84 \\ ],
85 \\ "int": 10,85 \\ "int": 10,
86 \\ "float": 3.5e086 \\ "float": 3.5
87 \\}87 \\}
88 ;88 ;
89 try std.testing.expectEqualStrings(expected, result);89 try std.testing.expectEqualStrings(expected, result);
...@@ -123,12 +123,12 @@ test "stringify basic types" {...@@ -123,12 +123,12 @@ test "stringify basic types" {
123 try testStringify("null", @as(?u8, null), .{});123 try testStringify("null", @as(?u8, null), .{});
124 try testStringify("null", @as(?*u32, null), .{});124 try testStringify("null", @as(?*u32, null), .{});
125 try testStringify("42", 42, .{});125 try testStringify("42", 42, .{});
126 try testStringify("4.2e1", 42.0, .{});126 try testStringify("42", 42.0, .{});
127 try testStringify("42", @as(u8, 42), .{});127 try testStringify("42", @as(u8, 42), .{});
128 try testStringify("42", @as(u128, 42), .{});128 try testStringify("42", @as(u128, 42), .{});
129 try testStringify("9999999999999999", 9999999999999999, .{});129 try testStringify("9999999999999999", 9999999999999999, .{});
130 try testStringify("4.2e1", @as(f32, 42), .{});130 try testStringify("42", @as(f32, 42), .{});
131 try testStringify("4.2e1", @as(f64, 42), .{});131 try testStringify("42", @as(f64, 42), .{});
132 try testStringify("\"ItBroke\"", @as(anyerror, error.ItBroke), .{});132 try testStringify("\"ItBroke\"", @as(anyerror, error.ItBroke), .{});
133 try testStringify("\"ItBroke\"", error.ItBroke, .{});133 try testStringify("\"ItBroke\"", error.ItBroke, .{});
134}134}
lib/std/math/big/int.zig+13-19
...@@ -2028,6 +2028,14 @@ pub const Mutable = struct {...@@ -2028,6 +2028,14 @@ pub const Mutable = struct {
2028 pub fn normalize(r: *Mutable, length: usize) void {2028 pub fn normalize(r: *Mutable, length: usize) void {
2029 r.len = llnormalize(r.limbs[0..length]);2029 r.len = llnormalize(r.limbs[0..length]);
2030 }2030 }
2031
2032 pub fn format(self: Mutable, w: *std.io.Writer) std.io.Writer.Error!void {
2033 return formatInteger(self, w, 10, .lower);
2034 }
2035
2036 pub fn formatInteger(self: Const, w: *std.io.Writer, base: u8, case: std.fmt.Case) std.io.Writer.Error!void {
2037 return self.toConst().formatInteger(w, base, case);
2038 }
2031};2039};
20322040
2033/// A arbitrary-precision big integer, with a fixed set of immutable limbs.2041/// A arbitrary-precision big integer, with a fixed set of immutable limbs.
...@@ -2321,7 +2329,7 @@ pub const Const = struct {...@@ -2321,7 +2329,7 @@ pub const Const = struct {
2321 /// this function will fail to print the string, printing "(BigInt)" instead of a number.2329 /// this function will fail to print the string, printing "(BigInt)" instead of a number.
2322 /// This is because the rendering algorithm requires reversing a string, which requires O(N) memory.2330 /// This is because the rendering algorithm requires reversing a string, which requires O(N) memory.
2323 /// See `toString` and `toStringAlloc` for a way to print big integers without failure.2331 /// See `toString` and `toStringAlloc` for a way to print big integers without failure.
2324 pub fn print(self: Const, w: *std.io.Writer, base: u8, case: std.fmt.Case) std.io.Writer.Error!void {2332 pub fn formatInteger(self: Const, w: *std.io.Writer, base: u8, case: std.fmt.Case) std.io.Writer.Error!void {
2325 const available_len = 64;2333 const available_len = 64;
2326 if (self.limbs.len > available_len)2334 if (self.limbs.len > available_len)
2327 return w.writeAll("(BigInt)");2335 return w.writeAll("(BigInt)");
...@@ -2337,20 +2345,6 @@ pub const Const = struct {...@@ -2337,20 +2345,6 @@ pub const Const = struct {
2337 return w.writeAll(buf[0..len]);2345 return w.writeAll(buf[0..len]);
2338 }2346 }
23392347
2340 const Format = struct {
2341 int: Const,
2342 base: u8,
2343 case: std.fmt.Case,
2344
2345 pub fn default(f: Format, w: *std.io.Writer) std.io.Writer.Error!void {
2346 return print(f.int, w, f.base, f.case);
2347 }
2348 };
2349
2350 pub fn fmt(self: Const, base: u8, case: std.fmt.Case) std.fmt.Formatter(Format, Format.default) {
2351 return .{ .data = .{ .int = self, .base = base, .case = case } };
2352 }
2353
2354 /// Converts self to a string in the requested base.2348 /// Converts self to a string in the requested base.
2355 /// Caller owns returned memory.2349 /// Caller owns returned memory.
2356 /// Asserts that `base` is in the range [2, 36].2350 /// Asserts that `base` is in the range [2, 36].
...@@ -2918,16 +2912,16 @@ pub const Managed = struct {...@@ -2918,16 +2912,16 @@ pub const Managed = struct {
2918 }2912 }
29192913
2920 /// To allow `std.fmt.format` to work with `Managed`.2914 /// To allow `std.fmt.format` to work with `Managed`.
2921 pub fn format(self: Managed, w: *std.io.Writer, comptime f: []const u8) std.io.Writer.Error!void {2915 pub fn format(self: Managed, w: *std.io.Writer) std.io.Writer.Error!void {
2922 return self.toConst().format(w, f);2916 return formatInteger(self, w, 10, .lower);
2923 }2917 }
29242918
2925 /// If the absolute value of integer is greater than or equal to `pow(2, 64 * @sizeOf(usize) * 8)`,2919 /// If the absolute value of integer is greater than or equal to `pow(2, 64 * @sizeOf(usize) * 8)`,
2926 /// this function will fail to print the string, printing "(BigInt)" instead of a number.2920 /// this function will fail to print the string, printing "(BigInt)" instead of a number.
2927 /// This is because the rendering algorithm requires reversing a string, which requires O(N) memory.2921 /// This is because the rendering algorithm requires reversing a string, which requires O(N) memory.
2928 /// See `toString` and `toStringAlloc` for a way to print big integers without failure.2922 /// See `toString` and `toStringAlloc` for a way to print big integers without failure.
2929 pub fn fmt(self: Managed, base: u8, case: std.fmt.Case) std.fmt.Formatter(Const.Format, Const.Format.default) {2923 pub fn formatInteger(self: Managed, w: *std.io.Writer, base: u8, case: std.fmt.Case) std.io.Writer.Error!void {
2930 return .{ .data = .{ .int = self.toConst(), .base = base, .case = case } };2924 return self.toConst().formatInteger(w, base, case);
2931 }2925 }
29322926
2933 /// Returns math.Order.lt, math.Order.eq, math.Order.gt if |a| < |b|, |a| ==2927 /// Returns math.Order.lt, math.Order.eq, math.Order.gt if |a| < |b|, |a| ==
lib/std/math/big/int_test.zig+4-4
...@@ -3813,8 +3813,8 @@ test "(BigInt) positive" {...@@ -3813,8 +3813,8 @@ test "(BigInt) positive" {
3813 try a.pow(&a, 64 * @sizeOf(Limb) * 8);3813 try a.pow(&a, 64 * @sizeOf(Limb) * 8);
3814 try b.sub(&a, &c);3814 try b.sub(&a, &c);
38153815
3816 try testing.expectFmt("(BigInt)", "{f}", .{a.fmt(10, .lower)});3816 try testing.expectFmt("(BigInt)", "{d}", .{a});
3817 try testing.expectFmt("1044388881413152506691752710716624382579964249047383780384233483283953907971557456848826811934997558340890106714439262837987573438185793607263236087851365277945956976543709998340361590134383718314428070011855946226376318839397712745672334684344586617496807908705803704071284048740118609114467977783598029006686938976881787785946905630190260940599579453432823469303026696443059025015972399867714215541693835559885291486318237914434496734087811872639496475100189041349008417061675093668333850551032972088269550769983616369411933015213796825837188091833656751221318492846368125550225998300412344784862595674492194617023806505913245610825731835380087608622102834270197698202313169017678006675195485079921636419370285375124784014907159135459982790513399611551794271106831134090584272884279791554849782954323534517065223269061394905987693002122963395687782878948440616007412945674919823050571642377154816321380631045902916136926708342856440730447899971901781465763473223850267253059899795996090799469201774624817718449867455659250178329070473119433165550807568221846571746373296884912819520317457002440926616910874148385078411929804522981857338977648103126085903001302413467189726673216491511131602920781738033436090243804708340403154190335", "{f}", .{b.fmt(10, .lower)});3817 try testing.expectFmt("1044388881413152506691752710716624382579964249047383780384233483283953907971557456848826811934997558340890106714439262837987573438185793607263236087851365277945956976543709998340361590134383718314428070011855946226376318839397712745672334684344586617496807908705803704071284048740118609114467977783598029006686938976881787785946905630190260940599579453432823469303026696443059025015972399867714215541693835559885291486318237914434496734087811872639496475100189041349008417061675093668333850551032972088269550769983616369411933015213796825837188091833656751221318492846368125550225998300412344784862595674492194617023806505913245610825731835380087608622102834270197698202313169017678006675195485079921636419370285375124784014907159135459982790513399611551794271106831134090584272884279791554849782954323534517065223269061394905987693002122963395687782878948440616007412945674919823050571642377154816321380631045902916136926708342856440730447899971901781465763473223850267253059899795996090799469201774624817718449867455659250178329070473119433165550807568221846571746373296884912819520317457002440926616910874148385078411929804522981857338977648103126085903001302413467189726673216491511131602920781738033436090243804708340403154190335", "{d}", .{b});
3818}3818}
38193819
3820test "(BigInt) negative" {3820test "(BigInt) negative" {
...@@ -3832,10 +3832,10 @@ test "(BigInt) negative" {...@@ -3832,10 +3832,10 @@ test "(BigInt) negative" {
3832 a.negate();3832 a.negate();
3833 try b.add(&a, &c);3833 try b.add(&a, &c);
38343834
3835 const a_fmt = try std.fmt.allocPrint(testing.allocator, "{f}", .{a.fmt(10, .lower)});3835 const a_fmt = try std.fmt.allocPrint(testing.allocator, "{d}", .{a});
3836 defer testing.allocator.free(a_fmt);3836 defer testing.allocator.free(a_fmt);
38373837
3838 const b_fmt = try std.fmt.allocPrint(testing.allocator, "{f}", .{b.fmt(10, .lower)});3838 const b_fmt = try std.fmt.allocPrint(testing.allocator, "{d}", .{b});
3839 defer testing.allocator.free(b_fmt);3839 defer testing.allocator.free(b_fmt);
38403840
3841 try testing.expect(mem.eql(u8, a_fmt, "(BigInt)"));3841 try testing.expect(mem.eql(u8, a_fmt, "(BigInt)"));
lib/std/zig.zig+2-2
...@@ -475,7 +475,7 @@ pub fn stringEscape(bytes: []const u8, w: *std.io.Writer) std.io.Writer.Error!vo...@@ -475,7 +475,7 @@ pub fn stringEscape(bytes: []const u8, w: *std.io.Writer) std.io.Writer.Error!vo
475 ' ', '!', '#'...'&', '('...'[', ']'...'~' => try w.writeByte(byte),475 ' ', '!', '#'...'&', '('...'[', ']'...'~' => try w.writeByte(byte),
476 else => {476 else => {
477 try w.writeAll("\\x");477 try w.writeAll("\\x");
478 try w.printIntOptions(byte, 16, .lower, .{ .width = 2, .fill = '0' });478 try w.printInt(byte, 16, .lower, .{ .width = 2, .fill = '0' });
479 },479 },
480 };480 };
481}481}
...@@ -492,7 +492,7 @@ pub fn charEscape(bytes: []const u8, w: *std.io.Writer) std.io.Writer.Error!void...@@ -492,7 +492,7 @@ pub fn charEscape(bytes: []const u8, w: *std.io.Writer) std.io.Writer.Error!void
492 ' ', '!', '#'...'&', '('...'[', ']'...'~' => try w.writeByte(byte),492 ' ', '!', '#'...'&', '('...'[', ']'...'~' => try w.writeByte(byte),
493 else => {493 else => {
494 try w.writeAll("\\x");494 try w.writeAll("\\x");
495 try w.printIntOptions(byte, 16, .lower, .{ .width = 2, .fill = '0' });495 try w.printInt(byte, 16, .lower, .{ .width = 2, .fill = '0' });
496 },496 },
497 };497 };
498}498}
lib/std/zig/llvm/Builder.zig+166-64
...@@ -246,7 +246,7 @@ pub const Type = enum(u32) {...@@ -246,7 +246,7 @@ pub const Type = enum(u32) {
246 _,246 _,
247247
248 pub const ptr_amdgpu_constant =248 pub const ptr_amdgpu_constant =
249 @field(Type, std.fmt.comptimePrint("ptr{f }", .{AddrSpace.amdgpu.constant}));249 @field(Type, std.fmt.comptimePrint("ptr{f}", .{AddrSpace.amdgpu.constant.fmt(" ")}));
250250
251 pub const Tag = enum(u4) {251 pub const Tag = enum(u4) {
252 simple,252 simple,
...@@ -779,7 +779,7 @@ pub const Type = enum(u32) {...@@ -779,7 +779,7 @@ pub const Type = enum(u32) {
779 }779 }
780 },780 },
781 .integer => try w.print("i{d}", .{item.data}),781 .integer => try w.print("i{d}", .{item.data}),
782 .pointer => try w.print("ptr{f }", .{@as(AddrSpace, @enumFromInt(item.data))}),782 .pointer => try w.print("ptr{f}", .{@as(AddrSpace, @enumFromInt(item.data)).fmt(" ")}),
783 .target => {783 .target => {
784 var extra = data.builder.typeExtraDataTrail(Type.Target, item.data);784 var extra = data.builder.typeExtraDataTrail(Type.Target, item.data);
785 const types = extra.trail.next(extra.data.types_len, Type, data.builder);785 const types = extra.trail.next(extra.data.types_len, Type, data.builder);
...@@ -1242,7 +1242,7 @@ pub const Attribute = union(Kind) {...@@ -1242,7 +1242,7 @@ pub const Attribute = union(Kind) {
1242 .sret,1242 .sret,
1243 .elementtype,1243 .elementtype,
1244 => |ty| try w.print(" {s}({f})", .{ @tagName(attribute), ty.fmt(data.builder, .percent) }),1244 => |ty| try w.print(" {s}({f})", .{ @tagName(attribute), ty.fmt(data.builder, .percent) }),
1245 .@"align" => |alignment| try w.print("{f }", .{alignment}),1245 .@"align" => |alignment| try w.print("{f}", .{alignment.fmt(" ")}),
1246 .dereferenceable,1246 .dereferenceable,
1247 .dereferenceable_or_null,1247 .dereferenceable_or_null,
1248 => |size| try w.print(" {s}({d})", .{ @tagName(attribute), size }),1248 => |size| try w.print(" {s}({d})", .{ @tagName(attribute), size }),
...@@ -1853,10 +1853,31 @@ pub const ThreadLocal = enum(u3) {...@@ -1853,10 +1853,31 @@ pub const ThreadLocal = enum(u3) {
1853 initialexec = 3,1853 initialexec = 3,
1854 localexec = 4,1854 localexec = 4,
18551855
1856 pub fn format(self: ThreadLocal, w: *Writer, comptime prefix: []const u8) Writer.Error!void {1856 pub fn format(tl: ThreadLocal, w: *Writer) Writer.Error!void {
1857 if (self == .default) return;1857 return Prefixed.format(.{ .thread_local = tl, .prefix = "" }, w);
1858 try w.print("{s}thread_local", .{prefix});1858 }
1859 if (self != .generaldynamic) try w.print("({s})", .{@tagName(self)});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 };
1860 }1881 }
1861};1882};
18621883
...@@ -1961,8 +1982,24 @@ pub const AddrSpace = enum(u24) {...@@ -1961,8 +1982,24 @@ pub const AddrSpace = enum(u24) {
1961 pub const funcref: AddrSpace = @enumFromInt(20);1982 pub const funcref: AddrSpace = @enumFromInt(20);
1962 };1983 };
19631984
1964 pub fn format(self: AddrSpace, w: *Writer, comptime prefix: []const u8) Writer.Error!void {1985 pub fn format(addr_space: AddrSpace, w: *Writer) Writer.Error!void {
1965 if (self != .default) try w.print("{s}addrspace({d})", .{ prefix, @intFromEnum(self) });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 };
1966 }2003 }
1967};2004};
19682005
...@@ -1994,8 +2031,18 @@ pub const Alignment = enum(u6) {...@@ -1994,8 +2031,18 @@ pub const Alignment = enum(u6) {
1994 return if (self == .default) 0 else (@intFromEnum(self) + 1);2031 return if (self == .default) 0 else (@intFromEnum(self) + 1);
1995 }2032 }
19962033
1997 pub fn format(self: Alignment, w: *Writer, comptime prefix: []const u8) Writer.Error!void {2034 pub const Prefixed = struct {
1998 try w.print("{s}align {d}", .{ prefix, self.toByteUnits() orelse return });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 };
1999 }2046 }
2000};2047};
20012048
...@@ -6978,8 +7025,27 @@ pub const MemoryAccessKind = enum(u1) {...@@ -6978,8 +7025,27 @@ pub const MemoryAccessKind = enum(u1) {
6978 normal,7025 normal,
6979 @"volatile",7026 @"volatile",
69807027
6981 pub fn format(self: MemoryAccessKind, w: *Writer, comptime prefix: []const u8) Writer.Error!void {7028 pub fn format(memory_access_kind: MemoryAccessKind, w: *Writer) Writer.Error!void {
6982 if (self != .normal) try w.print("{s}{s}", .{ prefix, @tagName(self) });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 };
6983 }7049 }
6984};7050};
69857051
...@@ -6987,10 +7053,27 @@ pub const SyncScope = enum(u1) {...@@ -6987,10 +7053,27 @@ pub const SyncScope = enum(u1) {
6987 singlethread,7053 singlethread,
6988 system,7054 system,
69897055
6990 pub fn format(self: SyncScope, w: *Writer, comptime prefix: []const u8) Writer.Error!void {7056 pub fn format(sync_scope: SyncScope, w: *Writer) Writer.Error!void {
6991 if (self != .system) try w.print(7057 return Prefixed.format(.{ .sync_scope = sync_scope, .prefix = "" }, w);
6992 \\{s}syncscope("{s}")7058 }
6993 , .{ prefix, @tagName(self) });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 };
6994 }7077 }
6995};7078};
69967079
...@@ -7003,8 +7086,27 @@ pub const AtomicOrdering = enum(u3) {...@@ -7003,8 +7086,27 @@ pub const AtomicOrdering = enum(u3) {
7003 acq_rel = 5,7086 acq_rel = 5,
7004 seq_cst = 6,7087 seq_cst = 6,
70057088
7006 pub fn format(self: AtomicOrdering, w: *Writer, comptime prefix: []const u8) Writer.Error!void {7089 pub fn format(atomic_ordering: AtomicOrdering, w: *Writer) Writer.Error!void {
7007 if (self != .none) try w.print("{s}{s}", .{ prefix, @tagName(self) });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 };
7008 }7110 }
7009};7111};
70107112
...@@ -8550,7 +8652,7 @@ pub fn init(options: Options) Allocator.Error!Builder {...@@ -8550,7 +8652,7 @@ pub fn init(options: Options) Allocator.Error!Builder {
8550 inline for (.{ 0, 4 }) |addr_space_index| {8652 inline for (.{ 0, 4 }) |addr_space_index| {
8551 const addr_space: AddrSpace = @enumFromInt(addr_space_index);8653 const addr_space: AddrSpace = @enumFromInt(addr_space_index);
8552 assert(self.ptrTypeAssumeCapacity(addr_space) ==8654 assert(self.ptrTypeAssumeCapacity(addr_space) ==
8553 @field(Type, std.fmt.comptimePrint("ptr{f }", .{addr_space})));8655 @field(Type, std.fmt.comptimePrint("ptr{f}", .{addr_space.fmt(" ")})));
8554 }8656 }
8555 }8657 }
85568658
...@@ -9469,7 +9571,7 @@ pub fn print(self: *Builder, w: *Writer) (Writer.Error || Allocator.Error)!void...@@ -9469,7 +9571,7 @@ pub fn print(self: *Builder, w: *Writer) (Writer.Error || Allocator.Error)!void
9469 metadata_formatter.need_comma = true;9571 metadata_formatter.need_comma = true;
9470 defer metadata_formatter.need_comma = undefined;9572 defer metadata_formatter.need_comma = undefined;
9471 try w.print(9573 try w.print(
9472 \\{f} ={f}{f}{f}{f}{f }{f}{f }{f} {s} {f}{f}{f, }{f}9574 \\{f} ={f}{f}{f}{f}{f}{f}{f}{f} {s} {f}{f}{f}{f}
9473 \\9575 \\
9474 , .{9576 , .{
9475 variable.global.fmt(self),9577 variable.global.fmt(self),
...@@ -9479,14 +9581,14 @@ pub fn print(self: *Builder, w: *Writer) (Writer.Error || Allocator.Error)!void...@@ -9479,14 +9581,14 @@ pub fn print(self: *Builder, w: *Writer) (Writer.Error || Allocator.Error)!void
9479 global.preemption,9581 global.preemption,
9480 global.visibility,9582 global.visibility,
9481 global.dll_storage_class,9583 global.dll_storage_class,
9482 variable.thread_local,9584 variable.thread_local.fmt(" "),
9483 global.unnamed_addr,9585 global.unnamed_addr,
9484 global.addr_space,9586 global.addr_space.fmt(" "),
9485 global.externally_initialized,9587 global.externally_initialized,
9486 @tagName(variable.mutability),9588 @tagName(variable.mutability),
9487 global.type.fmt(self, .percent),9589 global.type.fmt(self, .percent),
9488 variable.init.fmt(self, .{ .space = true }),9590 variable.init.fmt(self, .{ .space = true }),
9489 variable.alignment,9591 variable.alignment.fmt(", "),
9490 try metadata_formatter.fmt("!dbg ", global.dbg, null),9592 try metadata_formatter.fmt("!dbg ", global.dbg, null),
9491 });9593 });
9492 }9594 }
...@@ -9500,7 +9602,7 @@ pub fn print(self: *Builder, w: *Writer) (Writer.Error || Allocator.Error)!void...@@ -9500,7 +9602,7 @@ pub fn print(self: *Builder, w: *Writer) (Writer.Error || Allocator.Error)!void
9500 metadata_formatter.need_comma = true;9602 metadata_formatter.need_comma = true;
9501 defer metadata_formatter.need_comma = undefined;9603 defer metadata_formatter.need_comma = undefined;
9502 try w.print(9604 try w.print(
9503 \\{f} ={f}{f}{f}{f}{f }{f} alias {f}, {f}{f}9605 \\{f} ={f}{f}{f}{f}{f}{f} alias {f}, {f}{f}
9504 \\9606 \\
9505 , .{9607 , .{
9506 alias.global.fmt(self),9608 alias.global.fmt(self),
...@@ -9508,7 +9610,7 @@ pub fn print(self: *Builder, w: *Writer) (Writer.Error || Allocator.Error)!void...@@ -9508,7 +9610,7 @@ pub fn print(self: *Builder, w: *Writer) (Writer.Error || Allocator.Error)!void
9508 global.preemption,9610 global.preemption,
9509 global.visibility,9611 global.visibility,
9510 global.dll_storage_class,9612 global.dll_storage_class,
9511 alias.thread_local,9613 alias.thread_local.fmt(" "),
9512 global.unnamed_addr,9614 global.unnamed_addr,
9513 global.type.fmt(self, .percent),9615 global.type.fmt(self, .percent),
9514 alias.aliasee.fmt(self, .{ .percent = true }),9616 alias.aliasee.fmt(self, .{ .percent = true }),
...@@ -9564,15 +9666,15 @@ pub fn print(self: *Builder, w: *Writer) (Writer.Error || Allocator.Error)!void...@@ -9564,15 +9666,15 @@ pub fn print(self: *Builder, w: *Writer) (Writer.Error || Allocator.Error)!void
9564 try w.writeAll("...");9666 try w.writeAll("...");
9565 },9667 },
9566 }9668 }
9567 try w.print("){f}{f }", .{ global.unnamed_addr, global.addr_space });9669 try w.print("){f}{f}", .{ global.unnamed_addr, global.addr_space.fmt(" ") });
9568 if (function_attributes != .none) try w.print(" #{d}", .{9670 if (function_attributes != .none) try w.print(" #{d}", .{
9569 (try attribute_groups.getOrPutValue(self.gpa, function_attributes, {})).index,9671 (try attribute_groups.getOrPutValue(self.gpa, function_attributes, {})).index,
9570 });9672 });
9571 {9673 {
9572 metadata_formatter.need_comma = false;9674 metadata_formatter.need_comma = false;
9573 defer metadata_formatter.need_comma = undefined;9675 defer metadata_formatter.need_comma = undefined;
9574 try w.print("{f }{f}", .{9676 try w.print("{f}{f}", .{
9575 function.alignment,9677 function.alignment.fmt(" "),
9576 try metadata_formatter.fmt(" !dbg ", global.dbg, null),9678 try metadata_formatter.fmt(" !dbg ", global.dbg, null),
9577 });9679 });
9578 }9680 }
...@@ -9709,7 +9811,7 @@ pub fn print(self: *Builder, w: *Writer) (Writer.Error || Allocator.Error)!void...@@ -9709,7 +9811,7 @@ pub fn print(self: *Builder, w: *Writer) (Writer.Error || Allocator.Error)!void
9709 .@"alloca inalloca",9811 .@"alloca inalloca",
9710 => |tag| {9812 => |tag| {
9711 const extra = function.extraData(Function.Instruction.Alloca, instruction.data);9813 const extra = function.extraData(Function.Instruction.Alloca, instruction.data);
9712 try w.print(" %{f} = {s} {f}{f}{f, }{f, }", .{9814 try w.print(" %{f} = {s} {f}{f}{f}{f}", .{
9713 instruction_index.name(&function).fmt(self),9815 instruction_index.name(&function).fmt(self),
9714 @tagName(tag),9816 @tagName(tag),
9715 extra.type.fmt(self, .percent),9817 extra.type.fmt(self, .percent),
...@@ -9720,24 +9822,24 @@ pub fn print(self: *Builder, w: *Writer) (Writer.Error || Allocator.Error)!void...@@ -9720,24 +9822,24 @@ pub fn print(self: *Builder, w: *Writer) (Writer.Error || Allocator.Error)!void
9720 .comma = true,9822 .comma = true,
9721 .percent = true,9823 .percent = true,
9722 }),9824 }),
9723 extra.info.alignment,9825 extra.info.alignment.fmt(", "),
9724 extra.info.addr_space,9826 extra.info.addr_space.fmt(", "),
9725 });9827 });
9726 },9828 },
9727 .arg => unreachable,9829 .arg => unreachable,
9728 .atomicrmw => |tag| {9830 .atomicrmw => |tag| {
9729 const extra =9831 const extra =
9730 function.extraData(Function.Instruction.AtomicRmw, instruction.data);9832 function.extraData(Function.Instruction.AtomicRmw, instruction.data);
9731 try w.print(" %{f} = {s}{f } {s} {f}, {f}{f }{f }{f, }", .{9833 try w.print(" %{f} = {t}{f} {t} {f}, {f}{f}{f}{f}", .{
9732 instruction_index.name(&function).fmt(self),9834 instruction_index.name(&function).fmt(self),
9733 @tagName(tag),9835 tag,
9734 extra.info.access_kind,9836 extra.info.access_kind.fmt(" "),
9735 @tagName(extra.info.atomic_rmw_operation),9837 extra.info.atomic_rmw_operation,
9736 extra.ptr.fmt(function_index, self, .{ .percent = true }),9838 extra.ptr.fmt(function_index, self, .{ .percent = true }),
9737 extra.val.fmt(function_index, self, .{ .percent = true }),9839 extra.val.fmt(function_index, self, .{ .percent = true }),
9738 extra.info.sync_scope,9840 extra.info.sync_scope.fmt(" "),
9739 extra.info.success_ordering,9841 extra.info.success_ordering.fmt(" "),
9740 extra.info.alignment,9842 extra.info.alignment.fmt(", "),
9741 });9843 });
9742 },9844 },
9743 .block => {9845 .block => {
...@@ -9792,8 +9894,8 @@ pub fn print(self: *Builder, w: *Writer) (Writer.Error || Allocator.Error)!void...@@ -9792,8 +9894,8 @@ pub fn print(self: *Builder, w: *Writer) (Writer.Error || Allocator.Error)!void
9792 }),9894 }),
9793 .none => unreachable,9895 .none => unreachable,
9794 }9896 }
9795 try w.print("{s}{f}{f}{f} {f} {f}(", .{9897 try w.print("{t}{f}{f}{f} {f} {f}(", .{
9796 @tagName(tag),9898 tag,
9797 extra.data.info.call_conv,9899 extra.data.info.call_conv,
9798 extra.data.attributes.ret(self).fmt(self, .{}),9900 extra.data.attributes.ret(self).fmt(self, .{}),
9799 extra.data.callee.typeOf(function_index, self).pointerAddrSpace(self),9901 extra.data.callee.typeOf(function_index, self).pointerAddrSpace(self),
...@@ -9831,17 +9933,17 @@ pub fn print(self: *Builder, w: *Writer) (Writer.Error || Allocator.Error)!void...@@ -9831,17 +9933,17 @@ pub fn print(self: *Builder, w: *Writer) (Writer.Error || Allocator.Error)!void
9831 => |tag| {9933 => |tag| {
9832 const extra =9934 const extra =
9833 function.extraData(Function.Instruction.CmpXchg, instruction.data);9935 function.extraData(Function.Instruction.CmpXchg, instruction.data);
9834 try w.print(" %{f} = {s}{f } {f}, {f}, {f}{f }{f }{f }{f, }", .{9936 try w.print(" %{f} = {t}{f} {f}, {f}, {f}{f}{f}{f}{f}", .{
9835 instruction_index.name(&function).fmt(self),9937 instruction_index.name(&function).fmt(self),
9836 @tagName(tag),9938 tag,
9837 extra.info.access_kind,9939 extra.info.access_kind.fmt(" "),
9838 extra.ptr.fmt(function_index, self, .{ .percent = true }),9940 extra.ptr.fmt(function_index, self, .{ .percent = true }),
9839 extra.cmp.fmt(function_index, self, .{ .percent = true }),9941 extra.cmp.fmt(function_index, self, .{ .percent = true }),
9840 extra.new.fmt(function_index, self, .{ .percent = true }),9942 extra.new.fmt(function_index, self, .{ .percent = true }),
9841 extra.info.sync_scope,9943 extra.info.sync_scope.fmt(" "),
9842 extra.info.success_ordering,9944 extra.info.success_ordering.fmt(" "),
9843 extra.info.failure_ordering,9945 extra.info.failure_ordering.fmt(" "),
9844 extra.info.alignment,9946 extra.info.alignment.fmt(", "),
9845 });9947 });
9846 },9948 },
9847 .extractelement => |tag| {9949 .extractelement => |tag| {
...@@ -9869,10 +9971,10 @@ pub fn print(self: *Builder, w: *Writer) (Writer.Error || Allocator.Error)!void...@@ -9869,10 +9971,10 @@ pub fn print(self: *Builder, w: *Writer) (Writer.Error || Allocator.Error)!void
9869 },9971 },
9870 .fence => |tag| {9972 .fence => |tag| {
9871 const info: MemoryAccessInfo = @bitCast(instruction.data);9973 const info: MemoryAccessInfo = @bitCast(instruction.data);
9872 try w.print(" {s}{f }{f }", .{9974 try w.print(" {t}{f}{f}", .{
9873 @tagName(tag),9975 tag,
9874 info.sync_scope,9976 info.sync_scope.fmt(" "),
9875 info.success_ordering,9977 info.success_ordering.fmt(" "),
9876 });9978 });
9877 },9979 },
9878 .fneg,9980 .fneg,
...@@ -9947,15 +10049,15 @@ pub fn print(self: *Builder, w: *Writer) (Writer.Error || Allocator.Error)!void...@@ -9947,15 +10049,15 @@ pub fn print(self: *Builder, w: *Writer) (Writer.Error || Allocator.Error)!void
9947 .@"load atomic",10049 .@"load atomic",
9948 => |tag| {10050 => |tag| {
9949 const extra = function.extraData(Function.Instruction.Load, instruction.data);10051 const extra = function.extraData(Function.Instruction.Load, instruction.data);
9950 try w.print(" %{f} = {s}{f } {f}, {f}{f }{f }{f, }", .{10052 try w.print(" %{f} = {t}{f} {f}, {f}{f}{f}{f}", .{
9951 instruction_index.name(&function).fmt(self),10053 instruction_index.name(&function).fmt(self),
9952 @tagName(tag),10054 tag,
9953 extra.info.access_kind,10055 extra.info.access_kind.fmt(" "),
9954 extra.type.fmt(self, .percent),10056 extra.type.fmt(self, .percent),
9955 extra.ptr.fmt(function_index, self, .{ .percent = true }),10057 extra.ptr.fmt(function_index, self, .{ .percent = true }),
9956 extra.info.sync_scope,10058 extra.info.sync_scope.fmt(" "),
9957 extra.info.success_ordering,10059 extra.info.success_ordering.fmt(" "),
9958 extra.info.alignment,10060 extra.info.alignment.fmt(", "),
9959 });10061 });
9960 },10062 },
9961 .phi,10063 .phi,
...@@ -10015,14 +10117,14 @@ pub fn print(self: *Builder, w: *Writer) (Writer.Error || Allocator.Error)!void...@@ -10015,14 +10117,14 @@ pub fn print(self: *Builder, w: *Writer) (Writer.Error || Allocator.Error)!void
10015 .@"store atomic",10117 .@"store atomic",
10016 => |tag| {10118 => |tag| {
10017 const extra = function.extraData(Function.Instruction.Store, instruction.data);10119 const extra = function.extraData(Function.Instruction.Store, instruction.data);
10018 try w.print(" {s}{f } {f}, {f}{f }{f }{f, }", .{10120 try w.print(" {t}{f} {f}, {f}{f}{f}{f}", .{
10019 @tagName(tag),10121 tag,
10020 extra.info.access_kind,10122 extra.info.access_kind.fmt(" "),
10021 extra.val.fmt(function_index, self, .{ .percent = true }),10123 extra.val.fmt(function_index, self, .{ .percent = true }),
10022 extra.ptr.fmt(function_index, self, .{ .percent = true }),10124 extra.ptr.fmt(function_index, self, .{ .percent = true }),
10023 extra.info.sync_scope,10125 extra.info.sync_scope.fmt(" "),
10024 extra.info.success_ordering,10126 extra.info.success_ordering.fmt(" "),
10025 extra.info.alignment,10127 extra.info.alignment.fmt(", "),
10026 });10128 });
10027 },10129 },
10028 .@"switch" => |tag| {10130 .@"switch" => |tag| {
lib/std/zon/stringify.zig+1-1
...@@ -615,7 +615,7 @@ pub fn Serializer(Writer: type) type {...@@ -615,7 +615,7 @@ pub fn Serializer(Writer: type) type {
615615
616 /// Serialize an integer.616 /// Serialize an integer.
617 pub fn int(self: *Self, val: anytype) Writer.Error!void {617 pub fn int(self: *Self, val: anytype) Writer.Error!void {
618 //try self.writer.printIntOptions(val, 10, .lower, .{});618 //try self.writer.printInt(val, 10, .lower, .{});
619 try std.fmt.deprecatedFormat(self.writer, "{d}", .{val});619 try std.fmt.deprecatedFormat(self.writer, "{d}", .{val});
620 }620 }
621621
src/Builtin.zig+2-2
...@@ -200,8 +200,8 @@ pub fn append(opts: @This(), buffer: *std.ArrayList(u8)) Allocator.Error!void {...@@ -200,8 +200,8 @@ pub fn append(opts: @This(), buffer: *std.ArrayList(u8)) Allocator.Error!void {
200 }),200 }),
201 .windows => |windows| try buffer.print(201 .windows => |windows| try buffer.print(
202 \\ .windows = .{{202 \\ .windows = .{{
203 \\ .min = {fc},203 \\ .min = {f},
204 \\ .max = {fc},204 \\ .max = {f},
205 \\ }}}},205 \\ }}}},
206 \\206 \\
207 , .{ windows.min, windows.max }),207 , .{ windows.min, windows.max }),
src/Package/Fetch.zig+6-3
...@@ -227,9 +227,9 @@ pub const JobQueue = struct {...@@ -227,9 +227,9 @@ pub const JobQueue = struct {
227 }227 }
228228
229 try buf.writer().print(229 try buf.writer().print(
230 \\ pub const build_root = "{fq}";230 \\ pub const build_root = "{f}";
231 \\231 \\
232 , .{fetch.package_root});232 , .{std.fmt.alt(fetch.package_root, .formatEscapeString)});
233233
234 if (fetch.has_build_zig) {234 if (fetch.has_build_zig) {
235 try buf.writer().print(235 try buf.writer().print(
...@@ -1079,7 +1079,10 @@ fn initResource(f: *Fetch, uri: std.Uri, server_header_buffer: []u8) RunError!Re...@@ -1079,7 +1079,10 @@ fn initResource(f: *Fetch, uri: std.Uri, server_header_buffer: []u8) RunError!Re
1079 });1079 });
1080 const notes_start = try eb.reserveNotes(notes_len);1080 const notes_start = try eb.reserveNotes(notes_len);
1081 eb.extra.items[notes_start] = @intFromEnum(try eb.addErrorMessage(.{1081 eb.extra.items[notes_start] = @intFromEnum(try eb.addErrorMessage(.{
1082 .msg = try eb.printString("try .url = \"{f;+/}#{f}\",", .{ 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 }),
1083 }));1086 }));
1084 return error.FetchFailed;1087 return error.FetchFailed;
1085 }1088 }
src/Package/Fetch/git.zig+24-8
...@@ -662,13 +662,21 @@ pub const Session = struct {...@@ -662,13 +662,21 @@ pub const Session = struct {
662 fn init(allocator: Allocator, uri: std.Uri) !Location {662 fn init(allocator: Allocator, uri: std.Uri) !Location {
663 const scheme = try allocator.dupe(u8, uri.scheme);663 const scheme = try allocator.dupe(u8, uri.scheme);
664 errdefer allocator.free(scheme);664 errdefer allocator.free(scheme);
665 const user = if (uri.user) |user| try std.fmt.allocPrint(allocator, "{fuser}", .{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;
666 errdefer if (user) |s| allocator.free(s);668 errdefer if (user) |s| allocator.free(s);
667 const password = if (uri.password) |password| try std.fmt.allocPrint(allocator, "{fpassword}", .{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;
668 errdefer if (password) |s| allocator.free(s);672 errdefer if (password) |s| allocator.free(s);
669 const host = if (uri.host) |host| try std.fmt.allocPrint(allocator, "{fhost}", .{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;
670 errdefer if (host) |s| allocator.free(s);676 errdefer if (host) |s| allocator.free(s);
671 const path = try std.fmt.allocPrint(allocator, "{fpath}", .{uri.path});677 const path = try std.fmt.allocPrint(allocator, "{f}", .{
678 std.fmt.alt(uri.path, .formatPath),
679 });
672 errdefer allocator.free(path);680 errdefer allocator.free(path);
673 // The query and fragment are not used as part of the base server URI.681 // The query and fragment are not used as part of the base server URI.
674 return .{682 return .{
...@@ -699,7 +707,9 @@ pub const Session = struct {...@@ -699,7 +707,9 @@ pub const Session = struct {
699 fn getCapabilities(session: *Session, http_headers_buffer: []u8) !CapabilityIterator {707 fn getCapabilities(session: *Session, http_headers_buffer: []u8) !CapabilityIterator {
700 var info_refs_uri = session.location.uri;708 var info_refs_uri = session.location.uri;
701 {709 {
702 const session_uri_path = try std.fmt.allocPrint(session.allocator, "{fpath}", .{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 });
703 defer session.allocator.free(session_uri_path);713 defer session.allocator.free(session_uri_path);
704 info_refs_uri.path = .{ .percent_encoded = try std.fs.path.resolvePosix(session.allocator, &.{ "/", session_uri_path, "info/refs" }) };714 info_refs_uri.path = .{ .percent_encoded = try std.fs.path.resolvePosix(session.allocator, &.{ "/", session_uri_path, "info/refs" }) };
705 }715 }
...@@ -723,7 +733,9 @@ pub const Session = struct {...@@ -723,7 +733,9 @@ pub const Session = struct {
723 if (request.response.status != .ok) return error.ProtocolError;733 if (request.response.status != .ok) return error.ProtocolError;
724 const any_redirects_occurred = request.redirect_behavior.remaining() < max_redirects;734 const any_redirects_occurred = request.redirect_behavior.remaining() < max_redirects;
725 if (any_redirects_occurred) {735 if (any_redirects_occurred) {
726 const request_uri_path = try std.fmt.allocPrint(session.allocator, "{fpath}", .{request.uri.path});736 const request_uri_path = try std.fmt.allocPrint(session.allocator, "{f}", .{
737 std.fmt.alt(request.uri.path, .formatPath),
738 });
727 defer session.allocator.free(request_uri_path);739 defer session.allocator.free(request_uri_path);
728 if (!mem.endsWith(u8, request_uri_path, "/info/refs")) return error.UnparseableRedirect;740 if (!mem.endsWith(u8, request_uri_path, "/info/refs")) return error.UnparseableRedirect;
729 var new_uri = request.uri;741 var new_uri = request.uri;
...@@ -810,7 +822,9 @@ pub const Session = struct {...@@ -810,7 +822,9 @@ pub const Session = struct {
810 pub fn listRefs(session: Session, options: ListRefsOptions) !RefIterator {822 pub fn listRefs(session: Session, options: ListRefsOptions) !RefIterator {
811 var upload_pack_uri = session.location.uri;823 var upload_pack_uri = session.location.uri;
812 {824 {
813 const session_uri_path = try std.fmt.allocPrint(session.allocator, "{fpath}", .{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 });
814 defer session.allocator.free(session_uri_path);828 defer session.allocator.free(session_uri_path);
815 upload_pack_uri.path = .{ .percent_encoded = try std.fs.path.resolvePosix(session.allocator, &.{ "/", session_uri_path, "git-upload-pack" }) };829 upload_pack_uri.path = .{ .percent_encoded = try std.fs.path.resolvePosix(session.allocator, &.{ "/", session_uri_path, "git-upload-pack" }) };
816 }830 }
...@@ -925,7 +939,9 @@ pub const Session = struct {...@@ -925,7 +939,9 @@ pub const Session = struct {
925 ) !FetchStream {939 ) !FetchStream {
926 var upload_pack_uri = session.location.uri;940 var upload_pack_uri = session.location.uri;
927 {941 {
928 const session_uri_path = try std.fmt.allocPrint(session.allocator, "{fpath}", .{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 });
929 defer session.allocator.free(session_uri_path);945 defer session.allocator.free(session_uri_path);
930 upload_pack_uri.path = .{ .percent_encoded = try std.fs.path.resolvePosix(session.allocator, &.{ "/", session_uri_path, "git-upload-pack" }) };946 upload_pack_uri.path = .{ .percent_encoded = try std.fs.path.resolvePosix(session.allocator, &.{ "/", session_uri_path, "git-upload-pack" }) };
931 }947 }
src/Sema/LowerZon.zig+1-1
...@@ -492,7 +492,7 @@ fn lowerInt(...@@ -492,7 +492,7 @@ fn lowerInt(
492 if (!val.fitsInTwosComp(int_info.signedness, int_info.bits)) {492 if (!val.fitsInTwosComp(int_info.signedness, int_info.bits)) {
493 return self.fail(493 return self.fail(
494 node,494 node,
495 "type '{f}' cannot represent integer value '{f}'",495 "type '{f}' cannot represent integer value '{d}'",
496 .{ res_ty.fmt(self.sema.pt), val },496 .{ res_ty.fmt(self.sema.pt), val },
497 );497 );
498 }498 }
src/arch/riscv64/CodeGen.zig+2-2
...@@ -1151,7 +1151,7 @@ fn gen(func: *Func) !void {...@@ -1151,7 +1151,7 @@ fn gen(func: *Func) !void {
1151 func.ret_mcv.long.address().offset(-func.ret_mcv.short.indirect.off),1151 func.ret_mcv.long.address().offset(-func.ret_mcv.short.indirect.off),
1152 );1152 );
1153 func.ret_mcv.long = .{ .load_frame = .{ .index = frame_index } };1153 func.ret_mcv.long = .{ .load_frame = .{ .index = frame_index } };
1154 tracking_log.debug("spill {} to {f}", .{ func.ret_mcv.long, frame_index });1154 tracking_log.debug("spill {} to {}", .{ func.ret_mcv.long, frame_index });
1155 },1155 },
1156 else => unreachable,1156 else => unreachable,
1157 }1157 }
...@@ -1987,7 +1987,7 @@ fn allocFrameIndex(func: *Func, alloc: FrameAlloc) !FrameIndex {...@@ -1987,7 +1987,7 @@ fn allocFrameIndex(func: *Func, alloc: FrameAlloc) !FrameIndex {
1987 }1987 }
1988 const frame_index: FrameIndex = @enumFromInt(func.frame_allocs.len);1988 const frame_index: FrameIndex = @enumFromInt(func.frame_allocs.len);
1989 try func.frame_allocs.append(func.gpa, alloc);1989 try func.frame_allocs.append(func.gpa, alloc);
1990 log.debug("allocated frame {f}", .{frame_index});1990 log.debug("allocated frame {}", .{frame_index});
1991 return frame_index;1991 return frame_index;
1992}1992}
19931993
src/arch/riscv64/bits.zig+6
...@@ -249,6 +249,12 @@ pub const FrameIndex = enum(u32) {...@@ -249,6 +249,12 @@ pub const FrameIndex = enum(u32) {
249 spill_frame,249 spill_frame,
250 /// Other indices are used for local variable stack slots250 /// Other indices are used for local variable stack slots
251 _,251 _,
252
253 pub const named_count = @typeInfo(FrameIndex).@"enum".fields.len;
254
255 pub fn isNamed(fi: FrameIndex) bool {
256 return @intFromEnum(fi) < named_count;
257 }
252};258};
253259
254/// A linker symbol not yet allocated in VM.260/// A linker symbol not yet allocated in VM.
src/arch/x86_64/CodeGen.zig+27-27
...@@ -525,47 +525,47 @@ pub const MCValue = union(enum) {...@@ -525,47 +525,47 @@ pub const MCValue = union(enum) {
525 };525 };
526 }526 }
527527
528 pub fn format(mcv: MCValue, bw: *Writer) Writer.Error!void {528 pub fn format(mcv: MCValue, w: *Writer) Writer.Error!void {
529 switch (mcv) {529 switch (mcv) {
530 .none, .unreach, .dead, .undef => try bw.print("({s})", .{@tagName(mcv)}),530 .none, .unreach, .dead, .undef => try w.print("({s})", .{@tagName(mcv)}),
531 .immediate => |pl| try bw.print("0x{x}", .{pl}),531 .immediate => |pl| try w.print("0x{x}", .{pl}),
532 .memory => |pl| try bw.print("[ds:0x{x}]", .{pl}),532 .memory => |pl| try w.print("[ds:0x{x}]", .{pl}),
533 inline .eflags, .register => |pl| try bw.print("{s}", .{@tagName(pl)}),533 inline .eflags, .register => |pl| try w.print("{s}", .{@tagName(pl)}),
534 .register_pair => |pl| try bw.print("{s}:{s}", .{ @tagName(pl[1]), @tagName(pl[0]) }),534 .register_pair => |pl| try w.print("{s}:{s}", .{ @tagName(pl[1]), @tagName(pl[0]) }),
535 .register_triple => |pl| try bw.print("{s}:{s}:{s}", .{535 .register_triple => |pl| try w.print("{s}:{s}:{s}", .{
536 @tagName(pl[2]), @tagName(pl[1]), @tagName(pl[0]),536 @tagName(pl[2]), @tagName(pl[1]), @tagName(pl[0]),
537 }),537 }),
538 .register_quadruple => |pl| try bw.print("{s}:{s}:{s}:{s}", .{538 .register_quadruple => |pl| try w.print("{s}:{s}:{s}:{s}", .{
539 @tagName(pl[3]), @tagName(pl[2]), @tagName(pl[1]), @tagName(pl[0]),539 @tagName(pl[3]), @tagName(pl[2]), @tagName(pl[1]), @tagName(pl[0]),
540 }),540 }),
541 .register_offset => |pl| try bw.print("{s} + 0x{x}", .{ @tagName(pl.reg), pl.off }),541 .register_offset => |pl| try w.print("{s} + 0x{x}", .{ @tagName(pl.reg), pl.off }),
542 .register_overflow => |pl| try bw.print("{s}:{s}", .{542 .register_overflow => |pl| try w.print("{s}:{s}", .{
543 @tagName(pl.eflags),543 @tagName(pl.eflags),
544 @tagName(pl.reg),544 @tagName(pl.reg),
545 }),545 }),
546 .register_mask => |pl| try bw.print("mask({s},{f}):{c}{s}", .{546 .register_mask => |pl| try w.print("mask({s},{f}):{c}{s}", .{
547 @tagName(pl.info.kind),547 @tagName(pl.info.kind),
548 pl.info.scalar,548 pl.info.scalar,
549 @as(u8, if (pl.info.inverted) '!' else ' '),549 @as(u8, if (pl.info.inverted) '!' else ' '),
550 @tagName(pl.reg),550 @tagName(pl.reg),
551 }),551 }),
552 .indirect => |pl| try bw.print("[{s} + 0x{x}]", .{ @tagName(pl.reg), pl.off }),552 .indirect => |pl| try w.print("[{s} + 0x{x}]", .{ @tagName(pl.reg), pl.off }),
553 .indirect_load_frame => |pl| try bw.print("[[{f} + 0x{x}]]", .{ pl.index, pl.off }),553 .indirect_load_frame => |pl| try w.print("[[{} + 0x{x}]]", .{ pl.index, pl.off }),
554 .load_frame => |pl| try bw.print("[{f} + 0x{x}]", .{ pl.index, pl.off }),554 .load_frame => |pl| try w.print("[{} + 0x{x}]", .{ pl.index, pl.off }),
555 .lea_frame => |pl| try bw.print("{f} + 0x{x}", .{ pl.index, pl.off }),555 .lea_frame => |pl| try w.print("{} + 0x{x}", .{ pl.index, pl.off }),
556 .load_nav => |pl| try bw.print("[nav:{d}]", .{@intFromEnum(pl)}),556 .load_nav => |pl| try w.print("[nav:{d}]", .{@intFromEnum(pl)}),
557 .lea_nav => |pl| try bw.print("nav:{d}", .{@intFromEnum(pl)}),557 .lea_nav => |pl| try w.print("nav:{d}", .{@intFromEnum(pl)}),
558 .load_uav => |pl| try bw.print("[uav:{d}]", .{@intFromEnum(pl.val)}),558 .load_uav => |pl| try w.print("[uav:{d}]", .{@intFromEnum(pl.val)}),
559 .lea_uav => |pl| try bw.print("uav:{d}", .{@intFromEnum(pl.val)}),559 .lea_uav => |pl| try w.print("uav:{d}", .{@intFromEnum(pl.val)}),
560 .load_lazy_sym => |pl| try bw.print("[lazy:{s}:{d}]", .{ @tagName(pl.kind), @intFromEnum(pl.ty) }),560 .load_lazy_sym => |pl| try w.print("[lazy:{s}:{d}]", .{ @tagName(pl.kind), @intFromEnum(pl.ty) }),
561 .lea_lazy_sym => |pl| try bw.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 bw.print("[extern:{d}]", .{@intFromEnum(pl)}),562 .load_extern_func => |pl| try w.print("[extern:{d}]", .{@intFromEnum(pl)}),
563 .lea_extern_func => |pl| try bw.print("extern:{d}", .{@intFromEnum(pl)}),563 .lea_extern_func => |pl| try w.print("extern:{d}", .{@intFromEnum(pl)}),
564 .elementwise_args => |pl| try bw.print("elementwise:{d}:[{f} + 0x{x}]", .{564 .elementwise_args => |pl| try w.print("elementwise:{d}:[{} + 0x{x}]", .{
565 pl.regs, pl.frame_index, pl.frame_off,565 pl.regs, pl.frame_index, pl.frame_off,
566 }),566 }),
567 .reserved_frame => |pl| try bw.print("(dead:{f})", .{pl}),567 .reserved_frame => |pl| try w.print("(dead:{})", .{pl}),
568 .air_ref => |pl| try bw.print("(air:0x{x})", .{@intFromEnum(pl)}),568 .air_ref => |pl| try w.print("(air:0x{x})", .{@intFromEnum(pl)}),
569 }569 }
570 }570 }
571};571};
...@@ -2026,7 +2026,7 @@ fn gen(...@@ -2026,7 +2026,7 @@ fn gen(
2026 .{},2026 .{},
2027 );2027 );
2028 self.ret_mcv.long = .{ .load_frame = .{ .index = frame_index } };2028 self.ret_mcv.long = .{ .load_frame = .{ .index = frame_index } };
2029 tracking_log.debug("spill {f} to {f}", .{ self.ret_mcv.long, frame_index });2029 tracking_log.debug("spill {f} to {}", .{ self.ret_mcv.long, frame_index });
2030 },2030 },
2031 else => unreachable,2031 else => unreachable,
2032 }2032 }
src/arch/x86_64/bits.zig+6
...@@ -721,6 +721,12 @@ pub const FrameIndex = enum(u32) {...@@ -721,6 +721,12 @@ pub const FrameIndex = enum(u32) {
721 call_frame,721 call_frame,
722 // Other indices are used for local variable stack slots722 // Other indices are used for local variable stack slots
723 _,723 _,
724
725 pub const named_count = @typeInfo(FrameIndex).@"enum".fields.len;
726
727 pub fn isNamed(fi: FrameIndex) bool {
728 return @intFromEnum(fi) < named_count;
729 }
724};730};
725731
726pub const FrameAddr = struct { index: FrameIndex, off: i32 = 0 };732pub const FrameAddr = struct { index: FrameIndex, off: i32 = 0 };
src/arch/x86_64/encoder.zig+1-1
...@@ -259,7 +259,7 @@ pub const Instruction = struct {...@@ -259,7 +259,7 @@ pub const Instruction = struct {
259 switch (sib.base) {259 switch (sib.base) {
260 .none => any = false,260 .none => any = false,
261 .reg => |reg| try w.print("{s}", .{@tagName(reg)}),261 .reg => |reg| try w.print("{s}", .{@tagName(reg)}),
262 .frame => |frame_index| try w.print("{f}", .{frame_index}),262 .frame => |frame_index| try w.print("{}", .{frame_index}),
263 .table => try w.print("Table", .{}),263 .table => try w.print("Table", .{}),
264 .rip_inst => |inst_index| try w.print("RipInst({d})", .{inst_index}),264 .rip_inst => |inst_index| try w.print("RipInst({d})", .{inst_index}),
265 .nav => |nav| try w.print("Nav({d})", .{@intFromEnum(nav)}),265 .nav => |nav| try w.print("Nav({d})", .{@intFromEnum(nav)}),
src/link.zig+8-6
...@@ -838,8 +838,10 @@ pub const File = struct {...@@ -838,8 +838,10 @@ pub const File = struct {
838 const cached_pp_file_path = the_key.status.success.object_path;838 const cached_pp_file_path = the_key.status.success.object_path;
839 cached_pp_file_path.root_dir.handle.copyFile(cached_pp_file_path.sub_path, emit.root_dir.handle, emit.sub_path, .{}) catch |err| {839 cached_pp_file_path.root_dir.handle.copyFile(cached_pp_file_path.sub_path, emit.root_dir.handle, emit.sub_path, .{}) catch |err| {
840 const diags = &base.comp.link_diags;840 const diags = &base.comp.link_diags;
841 return diags.fail("failed to copy '{f'}' to '{f'}': {s}", .{841 return diags.fail("failed to copy '{f}' to '{f}': {s}", .{
842 @as(Path, cached_pp_file_path), @as(Path, emit), @errorName(err),842 std.fmt.alt(@as(Path, cached_pp_file_path), .formatEscapeChar),
843 std.fmt.alt(@as(Path, emit), .formatEscapeChar),
844 @errorName(err),
843 });845 });
844 };846 };
845 return;847 return;
...@@ -2086,14 +2088,14 @@ fn resolvePathInputLib(...@@ -2086,14 +2088,14 @@ fn resolvePathInputLib(
2086 }) {2088 }) {
2087 var file = test_path.root_dir.handle.openFile(test_path.sub_path, .{}) catch |err| switch (err) {2089 var file = test_path.root_dir.handle.openFile(test_path.sub_path, .{}) catch |err| switch (err) {
2088 error.FileNotFound => return .no_match,2090 error.FileNotFound => return .no_match,
2089 else => |e| fatal("unable to search for {s} library '{f'}': {s}", .{2091 else => |e| fatal("unable to search for {s} library '{f}': {s}", .{
2090 @tagName(link_mode), test_path, @errorName(e),2092 @tagName(link_mode), std.fmt.alt(test_path, .formatEscapeChar), @errorName(e),
2091 }),2093 }),
2092 };2094 };
2093 errdefer file.close();2095 errdefer file.close();
2094 try ld_script_bytes.resize(gpa, @max(std.elf.MAGIC.len, std.elf.ARMAG.len));2096 try ld_script_bytes.resize(gpa, @max(std.elf.MAGIC.len, std.elf.ARMAG.len));
2095 const n = file.preadAll(ld_script_bytes.items, 0) catch |err| fatal("failed to read '{f'}': {s}", .{2097 const n = file.preadAll(ld_script_bytes.items, 0) catch |err| fatal("failed to read '{f}': {s}", .{
2096 test_path, @errorName(err),2098 std.fmt.alt(test_path, .formatEscapeChar), @errorName(err),
2097 });2099 });
2098 const buf = ld_script_bytes.items[0..n];2100 const buf = ld_script_bytes.items[0..n];
2099 if (mem.startsWith(u8, buf, std.elf.MAGIC) or mem.startsWith(u8, buf, std.elf.ARMAG)) {2101 if (mem.startsWith(u8, buf, std.elf.MAGIC) or mem.startsWith(u8, buf, std.elf.ARMAG)) {
src/link/C.zig+2-2
...@@ -503,8 +503,8 @@ pub fn flush(self: *C, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.P...@@ -503,8 +503,8 @@ pub fn flush(self: *C, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.P
503 var fw = file.writer(&.{});503 var fw = file.writer(&.{});
504 var w = &fw.interface;504 var w = &fw.interface;
505 w.writeVecAll(f.all_buffers.items) catch |err| switch (err) {505 w.writeVecAll(f.all_buffers.items) catch |err| switch (err) {
506 error.WriteFailed => return diags.fail("failed to write to '{f'}': {s}", .{506 error.WriteFailed => return diags.fail("failed to write to '{f}': {s}", .{
507 self.base.emit, @errorName(fw.err.?),507 std.fmt.alt(self.base.emit, .formatEscapeChar), @errorName(fw.err.?),
508 }),508 }),
509 };509 };
510}510}
src/main.zig+3-1
...@@ -6964,7 +6964,9 @@ fn cmdFetch(...@@ -6964,7 +6964,9 @@ fn cmdFetch(
6964 std.log.info("resolved ref '{s}' to commit {s}", .{ target_ref, latest_commit_hex });6964 std.log.info("resolved ref '{s}' to commit {s}", .{ target_ref, latest_commit_hex });
69656965
6966 // include the original refspec in a query parameter, could be used to check for updates6966 // include the original refspec in a query parameter, could be used to check for updates
6967 uri.query = .{ .percent_encoded = try std.fmt.allocPrint(arena, "ref={f%}", .{fragment}) };6967 uri.query = .{ .percent_encoded = try std.fmt.allocPrint(arena, "ref={f}", .{
6968 std.fmt.alt(fragment, .formatEscaped),
6969 }) };
6968 } else {6970 } else {
6969 std.log.info("resolved to commit {s}", .{latest_commit_hex});6971 std.log.info("resolved to commit {s}", .{latest_commit_hex});
6970 }6972 }
src/print_value.zig+1-1
...@@ -77,7 +77,7 @@ pub fn print(...@@ -77,7 +77,7 @@ pub fn print(
77 .func => |func| try writer.print("(function '{f}')", .{ip.getNav(func.owner_nav).name.fmt(ip)}),77 .func => |func| try writer.print("(function '{f}')", .{ip.getNav(func.owner_nav).name.fmt(ip)}),
78 .int => |int| switch (int.storage) {78 .int => |int| switch (int.storage) {
79 inline .u64, .i64 => |x| try writer.print("{d}", .{x}),79 inline .u64, .i64 => |x| try writer.print("{d}", .{x}),
80 .big_int => |x| try writer.print("{fd}", .{x}),80 .big_int => |x| try writer.print("{d}", .{x}),
81 .lazy_align => |ty| if (opt_sema != null) {81 .lazy_align => |ty| if (opt_sema != null) {
82 const a = try Type.fromInterned(ty).abiAlignmentSema(pt);82 const a = try Type.fromInterned(ty).abiAlignmentSema(pt);
83 try writer.print("{d}", .{a.toByteUnits() orelse 0});83 try writer.print("{d}", .{a.toByteUnits() orelse 0});