aboutsummaryrefslogtreecommitdiff
path: root/src/AstGen.zig
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2022-01-15 23:13:44 -0700
committerAndrew Kelley <andrew@ziglang.org>2022-01-15 23:13:44 -0700
commit7f41e20802fd8f9eb19c0218f1e2000e2751592a (patch)
tree535a39fbae2c811e4c7af03b36cf52b3f164ad73 /src/AstGen.zig
parent7c6f5d26eadb137ab3fb2be340485ebd860a85fe (diff)
downloadzig-7f41e20802fd8f9eb19c0218f1e2000e2751592a.tar.gz
zig-7f41e20802fd8f9eb19c0218f1e2000e2751592a.zip
AstGen: emit `as` instructions for branching expressions
There is a mechanism to avoid redundant `as` ZIR instructions which is to pass `ResultLoc.coerced_ty` instead of `ResultLoc.ty` when it is known by AstGen that Sema will do the coercion. This commit downgrades `coerced_ty` to `ty` when a result location passes through an expression that branches, such as `if`, `switch`, `while`, and `for`, causing the `as` ZIR instruction to be emitted. This ensures that the type of a result location will be applied to, e.g. a `comptime_int` on either side of a branch on a runtime condition.
Diffstat (limited to 'src/AstGen.zig')
-rw-r--r--src/AstGen.zig25
1 files changed, 17 insertions, 8 deletions
diff --git a/src/AstGen.zig b/src/AstGen.zig
index 7c855fb62a..09d9b02a0e 100644
--- a/src/AstGen.zig
+++ b/src/AstGen.zig
@@ -281,6 +281,15 @@ pub const ResultLoc = union(enum) {
},
}
}
+
+ /// Turns a `coerced_ty` back into a `ty`. Should be called at branch points
+ /// such as if and switch expressions.
+ fn br(rl: ResultLoc) ResultLoc {
+ return switch (rl) {
+ .coerced_ty => |ty| .{ .ty = ty },
+ else => rl,
+ };
+ }
};
pub const align_rl: ResultLoc = .{ .ty = .u16_type };
@@ -748,15 +757,15 @@ fn expr(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: Ast.Node.Index) InnerEr
.field_access => return fieldAccess(gz, scope, rl, node),
.float_literal => return floatLiteral(gz, rl, node),
- .if_simple => return ifExpr(gz, scope, rl, node, tree.ifSimple(node)),
- .@"if" => return ifExpr(gz, scope, rl, node, tree.ifFull(node)),
+ .if_simple => return ifExpr(gz, scope, rl.br(), node, tree.ifSimple(node)),
+ .@"if" => return ifExpr(gz, scope, rl.br(), node, tree.ifFull(node)),
- .while_simple => return whileExpr(gz, scope, rl, node, tree.whileSimple(node)),
- .while_cont => return whileExpr(gz, scope, rl, node, tree.whileCont(node)),
- .@"while" => return whileExpr(gz, scope, rl, node, tree.whileFull(node)),
+ .while_simple => return whileExpr(gz, scope, rl.br(), node, tree.whileSimple(node)),
+ .while_cont => return whileExpr(gz, scope, rl.br(), node, tree.whileCont(node)),
+ .@"while" => return whileExpr(gz, scope, rl.br(), node, tree.whileFull(node)),
- .for_simple => return forExpr(gz, scope, rl, node, tree.forSimple(node)),
- .@"for" => return forExpr(gz, scope, rl, node, tree.forFull(node)),
+ .for_simple => return forExpr(gz, scope, rl.br(), node, tree.forSimple(node)),
+ .@"for" => return forExpr(gz, scope, rl.br(), node, tree.forFull(node)),
.slice_open => {
const lhs = try expr(gz, scope, .ref, node_datas[node].lhs);
@@ -943,7 +952,7 @@ fn expr(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: Ast.Node.Index) InnerEr
.error_set_decl => return errorSetDecl(gz, rl, node),
.array_access => return arrayAccess(gz, scope, rl, node),
.@"comptime" => return comptimeExprAst(gz, scope, rl, node),
- .@"switch", .switch_comma => return switchExpr(gz, scope, rl, node),
+ .@"switch", .switch_comma => return switchExpr(gz, scope, rl.br(), node),
.@"nosuspend" => return nosuspendExpr(gz, scope, rl, node),
.@"suspend" => return suspendExpr(gz, scope, node),