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 {...@@ -48,6 +48,8 @@ pub const Node = struct {
48 UndefinedLiteral,48 UndefinedLiteral,
49 ThisLiteral,49 ThisLiteral,
50 Asm,50 Asm,
51 AsmInput,
52 AsmOutput,
51 Unreachable,53 Unreachable,
52 ErrorType,54 ErrorType,
53 BuiltinCall,55 BuiltinCall,
...@@ -96,6 +98,8 @@ pub const Node = struct {...@@ -96,6 +98,8 @@ pub const Node = struct {
96 Id.UndefinedLiteral => @fieldParentPtr(NodeUndefinedLiteral, "base", base).iterate(index),98 Id.UndefinedLiteral => @fieldParentPtr(NodeUndefinedLiteral, "base", base).iterate(index),
97 Id.ThisLiteral => @fieldParentPtr(NodeThisLiteral, "base", base).iterate(index),99 Id.ThisLiteral => @fieldParentPtr(NodeThisLiteral, "base", base).iterate(index),
98 Id.Asm => @fieldParentPtr(NodeAsm, "base", base).iterate(index),100 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),
99 Id.Unreachable => @fieldParentPtr(NodeUnreachable, "base", base).iterate(index),103 Id.Unreachable => @fieldParentPtr(NodeUnreachable, "base", base).iterate(index),
100 Id.ErrorType => @fieldParentPtr(NodeErrorType, "base", base).iterate(index),104 Id.ErrorType => @fieldParentPtr(NodeErrorType, "base", base).iterate(index),
101 Id.BuiltinCall => @fieldParentPtr(NodeBuiltinCall, "base", base).iterate(index),105 Id.BuiltinCall => @fieldParentPtr(NodeBuiltinCall, "base", base).iterate(index),
...@@ -146,6 +150,8 @@ pub const Node = struct {...@@ -146,6 +150,8 @@ pub const Node = struct {
146 Id.Unreachable => @fieldParentPtr(NodeUnreachable, "base", base).firstToken(),150 Id.Unreachable => @fieldParentPtr(NodeUnreachable, "base", base).firstToken(),
147 Id.ThisLiteral => @fieldParentPtr(NodeThisLiteral, "base", base).firstToken(),151 Id.ThisLiteral => @fieldParentPtr(NodeThisLiteral, "base", base).firstToken(),
148 Id.Asm => @fieldParentPtr(NodeAsm, "base", base).firstToken(),152 Id.Asm => @fieldParentPtr(NodeAsm, "base", base).firstToken(),
153 Id.AsmInput => @fieldParentPtr(NodeAsmInput, "base", base).firstToken(),
154 Id.AsmOutput => @fieldParentPtr(NodeAsmOutput, "base", base).firstToken(),
149 Id.ErrorType => @fieldParentPtr(NodeErrorType, "base", base).firstToken(),155 Id.ErrorType => @fieldParentPtr(NodeErrorType, "base", base).firstToken(),
150 Id.BuiltinCall => @fieldParentPtr(NodeBuiltinCall, "base", base).firstToken(),156 Id.BuiltinCall => @fieldParentPtr(NodeBuiltinCall, "base", base).firstToken(),
151 Id.LineComment => @fieldParentPtr(NodeLineComment, "base", base).firstToken(),157 Id.LineComment => @fieldParentPtr(NodeLineComment, "base", base).firstToken(),
...@@ -194,6 +200,8 @@ pub const Node = struct {...@@ -194,6 +200,8 @@ pub const Node = struct {
194 Id.UndefinedLiteral => @fieldParentPtr(NodeUndefinedLiteral, "base", base).lastToken(),200 Id.UndefinedLiteral => @fieldParentPtr(NodeUndefinedLiteral, "base", base).lastToken(),
195 Id.ThisLiteral => @fieldParentPtr(NodeThisLiteral, "base", base).lastToken(),201 Id.ThisLiteral => @fieldParentPtr(NodeThisLiteral, "base", base).lastToken(),
196 Id.Asm => @fieldParentPtr(NodeAsm, "base", base).lastToken(),202 Id.Asm => @fieldParentPtr(NodeAsm, "base", base).lastToken(),
203 Id.AsmInput => @fieldParentPtr(NodeAsmInput, "base", base).lastToken(),
204 Id.AsmOutput => @fieldParentPtr(NodeAsmOutput, "base", base).lastToken(),
197 Id.Unreachable => @fieldParentPtr(NodeUnreachable, "base", base).lastToken(),205 Id.Unreachable => @fieldParentPtr(NodeUnreachable, "base", base).lastToken(),
198 Id.ErrorType => @fieldParentPtr(NodeErrorType, "base", base).lastToken(),206 Id.ErrorType => @fieldParentPtr(NodeErrorType, "base", base).lastToken(),
199 Id.BuiltinCall => @fieldParentPtr(NodeBuiltinCall, "base", base).lastToken(),207 Id.BuiltinCall => @fieldParentPtr(NodeBuiltinCall, "base", base).lastToken(),
...@@ -1516,31 +1524,105 @@ pub const NodeThisLiteral = struct {...@@ -1516,31 +1524,105 @@ pub const NodeThisLiteral = struct {
1516 }1524 }
1517};1525};
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
1519pub const NodeAsm = struct {1603pub const NodeAsm = struct {
1520 base: Node,1604 base: Node,
1521 asm_token: Token,1605 asm_token: Token,
1522 is_volatile: bool,1606 is_volatile: bool,
1523 template: Token,1607 template: Token,
1524 //tokens: ArrayList(AsmToken),1608 //tokens: ArrayList(AsmToken),
1525 outputs: ArrayList(AsmOutput),1609 outputs: ArrayList(&NodeAsmOutput),
1526 inputs: ArrayList(AsmInput),1610 inputs: ArrayList(&NodeAsmInput),
1527 cloppers: ArrayList(&NodeStringLiteral),1611 cloppers: ArrayList(&NodeStringLiteral),
1528 rparen: Token,1612 rparen: Token,
15291613
1530 const AsmOutput = struct {1614 pub fn iterate(self: &NodeAsm, index: usize) ?&Node {
1531 symbolic_name: Token,1615 var i = index;
1532 constraint: Token,
1533 variable_name: ?Token,
1534 return_type: ?&Node,
1535 };
15361616
1537 const AsmInput = struct {1617 if (i < self.outputs.len) return &self.outputs.at(index).base;
1538 symbolic_name: Token,1618 i -= self.outputs.len;
1539 constraint: Token,1619
1540 expr: &Node,1620 if (i < self.inputs.len) return &self.inputs.at(index).base;
1541 };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 {
1544 return null;1626 return null;
1545 }1627 }
15461628
std/zig/parser.zig+131-25
...@@ -164,8 +164,8 @@ pub const Parser = struct {...@@ -164,8 +164,8 @@ pub const Parser = struct {
164 WhileContinueExpr: &?&ast.Node,164 WhileContinueExpr: &?&ast.Node,
165 Statement: &ast.NodeBlock,165 Statement: &ast.NodeBlock,
166 Semicolon: &const &const ast.Node,166 Semicolon: &const &const ast.Node,
167 AsmOutputItems: &ArrayList(ast.NodeAsm.AsmOutput),167 AsmOutputItems: &ArrayList(&ast.NodeAsmOutput),
168 AsmInputItems: &ArrayList(ast.NodeAsm.AsmInput),168 AsmInputItems: &ArrayList(&ast.NodeAsmInput),
169 AsmClopperItems: &ArrayList(&ast.NodeStringLiteral),169 AsmClopperItems: &ArrayList(&ast.NodeStringLiteral),
170 ExprListItemOrEnd: ExprListCtx,170 ExprListItemOrEnd: ExprListCtx,
171 ExprListCommaOrEnd: ExprListCtx,171 ExprListCommaOrEnd: ExprListCtx,
...@@ -1510,8 +1510,8 @@ pub const Parser = struct {...@@ -1510,8 +1510,8 @@ pub const Parser = struct {
1510 .is_volatile = is_volatile,1510 .is_volatile = is_volatile,
1511 .template = template,1511 .template = template,
1512 //.tokens = ArrayList(ast.NodeAsm.AsmToken).init(arena),1512 //.tokens = ArrayList(ast.NodeAsm.AsmToken).init(arena),
1513 .outputs = ArrayList(ast.NodeAsm.AsmOutput).init(arena),1513 .outputs = ArrayList(&ast.NodeAsmOutput).init(arena),
1514 .inputs = ArrayList(ast.NodeAsm.AsmInput).init(arena),1514 .inputs = ArrayList(&ast.NodeAsmInput).init(arena),
1515 .cloppers = ArrayList(&ast.NodeStringLiteral).init(arena),1515 .cloppers = ArrayList(&ast.NodeStringLiteral).init(arena),
1516 .rparen = undefined,1516 .rparen = undefined,
1517 };1517 };
...@@ -1679,18 +1679,23 @@ pub const Parser = struct {...@@ -1679,18 +1679,23 @@ pub const Parser = struct {
1679 _ = (try self.eatToken(&stack, Token.Id.LParen)) ?? continue;1679 _ = (try self.eatToken(&stack, Token.Id.LParen)) ?? continue;
1680 try stack.append(State { .ExpectToken = Token.Id.RParen });1680 try stack.append(State { .ExpectToken = Token.Id.RParen });
16811681
1682 const res = try items.addOne();1682 const node = try arena.create(ast.NodeAsmOutput);
1683 *res = ast.NodeAsm.AsmOutput {1683 *node = ast.NodeAsmOutput {
1684 .symbolic_name = symbolic_name,1684 .base = self.initNode(ast.Node.Id.AsmOutput),
1685 .constraint = constraint,1685 .symbolic_name = try self.createIdentifier(arena, symbolic_name),
1686 .variable_name = null,1686 .constraint = try self.createStringLiteral(arena, constraint),
1687 .return_type = null,1687 .kind = undefined,
1688 };1688 };
1689 try items.append(node);
1690
1689 const symbol_or_arrow = self.getNextToken();1691 const symbol_or_arrow = self.getNextToken();
1690 switch (symbol_or_arrow.id) {1692 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 },
1692 Token.Id.Arrow => {1696 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 } });
1694 },1699 },
1695 else => {1700 else => {
1696 try self.parseError(&stack, symbol_or_arrow, "expected '->' or {}, found {}",1701 try self.parseError(&stack, symbol_or_arrow, "expected '->' or {}, found {}",
...@@ -1718,13 +1723,15 @@ pub const Parser = struct {...@@ -1718,13 +1723,15 @@ pub const Parser = struct {
1718 _ = (try self.eatToken(&stack, Token.Id.LParen)) ?? continue;1723 _ = (try self.eatToken(&stack, Token.Id.LParen)) ?? continue;
1719 try stack.append(State { .ExpectToken = Token.Id.RParen });1724 try stack.append(State { .ExpectToken = Token.Id.RParen });
17201725
1721 const res = try items.addOne();1726 const node = try arena.create(ast.NodeAsmInput);
1722 *res = ast.NodeAsm.AsmInput {1727 *node = ast.NodeAsmInput {
1723 .symbolic_name = symbolic_name,1728 .base = self.initNode(ast.Node.Id.AsmInput),
1724 .constraint = constraint,1729 .symbolic_name = try self.createIdentifier(arena, symbolic_name),
1730 .constraint = try self.createStringLiteral(arena, constraint),
1725 .expr = undefined,1731 .expr = undefined,
1726 };1732 };
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 } });
1728 },1735 },
17291736
1730 State.AsmClopperItems => |items| {1737 State.AsmClopperItems => |items| {
...@@ -3803,14 +3810,113 @@ pub const Parser = struct {...@@ -3803,14 +3810,113 @@ pub const Parser = struct {
38033810
3804 try stream.print("({}", self.tokenizer.getTokenSlice(asm_node.template));3811 try stream.print("({}", self.tokenizer.getTokenSlice(asm_node.template));
38053812
3813 try stack.append(RenderState { .Indent = indent });
3806 try stack.append(RenderState { .Text = ")" });3814 try stack.append(RenderState { .Text = ")" });
3807 @panic("TODO: Render asm");3815 {
3808 //\\ return asm volatile ("syscall"3816 const cloppers = asm_node.cloppers.toSliceConst();
3809 //\\ : [ret] "={rax}" (-> usize)3817 var i = cloppers.len;
3810 //\\ : [number] "{rax}" (number),3818 while (i != 0) {
3811 //\\ [arg1] "{rdi}" (arg1)3819 i -= 1;
3812 //\\ : "rcx", "r11");3820 try stack.append(RenderState { .Expression = &cloppers[i].base });
3813 },,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
3815 ast.Node.Id.StructField,3921 ast.Node.Id.StructField,
3816 ast.Node.Id.UnionTag,3922 ast.Node.Id.UnionTag,
...@@ -4672,7 +4778,7 @@ test "zig fmt: inline asm" {...@@ -4672,7 +4778,7 @@ test "zig fmt: inline asm" {
4672 \\ return asm volatile ("syscall"4778 \\ return asm volatile ("syscall"
4673 \\ : [ret] "={rax}" (-> usize)4779 \\ : [ret] "={rax}" (-> usize)
4674 \\ : [number] "{rax}" (number),4780 \\ : [number] "{rax}" (number),
4675 \\ [arg1] "{rdi}" (arg1)4781 \\ [arg1] "{rdi}" (arg1)
4676 \\ : "rcx", "r11");4782 \\ : "rcx", "r11");
4677 \\}4783 \\}
4678 \\4784 \\