authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-05-26 16:37:55-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-05-26 16:37:55-04:00
log0ab888c639dffcc48bc08a6ff186aa3da0ecbf74
treea094c3c1e9a38cc26e4fdf4c3cb45acd945bddcf
parent85ca611af1d7401dd336f4655a0ab15640cc8424

zig fmt: parse extra comma in asm expressions


4 files changed, 120 insertions(+), 29 deletions(-)

std/zig/ast.zig+1-1
...@@ -2071,7 +2071,7 @@ pub const Node = struct {...@@ -2071,7 +2071,7 @@ pub const Node = struct {
20712071
2072 const OutputList = SegmentedList(&AsmOutput, 2);2072 const OutputList = SegmentedList(&AsmOutput, 2);
2073 const InputList = SegmentedList(&AsmInput, 2);2073 const InputList = SegmentedList(&AsmInput, 2);
2074 const ClobberList = SegmentedList(&Node, 2);2074 const ClobberList = SegmentedList(TokenIndex, 2);
20752075
2076 pub fn iterate(self: &Asm, index: usize) ?&Node {2076 pub fn iterate(self: &Asm, index: usize) ?&Node {
2077 var i = index;2077 var i = index;
std/zig/parse.zig+5-3
...@@ -1153,9 +1153,11 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree {...@@ -1153,9 +1153,11 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree {
1153 continue;1153 continue;
1154 },1154 },
1155 State.AsmClobberItems => |items| {1155 State.AsmClobberItems => |items| {
1156 stack.append(State{ .AsmClobberItems = items }) catch unreachable;1156 while (eatToken(&tok_it, &tree, Token.Id.StringLiteral)) |strlit| {
1157 try stack.append(State{ .IfToken = Token.Id.Comma });1157 try items.push(strlit);
1158 try stack.append(State{ .StringLiteral = OptionalCtx{ .Required = try items.addOne() } });1158 if (eatToken(&tok_it, &tree, Token.Id.Comma) == null)
1159 break;
1160 }
1159 continue;1161 continue;
1160 },1162 },
11611163
std/zig/parser_test.zig+43-1
...@@ -1,3 +1,44 @@...@@ -1,3 +1,44 @@
1test "zig fmt: simple asm" {
2 try testTransform(
3 \\comptime {
4 \\ asm volatile (
5 \\ \\.globl aoeu;
6 \\ \\.type aoeu, @function;
7 \\ \\.set aoeu, derp;
8 \\ );
9 \\
10 \\ asm ("not real assembly"
11 \\ :[a] "x" (x),);
12 \\ asm ("not real assembly"
13 \\ :[a] "x" (->i32),:[a] "x" (1),);
14 \\ asm ("still not real assembly"
15 \\ :::"a","b",);
16 \\}
17 ,
18 \\comptime {
19 \\ asm volatile (
20 \\ \\.globl aoeu;
21 \\ \\.type aoeu, @function;
22 \\ \\.set aoeu, derp;
23 \\ );
24 \\
25 \\ asm ("not real assembly"
26 \\ : [a] "x" (x)
27 \\ );
28 \\ asm ("not real assembly"
29 \\ : [a] "x" (-> i32)
30 \\ : [a] "x" (1)
31 \\ );
32 \\ asm ("still not real assembly"
33 \\ :
34 \\ :
35 \\ : "a", "b"
36 \\ );
37 \\}
38 \\
39 );
40}
41
1test "zig fmt: nested struct literal with one item" {42test "zig fmt: nested struct literal with one item" {
2 try testCanonical(43 try testCanonical(
3 \\const a = foo{44 \\const a = foo{
...@@ -1295,7 +1336,8 @@ test "zig fmt: inline asm" {...@@ -1295,7 +1336,8 @@ test "zig fmt: inline asm" {
1295 \\ : [ret] "={rax}" (-> usize)1336 \\ : [ret] "={rax}" (-> usize)
1296 \\ : [number] "{rax}" (number),1337 \\ : [number] "{rax}" (number),
1297 \\ [arg1] "{rdi}" (arg1)1338 \\ [arg1] "{rdi}" (arg1)
1298 \\ : "rcx", "r11");1339 \\ : "rcx", "r11"
1340 \\ );
1299 \\}1341 \\}
1300 \\1342 \\
1301 );1343 );
std/zig/render.zig+71-24
...@@ -1203,19 +1203,35 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind...@@ -1203,19 +1203,35 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind
1203 try renderToken(tree, stream, tree.nextToken(asm_node.asm_token), indent, Space.None); // (1203 try renderToken(tree, stream, tree.nextToken(asm_node.asm_token), indent, Space.None); // (
1204 }1204 }
12051205
1206 if (asm_node.outputs.len == 0 and asm_node.inputs.len == 0 and asm_node.clobbers.len == 0) {
1207 try renderExpression(allocator, stream, tree, indent, asm_node.template, Space.None);
1208 try renderToken(tree, stream, asm_node.rparen, indent, space);
1209 return;
1210 }
1211
1206 try renderExpression(allocator, stream, tree, indent, asm_node.template, Space.Newline);1212 try renderExpression(allocator, stream, tree, indent, asm_node.template, Space.Newline);
1213
1207 const indent_once = indent + indent_delta;1214 const indent_once = indent + indent_delta;
1208 try stream.writeByteNTimes(' ', indent_once);1215 try stream.writeByteNTimes(' ', indent_once);
1209 try stream.print(": ");1216
1217 const colon1 = tree.nextToken(asm_node.template.lastToken());
1210 const indent_extra = indent_once + 2;1218 const indent_extra = indent_once + 2;
12111219
1212 {1220 const colon2 = if (asm_node.outputs.len == 0) blk: {
1221 try renderToken(tree, stream, colon1, indent, Space.Newline); // :
1222 try stream.writeByteNTimes(' ', indent_once);
1223
1224 break :blk tree.nextToken(colon1);
1225 } else blk: {
1226 try renderToken(tree, stream, colon1, indent, Space.Space); // :
1227
1213 var it = asm_node.outputs.iterator(0);1228 var it = asm_node.outputs.iterator(0);
1214 while (it.next()) |asm_output| {1229 while (true) {
1230 const asm_output = ??it.next();
1215 const node = &(asm_output.*).base;1231 const node = &(asm_output.*).base;
1216 try renderExpression(allocator, stream, tree, indent_extra, node, Space.None);
12171232
1218 if (it.peek()) |next_asm_output| {1233 if (it.peek()) |next_asm_output| {
1234 try renderExpression(allocator, stream, tree, indent_extra, node, Space.None);
1219 const next_node = &(next_asm_output.*).base;1235 const next_node = &(next_asm_output.*).base;
12201236
1221 const comma = tree.prevToken(next_asm_output.*.firstToken());1237 const comma = tree.prevToken(next_asm_output.*.firstToken());
...@@ -1223,21 +1239,38 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind...@@ -1223,21 +1239,38 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind
1223 try renderExtraNewline(tree, stream, next_node);1239 try renderExtraNewline(tree, stream, next_node);
12241240
1225 try stream.writeByteNTimes(' ', indent_extra);1241 try stream.writeByteNTimes(' ', indent_extra);
1242 } else if (asm_node.inputs.len == 0 and asm_node.clobbers.len == 0) {
1243 try renderExpression(allocator, stream, tree, indent_extra, node, Space.Newline);
1244 try stream.writeByteNTimes(' ', indent);
1245 try renderToken(tree, stream, asm_node.rparen, indent, space);
1246 return;
1247 } else {
1248 try renderExpression(allocator, stream, tree, indent_extra, node, Space.Newline);
1249 try stream.writeByteNTimes(' ', indent_once);
1250 const comma_or_colon = tree.nextToken(node.lastToken());
1251 break :blk switch (tree.tokens.at(comma_or_colon).id) {
1252 Token.Id.Comma => tree.nextToken(comma_or_colon),
1253 else => comma_or_colon,
1254 };
1226 }1255 }
1227 }1256 }
1228 }1257 };
12291258
1230 try stream.write("\n");1259 const colon3 = if (asm_node.inputs.len == 0) blk: {
1231 try stream.writeByteNTimes(' ', indent_once);1260 try renderToken(tree, stream, colon2, indent, Space.Newline); // :
1232 try stream.write(": ");1261 try stream.writeByteNTimes(' ', indent_once);
1262
1263 break :blk tree.nextToken(colon2);
1264 } else blk: {
1265 try renderToken(tree, stream, colon2, indent, Space.Space); // :
12331266
1234 {
1235 var it = asm_node.inputs.iterator(0);1267 var it = asm_node.inputs.iterator(0);
1236 while (it.next()) |asm_input| {1268 while (true) {
1269 const asm_input = ??it.next();
1237 const node = &(asm_input.*).base;1270 const node = &(asm_input.*).base;
1238 try renderExpression(allocator, stream, tree, indent_extra, node, Space.None);
12391271
1240 if (it.peek()) |next_asm_input| {1272 if (it.peek()) |next_asm_input| {
1273 try renderExpression(allocator, stream, tree, indent_extra, node, Space.None);
1241 const next_node = &(next_asm_input.*).base;1274 const next_node = &(next_asm_input.*).base;
12421275
1243 const comma = tree.prevToken(next_asm_input.*.firstToken());1276 const comma = tree.prevToken(next_asm_input.*.firstToken());
...@@ -1245,26 +1278,40 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind...@@ -1245,26 +1278,40 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind
1245 try renderExtraNewline(tree, stream, next_node);1278 try renderExtraNewline(tree, stream, next_node);
12461279
1247 try stream.writeByteNTimes(' ', indent_extra);1280 try stream.writeByteNTimes(' ', indent_extra);
1281 } else if (asm_node.clobbers.len == 0) {
1282 try renderExpression(allocator, stream, tree, indent_extra, node, Space.Newline);
1283 try stream.writeByteNTimes(' ', indent);
1284 try renderToken(tree, stream, asm_node.rparen, indent, space); // )
1285 return;
1286 } else {
1287 try renderExpression(allocator, stream, tree, indent_extra, node, Space.Newline);
1288 try stream.writeByteNTimes(' ', indent_once);
1289 const comma_or_colon = tree.nextToken(node.lastToken());
1290 break :blk switch (tree.tokens.at(comma_or_colon).id) {
1291 Token.Id.Comma => tree.nextToken(comma_or_colon),
1292 else => comma_or_colon,
1293 };
1248 }1294 }
1249 }1295 }
1250 }1296 };
12511297
1252 try stream.write("\n");1298 try renderToken(tree, stream, colon3, indent, Space.Space); // :
1253 try stream.writeByteNTimes(' ', indent_once);
1254 try stream.write(": ");
12551299
1256 {1300 var it = asm_node.clobbers.iterator(0);
1257 var it = asm_node.clobbers.iterator(0);1301 while (true) {
1258 while (it.next()) |node| {1302 const clobber_token = ??it.next();
1259 try renderExpression(allocator, stream, tree, indent_once, node.*, Space.None);
12601303
1261 if (it.peek() != null) {1304 if (it.peek() == null) {
1262 try stream.write(", ");1305 try renderToken(tree, stream, clobber_token.*, indent_once, Space.Newline);
1263 }1306 try stream.writeByteNTimes(' ', indent);
1307 try renderToken(tree, stream, asm_node.rparen, indent, space);
1308 return;
1309 } else {
1310 try renderToken(tree, stream, clobber_token.*, indent_once, Space.None);
1311 const comma = tree.nextToken(clobber_token.*);
1312 try renderToken(tree, stream, comma, indent_once, Space.Space); // ,
1264 }1313 }
1265 }1314 }
1266
1267 try renderToken(tree, stream, asm_node.rparen, indent, space);
1268 },1315 },
12691316
1270 ast.Node.Id.AsmInput => {1317 ast.Node.Id.AsmInput => {