Commit 54f073377c

Andrew Kelley <andrew@ziglang.org>
2025-07-16 01:10:36
std.zig.render: handle legacy clobber updating more gracefully
"that's really easy to handle correctly" he said
1 parent 15f45e8
Changed files (2)
lib/std/zig/parser_test.zig
@@ -32,7 +32,7 @@ test "zig fmt: tuple struct" {
 }
 
 test "zig fmt: preserves clobbers in inline asm with stray comma" {
-    try testCanonical(
+    try testTransform(
         \\fn foo() void {
         \\    asm volatile (""
         \\        : [_] "" (-> type),
@@ -46,6 +46,20 @@ test "zig fmt: preserves clobbers in inline asm with stray comma" {
         \\    );
         \\}
         \\
+    ,
+        \\fn foo() void {
+        \\    asm volatile (""
+        \\        : [_] "" (-> type),
+        \\        :
+        \\        : .{ .clobber = true }
+        \\    );
+        \\    asm volatile (""
+        \\        :
+        \\        : [_] "" (type),
+        \\        : .{ .clobber = true }
+        \\    );
+        \\}
+        \\
     );
 }
 
@@ -64,7 +78,7 @@ test "zig fmt: remove trailing comma at the end of assembly clobber" {
         \\    asm volatile (""
         \\        : [_] "" (-> type),
         \\        :
-        \\        : "clobber1", "clobber2"
+        \\        : .{ .clobber1 = true, .clobber2 = true }
         \\    );
         \\}
         \\
@@ -628,7 +642,7 @@ test "zig fmt: builtin call with trailing comma" {
 }
 
 test "zig fmt: asm expression with comptime content" {
-    try testCanonical(
+    try testTransform(
         \\comptime {
         \\    asm ("foo" ++ "bar");
         \\}
@@ -648,6 +662,26 @@ test "zig fmt: asm expression with comptime content" {
         \\    );
         \\}
         \\
+    ,
+        \\comptime {
+        \\    asm ("foo" ++ "bar");
+        \\}
+        \\pub fn main() void {
+        \\    asm volatile ("foo" ++ "bar");
+        \\    asm volatile ("foo" ++ "bar"
+        \\        : [_] "" (x),
+        \\    );
+        \\    asm volatile ("foo" ++ "bar"
+        \\        : [_] "" (x),
+        \\        : [_] "" (y),
+        \\    );
+        \\    asm volatile ("foo" ++ "bar"
+        \\        : [_] "" (x),
+        \\        : [_] "" (y),
+        \\        : .{ .h = true, .e = true, .l = true, .l = true, .o = true }
+        \\    );
+        \\}
+        \\
     );
 }
 
@@ -2182,7 +2216,7 @@ test "zig fmt: simple asm" {
         \\        : [a] "x" (-> i32),
         \\        : [a] "x" (1),
         \\    );
-        \\    asm ("still not real assembly" ::: "a", "b");
+        \\    asm ("still not real assembly" ::: .{ .a = true, .b = true });
         \\}
         \\
     );
@@ -3907,7 +3941,7 @@ test "zig fmt: fn type" {
 }
 
 test "zig fmt: inline asm" {
-    try testCanonical(
+    try testTransform(
         \\pub fn syscall1(number: usize, arg1: usize) usize {
         \\    return asm volatile ("syscall"
         \\        : [ret] "={rax}" (-> usize),
@@ -3917,6 +3951,16 @@ test "zig fmt: inline asm" {
         \\    );
         \\}
         \\
+    ,
+        \\pub fn syscall1(number: usize, arg1: usize) usize {
+        \\    return asm volatile ("syscall"
+        \\        : [ret] "={rax}" (-> usize),
+        \\        : [number] "{rax}" (number),
+        \\          [arg1] "{rdi}" (arg1),
+        \\        : .{ .rcx = true, .r11 = true }
+        \\    );
+        \\}
+        \\
     );
 }
 
@@ -3998,7 +4042,7 @@ test "zig fmt: inline asm parameter alignment" {
         \\    asm volatile (
         \\        \\ foo
         \\        \\ bar
-        \\        ::: "", "");
+        \\        ::: .{ .a = true, .b = true });
         \\    asm volatile (
         \\        \\ foo
         \\        \\ bar
@@ -4006,8 +4050,7 @@ test "zig fmt: inline asm parameter alignment" {
         \\          [_] "" (-> usize),
         \\        : [_] "" (0),
         \\          [_] "" (0),
-        \\        : "", ""
-        \\    );
+        \\        : .{});
         \\}
         \\
     );
@@ -5325,7 +5368,7 @@ test "zig fmt: make single-line if no trailing comma, fmt: off" {
         \\        asm ("not real assembly"
         \\            :[a] "x" (->i32),:[a] "x" (1),);
         \\        asm volatile ("still not real assembly"
-        \\            :::"a","b",);
+        \\            :::.{.a = true,.b = true,});
         \\    }
         \\}
     );
