stage2 parser: split out PrefixOp into separate AST Nodes

This is part of a larger effort to improve the memory layout of AST
nodes of the self-hosted parser to reduce wasted memory. Reduction of
wasted memory also translates to improved performance because of fewer
memory allocations, and fewer cache misses.

Compared to master, when running `zig fmt` on the std lib:

 * cache-misses: 801,829 => 768,624
 * instructions: 3,234,877,167 => 3,232,075,022
 * peak memory: 81480 KB => 75964 KB
This commit is contained in:
Andrew Kelley
2020-07-13 20:13:51 -07:00
parent 204f61d7f5
commit 14cef9dd3d
5 changed files with 725 additions and 422 deletions

View File

@@ -1308,10 +1308,18 @@ fn astGenExpr(self: *Module, scope: *Scope, ast_node: *ast.Node) InnerError!*zir
.ControlFlowExpression => return self.astGenControlFlowExpression(scope, @fieldParentPtr(ast.Node.ControlFlowExpression, "base", ast_node)),
.If => return self.astGenIf(scope, @fieldParentPtr(ast.Node.If, "base", ast_node)),
.InfixOp => return self.astGenInfixOp(scope, @fieldParentPtr(ast.Node.InfixOp, "base", ast_node)),
.BoolNot => return self.astGenBoolNot(scope, @fieldParentPtr(ast.Node.BoolNot, "base", ast_node)),
else => return self.failNode(scope, ast_node, "TODO implement astGenExpr for {}", .{@tagName(ast_node.id)}),
}
}
fn astGenBoolNot(self: *Module, scope: *Scope, node: *ast.Node.BoolNot) InnerError!*zir.Inst {
const operand = try self.astGenExpr(scope, node.rhs);
const tree = scope.tree();
const src = tree.token_locs[node.op_token].start;
return self.addZIRInst(scope, src, zir.Inst.BoolNot, .{ .operand = operand }, .{});
}
fn astGenInfixOp(self: *Module, scope: *Scope, infix_node: *ast.Node.InfixOp) InnerError!*zir.Inst {
switch (infix_node.op) {
.Assign => {