aboutsummaryrefslogtreecommitdiff
path: root/src/AstGen.zig
diff options
context:
space:
mode:
authorVeikka Tuominen <git@vexu.eu>2022-04-15 20:43:07 +0300
committerVeikka Tuominen <git@vexu.eu>2022-04-15 22:33:07 +0300
commit1c4c826a505b3f4863a0125f7915273ad2e7c1c0 (patch)
treed678ced032ae0205a2b4fca08e372dde5b5ee6a3 /src/AstGen.zig
parent7be62f695ffb468e19241a564d544d6a0adab829 (diff)
downloadzig-1c4c826a505b3f4863a0125f7915273ad2e7c1c0.tar.gz
zig-1c4c826a505b3f4863a0125f7915273ad2e7c1c0.zip
AstGen: fix defer generation in `breakExpr`
Diffstat (limited to 'src/AstGen.zig')
-rw-r--r--src/AstGen.zig27
1 files changed, 13 insertions, 14 deletions
diff --git a/src/AstGen.zig b/src/AstGen.zig
index a5351f8769..34b29b28fb 100644
--- a/src/AstGen.zig
+++ b/src/AstGen.zig
@@ -1807,6 +1807,8 @@ fn breakExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index) Inn
.@"break";
if (rhs == 0) {
+ try genDefers(parent_gz, scope, parent_scope, .normal_only);
+
_ = try parent_gz.addBreak(break_tag, block_inst, .void_value);
return Zir.Inst.Ref.unreachable_value;
}
@@ -1819,12 +1821,15 @@ fn breakExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index) Inn
const prev_rvalue_noresult = parent_gz.rvalue_noresult;
parent_gz.rvalue_noresult = .none;
const operand = try reachableExpr(parent_gz, parent_scope, block_gz.break_result_loc, rhs, node);
+ const search_index = @intCast(Zir.Inst.Index, astgen.instructions.len);
parent_gz.rvalue_noresult = prev_rvalue_noresult;
+ try genDefers(parent_gz, scope, parent_scope, .normal_only);
+
switch (block_gz.break_result_loc) {
.block_ptr => {
const br = try parent_gz.addBreak(break_tag, block_inst, operand);
- try block_gz.labeled_breaks.append(astgen.gpa, br);
+ try block_gz.labeled_breaks.append(astgen.gpa, .{ .br = br, .search = search_index });
},
.ptr => {
// In this case we don't have any mechanism to intercept it;
@@ -1843,13 +1848,7 @@ fn breakExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index) Inn
.local_val => scope = scope.cast(Scope.LocalVal).?.parent,
.local_ptr => scope = scope.cast(Scope.LocalPtr).?.parent,
.namespace => break,
- .defer_normal => {
- const defer_scope = scope.cast(Scope.Defer).?;
- scope = defer_scope.parent;
- const expr_node = node_datas[defer_scope.defer_node].rhs;
- try unusedResultDeferExpr(parent_gz, defer_scope, defer_scope.parent, expr_node);
- },
- .defer_error => scope = scope.cast(Scope.Defer).?.parent,
+ .defer_normal, .defer_error => scope = scope.cast(Scope.Defer).?.parent,
.top => unreachable,
}
}
@@ -2030,7 +2029,7 @@ fn labeledBlockExpr(
// The code took advantage of the result location as a pointer.
// Turn the break instruction operands into void.
for (block_scope.labeled_breaks.items) |br| {
- zir_datas[br].@"break".operand = .void_value;
+ zir_datas[br.br].@"break".operand = .void_value;
}
try block_scope.setBlockBody(block_inst);
@@ -2047,17 +2046,17 @@ fn labeledBlockExpr(
for (block_scope.labeled_breaks.items) |br| {
// We expect the `store_to_block_ptr` to be created between 1-3 instructions
// prior to the break.
- var search_index = br -| 3;
- while (search_index < br) : (search_index += 1) {
+ var search_index = br.search -| 3;
+ while (search_index < br.search) : (search_index += 1) {
if (zir_tags[search_index] == .store_to_block_ptr and
zir_datas[search_index].bin.lhs == block_scope.rl_ptr)
{
zir_tags[search_index] = .as;
zir_datas[search_index].bin = .{
.lhs = block_scope.rl_ty_inst,
- .rhs = zir_datas[br].@"break".operand,
+ .rhs = zir_datas[br.br].@"break".operand,
};
- zir_datas[br].@"break".operand = indexToRef(search_index);
+ zir_datas[br.br].@"break".operand = indexToRef(search_index);
break;
}
} else unreachable;
@@ -9719,7 +9718,7 @@ const GenZir = struct {
break_count: usize = 0,
/// Tracks `break :foo bar` instructions so they can possibly be elided later if
/// the labeled block ends up not needing a result location pointer.
- labeled_breaks: ArrayListUnmanaged(Zir.Inst.Index) = .{},
+ labeled_breaks: ArrayListUnmanaged(struct { br: Zir.Inst.Index, search: Zir.Inst.Index }) = .{},
suspend_node: Ast.Node.Index = 0,
nosuspend_node: Ast.Node.Index = 0,