@@ -5737,7 +5780,7 @@ test "zig fmt: canonicalize symbols (asm)" {
         \\          [@"arg1"] "{rdi}" (arg),
         \\          [arg2] "{rsi}" (arg),
         \\          [arg3] "{rdx}" (arg),
-        \\        : "rcx", "r11"
+        \\        : "rcx", "fn"
         \\    );
         \\
         \\    const @"false": usize = 10;
@@ -5759,7 +5802,7 @@ test "zig fmt: canonicalize symbols (asm)" {
         \\          [arg1] "{rdi}" (arg),
         \\          [arg2] "{rsi}" (arg),
         \\          [arg3] "{rdx}" (arg),
-        \\        : "rcx", "r11"
+        \\        : .{ .rcx = true, .@"fn" = true }
         \\    );
         \\
         \\    const @"false": usize = 10;
lib/std/zig/render.zig
@@ -2398,8 +2398,8 @@ fn renderAsmLegacy(
 
             var tok_i = first_clobber;
             while (true) : (tok_i += 1) {
-                try ais.writer().writeAll(".@");
-                try ais.writer().writeAll(tokenSliceForRender(tree, tok_i));
+                try ais.writer().writeByte('.');
+                _ = try writeStringLiteralAsIdentifier(r, tok_i);
                 try ais.writer().writeAll(" = true");
 
                 tok_i += 1;
@@ -2411,6 +2411,7 @@ fn renderAsmLegacy(
                     },
                     .comma => {
                         if (tree.tokenTag(tok_i + 1) == .r_paren) {
+                            try ais.writer().writeAll(" }");
                             ais.popIndent();
                             return renderToken(r, tok_i + 1, space);
                         } else {
@@ -2512,11 +2513,10 @@ fn renderAsmLegacy(
         switch (tree.tokenTag(tok_i + 1)) {
             .r_paren => {
                 ais.setIndentDelta(indent_delta);
-                try ais.writer().writeAll(".@");
-                const lexeme = tokenSliceForRender(tree, tok_i);
-                try ais.writer().writeAll(lexeme);
+                try ais.writer().writeByte('.');
+                const lexeme_len = try writeStringLiteralAsIdentifier(r, tok_i);
                 try ais.writer().writeAll(" = true }");
-                try renderSpace(r, tok_i, lexeme.len, .newline);
+                try renderSpace(r, tok_i, lexeme_len, .newline);
                 ais.popIndent();
                 return renderToken(r, tok_i + 1, space);
             },
@@ -2524,17 +2524,16 @@ fn renderAsmLegacy(
                 switch (tree.tokenTag(tok_i + 2)) {
                     .r_paren => {
                         ais.setIndentDelta(indent_delta);
-                        try ais.writer().writeAll(".@");
-                        const lexeme = tokenSliceForRender(tree, tok_i);
-                        try ais.writer().writeAll(lexeme);
+                        try ais.writer().writeByte('.');
+                        const lexeme_len = try writeStringLiteralAsIdentifier(r, tok_i);
                         try ais.writer().writeAll(" = true }");
-                        try renderSpace(r, tok_i, lexeme.len, .newline);
+                        try renderSpace(r, tok_i, lexeme_len, .newline);
                         ais.popIndent();
                         return renderToken(r, tok_i + 2, space);
                     },
                     else => {
-                        try ais.writer().writeAll(".@");
-                        try ais.writer().writeAll(tokenSliceForRender(tree, tok_i));
+                        try ais.writer().writeByte('.');
+                        _ = try writeStringLiteralAsIdentifier(r, tok_i);
                         try ais.writer().writeAll(" = true");
                         try renderToken(r, tok_i + 1, .space);
                         tok_i += 2;
@@ -3232,6 +3231,22 @@ fn tokenSliceForRender(tree: Ast, token_index: Ast.TokenIndex) []const u8 {
     return ret;
 }
 
+fn writeStringLiteralAsIdentifier(r: *Render, token_index: Ast.TokenIndex) !usize {
+    const tree = r.tree;
+    const ais = r.ais;
+    assert(tree.tokenTag(token_index) == .string_literal);
+    const lexeme = tokenSliceForRender(tree, token_index);
+    const unquoted = lexeme[1..][0 .. lexeme.len - 2];
+    if (std.zig.isValidId(unquoted)) {
+        try ais.writer().writeAll(unquoted);
+        return unquoted.len;
+    } else {
+        try ais.writer().writeByte('@');
+        try ais.writer().writeAll(lexeme);
+        return lexeme.len + 1;
+    }
+}
+
 fn hasSameLineComment(tree: Ast, token_index: Ast.TokenIndex) bool {
     const between_source = tree.source[tree.tokenStart(token_index)..tree.tokenStart(token_index + 1)];
     for (between_source) |byte| switch (byte) {