authorgravatar for jhc@dismail.deJimmi Holst Christensen <jhc@dismail.de> 2018-04-10 09:27:11+02:00
committergravatar for jhc@dismail.deJimmi Holst Christensen <jhc@dismail.de> 2018-04-10 09:27:11+02:00
log2c7996f4006b94f81fc3b1c1e3f73a4a7a291782
tree4ff2ccc5b4d01a376609e0b4b9111280859b5d95
parenta09bb408a20fcfc0575a9298b318803b07517b0a

std.zig.parser can now render asm expressions


2 files changed, 227 insertions(+), 39 deletions(-)

std/zig/ast.zig+96-14
......@@ -48,6 +48,8 @@ pub const Node = struct {
4848 UndefinedLiteral,
4949 ThisLiteral,
5050 Asm,
51 AsmInput,
52 AsmOutput,
5153 Unreachable,
5254 ErrorType,
5355 BuiltinCall,
......@@ -96,6 +98,8 @@ pub const Node = struct {
9698 Id.UndefinedLiteral => @fieldParentPtr(NodeUndefinedLiteral, "base", base).iterate(index),
9799 Id.ThisLiteral => @fieldParentPtr(NodeThisLiteral, "base", base).iterate(index),
98100 Id.Asm => @fieldParentPtr(NodeAsm, "base", base).iterate(index),
101 Id.AsmInput => @fieldParentPtr(NodeAsmInput, "base", base).iterate(index),
102 Id.AsmOutput => @fieldParentPtr(NodeAsmOutput, "base", base).iterate(index),
99103 Id.Unreachable => @fieldParentPtr(NodeUnreachable, "base", base).iterate(index),
100104 Id.ErrorType => @fieldParentPtr(NodeErrorType, "base", base).iterate(index),
101105 Id.BuiltinCall => @fieldParentPtr(NodeBuiltinCall, "base", base).iterate(index),
......@@ -146,6 +150,8 @@ pub const Node = struct {
146150 Id.Unreachable => @fieldParentPtr(NodeUnreachable, "base", base).firstToken(),
147151 Id.ThisLiteral => @fieldParentPtr(NodeThisLiteral, "base", base).firstToken(),
148152 Id.Asm => @fieldParentPtr(NodeAsm, "base", base).firstToken(),
153 Id.AsmInput => @fieldParentPtr(NodeAsmInput, "base", base).firstToken(),
154 Id.AsmOutput => @fieldParentPtr(NodeAsmOutput, "base", base).firstToken(),
149155 Id.ErrorType => @fieldParentPtr(NodeErrorType, "base", base).firstToken(),
150156 Id.BuiltinCall => @fieldParentPtr(NodeBuiltinCall, "base", base).firstToken(),
151157 Id.LineComment => @fieldParentPtr(NodeLineComment, "base", base).firstToken(),
......@@ -194,6 +200,8 @@ pub const Node = struct {
194200 Id.UndefinedLiteral => @fieldParentPtr(NodeUndefinedLiteral, "base", base).lastToken(),
195201 Id.ThisLiteral => @fieldParentPtr(NodeThisLiteral, "base", base).lastToken(),
196202 Id.Asm => @fieldParentPtr(NodeAsm, "base", base).lastToken(),
203 Id.AsmInput => @fieldParentPtr(NodeAsmInput, "base", base).lastToken(),
204 Id.AsmOutput => @fieldParentPtr(NodeAsmOutput, "base", base).lastToken(),
197205 Id.Unreachable => @fieldParentPtr(NodeUnreachable, "base", base).lastToken(),
198206 Id.ErrorType => @fieldParentPtr(NodeErrorType, "base", base).lastToken(),
199207 Id.BuiltinCall => @fieldParentPtr(NodeBuiltinCall, "base", base).lastToken(),
......@@ -1516,31 +1524,105 @@ pub const NodeThisLiteral = struct {
15161524 }
15171525};
15181526
1527pub const NodeAsmOutput = struct {
1528 base: Node,
1529 symbolic_name: &NodeIdentifier,
1530 constraint: &NodeStringLiteral,
1531 kind: Kind,
1532
1533 const Kind = union(enum) {
1534 Variable: &NodeIdentifier,
1535 Return: &Node
1536 };
1537
1538 pub fn iterate(self: &NodeAsmOutput, index: usize) ?&Node {
1539 var i = index;
1540
1541 if (i < 1) return &self.symbolic_name.base;
1542 i -= 1;
1543
1544 if (i < 1) return &self.constraint.base;
1545 i -= 1;
1546
1547 switch (self.kind) {
1548 Kind.Variable => |variable_name| {
1549 if (i < 1) return &variable_name.base;
1550 i -= 1;
1551 },
1552 Kind.Return => |return_type| {
1553 if (i < 1) return return_type;
1554 i -= 1;
1555 }
1556 }
1557
1558 return null;
1559 }
1560
1561 pub fn firstToken(self: &NodeAsmOutput) Token {
1562 return self.symbolic_name.firstToken();
1563 }
1564
1565 pub fn lastToken(self: &NodeAsmOutput) Token {
1566 return switch (self.kind) {
1567 Kind.Variable => |variable_name| variable_name.lastToken(),
1568 Kind.Return => |return_type| return_type.lastToken(),
1569 };
1570 }
1571};
1572
1573pub const NodeAsmInput = struct {
1574 base: Node,
1575 symbolic_name: &NodeIdentifier,
1576 constraint: &NodeStringLiteral,
1577 expr: &Node,
1578
1579 pub fn iterate(self: &NodeAsmInput, index: usize) ?&Node {
1580 var i = index;
1581
1582 if (i < 1) return &self.symbolic_name.base;
1583 i -= 1;
1584
1585 if (i < 1) return &self.constraint.base;
1586 i -= 1;
1587
1588 if (i < 1) return self.expr;
1589 i -= 1;
1590
1591 return null;
1592 }
1593
1594 pub fn firstToken(self: &NodeAsmInput) Token {
1595 return self.symbolic_name.firstToken();
1596 }
1597
1598 pub fn lastToken(self: &NodeAsmInput) Token {
1599 return self.expr.lastToken();
1600 }
1601};
1602
15191603pub const NodeAsm = struct {
15201604 base: Node,
15211605 asm_token: Token,
15221606 is_volatile: bool,
15231607 template: Token,
15241608 //tokens: ArrayList(AsmToken),
1525 outputs: ArrayList(AsmOutput),
1526 inputs: ArrayList(AsmInput),
1609 outputs: ArrayList(&NodeAsmOutput),
1610 inputs: ArrayList(&NodeAsmInput),
15271611 cloppers: ArrayList(&NodeStringLiteral),
15281612 rparen: Token,
15291613
1530 const AsmOutput = struct {
1531 symbolic_name: Token,
1532 constraint: Token,
1533 variable_name: ?Token,
1534 return_type: ?&Node,
1535 };
1614 pub fn iterate(self: &NodeAsm, index: usize) ?&Node {
1615 var i = index;
15361616
1537 const AsmInput = struct {
1538 symbolic_name: Token,
1539 constraint: Token,
1540 expr: &Node,
1541 };
1617 if (i < self.outputs.len) return &self.outputs.at(index).base;
1618 i -= self.outputs.len;
1619
1620 if (i < self.inputs.len) return &self.inputs.at(index).base;
1621 i -= self.inputs.len;
1622
1623 if (i < self.cloppers.len) return &self.cloppers.at(index).base;
1624 i -= self.cloppers.len;
15421625
1543 pub fn iterate(self: &NodeAsm, index: usize) ?&Node {
15441626 return null;
15451627 }
15461628
std/zig/parser.zig+131-25
......@@ -164,8 +164,8 @@ pub const Parser = struct {
164164 WhileContinueExpr: &?&ast.Node,
165165 Statement: &ast.NodeBlock,
166166 Semicolon: &const &const ast.Node,
167 AsmOutputItems: &ArrayList(ast.NodeAsm.AsmOutput),
168 AsmInputItems: &ArrayList(ast.NodeAsm.AsmInput),
167 AsmOutputItems: &ArrayList(&ast.NodeAsmOutput),
168 AsmInputItems: &ArrayList(&ast.NodeAsmInput),
169169 AsmClopperItems: &ArrayList(&ast.NodeStringLiteral),
170170 ExprListItemOrEnd: ExprListCtx,
171171 ExprListCommaOrEnd: ExprListCtx,
......@@ -1510,8 +1510,8 @@ pub const Parser = struct {
15101510 .is_volatile = is_volatile,
15111511 .template = template,
15121512 //.tokens = ArrayList(ast.NodeAsm.AsmToken).init(arena),
1513 .outputs = ArrayList(ast.NodeAsm.AsmOutput).init(arena),
1514 .inputs = ArrayList(ast.NodeAsm.AsmInput).init(arena),
1513 .outputs = ArrayList(&ast.NodeAsmOutput).init(arena),
1514 .inputs = ArrayList(&ast.NodeAsmInput).init(arena),
15151515 .cloppers = ArrayList(&ast.NodeStringLiteral).init(arena),
15161516 .rparen = undefined,
15171517 };
......@@ -1679,18 +1679,23 @@ pub const Parser = struct {
16791679 _ = (try self.eatToken(&stack, Token.Id.LParen)) ?? continue;
16801680 try stack.append(State { .ExpectToken = Token.Id.RParen });
16811681
1682 const res = try items.addOne();
1683 *res = ast.NodeAsm.AsmOutput {
1684 .symbolic_name = symbolic_name,
1685 .constraint = constraint,
1686 .variable_name = null,
1687 .return_type = null,
1682 const node = try arena.create(ast.NodeAsmOutput);
1683 *node = ast.NodeAsmOutput {
1684 .base = self.initNode(ast.Node.Id.AsmOutput),
1685 .symbolic_name = try self.createIdentifier(arena, symbolic_name),
1686 .constraint = try self.createStringLiteral(arena, constraint),
1687 .kind = undefined,
16881688 };
1689 try items.append(node);
1690
16891691 const symbol_or_arrow = self.getNextToken();
16901692 switch (symbol_or_arrow.id) {
1691 Token.Id.Identifier => res.variable_name = symbol_or_arrow,
1693 Token.Id.Identifier => {
1694 node.kind = ast.NodeAsmOutput.Kind { .Variable = try self.createIdentifier(arena, symbol_or_arrow) };
1695 },
16921696 Token.Id.Arrow => {
1693 try stack.append(State { .TypeExprBegin = DestPtr { .NullableField = &res.return_type } });
1697 node.kind = ast.NodeAsmOutput.Kind { .Return = undefined };
1698 try stack.append(State { .TypeExprBegin = DestPtr { .Field = &node.kind.Return } });
16941699 },
16951700 else => {
16961701 try self.parseError(&stack, symbol_or_arrow, "expected '->' or {}, found {}",
......@@ -1718,13 +1723,15 @@ pub const Parser = struct {
17181723 _ = (try self.eatToken(&stack, Token.Id.LParen)) ?? continue;
17191724 try stack.append(State { .ExpectToken = Token.Id.RParen });
17201725
1721 const res = try items.addOne();
1722 *res = ast.NodeAsm.AsmInput {
1723 .symbolic_name = symbolic_name,
1724 .constraint = constraint,
1726 const node = try arena.create(ast.NodeAsmInput);
1727 *node = ast.NodeAsmInput {
1728 .base = self.initNode(ast.Node.Id.AsmInput),
1729 .symbolic_name = try self.createIdentifier(arena, symbolic_name),
1730 .constraint = try self.createStringLiteral(arena, constraint),
17251731 .expr = undefined,
17261732 };
1727 try stack.append(State { .Expression = DestPtr { .Field = &res.expr } });
1733 try items.append(node);
1734 try stack.append(State { .Expression = DestPtr { .Field = &node.expr } });
17281735 },
17291736
17301737 State.AsmClopperItems => |items| {
......@@ -3803,14 +3810,113 @@ pub const Parser = struct {
38033810
38043811 try stream.print("({}", self.tokenizer.getTokenSlice(asm_node.template));
38053812
3813 try stack.append(RenderState { .Indent = indent });
38063814 try stack.append(RenderState { .Text = ")" });
3807 @panic("TODO: Render asm");
3808 //\\ return asm volatile ("syscall"
3809 //\\ : [ret] "={rax}" (-> usize)
3810 //\\ : [number] "{rax}" (number),
3811 //\\ [arg1] "{rdi}" (arg1)
3812 //\\ : "rcx", "r11");
3813 },,
3815 {
3816 const cloppers = asm_node.cloppers.toSliceConst();
3817 var i = cloppers.len;
3818 while (i != 0) {
3819 i -= 1;
3820 try stack.append(RenderState { .Expression = &cloppers[i].base });
3821
3822 if (i != 0) {
3823 try stack.append(RenderState { .Text = ", " });
3824 }
3825 }
3826 }
3827 try stack.append(RenderState { .Text = ": " });
3828 try stack.append(RenderState.PrintIndent);
3829 try stack.append(RenderState { .Indent = indent + indent_delta });
3830 try stack.append(RenderState { .Text = "\n" });
3831 {
3832 const inputs = asm_node.inputs.toSliceConst();
3833 var i = inputs.len;
3834 while (i != 0) {
3835 i -= 1;
3836 const node = inputs[i];
3837 try stack.append(RenderState { .Expression = &node.base});
3838
3839 if (i != 0) {
3840 try stack.append(RenderState.PrintIndent);
3841 try stack.append(RenderState {
3842 .Text = blk: {
3843 const prev_node = inputs[i - 1];
3844 const loc = self.tokenizer.getTokenLocation(prev_node.lastToken().end, node.firstToken());
3845 if (loc.line >= 2) {
3846 break :blk "\n\n";
3847 }
3848 break :blk "\n";
3849 },
3850 });
3851 try stack.append(RenderState { .Text = "," });
3852 }
3853 }
3854 }
3855 try stack.append(RenderState { .Indent = indent + indent_delta + 2});
3856 try stack.append(RenderState { .Text = ": "});
3857 try stack.append(RenderState.PrintIndent);
3858 try stack.append(RenderState { .Indent = indent + indent_delta});
3859 try stack.append(RenderState { .Text = "\n" });
3860 {
3861 const outputs = asm_node.outputs.toSliceConst();
3862 var i = outputs.len;
3863 while (i != 0) {
3864 i -= 1;
3865 const node = outputs[i];
3866 try stack.append(RenderState { .Expression = &node.base});
3867
3868 if (i != 0) {
3869 try stack.append(RenderState.PrintIndent);
3870 try stack.append(RenderState {
3871 .Text = blk: {
3872 const prev_node = outputs[i - 1];
3873 const loc = self.tokenizer.getTokenLocation(prev_node.lastToken().end, node.firstToken());
3874 if (loc.line >= 2) {
3875 break :blk "\n\n";
3876 }
3877 break :blk "\n";
3878 },
3879 });
3880 try stack.append(RenderState { .Text = "," });
3881 }
3882 }
3883 }
3884 try stack.append(RenderState { .Indent = indent + indent_delta + 2});
3885 try stack.append(RenderState { .Text = ": "});
3886 try stack.append(RenderState.PrintIndent);
3887 try stack.append(RenderState { .Indent = indent + indent_delta});
3888 try stack.append(RenderState { .Text = "\n" });
3889 },
3890 ast.Node.Id.AsmInput => {
3891 const asm_input = @fieldParentPtr(ast.NodeAsmInput, "base", base);
3892
3893 try stack.append(RenderState { .Text = ")"});
3894 try stack.append(RenderState { .Expression = asm_input.expr});
3895 try stack.append(RenderState { .Text = " ("});
3896 try stack.append(RenderState { .Expression = &asm_input.constraint.base});
3897 try stack.append(RenderState { .Text = "] "});
3898 try stack.append(RenderState { .Expression = &asm_input.symbolic_name.base});
3899 try stack.append(RenderState { .Text = "["});
3900 },
3901 ast.Node.Id.AsmOutput => {
3902 const asm_output = @fieldParentPtr(ast.NodeAsmOutput, "base", base);
3903
3904 try stack.append(RenderState { .Text = ")"});
3905 switch (asm_output.kind) {
3906 ast.NodeAsmOutput.Kind.Variable => |variable_name| {
3907 try stack.append(RenderState { .Expression = &variable_name.base});
3908 },
3909 ast.NodeAsmOutput.Kind.Return => |return_type| {
3910 try stack.append(RenderState { .Expression = return_type});
3911 try stack.append(RenderState { .Text = "-> "});
3912 },
3913 }
3914 try stack.append(RenderState { .Text = " ("});
3915 try stack.append(RenderState { .Expression = &asm_output.constraint.base});
3916 try stack.append(RenderState { .Text = "] "});
3917 try stack.append(RenderState { .Expression = &asm_output.symbolic_name.base});
3918 try stack.append(RenderState { .Text = "["});
3919 },
38143920
38153921 ast.Node.Id.StructField,
38163922 ast.Node.Id.UnionTag,
......@@ -4672,7 +4778,7 @@ test "zig fmt: inline asm" {
46724778 \\ return asm volatile ("syscall"
46734779 \\ : [ret] "={rax}" (-> usize)
46744780 \\ : [number] "{rax}" (number),
4675 \\ [arg1] "{rdi}" (arg1)
4781 \\ [arg1] "{rdi}" (arg1)
46764782 \\ : "rcx", "r11");
46774783 \\}
46784784 \\