aboutsummaryrefslogtreecommitdiff
path: root/src/AstGen.zig
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2021-07-07 19:50:56 -0700
committerAndrew Kelley <andrew@ziglang.org>2021-07-07 19:50:56 -0700
commit5c8bd443d92c6306f60857720103ae46ca7b8b3e (patch)
treefbac6bd8a6d337ef035b07ef766b3718f91e0781 /src/AstGen.zig
parent5816997ae79c6025d5f85aab0c9ab456fecadec9 (diff)
downloadzig-5c8bd443d92c6306f60857720103ae46ca7b8b3e.tar.gz
zig-5c8bd443d92c6306f60857720103ae46ca7b8b3e.zip
stage2: fix if expressions on error unions
AstGen had the then-else logic backwards for if expressions on error unions. This commit fixes it. Turns out AstGen only really needs `is_non_null` and `is_non_err`, and does not need the `is_null` or `is_err` variants. So I removed the `is_null{,_ptr}` and `is_err{,_ptr}` ZIR instructions (-4) and added `is_non_err`, `is_non_err_ptr` ZIR instructions (+2) for a total of (-2) ZIR instructions, giving us a tiny bit more headroom within the 256 tag limit. This required swapping the order of then/else blocks in a handful of cases, but ultimately means the ZIR will be in the same as source order, which is convenient when debugging. AIR code on the other hand, gains the `is_non_err` and `is_non_err_ptr` instructions. Sema: fix logic in zirErrUnionCode and zirErrUnionCodePtr returning the wrong result type.
Diffstat (limited to 'src/AstGen.zig')
-rw-r--r--src/AstGen.zig92
1 files changed, 46 insertions, 46 deletions
diff --git a/src/AstGen.zig b/src/AstGen.zig
index f7fea3a99c..a816628f66 100644
--- a/src/AstGen.zig
+++ b/src/AstGen.zig
@@ -786,7 +786,7 @@ fn expr(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) InnerEr
rl,
node,
node_datas[node].lhs,
- .is_err_ptr,
+ .is_non_err_ptr,
.err_union_payload_unsafe_ptr,
.err_union_code_ptr,
node_datas[node].rhs,
@@ -798,7 +798,7 @@ fn expr(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) InnerEr
rl,
node,
node_datas[node].lhs,
- .is_err,
+ .is_non_err,
.err_union_payload_unsafe,
.err_union_code,
node_datas[node].rhs,
@@ -813,7 +813,7 @@ fn expr(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) InnerEr
rl,
node,
node_datas[node].lhs,
- .is_null_ptr,
+ .is_non_null_ptr,
.optional_payload_unsafe_ptr,
undefined,
node_datas[node].rhs,
@@ -825,7 +825,7 @@ fn expr(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) InnerEr
rl,
node,
node_datas[node].lhs,
- .is_null,
+ .is_non_null,
.optional_payload_unsafe,
undefined,
node_datas[node].rhs,
@@ -1948,11 +1948,9 @@ fn unusedResultExpr(gz: *GenZir, scope: *Scope, statement: ast.Node.Index) Inner
.float128,
.int_type,
.is_non_null,
- .is_null,
.is_non_null_ptr,
- .is_null_ptr,
- .is_err,
- .is_err_ptr,
+ .is_non_err,
+ .is_non_err_ptr,
.mod_rem,
.mul,
.mulwrap,
@@ -4621,8 +4619,8 @@ fn tryExpr(
};
const err_ops = switch (rl) {
// zig fmt: off
- .ref => [3]Zir.Inst.Tag{ .is_err_ptr, .err_union_code_ptr, .err_union_payload_unsafe_ptr },
- else => [3]Zir.Inst.Tag{ .is_err, .err_union_code, .err_union_payload_unsafe },
+ .ref => [3]Zir.Inst.Tag{ .is_non_err_ptr, .err_union_code_ptr, .err_union_payload_unsafe_ptr },
+ else => [3]Zir.Inst.Tag{ .is_non_err, .err_union_code, .err_union_payload_unsafe },
// zig fmt: on
};
// This could be a pointer or value depending on the `operand_rl` parameter.
@@ -4640,21 +4638,21 @@ fn tryExpr(
var then_scope = parent_gz.makeSubBlock(scope);
defer then_scope.instructions.deinit(astgen.gpa);
- const err_code = try then_scope.addUnNode(err_ops[1], operand, node);
- try genDefers(&then_scope, &fn_block.base, scope, .{ .both = err_code });
- const then_result = try then_scope.addUnNode(.ret_node, err_code, node);
-
- var else_scope = parent_gz.makeSubBlock(scope);
- defer else_scope.instructions.deinit(astgen.gpa);
-
block_scope.break_count += 1;
// This could be a pointer or value depending on `err_ops[2]`.
- const unwrapped_payload = try else_scope.addUnNode(err_ops[2], operand, node);
- const else_result = switch (rl) {
+ const unwrapped_payload = try then_scope.addUnNode(err_ops[2], operand, node);
+ const then_result = switch (rl) {
.ref => unwrapped_payload,
- else => try rvalue(&else_scope, block_scope.break_result_loc, unwrapped_payload, node),
+ else => try rvalue(&then_scope, block_scope.break_result_loc, unwrapped_payload, node),
};
+ var else_scope = parent_gz.makeSubBlock(scope);
+ defer else_scope.instructions.deinit(astgen.gpa);
+
+ const err_code = try else_scope.addUnNode(err_ops[1], operand, node);
+ try genDefers(&else_scope, &fn_block.base, scope, .{ .both = err_code });
+ const else_result = try else_scope.addUnNode(.ret_node, err_code, node);
+
return finishThenElseBlock(
parent_gz,
rl,
@@ -4711,18 +4709,28 @@ fn orelseCatchExpr(
var then_scope = parent_gz.makeSubBlock(scope);
defer then_scope.instructions.deinit(astgen.gpa);
+ // This could be a pointer or value depending on `unwrap_op`.
+ const unwrapped_payload = try then_scope.addUnNode(unwrap_op, operand, node);
+ const then_result = switch (rl) {
+ .ref => unwrapped_payload,
+ else => try rvalue(&then_scope, block_scope.break_result_loc, unwrapped_payload, node),
+ };
+
+ var else_scope = parent_gz.makeSubBlock(scope);
+ defer else_scope.instructions.deinit(astgen.gpa);
+
var err_val_scope: Scope.LocalVal = undefined;
- const then_sub_scope = blk: {
- const payload = payload_token orelse break :blk &then_scope.base;
+ const else_sub_scope = blk: {
+ const payload = payload_token orelse break :blk &else_scope.base;
if (mem.eql(u8, tree.tokenSlice(payload), "_")) {
return astgen.failTok(payload, "discard of error capture; omit it instead", .{});
}
const err_name = try astgen.identAsString(payload);
err_val_scope = .{
- .parent = &then_scope.base,
- .gen_zir = &then_scope,
+ .parent = &else_scope.base,
+ .gen_zir = &else_scope,
.name = err_name,
- .inst = try then_scope.addUnNode(unwrap_code_op, operand, node),
+ .inst = try else_scope.addUnNode(unwrap_code_op, operand, node),
.token_src = payload,
.id_cat = .@"capture",
};
@@ -4730,23 +4738,13 @@ fn orelseCatchExpr(
};
block_scope.break_count += 1;
- const then_result = try expr(&then_scope, then_sub_scope, block_scope.break_result_loc, rhs);
- try checkUsed(parent_gz, &then_scope.base, then_sub_scope);
+ const else_result = try expr(&else_scope, else_sub_scope, block_scope.break_result_loc, rhs);
+ try checkUsed(parent_gz, &else_scope.base, else_sub_scope);
// We hold off on the break instructions as well as copying the then/else
// instructions into place until we know whether to keep store_to_block_ptr
// instructions or not.
- var else_scope = parent_gz.makeSubBlock(scope);
- defer else_scope.instructions.deinit(astgen.gpa);
-
- // This could be a pointer or value depending on `unwrap_op`.
- const unwrapped_payload = try else_scope.addUnNode(unwrap_op, operand, node);
- const else_result = switch (rl) {
- .ref => unwrapped_payload,
- else => try rvalue(&else_scope, block_scope.break_result_loc, unwrapped_payload, node),
- };
-
return finishThenElseBlock(
parent_gz,
rl,
@@ -4964,7 +4962,7 @@ fn ifExpr(
if (if_full.error_token) |_| {
const cond_rl: ResultLoc = if (payload_is_ref) .ref else .none;
const err_union = try expr(&block_scope, &block_scope.base, cond_rl, if_full.ast.cond_expr);
- const tag: Zir.Inst.Tag = if (payload_is_ref) .is_err_ptr else .is_err;
+ const tag: Zir.Inst.Tag = if (payload_is_ref) .is_non_err_ptr else .is_non_err;
break :c .{
.inst = err_union,
.bool_bit = try block_scope.addUnNode(tag, err_union, node),
@@ -5221,7 +5219,7 @@ fn whileExpr(
if (while_full.error_token) |_| {
const cond_rl: ResultLoc = if (payload_is_ref) .ref else .none;
const err_union = try expr(&continue_scope, &continue_scope.base, cond_rl, while_full.ast.cond_expr);
- const tag: Zir.Inst.Tag = if (payload_is_ref) .is_err_ptr else .is_err;
+ const tag: Zir.Inst.Tag = if (payload_is_ref) .is_non_err_ptr else .is_non_err;
break :c .{
.inst = err_union,
.bool_bit = try continue_scope.addUnNode(tag, err_union, node),
@@ -6229,23 +6227,25 @@ fn ret(gz: *GenZir, scope: *Scope, node: ast.Node.Index) InnerError!Zir.Inst.Ref
}
// Emit conditional branch for generating errdefers.
- const is_err = try gz.addUnNode(.is_err, operand, node);
+ const is_non_err = try gz.addUnNode(.is_non_err, operand, node);
const condbr = try gz.addCondBr(.condbr, node);
var then_scope = gz.makeSubBlock(scope);
defer then_scope.instructions.deinit(astgen.gpa);
- const which_ones: DefersToEmit = if (!defer_counts.need_err_code) .both_sans_err else .{
- .both = try then_scope.addUnNode(.err_union_code, operand, node),
- };
- try genDefers(&then_scope, defer_outer, scope, which_ones);
+
+ try genDefers(&then_scope, defer_outer, scope, .normal_only);
_ = try then_scope.addUnNode(.ret_node, operand, node);
var else_scope = gz.makeSubBlock(scope);
defer else_scope.instructions.deinit(astgen.gpa);
- try genDefers(&else_scope, defer_outer, scope, .normal_only);
+
+ const which_ones: DefersToEmit = if (!defer_counts.need_err_code) .both_sans_err else .{
+ .both = try else_scope.addUnNode(.err_union_code, operand, node),
+ };
+ try genDefers(&else_scope, defer_outer, scope, which_ones);
_ = try else_scope.addUnNode(.ret_node, operand, node);
- try setCondBrPayload(condbr, is_err, &then_scope, &else_scope);
+ try setCondBrPayload(condbr, is_non_err, &then_scope, &else_scope);
return Zir.Inst.Ref.unreachable_value;
},