Commit 2c7996f400
Changed files (2)
std
std/zig/ast.zig
@@ -48,6 +48,8 @@ pub const Node = struct {
UndefinedLiteral,
ThisLiteral,
Asm,
+ AsmInput,
+ AsmOutput,
Unreachable,
ErrorType,
BuiltinCall,
@@ -96,6 +98,8 @@ pub const Node = struct {
Id.UndefinedLiteral => @fieldParentPtr(NodeUndefinedLiteral, "base", base).iterate(index),
Id.ThisLiteral => @fieldParentPtr(NodeThisLiteral, "base", base).iterate(index),
Id.Asm => @fieldParentPtr(NodeAsm, "base", base).iterate(index),
+ Id.AsmInput => @fieldParentPtr(NodeAsmInput, "base", base).iterate(index),
+ Id.AsmOutput => @fieldParentPtr(NodeAsmOutput, "base", base).iterate(index),
Id.Unreachable => @fieldParentPtr(NodeUnreachable, "base", base).iterate(index),
Id.ErrorType => @fieldParentPtr(NodeErrorType, "base", base).iterate(index),
Id.BuiltinCall => @fieldParentPtr(NodeBuiltinCall, "base", base).iterate(index),
@@ -146,6 +150,8 @@ pub const Node = struct {
Id.Unreachable => @fieldParentPtr(NodeUnreachable, "base", base).firstToken(),
Id.ThisLiteral => @fieldParentPtr(NodeThisLiteral, "base", base).firstToken(),
Id.Asm => @fieldParentPtr(NodeAsm, "base", base).firstToken(),
+ Id.AsmInput => @fieldParentPtr(NodeAsmInput, "base", base).firstToken(),
+ Id.AsmOutput => @fieldParentPtr(NodeAsmOutput, "base", base).firstToken(),
Id.ErrorType => @fieldParentPtr(NodeErrorType, "base", base).firstToken(),
Id.BuiltinCall => @fieldParentPtr(NodeBuiltinCall, "base", base).firstToken(),
Id.LineComment => @fieldParentPtr(NodeLineComment, "base", base).firstToken(),
@@ -194,6 +200,8 @@ pub const Node = struct {
Id.UndefinedLiteral => @fieldParentPtr(NodeUndefinedLiteral, "base", base).lastToken(),
Id.ThisLiteral => @fieldParentPtr(NodeThisLiteral, "base", base).lastToken(),
Id.Asm => @fieldParentPtr(NodeAsm, "base", base).lastToken(),
+ Id.AsmInput => @fieldParentPtr(NodeAsmInput, "base", base).lastToken(),
+ Id.AsmOutput => @fieldParentPtr(NodeAsmOutput, "base", base).lastToken(),
Id.Unreachable => @fieldParentPtr(NodeUnreachable, "base", base).lastToken(),
Id.ErrorType => @fieldParentPtr(NodeErrorType, "base", base).lastToken(),
Id.BuiltinCall => @fieldParentPtr(NodeBuiltinCall, "base", base).lastToken(),
@@ -1516,31 +1524,105 @@ pub const NodeThisLiteral = struct {
}
};
+pub const NodeAsmOutput = struct {
+ base: Node,
+ symbolic_name: &NodeIdentifier,
+ constraint: &NodeStringLiteral,
+ kind: Kind,
+
+ const Kind = union(enum) {
+ Variable: &NodeIdentifier,
+ Return: &Node
+ };
+
+ pub fn iterate(self: &NodeAsmOutput, index: usize) ?&Node {
+ var i = index;
+
+ if (i < 1) return &self.symbolic_name.base;
+ i -= 1;
+
+ if (i < 1) return &self.constraint.base;
+ i -= 1;
+
+ switch (self.kind) {
+ Kind.Variable => |variable_name| {
+ if (i < 1) return &variable_name.base;
+ i -= 1;
+ },
+ Kind.Return => |return_type| {
+ if (i < 1) return return_type;
+ i -= 1;
+ }
+ }
+
+ return null;
+ }
+
+ pub fn firstToken(self: &NodeAsmOutput) Token {
+ return self.symbolic_name.firstToken();
+ }
+
+ pub fn lastToken(self: &NodeAsmOutput) Token {
+ return switch (self.kind) {
+ Kind.Variable => |variable_name| variable_name.lastToken(),
+ Kind.Return => |return_type| return_type.lastToken(),
+ };
+ }
+};
+
+pub const NodeAsmInput = struct {
+ base: Node,
+ symbolic_name: &NodeIdentifier,
+ constraint: &NodeStringLiteral,
+ expr: &Node,
+
+ pub fn iterate(self: &NodeAsmInput, index: usize) ?&Node {
+ var i = index;
+
+ if (i < 1) return &self.symbolic_name.base;
+ i -= 1;
+
+ if (i < 1) return &self.constraint.base;
+ i -= 1;
+
+ if (i < 1) return self.expr;
+ i -= 1;
+
+ return null;
+ }
+
+ pub fn firstToken(self: &NodeAsmInput) Token {
+ return self.symbolic_name.firstToken();
+ }
+
+ pub fn lastToken(self: &NodeAsmInput) Token {
+ return self.expr.lastToken();
+ }
+};
+
pub const NodeAsm = struct {
base: Node,
asm_token: Token,
is_volatile: bool,
template: Token,
//tokens: ArrayList(AsmToken),
- outputs: ArrayList(AsmOutput),
- inputs: ArrayList(AsmInput),
+ outputs: ArrayList(&NodeAsmOutput),
+ inputs: ArrayList(&NodeAsmInput),
cloppers: ArrayList(&NodeStringLiteral),
rparen: Token,
- const AsmOutput = struct {
- symbolic_name: Token,
- constraint: Token,
- variable_name: ?Token,
- return_type: ?&Node,
- };
+ pub fn iterate(self: &NodeAsm, index: usize) ?&Node {
+ var i = index;
- const AsmInput = struct {
- symbolic_name: Token,
- constraint: Token,
- expr: &Node,
- };
+ if (i < self.outputs.len) return &self.outputs.at(index).base;
+ i -= self.outputs.len;
+
+ if (i < self.inputs.len) return &self.inputs.at(index).base;
+ i -= self.inputs.len;
+
+ if (i < self.cloppers.len) return &self.cloppers.at(index).base;
+ i -= self.cloppers.len;
- pub fn iterate(self: &NodeAsm, index: usize) ?&Node {
return null;
}
std/zig/parser.zig
@@ -164,8 +164,8 @@ pub const Parser = struct {
WhileContinueExpr: &?&ast.Node,
Statement: &ast.NodeBlock,
Semicolon: &const &const ast.Node,
- AsmOutputItems: &ArrayList(ast.NodeAsm.AsmOutput),
- AsmInputItems: &ArrayList(ast.NodeAsm.AsmInput),
+ AsmOutputItems: &ArrayList(&ast.NodeAsmOutput),
+ AsmInputItems: &ArrayList(&ast.NodeAsmInput),
AsmClopperItems: &ArrayList(&ast.NodeStringLiteral),
ExprListItemOrEnd: ExprListCtx,
ExprListCommaOrEnd: ExprListCtx,
@@ -1510,8 +1510,8 @@ pub const Parser = struct {
.is_volatile = is_volatile,
.template = template,
//.tokens = ArrayList(ast.NodeAsm.AsmToken).init(arena),
- .outputs = ArrayList(ast.NodeAsm.AsmOutput).init(arena),
- .inputs = ArrayList(ast.NodeAsm.AsmInput).init(arena),
+ .outputs = ArrayList(&ast.NodeAsmOutput).init(arena),
+ .inputs = ArrayList(&ast.NodeAsmInput).init(arena),
.cloppers = ArrayList(&ast.NodeStringLiteral).init(arena),
.rparen = undefined,
};
@@ -1679,18 +1679,23 @@ pub const Parser = struct {
_ = (try self.eatToken(&stack, Token.Id.LParen)) ?? continue;
try stack.append(State { .ExpectToken = Token.Id.RParen });
- const res = try items.addOne();
- *res = ast.NodeAsm.AsmOutput {
- .symbolic_name = symbolic_name,
- .constraint = constraint,
- .variable_name = null,
- .return_type = null,
+ const node = try arena.create(ast.NodeAsmOutput);
+ *node = ast.NodeAsmOutput {
+ .base = self.initNode(ast.Node.Id.AsmOutput),
+ .symbolic_name = try self.createIdentifier(arena, symbolic_name),
+ .constraint = try self.createStringLiteral(arena, constraint),
+ .kind = undefined,
};
+ try items.append(node);
+
const symbol_or_arrow = self.getNextToken();
switch (symbol_or_arrow.id) {
- Token.Id.Identifier => res.variable_name = symbol_or_arrow,
+ Token.Id.Identifier => {
+ node.kind = ast.NodeAsmOutput.Kind { .Variable = try self.createIdentifier(arena, symbol_or_arrow) };
+ },
Token.Id.Arrow => {
- try stack.append(State { .TypeExprBegin = DestPtr { .NullableField = &res.return_type } });
+ node.kind = ast.NodeAsmOutput.Kind { .Return = undefined };
+ try stack.append(State { .TypeExprBegin = DestPtr { .Field = &node.kind.Return } });
},
else => {
try self.parseError(&stack, symbol_or_arrow, "expected '->' or {}, found {}",
@@ -1718,13 +1723,15 @@ pub const Parser = struct {
_ = (try self.eatToken(&stack, Token.Id.LParen)) ?? continue;
try stack.append(State { .ExpectToken = Token.Id.RParen });
- const res = try items.addOne();
- *res = ast.NodeAsm.AsmInput {
- .symbolic_name = symbolic_name,
- .constraint = constraint,
+ const node = try arena.create(ast.NodeAsmInput);
+ *node = ast.NodeAsmInput {
+ .base = self.initNode(ast.Node.Id.AsmInput),
+ .symbolic_name = try self.createIdentifier(arena, symbolic_name),
+ .constraint = try self.createStringLiteral(arena, constraint),
.expr = undefined,
};
- try stack.append(State { .Expression = DestPtr { .Field = &res.expr } });
+ try items.append(node);
+ try stack.append(State { .Expression = DestPtr { .Field = &node.expr } });
},
State.AsmClopperItems => |items| {
@@ -3803,14 +3810,113 @@ pub const Parser = struct {
try stream.print("({}", self.tokenizer.getTokenSlice(asm_node.template));
+ try stack.append(RenderState { .Indent = indent });
try stack.append(RenderState { .Text = ")" });
- @panic("TODO: Render asm");
- //\\ return asm volatile ("syscall"
- //\\ : [ret] "={rax}" (-> usize)
- //\\ : [number] "{rax}" (number),
- //\\ [arg1] "{rdi}" (arg1)
- //\\ : "rcx", "r11");
- },,
+ {
+ const cloppers = asm_node.cloppers.toSliceConst();
+ var i = cloppers.len;
+ while (i != 0) {
+ i -= 1;
+ try stack.append(RenderState { .Expression = &cloppers[i].base });
+
+ if (i != 0) {
+ try stack.append(RenderState { .Text = ", " });
+ }
+ }
+ }
+ try stack.append(RenderState { .Text = ": " });
+ try stack.append(RenderState.PrintIndent);
+ try stack.append(RenderState { .Indent = indent + indent_delta });
+ try stack.append(RenderState { .Text = "\n" });
+ {
+ const inputs = asm_node.inputs.toSliceConst();
+ var i = inputs.len;
+ while (i != 0) {
+ i -= 1;
+ const node = inputs[i];
+ try stack.append(RenderState { .Expression = &node.base});
+
+ if (i != 0) {
+ try stack.append(RenderState.PrintIndent);
+ try stack.append(RenderState {
+ .Text = blk: {
+ const prev_node = inputs[i - 1];
+ const loc = self.tokenizer.getTokenLocation(prev_node.lastToken().end, node.firstToken());
+ if (loc.line >= 2) {
+ break :blk "\n\n";
+ }
+ break :blk "\n";
+ },
+ });
+ try stack.append(RenderState { .Text = "," });
+ }
+ }
+ }
+ try stack.append(RenderState { .Indent = indent + indent_delta + 2});
+ try stack.append(RenderState { .Text = ": "});
+ try stack.append(RenderState.PrintIndent);
+ try stack.append(RenderState { .Indent = indent + indent_delta});
+ try stack.append(RenderState { .Text = "\n" });
+ {
+ const outputs = asm_node.outputs.toSliceConst();
+ var i = outputs.len;
+ while (i != 0) {
+ i -= 1;
+ const node = outputs[i];
+ try stack.append(RenderState { .Expression = &node.base});
+
+ if (i != 0) {
+ try stack.append(RenderState.PrintIndent);
+ try stack.append(RenderState {
+ .Text = blk: {
+ const prev_node = outputs[i - 1];
+ const loc = self.tokenizer.getTokenLocation(prev_node.lastToken().end, node.firstToken());
+ if (loc.line >= 2) {
+ break :blk "\n\n";
+ }
+ break :blk "\n";
+ },
+ });
+ try stack.append(RenderState { .Text = "," });
+ }
+ }
+ }
+ try stack.append(RenderState { .Indent = indent + indent_delta + 2});
+ try stack.append(RenderState { .Text = ": "});
+ try stack.append(RenderState.PrintIndent);
+ try stack.append(RenderState { .Indent = indent + indent_delta});
+ try stack.append(RenderState { .Text = "\n" });
+ },
+ ast.Node.Id.AsmInput => {
+ const asm_input = @fieldParentPtr(ast.NodeAsmInput, "base", base);
+
+ try stack.append(RenderState { .Text = ")"});
+ try stack.append(RenderState { .Expression = asm_input.expr});
+ try stack.append(RenderState { .Text = " ("});
+ try stack.append(RenderState { .Expression = &asm_input.constraint.base});
+ try stack.append(RenderState { .Text = "] "});
+ try stack.append(RenderState { .Expression = &asm_input.symbolic_name.base});
+ try stack.append(RenderState { .Text = "["});
+ },
+ ast.Node.Id.AsmOutput => {
+ const asm_output = @fieldParentPtr(ast.NodeAsmOutput, "base", base);
+
+ try stack.append(RenderState { .Text = ")"});
+ switch (asm_output.kind) {
+ ast.NodeAsmOutput.Kind.Variable => |variable_name| {
+ try stack.append(RenderState { .Expression = &variable_name.base});
+ },
+ ast.NodeAsmOutput.Kind.Return => |return_type| {
+ try stack.append(RenderState { .Expression = return_type});
+ try stack.append(RenderState { .Text = "-> "});
+ },
+ }
+ try stack.append(RenderState { .Text = " ("});
+ try stack.append(RenderState { .Expression = &asm_output.constraint.base});
+ try stack.append(RenderState { .Text = "] "});
+ try stack.append(RenderState { .Expression = &asm_output.symbolic_name.base});
+ try stack.append(RenderState { .Text = "["});
+ },
ast.Node.Id.StructField,
ast.Node.Id.UnionTag,
@@ -4672,7 +4778,7 @@ test "zig fmt: inline asm" {
\\ return asm volatile ("syscall"
\\ : [ret] "={rax}" (-> usize)
\\ : [number] "{rax}" (number),
- \\ [arg1] "{rdi}" (arg1)
+ \\ [arg1] "{rdi}" (arg1)
\\ : "rcx", "r11");
\\}
\\