zig fmt: parse extra comma in asm expressions

This commit is contained in:
Andrew Kelley 2018-05-26 16:37:55 -04:00
parent 85ca611af1
commit 0ab888c639
4 changed files with 120 additions and 29 deletions

View File

@ -2071,7 +2071,7 @@ pub const Node = struct {
const OutputList = SegmentedList(&AsmOutput, 2); const OutputList = SegmentedList(&AsmOutput, 2);
const InputList = SegmentedList(&AsmInput, 2); const InputList = SegmentedList(&AsmInput, 2);
const ClobberList = SegmentedList(&Node, 2); const ClobberList = SegmentedList(TokenIndex, 2);
pub fn iterate(self: &Asm, index: usize) ?&Node { pub fn iterate(self: &Asm, index: usize) ?&Node {
var i = index; var i = index;

View File

@ -1153,9 +1153,11 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree {
continue; continue;
}, },
State.AsmClobberItems => |items| { State.AsmClobberItems => |items| {
stack.append(State{ .AsmClobberItems = items }) catch unreachable; while (eatToken(&tok_it, &tree, Token.Id.StringLiteral)) |strlit| {
try stack.append(State{ .IfToken = Token.Id.Comma }); try items.push(strlit);
try stack.append(State{ .StringLiteral = OptionalCtx{ .Required = try items.addOne() } }); if (eatToken(&tok_it, &tree, Token.Id.Comma) == null)
break;
}
continue; continue;
}, },

View File

@ -1,3 +1,44 @@
test "zig fmt: simple asm" {
try testTransform(
\\comptime {
\\ asm volatile (
\\ \\.globl aoeu;
\\ \\.type aoeu, @function;
\\ \\.set aoeu, derp;
\\ );
\\
\\ asm ("not real assembly"
\\ :[a] "x" (x),);
\\ asm ("not real assembly"
\\ :[a] "x" (->i32),:[a] "x" (1),);
\\ asm ("still not real assembly"
\\ :::"a","b",);
\\}
,
\\comptime {
\\ asm volatile (
\\ \\.globl aoeu;
\\ \\.type aoeu, @function;
\\ \\.set aoeu, derp;
\\ );
\\
\\ asm ("not real assembly"
\\ : [a] "x" (x)
\\ );
\\ asm ("not real assembly"
\\ : [a] "x" (-> i32)
\\ : [a] "x" (1)
\\ );
\\ asm ("still not real assembly"
\\ :
\\ :
\\ : "a", "b"
\\ );
\\}
\\
);
}
test "zig fmt: nested struct literal with one item" { test "zig fmt: nested struct literal with one item" {
try testCanonical( try testCanonical(
\\const a = foo{ \\const a = foo{
@ -1295,7 +1336,8 @@ test "zig fmt: inline asm" {
\\ : [ret] "={rax}" (-> usize) \\ : [ret] "={rax}" (-> usize)
\\ : [number] "{rax}" (number), \\ : [number] "{rax}" (number),
\\ [arg1] "{rdi}" (arg1) \\ [arg1] "{rdi}" (arg1)
\\ : "rcx", "r11"); \\ : "rcx", "r11"
\\ );
\\} \\}
\\ \\
); );

View File

@ -1203,19 +1203,35 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind
try renderToken(tree, stream, tree.nextToken(asm_node.asm_token), indent, Space.None); // ( try renderToken(tree, stream, tree.nextToken(asm_node.asm_token), indent, Space.None); // (
} }
if (asm_node.outputs.len == 0 and asm_node.inputs.len == 0 and asm_node.clobbers.len == 0) {
try renderExpression(allocator, stream, tree, indent, asm_node.template, Space.None);
try renderToken(tree, stream, asm_node.rparen, indent, space);
return;
}
try renderExpression(allocator, stream, tree, indent, asm_node.template, Space.Newline); try renderExpression(allocator, stream, tree, indent, asm_node.template, Space.Newline);
const indent_once = indent + indent_delta; const indent_once = indent + indent_delta;
try stream.writeByteNTimes(' ', indent_once); try stream.writeByteNTimes(' ', indent_once);
try stream.print(": ");
const colon1 = tree.nextToken(asm_node.template.lastToken());
const indent_extra = indent_once + 2; const indent_extra = indent_once + 2;
{ const colon2 = if (asm_node.outputs.len == 0) blk: {
try renderToken(tree, stream, colon1, indent, Space.Newline); // :
try stream.writeByteNTimes(' ', indent_once);
break :blk tree.nextToken(colon1);
} else blk: {
try renderToken(tree, stream, colon1, indent, Space.Space); // :
var it = asm_node.outputs.iterator(0); var it = asm_node.outputs.iterator(0);
while (it.next()) |asm_output| { while (true) {
const asm_output = ??it.next();
const node = &(asm_output.*).base; const node = &(asm_output.*).base;
try renderExpression(allocator, stream, tree, indent_extra, node, Space.None);
if (it.peek()) |next_asm_output| { if (it.peek()) |next_asm_output| {
try renderExpression(allocator, stream, tree, indent_extra, node, Space.None);
const next_node = &(next_asm_output.*).base; const next_node = &(next_asm_output.*).base;
const comma = tree.prevToken(next_asm_output.*.firstToken()); const comma = tree.prevToken(next_asm_output.*.firstToken());
@ -1223,21 +1239,38 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind
try renderExtraNewline(tree, stream, next_node); try renderExtraNewline(tree, stream, next_node);
try stream.writeByteNTimes(' ', indent_extra); try stream.writeByteNTimes(' ', indent_extra);
} } else if (asm_node.inputs.len == 0 and asm_node.clobbers.len == 0) {
} try renderExpression(allocator, stream, tree, indent_extra, node, Space.Newline);
} try stream.writeByteNTimes(' ', indent);
try renderToken(tree, stream, asm_node.rparen, indent, space);
try stream.write("\n"); return;
} else {
try renderExpression(allocator, stream, tree, indent_extra, node, Space.Newline);
try stream.writeByteNTimes(' ', indent_once); try stream.writeByteNTimes(' ', indent_once);
try stream.write(": "); const comma_or_colon = tree.nextToken(node.lastToken());
break :blk switch (tree.tokens.at(comma_or_colon).id) {
Token.Id.Comma => tree.nextToken(comma_or_colon),
else => comma_or_colon,
};
}
}
};
const colon3 = if (asm_node.inputs.len == 0) blk: {
try renderToken(tree, stream, colon2, indent, Space.Newline); // :
try stream.writeByteNTimes(' ', indent_once);
break :blk tree.nextToken(colon2);
} else blk: {
try renderToken(tree, stream, colon2, indent, Space.Space); // :
{
var it = asm_node.inputs.iterator(0); var it = asm_node.inputs.iterator(0);
while (it.next()) |asm_input| { while (true) {
const asm_input = ??it.next();
const node = &(asm_input.*).base; const node = &(asm_input.*).base;
try renderExpression(allocator, stream, tree, indent_extra, node, Space.None);
if (it.peek()) |next_asm_input| { if (it.peek()) |next_asm_input| {
try renderExpression(allocator, stream, tree, indent_extra, node, Space.None);
const next_node = &(next_asm_input.*).base; const next_node = &(next_asm_input.*).base;
const comma = tree.prevToken(next_asm_input.*.firstToken()); const comma = tree.prevToken(next_asm_input.*.firstToken());
@ -1245,26 +1278,40 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind
try renderExtraNewline(tree, stream, next_node); try renderExtraNewline(tree, stream, next_node);
try stream.writeByteNTimes(' ', indent_extra); try stream.writeByteNTimes(' ', indent_extra);
} } else if (asm_node.clobbers.len == 0) {
} try renderExpression(allocator, stream, tree, indent_extra, node, Space.Newline);
} try stream.writeByteNTimes(' ', indent);
try renderToken(tree, stream, asm_node.rparen, indent, space); // )
try stream.write("\n"); return;
} else {
try renderExpression(allocator, stream, tree, indent_extra, node, Space.Newline);
try stream.writeByteNTimes(' ', indent_once); try stream.writeByteNTimes(' ', indent_once);
try stream.write(": "); const comma_or_colon = tree.nextToken(node.lastToken());
break :blk switch (tree.tokens.at(comma_or_colon).id) {
Token.Id.Comma => tree.nextToken(comma_or_colon),
else => comma_or_colon,
};
}
}
};
try renderToken(tree, stream, colon3, indent, Space.Space); // :
{
var it = asm_node.clobbers.iterator(0); var it = asm_node.clobbers.iterator(0);
while (it.next()) |node| { while (true) {
try renderExpression(allocator, stream, tree, indent_once, node.*, Space.None); const clobber_token = ??it.next();
if (it.peek() != null) {
try stream.write(", ");
}
}
}
if (it.peek() == null) {
try renderToken(tree, stream, clobber_token.*, indent_once, Space.Newline);
try stream.writeByteNTimes(' ', indent);
try renderToken(tree, stream, asm_node.rparen, indent, space); try renderToken(tree, stream, asm_node.rparen, indent, space);
return;
} else {
try renderToken(tree, stream, clobber_token.*, indent_once, Space.None);
const comma = tree.nextToken(clobber_token.*);
try renderToken(tree, stream, comma, indent_once, Space.Space); // ,
}
}
}, },
ast.Node.Id.AsmInput => { ast.Node.Id.AsmInput => {