authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-07-15 16:10:36-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-07-16 10:27:39-07:00
log54f073377c724641d43f230ea1cc7aec33c08476
tree216e6116e2da693ad5d98d3b59e6406e88acc949
parent15f45e89a751bd2d2dbbbf8d50138f91ce7bf754

std.zig.render: handle legacy clobber updating more gracefully

"that's really easy to handle correctly" he said

2 files changed, 81 insertions(+), 23 deletions(-)

lib/std/zig/parser_test.zig+54-11
...@@ -32,7 +32,7 @@ test "zig fmt: tuple struct" {...@@ -32,7 +32,7 @@ test "zig fmt: tuple struct" {
32}32}
3333
34test "zig fmt: preserves clobbers in inline asm with stray comma" {34test "zig fmt: preserves clobbers in inline asm with stray comma" {
35 try testCanonical(35 try testTransform(
36 \\fn foo() void {36 \\fn foo() void {
37 \\ asm volatile (""37 \\ asm volatile (""
38 \\ : [_] "" (-> type),38 \\ : [_] "" (-> type),
...@@ -46,6 +46,20 @@ test "zig fmt: preserves clobbers in inline asm with stray comma" {...@@ -46,6 +46,20 @@ test "zig fmt: preserves clobbers in inline asm with stray comma" {
46 \\ );46 \\ );
47 \\}47 \\}
48 \\48 \\
49 ,
50 \\fn foo() void {
51 \\ asm volatile (""
52 \\ : [_] "" (-> type),
53 \\ :
54 \\ : .{ .clobber = true }
55 \\ );
56 \\ asm volatile (""
57 \\ :
58 \\ : [_] "" (type),
59 \\ : .{ .clobber = true }
60 \\ );
61 \\}
62 \\
49 );63 );
50}64}
5165
...@@ -64,7 +78,7 @@ test "zig fmt: remove trailing comma at the end of assembly clobber" {...@@ -64,7 +78,7 @@ test "zig fmt: remove trailing comma at the end of assembly clobber" {
64 \\ asm volatile (""78 \\ asm volatile (""
65 \\ : [_] "" (-> type),79 \\ : [_] "" (-> type),
66 \\ :80 \\ :
67 \\ : "clobber1", "clobber2"81 \\ : .{ .clobber1 = true, .clobber2 = true }
68 \\ );82 \\ );
69 \\}83 \\}
70 \\84 \\
...@@ -628,7 +642,7 @@ test "zig fmt: builtin call with trailing comma" {...@@ -628,7 +642,7 @@ test "zig fmt: builtin call with trailing comma" {
628}642}
629643
630test "zig fmt: asm expression with comptime content" {644test "zig fmt: asm expression with comptime content" {
631 try testCanonical(645 try testTransform(
632 \\comptime {646 \\comptime {
633 \\ asm ("foo" ++ "bar");647 \\ asm ("foo" ++ "bar");
634 \\}648 \\}
...@@ -648,6 +662,26 @@ test "zig fmt: asm expression with comptime content" {...@@ -648,6 +662,26 @@ test "zig fmt: asm expression with comptime content" {
648 \\ );662 \\ );
649 \\}663 \\}
650 \\664 \\
665 ,
666 \\comptime {
667 \\ asm ("foo" ++ "bar");
668 \\}
669 \\pub fn main() void {
670 \\ asm volatile ("foo" ++ "bar");
671 \\ asm volatile ("foo" ++ "bar"
672 \\ : [_] "" (x),
673 \\ );
674 \\ asm volatile ("foo" ++ "bar"
675 \\ : [_] "" (x),
676 \\ : [_] "" (y),
677 \\ );
678 \\ asm volatile ("foo" ++ "bar"
679 \\ : [_] "" (x),
680 \\ : [_] "" (y),
681 \\ : .{ .h = true, .e = true, .l = true, .l = true, .o = true }
682 \\ );
683 \\}
684 \\
651 );685 );
652}686}
653687
...@@ -2182,7 +2216,7 @@ test "zig fmt: simple asm" {...@@ -2182,7 +2216,7 @@ test "zig fmt: simple asm" {
2182 \\ : [a] "x" (-> i32),2216 \\ : [a] "x" (-> i32),
2183 \\ : [a] "x" (1),2217 \\ : [a] "x" (1),
2184 \\ );2218 \\ );
2185 \\ asm ("still not real assembly" ::: "a", "b");2219 \\ asm ("still not real assembly" ::: .{ .a = true, .b = true });
2186 \\}2220 \\}
2187 \\2221 \\
2188 );2222 );
...@@ -3907,7 +3941,7 @@ test "zig fmt: fn type" {...@@ -3907,7 +3941,7 @@ test "zig fmt: fn type" {
3907}3941}
39083942
3909test "zig fmt: inline asm" {3943test "zig fmt: inline asm" {
3910 try testCanonical(3944 try testTransform(
3911 \\pub fn syscall1(number: usize, arg1: usize) usize {3945 \\pub fn syscall1(number: usize, arg1: usize) usize {
3912 \\ return asm volatile ("syscall"3946 \\ return asm volatile ("syscall"
3913 \\ : [ret] "={rax}" (-> usize),3947 \\ : [ret] "={rax}" (-> usize),
...@@ -3917,6 +3951,16 @@ test "zig fmt: inline asm" {...@@ -3917,6 +3951,16 @@ test "zig fmt: inline asm" {
3917 \\ );3951 \\ );
3918 \\}3952 \\}
3919 \\3953 \\
3954 ,
3955 \\pub fn syscall1(number: usize, arg1: usize) usize {
3956 \\ return asm volatile ("syscall"
3957 \\ : [ret] "={rax}" (-> usize),
3958 \\ : [number] "{rax}" (number),
3959 \\ [arg1] "{rdi}" (arg1),
3960 \\ : .{ .rcx = true, .r11 = true }
3961 \\ );
3962 \\}
3963 \\
3920 );3964 );
3921}3965}
39223966
...@@ -3998,7 +4042,7 @@ test "zig fmt: inline asm parameter alignment" {...@@ -3998,7 +4042,7 @@ test "zig fmt: inline asm parameter alignment" {
3998 \\ asm volatile (4042 \\ asm volatile (
3999 \\ \\ foo4043 \\ \\ foo
4000 \\ \\ bar4044 \\ \\ bar
4001 \\ ::: "", "");4045 \\ ::: .{ .a = true, .b = true });
4002 \\ asm volatile (4046 \\ asm volatile (
4003 \\ \\ foo4047 \\ \\ foo
4004 \\ \\ bar4048 \\ \\ bar
...@@ -4006,8 +4050,7 @@ test "zig fmt: inline asm parameter alignment" {...@@ -4006,8 +4050,7 @@ test "zig fmt: inline asm parameter alignment" {
4006 \\ [_] "" (-> usize),4050 \\ [_] "" (-> usize),
4007 \\ : [_] "" (0),4051 \\ : [_] "" (0),
4008 \\ [_] "" (0),4052 \\ [_] "" (0),
4009 \\ : "", ""4053 \\ : .{});
4010 \\ );
4011 \\}4054 \\}
4012 \\4055 \\
4013 );4056 );
...@@ -5325,7 +5368,7 @@ test "zig fmt: make single-line if no trailing comma, fmt: off" {...@@ -5325,7 +5368,7 @@ test "zig fmt: make single-line if no trailing comma, fmt: off" {
5325 \\ asm ("not real assembly"5368 \\ asm ("not real assembly"
5326 \\ :[a] "x" (->i32),:[a] "x" (1),);5369 \\ :[a] "x" (->i32),:[a] "x" (1),);
5327 \\ asm volatile ("still not real assembly"5370 \\ asm volatile ("still not real assembly"
5328 \\ :::"a","b",);5371 \\ :::.{.a = true,.b = true,});
5329 \\ }5372 \\ }
5330 \\}5373 \\}
5331 );5374 );
...@@ -5737,7 +5780,7 @@ test "zig fmt: canonicalize symbols (asm)" {...@@ -5737,7 +5780,7 @@ test "zig fmt: canonicalize symbols (asm)" {
5737 \\ [@"arg1"] "{rdi}" (arg),5780 \\ [@"arg1"] "{rdi}" (arg),
5738 \\ [arg2] "{rsi}" (arg),5781 \\ [arg2] "{rsi}" (arg),
5739 \\ [arg3] "{rdx}" (arg),5782 \\ [arg3] "{rdx}" (arg),
5740 \\ : "rcx", "r11"5783 \\ : "rcx", "fn"
5741 \\ );5784 \\ );
5742 \\5785 \\
5743 \\ const @"false": usize = 10;5786 \\ const @"false": usize = 10;
...@@ -5759,7 +5802,7 @@ test "zig fmt: canonicalize symbols (asm)" {...@@ -5759,7 +5802,7 @@ test "zig fmt: canonicalize symbols (asm)" {
5759 \\ [arg1] "{rdi}" (arg),5802 \\ [arg1] "{rdi}" (arg),
5760 \\ [arg2] "{rsi}" (arg),5803 \\ [arg2] "{rsi}" (arg),
5761 \\ [arg3] "{rdx}" (arg),5804 \\ [arg3] "{rdx}" (arg),
5762 \\ : "rcx", "r11"5805 \\ : .{ .rcx = true, .@"fn" = true }
5763 \\ );5806 \\ );
5764 \\5807 \\
5765 \\ const @"false": usize = 10;5808 \\ const @"false": usize = 10;
lib/std/zig/render.zig+27-12
...@@ -2398,8 +2398,8 @@ fn renderAsmLegacy(...@@ -2398,8 +2398,8 @@ fn renderAsmLegacy(
23982398
2399 var tok_i = first_clobber;2399 var tok_i = first_clobber;
2400 while (true) : (tok_i += 1) {2400 while (true) : (tok_i += 1) {
2401 try ais.writer().writeAll(".@");2401 try ais.writer().writeByte('.');
2402 try ais.writer().writeAll(tokenSliceForRender(tree, tok_i));2402 _ = try writeStringLiteralAsIdentifier(r, tok_i);
2403 try ais.writer().writeAll(" = true");2403 try ais.writer().writeAll(" = true");
24042404
2405 tok_i += 1;2405 tok_i += 1;
...@@ -2411,6 +2411,7 @@ fn renderAsmLegacy(...@@ -2411,6 +2411,7 @@ fn renderAsmLegacy(
2411 },2411 },
2412 .comma => {2412 .comma => {
2413 if (tree.tokenTag(tok_i + 1) == .r_paren) {2413 if (tree.tokenTag(tok_i + 1) == .r_paren) {
2414 try ais.writer().writeAll(" }");
2414 ais.popIndent();2415 ais.popIndent();
2415 return renderToken(r, tok_i + 1, space);2416 return renderToken(r, tok_i + 1, space);
2416 } else {2417 } else {
...@@ -2512,11 +2513,10 @@ fn renderAsmLegacy(...@@ -2512,11 +2513,10 @@ fn renderAsmLegacy(
2512 switch (tree.tokenTag(tok_i + 1)) {2513 switch (tree.tokenTag(tok_i + 1)) {
2513 .r_paren => {2514 .r_paren => {
2514 ais.setIndentDelta(indent_delta);2515 ais.setIndentDelta(indent_delta);
2515 try ais.writer().writeAll(".@");2516 try ais.writer().writeByte('.');
2516 const lexeme = tokenSliceForRender(tree, tok_i);2517 const lexeme_len = try writeStringLiteralAsIdentifier(r, tok_i);
2517 try ais.writer().writeAll(lexeme);
2518 try ais.writer().writeAll(" = true }");2518 try ais.writer().writeAll(" = true }");
2519 try renderSpace(r, tok_i, lexeme.len, .newline);2519 try renderSpace(r, tok_i, lexeme_len, .newline);
2520 ais.popIndent();2520 ais.popIndent();
2521 return renderToken(r, tok_i + 1, space);2521 return renderToken(r, tok_i + 1, space);
2522 },2522 },
...@@ -2524,17 +2524,16 @@ fn renderAsmLegacy(...@@ -2524,17 +2524,16 @@ fn renderAsmLegacy(
2524 switch (tree.tokenTag(tok_i + 2)) {2524 switch (tree.tokenTag(tok_i + 2)) {
2525 .r_paren => {2525 .r_paren => {
2526 ais.setIndentDelta(indent_delta);2526 ais.setIndentDelta(indent_delta);
2527 try ais.writer().writeAll(".@");2527 try ais.writer().writeByte('.');
2528 const lexeme = tokenSliceForRender(tree, tok_i);2528 const lexeme_len = try writeStringLiteralAsIdentifier(r, tok_i);
2529 try ais.writer().writeAll(lexeme);
2530 try ais.writer().writeAll(" = true }");2529 try ais.writer().writeAll(" = true }");
2531 try renderSpace(r, tok_i, lexeme.len, .newline);2530 try renderSpace(r, tok_i, lexeme_len, .newline);
2532 ais.popIndent();2531 ais.popIndent();
2533 return renderToken(r, tok_i + 2, space);2532 return renderToken(r, tok_i + 2, space);
2534 },2533 },
2535 else => {2534 else => {
2536 try ais.writer().writeAll(".@");2535 try ais.writer().writeByte('.');
2537 try ais.writer().writeAll(tokenSliceForRender(tree, tok_i));2536 _ = try writeStringLiteralAsIdentifier(r, tok_i);
2538 try ais.writer().writeAll(" = true");2537 try ais.writer().writeAll(" = true");
2539 try renderToken(r, tok_i + 1, .space);2538 try renderToken(r, tok_i + 1, .space);
2540 tok_i += 2;2539 tok_i += 2;
...@@ -3232,6 +3231,22 @@ fn tokenSliceForRender(tree: Ast, token_index: Ast.TokenIndex) []const u8 {...@@ -3232,6 +3231,22 @@ fn tokenSliceForRender(tree: Ast, token_index: Ast.TokenIndex) []const u8 {
3232 return ret;3231 return ret;
3233}3232}
32343233
3234fn writeStringLiteralAsIdentifier(r: *Render, token_index: Ast.TokenIndex) !usize {
3235 const tree = r.tree;
3236 const ais = r.ais;
3237 assert(tree.tokenTag(token_index) == .string_literal);
3238 const lexeme = tokenSliceForRender(tree, token_index);
3239 const unquoted = lexeme[1..][0 .. lexeme.len - 2];
3240 if (std.zig.isValidId(unquoted)) {
3241 try ais.writer().writeAll(unquoted);
3242 return unquoted.len;
3243 } else {
3244 try ais.writer().writeByte('@');
3245 try ais.writer().writeAll(lexeme);
3246 return lexeme.len + 1;
3247 }
3248}
3249
3235fn hasSameLineComment(tree: Ast, token_index: Ast.TokenIndex) bool {3250fn hasSameLineComment(tree: Ast, token_index: Ast.TokenIndex) bool {
3236 const between_source = tree.source[tree.tokenStart(token_index)..tree.tokenStart(token_index + 1)];3251 const between_source = tree.source[tree.tokenStart(token_index)..tree.tokenStart(token_index + 1)];
3237 for (between_source) |byte| switch (byte) {3252 for (between_source) |byte| switch (byte) {