| ... | @@ -2756,8 +2756,47 @@ fn renderAsm( | ... | @@ -2756,8 +2756,47 @@ fn renderAsm( |
| 2756 | try renderToken(r, asm_node.ast.asm_token + 1, .none); // lparen | 2756 | try renderToken(r, asm_node.ast.asm_token + 1, .none); // lparen |
| 2757 | } | 2757 | } |
| 2758 | | 2758 | |
| | 2759 | const render_colons: [3]?Ast.TokenIndex = colons: { |
| | 2760 | var colons: [3]Ast.TokenIndex = undefined; |
| | 2761 | var render: u2 = 0; |
| | 2762 | |
| | 2763 | const rparen = asm_node.ast.rparen; |
| | 2764 | filled: { |
| | 2765 | colons[0] = tree.lastToken(asm_node.ast.template) + 1; |
| | 2766 | if (colons[0] == rparen) break :filled; |
| | 2767 | |
| | 2768 | if (asm_node.outputs.len != 0) { |
| | 2769 | colons[1] = tree.lastToken(asm_node.outputs[asm_node.outputs.len - 1]) + 1; |
| | 2770 | colons[1] += @intFromBool(tree.tokenTag(colons[1]) == .comma); |
| | 2771 | render = 1; |
| | 2772 | } else { |
| | 2773 | colons[1] = colons[0] + 1; |
| | 2774 | if (hasComment(tree, colons[0], colons[1])) render = 1; |
| | 2775 | } |
| | 2776 | if (colons[1] == rparen) break :filled; |
| | 2777 | |
| | 2778 | // Next colon is not checked for here since it cannot present without clobbers |
| | 2779 | if (asm_node.inputs.len != 0) { |
| | 2780 | render = 2; |
| | 2781 | } else { |
| | 2782 | const colon_or_rparen = colons[1] + 1; |
| | 2783 | if (hasComment(tree, colons[1], colon_or_rparen)) render = 2; |
| | 2784 | } |
| | 2785 | |
| | 2786 | if (asm_node.ast.clobbers.unwrap()) |clobbers| { |
| | 2787 | colons[2] = tree.firstToken(clobbers) - 1; |
| | 2788 | render = 3; |
| | 2789 | } |
| | 2790 | } |
| | 2791 | |
| | 2792 | var opt_colons: [3]?Ast.TokenIndex = @splat(null); |
| | 2793 | for (0..render) |i| opt_colons[i] = colons[i]; |
| | 2794 | break :colons opt_colons; |
| | 2795 | }; |
| | 2796 | |
| | 2797 | try ais.forcePushIndent(.normal); |
| | 2798 | |
| 2759 | if (asm_node.ast.items.len == 0) { | 2799 | if (asm_node.ast.items.len == 0) { |
| 2760 | try ais.forcePushIndent(.normal); | | |
| 2761 | if (asm_node.ast.clobbers.unwrap()) |clobbers| { | 2800 | if (asm_node.ast.clobbers.unwrap()) |clobbers| { |
| 2762 | // asm ("foo" ::: clobbers) | 2801 | // asm ("foo" ::: clobbers) |
| 2763 | try renderExpression(r, asm_node.ast.template, .space); | 2802 | try renderExpression(r, asm_node.ast.template, .space); |
| ... | @@ -2771,13 +2810,14 @@ fn renderAsm( | ... | @@ -2771,13 +2810,14 @@ fn renderAsm( |
| 2771 | return renderToken(r, asm_node.ast.rparen, space); // rparen | 2810 | return renderToken(r, asm_node.ast.rparen, space); // rparen |
| 2772 | } | 2811 | } |
| 2773 | | 2812 | |
| 2774 | // asm ("foo") | 2813 | if (render_colons[0] == null) { |
| 2775 | try renderExpression(r, asm_node.ast.template, .none); | 2814 | // asm ("foo") |
| 2776 | ais.popIndent(); | 2815 | try renderExpression(r, asm_node.ast.template, .none); |
| 2777 | return renderToken(r, asm_node.ast.rparen, space); // rparen | 2816 | ais.popIndent(); |
| | 2817 | return renderToken(r, asm_node.ast.rparen, space); // rparen |
| | 2818 | } |
| 2778 | } | 2819 | } |
| 2779 | | 2820 | |
| 2780 | try ais.forcePushIndent(.normal); | | |
| 2781 | try renderExpression(r, asm_node.ast.template, .newline); | 2821 | try renderExpression(r, asm_node.ast.template, .newline); |
| 2782 | ais.forceLastIndent(); // Might have been dedented by a multiline string literal | 2822 | ais.forceLastIndent(); // Might have been dedented by a multiline string literal |
| 2783 | assert(ais.current_line_empty); | 2823 | assert(ais.current_line_empty); |
| ... | @@ -2785,86 +2825,62 @@ fn renderAsm( | ... | @@ -2785,86 +2825,62 @@ fn renderAsm( |
| 2785 | const prev_indent_delta = ais.indent_delta; // May be part of another asm expression | 2825 | const prev_indent_delta = ais.indent_delta; // May be part of another asm expression |
| 2786 | // so indent_delta can't be unconditionally used | 2826 | // so indent_delta can't be unconditionally used |
| 2787 | ais.setIndentDelta(asm_indent_delta); | 2827 | ais.setIndentDelta(asm_indent_delta); |
| 2788 | const colon1 = tree.lastToken(asm_node.ast.template) + 1; | | |
| 2789 | | 2828 | |
| 2790 | const colon2 = if (asm_node.outputs.len == 0) colon2: { | 2829 | rendered: { |
| 2791 | try renderToken(r, colon1, .newline); // : | 2830 | if (render_colons[0]) |colon1| { |
| 2792 | break :colon2 colon1 + 1; | 2831 | if (asm_node.outputs.len != 0) { |
| 2793 | } else colon2: { | 2832 | try renderToken(r, colon1, .space); |
| 2794 | try renderToken(r, colon1, .space); // : | 2833 | try ais.forcePushIndent(.normal); |
| 2795 | | 2834 | |
| 2796 | try ais.forcePushIndent(.normal); | 2835 | const final = asm_node.outputs.len - 1; |
| 2797 | for (asm_node.outputs, 0..) |asm_output, i| { | 2836 | for (asm_node.outputs[0..final], 0..) |asm_output, i| { |
| 2798 | if (i + 1 < asm_node.outputs.len) { | 2837 | try renderAsmOutput(r, asm_output, .none); |
| 2799 | const next_asm_output = asm_node.outputs[i + 1]; | 2838 | |
| 2800 | try renderAsmOutput(r, asm_output, .none); | 2839 | const next_start = tree.firstToken(asm_node.outputs[i + 1]); |
| | 2840 | try renderToken(r, next_start - 1, .newline); // , |
| | 2841 | try renderExtraNewlineToken(r, next_start); |
| | 2842 | } |
| 2801 | | 2843 | |
| 2802 | const comma = tree.firstToken(next_asm_output) - 1; | | |
| 2803 | try renderToken(r, comma, .newline); // , | | |
| 2804 | try renderExtraNewlineToken(r, tree.firstToken(next_asm_output)); | | |
| 2805 | } else if (asm_node.inputs.len == 0 and asm_node.ast.clobbers == .none) { | | |
| 2806 | try ais.pushSpace(.comma); | 2844 | try ais.pushSpace(.comma); |
| 2807 | try renderAsmOutput(r, asm_output, .comma); | 2845 | try renderAsmOutput(r, asm_node.outputs[final], .comma); |
| 2808 | ais.popSpace(); | 2846 | ais.popSpace(); |
| 2809 | ais.popIndent(); | 2847 | ais.popIndent(); |
| 2810 | ais.setIndentDelta(indent_delta); | | |
| 2811 | ais.popIndent(); | | |
| 2812 | return renderToken(r, asm_node.ast.rparen, space); // rparen | | |
| 2813 | } else { | 2848 | } else { |
| 2814 | try ais.pushSpace(.comma); | 2849 | try renderToken(r, colon1, .newline); |
| 2815 | try renderAsmOutput(r, asm_output, .comma); | | |
| 2816 | ais.popSpace(); | | |
| 2817 | const comma_or_colon = tree.lastToken(asm_output) + 1; | | |
| 2818 | ais.popIndent(); | | |
| 2819 | break :colon2 switch (tree.tokenTag(comma_or_colon)) { | | |
| 2820 | .comma => comma_or_colon + 1, | | |
| 2821 | else => comma_or_colon, | | |
| 2822 | }; | | |
| 2823 | } | 2850 | } |
| 2824 | } else unreachable; | 2851 | } else unreachable; |
| 2825 | }; | | |
| 2826 | | 2852 | |
| 2827 | const colon3 = if (asm_node.inputs.len == 0) colon3: { | 2853 | if (render_colons[1]) |colon2| { |
| 2828 | try renderToken(r, colon2, .newline); // : | 2854 | if (asm_node.inputs.len != 0) { |
| 2829 | break :colon3 colon2 + 1; | 2855 | try renderToken(r, colon2, .space); |
| 2830 | } else colon3: { | 2856 | try ais.forcePushIndent(.normal); |
| 2831 | try renderToken(r, colon2, .space); // : | 2857 | |
| 2832 | try ais.forcePushIndent(.normal); | 2858 | const final = asm_node.inputs.len - 1; |
| 2833 | for (asm_node.inputs, 0..) |asm_input, i| { | 2859 | for (asm_node.inputs[0..final], 0..) |asm_input, i| { |
| 2834 | if (i + 1 < asm_node.inputs.len) { | 2860 | try renderAsmInput(r, asm_input, .none); |
| 2835 | const next_asm_input = asm_node.inputs[i + 1]; | 2861 | |
| 2836 | try renderAsmInput(r, asm_input, .none); | 2862 | const next_start = tree.firstToken(asm_node.inputs[i + 1]); |
| 2837 | | 2863 | try renderToken(r, next_start - 1, .newline); // , |
| 2838 | const first_token = tree.firstToken(next_asm_input); | 2864 | try renderExtraNewlineToken(r, next_start); |
| 2839 | try renderToken(r, first_token - 1, .newline); // , | 2865 | } |
| 2840 | try renderExtraNewlineToken(r, first_token); | 2866 | |
| 2841 | } else if (asm_node.ast.clobbers == .none) { | | |
| 2842 | try ais.pushSpace(.comma); | 2867 | try ais.pushSpace(.comma); |
| 2843 | try renderAsmInput(r, asm_input, .comma); | 2868 | try renderAsmInput(r, asm_node.inputs[final], .comma); |
| 2844 | ais.popSpace(); | 2869 | ais.popSpace(); |
| 2845 | ais.popIndent(); | 2870 | ais.popIndent(); |
| 2846 | ais.setIndentDelta(indent_delta); | | |
| 2847 | ais.popIndent(); | | |
| 2848 | return renderToken(r, asm_node.ast.rparen, space); // rparen | | |
| 2849 | } else { | 2871 | } else { |
| 2850 | try ais.pushSpace(.comma); | 2872 | try renderToken(r, colon2, .newline); |
| 2851 | try renderAsmInput(r, asm_input, .comma); | | |
| 2852 | ais.popSpace(); | | |
| 2853 | const comma_or_colon = tree.lastToken(asm_input) + 1; | | |
| 2854 | ais.popIndent(); | | |
| 2855 | break :colon3 switch (tree.tokenTag(comma_or_colon)) { | | |
| 2856 | .comma => comma_or_colon + 1, | | |
| 2857 | else => comma_or_colon, | | |
| 2858 | }; | | |
| 2859 | } | 2873 | } |
| | 2874 | } else break :rendered; |
| | 2875 | |
| | 2876 | if (render_colons[2]) |colon3| { |
| | 2877 | const clobbers = asm_node.ast.clobbers.unwrap().?; |
| | 2878 | try renderToken(r, colon3, .maybe_space); |
| | 2879 | try renderExpression(r, clobbers, .none); |
| | 2880 | ais.forceLastIndent(); // Might have been dedented by a multiline string literal |
| 2860 | } | 2881 | } |
| 2861 | unreachable; | 2882 | } |
| 2862 | }; | | |
| 2863 | | 2883 | |
| 2864 | try renderToken(r, colon3, .maybe_space); // : | | |
| 2865 | const clobbers = asm_node.ast.clobbers.unwrap().?; | | |
| 2866 | try renderExpression(r, clobbers, .none); | | |
| 2867 | ais.forceLastIndent(); // Might have been dedented by a multiline string literal | | |
| 2868 | ais.setIndentDelta(prev_indent_delta); | 2884 | ais.setIndentDelta(prev_indent_delta); |
| 2869 | ais.popIndent(); | 2885 | ais.popIndent(); |
| 2870 | return renderToken(r, asm_node.ast.rparen, space); // rparen | 2886 | return renderToken(r, asm_node.ast.rparen, space); // rparen |