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" {
3232}
3333
3434test "zig fmt: preserves clobbers in inline asm with stray comma" {
35 try testCanonical(
35 try testTransform(
3636 \\fn foo() void {
3737 \\ asm volatile (""
3838 \\ : [_] "" (-> type),
......@@ -46,6 +46,20 @@ test "zig fmt: preserves clobbers in inline asm with stray comma" {
4646 \\ );
4747 \\}
4848 \\
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 \\
4963 );
5064}
5165
......@@ -64,7 +78,7 @@ test "zig fmt: remove trailing comma at the end of assembly clobber" {
6478 \\ asm volatile (""
6579 \\ : [_] "" (-> type),
6680 \\ :
67 \\ : "clobber1", "clobber2"
81 \\ : .{ .clobber1 = true, .clobber2 = true }
6882 \\ );
6983 \\}
7084 \\
......@@ -628,7 +642,7 @@ test "zig fmt: builtin call with trailing comma" {
628642}
629643
630644test "zig fmt: asm expression with comptime content" {
631 try testCanonical(
645 try testTransform(
632646 \\comptime {
633647 \\ asm ("foo" ++ "bar");
634648 \\}
......@@ -648,6 +662,26 @@ test "zig fmt: asm expression with comptime content" {
648662 \\ );
649663 \\}
650664 \\
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 \\
651685 );
652686}
653687
......@@ -2182,7 +2216,7 @@ test "zig fmt: simple asm" {
21822216 \\ : [a] "x" (-> i32),
21832217 \\ : [a] "x" (1),
21842218 \\ );
2185 \\ asm ("still not real assembly" ::: "a", "b");
2219 \\ asm ("still not real assembly" ::: .{ .a = true, .b = true });
21862220 \\}
21872221 \\
21882222 );
......@@ -3907,7 +3941,7 @@ test "zig fmt: fn type" {
39073941}
39083942
39093943test "zig fmt: inline asm" {
3910 try testCanonical(
3944 try testTransform(
39113945 \\pub fn syscall1(number: usize, arg1: usize) usize {
39123946 \\ return asm volatile ("syscall"
39133947 \\ : [ret] "={rax}" (-> usize),
......@@ -3917,6 +3951,16 @@ test "zig fmt: inline asm" {
39173951 \\ );
39183952 \\}
39193953 \\
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 \\
39203964 );
39213965}
39223966
......@@ -3998,7 +4042,7 @@ test "zig fmt: inline asm parameter alignment" {
39984042 \\ asm volatile (
39994043 \\ \\ foo
40004044 \\ \\ bar
4001 \\ ::: "", "");
4045 \\ ::: .{ .a = true, .b = true });
40024046 \\ asm volatile (
40034047 \\ \\ foo
40044048 \\ \\ bar
......@@ -4006,8 +4050,7 @@ test "zig fmt: inline asm parameter alignment" {
40064050 \\ [_] "" (-> usize),
40074051 \\ : [_] "" (0),
40084052 \\ [_] "" (0),
4009 \\ : "", ""
4010 \\ );
4053 \\ : .{});
40114054 \\}
40124055 \\
40134056 );
......@@ -5325,7 +5368,7 @@ test "zig fmt: make single-line if no trailing comma, fmt: off" {
53255368 \\ asm ("not real assembly"
53265369 \\ :[a] "x" (->i32),:[a] "x" (1),);
53275370 \\ asm volatile ("still not real assembly"
5328 \\ :::"a","b",);
5371 \\ :::.{.a = true,.b = true,});
53295372 \\ }
53305373 \\}
53315374 );
......@@ -5737,7 +5780,7 @@ test "zig fmt: canonicalize symbols (asm)" {
57375780 \\ [@"arg1"] "{rdi}" (arg),
57385781 \\ [arg2] "{rsi}" (arg),
57395782 \\ [arg3] "{rdx}" (arg),
5740 \\ : "rcx", "r11"
5783 \\ : "rcx", "fn"
57415784 \\ );
57425785 \\
57435786 \\ const @"false": usize = 10;
......@@ -5759,7 +5802,7 @@ test "zig fmt: canonicalize symbols (asm)" {
57595802 \\ [arg1] "{rdi}" (arg),
57605803 \\ [arg2] "{rsi}" (arg),
57615804 \\ [arg3] "{rdx}" (arg),
5762 \\ : "rcx", "r11"
5805 \\ : .{ .rcx = true, .@"fn" = true }
57635806 \\ );
57645807 \\
57655808 \\ const @"false": usize = 10;
lib/std/zig/render.zig+27-12
......@@ -2398,8 +2398,8 @@ fn renderAsmLegacy(
23982398
23992399 var tok_i = first_clobber;
24002400 while (true) : (tok_i += 1) {
2401 try ais.writer().writeAll(".@");
2402 try ais.writer().writeAll(tokenSliceForRender(tree, tok_i));
2401 try ais.writer().writeByte('.');
2402 _ = try writeStringLiteralAsIdentifier(r, tok_i);
24032403 try ais.writer().writeAll(" = true");
24042404
24052405 tok_i += 1;
......@@ -2411,6 +2411,7 @@ fn renderAsmLegacy(
24112411 },
24122412 .comma => {
24132413 if (tree.tokenTag(tok_i + 1) == .r_paren) {
2414 try ais.writer().writeAll(" }");
24142415 ais.popIndent();
24152416 return renderToken(r, tok_i + 1, space);
24162417 } else {
......@@ -2512,11 +2513,10 @@ fn renderAsmLegacy(
25122513 switch (tree.tokenTag(tok_i + 1)) {
25132514 .r_paren => {
25142515 ais.setIndentDelta(indent_delta);
2515 try ais.writer().writeAll(".@");
2516 const lexeme = tokenSliceForRender(tree, tok_i);
2517 try ais.writer().writeAll(lexeme);
2516 try ais.writer().writeByte('.');
2517 const lexeme_len = try writeStringLiteralAsIdentifier(r, tok_i);
25182518 try ais.writer().writeAll(" = true }");
2519 try renderSpace(r, tok_i, lexeme.len, .newline);
2519 try renderSpace(r, tok_i, lexeme_len, .newline);
25202520 ais.popIndent();
25212521 return renderToken(r, tok_i + 1, space);
25222522 },
......@@ -2524,17 +2524,16 @@ fn renderAsmLegacy(
25242524 switch (tree.tokenTag(tok_i + 2)) {
25252525 .r_paren => {
25262526 ais.setIndentDelta(indent_delta);
2527 try ais.writer().writeAll(".@");
2528 const lexeme = tokenSliceForRender(tree, tok_i);
2529 try ais.writer().writeAll(lexeme);
2527 try ais.writer().writeByte('.');
2528 const lexeme_len = try writeStringLiteralAsIdentifier(r, tok_i);
25302529 try ais.writer().writeAll(" = true }");
2531 try renderSpace(r, tok_i, lexeme.len, .newline);
2530 try renderSpace(r, tok_i, lexeme_len, .newline);
25322531 ais.popIndent();
25332532 return renderToken(r, tok_i + 2, space);
25342533 },
25352534 else => {
2536 try ais.writer().writeAll(".@");
2537 try ais.writer().writeAll(tokenSliceForRender(tree, tok_i));
2535 try ais.writer().writeByte('.');
2536 _ = try writeStringLiteralAsIdentifier(r, tok_i);
25382537 try ais.writer().writeAll(" = true");
25392538 try renderToken(r, tok_i + 1, .space);
25402539 tok_i += 2;
......@@ -3232,6 +3231,22 @@ fn tokenSliceForRender(tree: Ast, token_index: Ast.TokenIndex) []const u8 {
32323231 return ret;
32333232}
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
32353250fn hasSameLineComment(tree: Ast, token_index: Ast.TokenIndex) bool {
32363251 const between_source = tree.source[tree.tokenStart(token_index)..tree.tokenStart(token_index + 1)];
32373252 for (between_source) |byte| switch (byte) {