From 8545836a4d8ab0ae1411b827c0fe1bcdcb268b72 Mon Sep 17 00:00:00 2001 From: Linus Groh Date: Wed, 15 Oct 2025 17:30:06 +0200 Subject: [PATCH] Remove legacy asm clobbers syntax handling --- lib/compiler/reduce/Walk.zig | 9 -- lib/docs/wasm/Walk.zig | 2 - lib/std/zig/Ast.zig | 118 ---------------------- lib/std/zig/Ast/Render.zig | 182 ---------------------------------- lib/std/zig/AstGen.zig | 10 -- lib/std/zig/AstRlAnnotate.zig | 1 - lib/std/zig/Parse.zig | 26 ----- lib/std/zig/ZonGen.zig | 2 +- lib/std/zig/parser_test.zig | 92 ++--------------- 9 files changed, 11 insertions(+), 431 deletions(-) diff --git a/lib/compiler/reduce/Walk.zig b/lib/compiler/reduce/Walk.zig index 1caf942fac..230354fee5 100644 --- a/lib/compiler/reduce/Walk.zig +++ b/lib/compiler/reduce/Walk.zig @@ -501,10 +501,6 @@ fn walkExpression(w: *Walk, node: Ast.Node.Index) Error!void { .@"asm", => return walkAsm(w, ast.fullAsm(node).?), - .asm_legacy => { - return walkAsmLegacy(w, ast.legacyAsm(node).?); - }, - .enum_literal => { return walkIdentifier(w, ast.nodeMainToken(node)); // name }, @@ -881,11 +877,6 @@ fn walkAsm(w: *Walk, asm_node: Ast.full.Asm) Error!void { try walkExpressions(w, asm_node.ast.items); } -fn walkAsmLegacy(w: *Walk, asm_node: Ast.full.AsmLegacy) Error!void { - try walkExpression(w, asm_node.ast.template); - try walkExpressions(w, asm_node.ast.items); -} - /// Check if it is already gutted (i.e. its body replaced with `@trap()`). fn isFnBodyGutted(ast: *const Ast, body_node: Ast.Node.Index) bool { // skip over discards diff --git a/lib/docs/wasm/Walk.zig b/lib/docs/wasm/Walk.zig index bd3051c98f..074d4c2f14 100644 --- a/lib/docs/wasm/Walk.zig +++ b/lib/docs/wasm/Walk.zig @@ -791,8 +791,6 @@ fn expr(w: *Walk, scope: *Scope, parent_decl: Decl.Index, node: Ast.Node.Index) try expr(w, scope, parent_decl, full.ast.template); }, - .asm_legacy => {}, - .builtin_call_two, .builtin_call_two_comma, .builtin_call, diff --git a/lib/std/zig/Ast.zig b/lib/std/zig/Ast.zig index 72ca20a6c0..ecb99820df 100644 --- a/lib/std/zig/Ast.zig +++ b/lib/std/zig/Ast.zig @@ -636,7 +636,6 @@ pub fn firstToken(tree: Ast, node: Node.Index) TokenIndex { .@"nosuspend", .asm_simple, .@"asm", - .asm_legacy, .array_type, .array_type_sentinel, .error_value, @@ -1050,11 +1049,6 @@ pub fn lastToken(tree: Ast, node: Node.Index) TokenIndex { n = @enumFromInt(tree.extra_data[@intFromEnum(members.end) - 1]); // last parameter } }, - .asm_legacy => { - _, const extra_index = tree.nodeData(n).node_and_extra; - const extra = tree.extraData(extra_index, Node.AsmLegacy); - return extra.rparen + end_offset; - }, .@"asm" => { _, const extra_index = tree.nodeData(n).node_and_extra; const extra = tree.extraData(extra_index, Node.Asm); @@ -1897,18 +1891,6 @@ pub fn asmSimple(tree: Ast, node: Node.Index) full.Asm { }); } -pub fn asmLegacy(tree: Ast, node: Node.Index) full.AsmLegacy { - const template, const extra_index = tree.nodeData(node).node_and_extra; - const extra = tree.extraData(extra_index, Node.AsmLegacy); - const items = tree.extraDataSlice(.{ .start = extra.items_start, .end = extra.items_end }, Node.Index); - return tree.legacyAsmComponents(.{ - .asm_token = tree.nodeMainToken(node), - .template = template, - .items = items, - .rparen = extra.rparen, - }); -} - pub fn asmFull(tree: Ast, node: Node.Index) full.Asm { const template, const extra_index = tree.nodeData(node).node_and_extra; const extra = tree.extraData(extra_index, Node.Asm); @@ -2214,67 +2196,6 @@ fn fullSwitchCaseComponents(tree: Ast, info: full.SwitchCase.Components, node: N return result; } -fn legacyAsmComponents(tree: Ast, info: full.AsmLegacy.Components) full.AsmLegacy { - var result: full.AsmLegacy = .{ - .ast = info, - .volatile_token = null, - .inputs = &.{}, - .outputs = &.{}, - .first_clobber = null, - }; - if (tree.tokenTag(info.asm_token + 1) == .keyword_volatile) { - result.volatile_token = info.asm_token + 1; - } - const outputs_end: usize = for (info.items, 0..) |item, i| { - switch (tree.nodeTag(item)) { - .asm_output => continue, - else => break i, - } - } else info.items.len; - - result.outputs = info.items[0..outputs_end]; - result.inputs = info.items[outputs_end..]; - - if (info.items.len == 0) { - // asm ("foo" ::: "a", "b"); - const template_token = tree.lastToken(info.template); - if (tree.tokenTag(template_token + 1) == .colon and - tree.tokenTag(template_token + 2) == .colon and - tree.tokenTag(template_token + 3) == .colon and - tree.tokenTag(template_token + 4) == .string_literal) - { - result.first_clobber = template_token + 4; - } - } else if (result.inputs.len != 0) { - // asm ("foo" :: [_] "" (y) : "a", "b"); - const last_input = result.inputs[result.inputs.len - 1]; - const rparen = tree.lastToken(last_input); - var i = rparen + 1; - // Allow a (useless) comma right after the closing parenthesis. - if (tree.tokenTag(i) == .comma) i = i + 1; - if (tree.tokenTag(i) == .colon and - tree.tokenTag(i + 1) == .string_literal) - { - result.first_clobber = i + 1; - } - } else { - // asm ("foo" : [_] "" (x) :: "a", "b"); - const last_output = result.outputs[result.outputs.len - 1]; - const rparen = tree.lastToken(last_output); - var i = rparen + 1; - // Allow a (useless) comma right after the closing parenthesis. - if (tree.tokenTag(i) == .comma) i = i + 1; - if (tree.tokenTag(i) == .colon and - tree.tokenTag(i + 1) == .colon and - tree.tokenTag(i + 2) == .string_literal) - { - result.first_clobber = i + 2; - } - } - - return result; -} - fn fullAsmComponents(tree: Ast, info: full.Asm.Components) full.Asm { var result: full.Asm = .{ .ast = info, @@ -2492,14 +2413,6 @@ pub fn fullAsm(tree: Ast, node: Node.Index) ?full.Asm { }; } -/// To be deleted after 0.15.0 is tagged -pub fn legacyAsm(tree: Ast, node: Node.Index) ?full.AsmLegacy { - return switch (tree.nodeTag(node)) { - .asm_legacy => tree.asmLegacy(node), - else => null, - }; -} - pub fn fullCall(tree: Ast, buffer: *[1]Ast.Node.Index, node: Node.Index) ?full.Call { return switch (tree.nodeTag(node)) { .call, .call_comma => tree.callFull(node), @@ -2894,21 +2807,6 @@ pub const full = struct { }; }; - pub const AsmLegacy = struct { - ast: Components, - volatile_token: ?TokenIndex, - first_clobber: ?TokenIndex, - outputs: []const Node.Index, - inputs: []const Node.Index, - - pub const Components = struct { - asm_token: TokenIndex, - template: Node.Index, - items: []const Node.Index, - rparen: TokenIndex, - }; - }; - pub const Call = struct { ast: Components, @@ -3905,14 +3803,6 @@ pub const Node = struct { /// /// The `main_token` field is the `asm` token. asm_simple, - /// `asm(lhs, a)`. - /// - /// The `data` field is a `.node_and_extra`: - /// 1. a `Node.Index` to lhs. - /// 2. a `ExtraIndex` to `AsmLegacy`. - /// - /// The `main_token` field is the `asm` token. - asm_legacy, /// `asm(a, b)`. /// /// The `data` field is a `.node_and_extra`: @@ -4089,14 +3979,6 @@ pub const Node = struct { callconv_expr: OptionalIndex, }; - /// To be removed after 0.15.0 is tagged - pub const AsmLegacy = struct { - items_start: ExtraIndex, - items_end: ExtraIndex, - /// Needed to make lastToken() work. - rparen: TokenIndex, - }; - pub const Asm = struct { items_start: ExtraIndex, items_end: ExtraIndex, diff --git a/lib/std/zig/Ast/Render.zig b/lib/std/zig/Ast/Render.zig index bc66703774..5e81f247e4 100644 --- a/lib/std/zig/Ast/Render.zig +++ b/lib/std/zig/Ast/Render.zig @@ -896,9 +896,6 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void { .@"asm", => return renderAsm(r, tree.fullAsm(node).?, space), - // To be removed after 0.15.0 is tagged - .asm_legacy => return renderAsmLegacy(r, tree.legacyAsm(node).?, space), - .enum_literal => { try renderToken(r, tree.nodeMainToken(node) - 1, .none); // . return renderIdentifier(r, tree.nodeMainToken(node), space, .eagerly_unquote); // name @@ -2413,185 +2410,6 @@ fn renderContainerDecl( return renderToken(r, rbrace, space); // rbrace } -fn renderAsmLegacy( - r: *Render, - asm_node: Ast.full.AsmLegacy, - space: Space, -) Error!void { - const tree = r.tree; - const ais = r.ais; - - try renderToken(r, asm_node.ast.asm_token, .space); // asm - - if (asm_node.volatile_token) |volatile_token| { - try renderToken(r, volatile_token, .space); // volatile - try renderToken(r, volatile_token + 1, .none); // lparen - } else { - try renderToken(r, asm_node.ast.asm_token + 1, .none); // lparen - } - - if (asm_node.ast.items.len == 0) { - try ais.forcePushIndent(.normal); - if (asm_node.first_clobber) |first_clobber| { - // asm ("foo" ::: "a", "b") - // asm ("foo" ::: "a", "b",) - try renderExpression(r, asm_node.ast.template, .space); - // Render the three colons. - try renderToken(r, first_clobber - 3, .none); - try renderToken(r, first_clobber - 2, .none); - try renderToken(r, first_clobber - 1, .space); - - try ais.writeAll(".{ "); - - var tok_i = first_clobber; - while (true) : (tok_i += 1) { - try ais.writeByte('.'); - _ = try writeStringLiteralAsIdentifier(r, tok_i); - try ais.writeAll(" = true"); - - tok_i += 1; - switch (tree.tokenTag(tok_i)) { - .r_paren => { - try ais.writeAll(" }"); - ais.popIndent(); - return renderToken(r, tok_i, space); - }, - .comma => { - if (tree.tokenTag(tok_i + 1) == .r_paren) { - try ais.writeAll(" }"); - ais.popIndent(); - return renderToken(r, tok_i + 1, space); - } else { - try renderToken(r, tok_i, .space); - } - }, - else => unreachable, - } - } - } else { - unreachable; - } - } - - try ais.forcePushIndent(.normal); - try renderExpression(r, asm_node.ast.template, .newline); - ais.setIndentDelta(asm_indent_delta); - const colon1 = tree.lastToken(asm_node.ast.template) + 1; - - const colon2 = if (asm_node.outputs.len == 0) colon2: { - try renderToken(r, colon1, .newline); // : - break :colon2 colon1 + 1; - } else colon2: { - try renderToken(r, colon1, .space); // : - - try ais.forcePushIndent(.normal); - for (asm_node.outputs, 0..) |asm_output, i| { - if (i + 1 < asm_node.outputs.len) { - const next_asm_output = asm_node.outputs[i + 1]; - try renderAsmOutput(r, asm_output, .none); - - const comma = tree.firstToken(next_asm_output) - 1; - try renderToken(r, comma, .newline); // , - try renderExtraNewlineToken(r, tree.firstToken(next_asm_output)); - } else if (asm_node.inputs.len == 0 and asm_node.first_clobber == null) { - try ais.pushSpace(.comma); - try renderAsmOutput(r, asm_output, .comma); - ais.popSpace(); - ais.popIndent(); - ais.setIndentDelta(indent_delta); - ais.popIndent(); - return renderToken(r, asm_node.ast.rparen, space); // rparen - } else { - try ais.pushSpace(.comma); - try renderAsmOutput(r, asm_output, .comma); - ais.popSpace(); - const comma_or_colon = tree.lastToken(asm_output) + 1; - ais.popIndent(); - break :colon2 switch (tree.tokenTag(comma_or_colon)) { - .comma => comma_or_colon + 1, - else => comma_or_colon, - }; - } - } else unreachable; - }; - - const colon3 = if (asm_node.inputs.len == 0) colon3: { - try renderToken(r, colon2, .newline); // : - break :colon3 colon2 + 1; - } else colon3: { - try renderToken(r, colon2, .space); // : - try ais.forcePushIndent(.normal); - for (asm_node.inputs, 0..) |asm_input, i| { - if (i + 1 < asm_node.inputs.len) { - const next_asm_input = asm_node.inputs[i + 1]; - try renderAsmInput(r, asm_input, .none); - - const first_token = tree.firstToken(next_asm_input); - try renderToken(r, first_token - 1, .newline); // , - try renderExtraNewlineToken(r, first_token); - } else if (asm_node.first_clobber == null) { - try ais.pushSpace(.comma); - try renderAsmInput(r, asm_input, .comma); - ais.popSpace(); - ais.popIndent(); - ais.setIndentDelta(indent_delta); - ais.popIndent(); - return renderToken(r, asm_node.ast.rparen, space); // rparen - } else { - try ais.pushSpace(.comma); - try renderAsmInput(r, asm_input, .comma); - ais.popSpace(); - const comma_or_colon = tree.lastToken(asm_input) + 1; - ais.popIndent(); - break :colon3 switch (tree.tokenTag(comma_or_colon)) { - .comma => comma_or_colon + 1, - else => comma_or_colon, - }; - } - } - unreachable; - }; - - try renderToken(r, colon3, .space); // : - try ais.writeAll(".{ "); - const first_clobber = asm_node.first_clobber.?; - var tok_i = first_clobber; - while (true) { - switch (tree.tokenTag(tok_i + 1)) { - .r_paren => { - ais.setIndentDelta(indent_delta); - try ais.writeByte('.'); - const lexeme_len = try writeStringLiteralAsIdentifier(r, tok_i); - try ais.writeAll(" = true }"); - try renderSpace(r, tok_i, lexeme_len, .newline); - ais.popIndent(); - return renderToken(r, tok_i + 1, space); - }, - .comma => { - switch (tree.tokenTag(tok_i + 2)) { - .r_paren => { - ais.setIndentDelta(indent_delta); - try ais.writeByte('.'); - const lexeme_len = try writeStringLiteralAsIdentifier(r, tok_i); - try ais.writeAll(" = true }"); - try renderSpace(r, tok_i, lexeme_len, .newline); - ais.popIndent(); - return renderToken(r, tok_i + 2, space); - }, - else => { - try ais.writeByte('.'); - _ = try writeStringLiteralAsIdentifier(r, tok_i); - try ais.writeAll(" = true"); - try renderToken(r, tok_i + 1, .space); - tok_i += 2; - }, - } - }, - else => unreachable, - } - } -} - fn renderAsm( r: *Render, asm_node: Ast.full.Asm, diff --git a/lib/std/zig/AstGen.zig b/lib/std/zig/AstGen.zig index 6306dde4f8..6b73f1ff42 100644 --- a/lib/std/zig/AstGen.zig +++ b/lib/std/zig/AstGen.zig @@ -507,7 +507,6 @@ fn lvalExpr(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Ins .bool_or, .@"asm", .asm_simple, - .asm_legacy, .string_literal, .number_literal, .call, @@ -814,12 +813,6 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE .@"asm", => return asmExpr(gz, scope, ri, node, tree.fullAsm(node).?), - .asm_legacy => { - return astgen.failNodeNotes(node, "legacy asm clobbers syntax", .{}, &[_]u32{ - try astgen.errNoteNode(node, "use 'zig fmt' to auto-upgrade", .{}), - }); - }, - .string_literal => return stringLiteral(gz, ri, node), .multiline_string_literal => return multilineStringLiteral(gz, ri, node), @@ -10502,7 +10495,6 @@ fn nodeMayEvalToError(tree: *const Ast, start_node: Ast.Node.Index) BuiltinFn.Ev .@"asm", .asm_simple, - .asm_legacy, .identifier, .field_access, .deref, @@ -10746,7 +10738,6 @@ fn nodeImpliesMoreThanOnePossibleValue(tree: *const Ast, start_node: Ast.Node.In .tagged_union_enum_tag_trailing, .@"asm", .asm_simple, - .asm_legacy, .add, .add_wrap, .add_sat, @@ -10985,7 +10976,6 @@ fn nodeImpliesComptimeOnly(tree: *const Ast, start_node: Ast.Node.Index) bool { .tagged_union_enum_tag_trailing, .@"asm", .asm_simple, - .asm_legacy, .add, .add_wrap, .add_sat, diff --git a/lib/std/zig/AstRlAnnotate.zig b/lib/std/zig/AstRlAnnotate.zig index c7e9abf2bb..e1a83fb75a 100644 --- a/lib/std/zig/AstRlAnnotate.zig +++ b/lib/std/zig/AstRlAnnotate.zig @@ -310,7 +310,6 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI .unreachable_literal, .asm_simple, .@"asm", - .asm_legacy, .enum_literal, .error_value, .anyframe_literal, diff --git a/lib/std/zig/Parse.zig b/lib/std/zig/Parse.zig index 4d8c710816..991b3c6010 100644 --- a/lib/std/zig/Parse.zig +++ b/lib/std/zig/Parse.zig @@ -2857,32 +2857,6 @@ fn expectAsmExpr(p: *Parse) !Node.Index { _ = p.eatToken(.colon) orelse break :clobbers .none; - // For automatic upgrades; delete after 0.15.0 released. - if (p.tokenTag(p.tok_i) == .string_literal) { - while (p.eatToken(.string_literal)) |_| { - switch (p.tokenTag(p.tok_i)) { - .comma => p.tok_i += 1, - .colon, .r_paren, .r_brace, .r_bracket => break, - // Likely just a missing comma; give error but continue parsing. - else => try p.warnExpected(.comma), - } - } - const rparen = try p.expectToken(.r_paren); - const span = try p.listToSpan(p.scratch.items[scratch_top..]); - return p.addNode(.{ - .tag = .asm_legacy, - .main_token = asm_token, - .data = .{ .node_and_extra = .{ - template, - try p.addExtra(Node.AsmLegacy{ - .items_start = span.start, - .items_end = span.end, - .rparen = rparen, - }), - } }, - }); - } - break :clobbers (try p.expectExpr()).toOptional(); } else .none; diff --git a/lib/std/zig/ZonGen.zig b/lib/std/zig/ZonGen.zig index 0137f84911..49f0cb8050 100644 --- a/lib/std/zig/ZonGen.zig +++ b/lib/std/zig/ZonGen.zig @@ -238,7 +238,7 @@ fn expr(zg: *ZonGen, node: Ast.Node.Index, dest_node: Zoir.Node.Index) Allocator => try zg.addErrorNode(node, "control flow is not allowed in ZON", .{}), .@"comptime" => try zg.addErrorNode(node, "keyword 'comptime' is not allowed in ZON", .{}), - .asm_simple, .@"asm", .asm_legacy => try zg.addErrorNode(node, "inline asm is not allowed in ZON", .{}), + .asm_simple, .@"asm" => try zg.addErrorNode(node, "inline asm is not allowed in ZON", .{}), .builtin_call_two, .builtin_call_two_comma, diff --git a/lib/std/zig/parser_test.zig b/lib/std/zig/parser_test.zig index b563fa90e3..b685206c56 100644 --- a/lib/std/zig/parser_test.zig +++ b/lib/std/zig/parser_test.zig @@ -31,54 +31,16 @@ test "zig fmt: tuple struct" { } test "zig fmt: preserves clobbers in inline asm with stray comma" { - try testTransform( + try testCanonical( \\fn foo() void { \\ asm volatile ("" \\ : [_] "" (-> type), \\ : - \\ : "clobber" - \\ ); + \\ : .{ .clobber = true }); \\ asm volatile ("" \\ : \\ : [_] "" (type), - \\ : "clobber" - \\ ); - \\} - \\ - , - \\fn foo() void { - \\ asm volatile ("" - \\ : [_] "" (-> type), - \\ : - \\ : .{ .clobber = true } - \\ ); - \\ asm volatile ("" - \\ : - \\ : [_] "" (type), - \\ : .{ .clobber = true } - \\ ); - \\} - \\ - ); -} - -test "zig fmt: remove trailing comma at the end of assembly clobber" { - try testTransform( - \\fn foo() void { - \\ asm volatile ("" - \\ : [_] "" (-> type), - \\ : - \\ : "clobber1", "clobber2", - \\ ); - \\} - \\ - , - \\fn foo() void { - \\ asm volatile ("" - \\ : [_] "" (-> type), - \\ : - \\ : .{ .clobber1 = true, .clobber2 = true } - \\ ); + \\ : .{ .clobber = true }); \\} \\ ); @@ -641,7 +603,7 @@ test "zig fmt: builtin call with trailing comma" { } test "zig fmt: asm expression with comptime content" { - try testTransform( + try testCanonical( \\comptime { \\ asm ("foo" ++ "bar"); \\} @@ -657,28 +619,7 @@ test "zig fmt: asm expression with comptime content" { \\ asm volatile ("foo" ++ "bar" \\ : [_] "" (x), \\ : [_] "" (y), - \\ : "h", "e", "l", "l", "o" - \\ ); - \\} - \\ - , - \\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 } - \\ ); + \\ : .{ .h = true, .e = true, .l = true, .l = true, .o = true }); \\} \\ ); @@ -2198,7 +2139,7 @@ test "zig fmt: simple asm" { \\ asm ("not real assembly" \\ :[a] "x" (->i32),:[a] "x" (1),); \\ asm ("still not real assembly" - \\ :::"a","b",); + \\ :::.{.a=true,.b=true}); \\} , \\comptime { @@ -3940,24 +3881,13 @@ test "zig fmt: fn type" { } test "zig fmt: inline asm" { - try testTransform( + try testCanonical( \\pub fn syscall1(number: usize, arg1: usize) usize { \\ return asm volatile ("syscall" \\ : [ret] "={rax}" (-> usize), \\ : [number] "{rax}" (number), \\ [arg1] "{rdi}" (arg1), - \\ : "rcx", "r11" - \\ ); - \\} - \\ - , - \\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 } - \\ ); + \\ : .{ .rcx = true, .r11 = true }); \\} \\ ); @@ -5789,8 +5719,7 @@ test "zig fmt: canonicalize symbols (asm)" { \\ [@"arg1"] "{rdi}" (arg), \\ [arg2] "{rsi}" (arg), \\ [arg3] "{rdx}" (arg), - \\ : "rcx", "fn" - \\ ); + \\ : .{ .rcx = true, .@"fn" = true }); \\ \\ const @"false": usize = 10; \\ const @"true" = "explode"; @@ -5811,8 +5740,7 @@ test "zig fmt: canonicalize symbols (asm)" { \\ [arg1] "{rdi}" (arg), \\ [arg2] "{rsi}" (arg), \\ [arg3] "{rdx}" (arg), - \\ : .{ .rcx = true, .@"fn" = true } - \\ ); + \\ : .{ .rcx = true, .@"fn" = true }); \\ \\ const @"false": usize = 10; \\ const @"true" = "explode";