mirror of
https://github.com/ziglang/zig.git
synced 2026-02-21 16:54:52 +00:00
std.zig.parser can now render asm expressions
This commit is contained in:
parent
a09bb408a2
commit
2c7996f400
112
std/zig/ast.zig
112
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,
|
||||
};
|
||||
|
||||
const AsmInput = struct {
|
||||
symbolic_name: Token,
|
||||
constraint: Token,
|
||||
expr: &Node,
|
||||
};
|
||||
|
||||
pub fn iterate(self: &NodeAsm, index: usize) ?&Node {
|
||||
var i = index;
|
||||
|
||||
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;
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@ -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");
|
||||
\\}
|
||||
\\
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user