aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/AstGen.zig42
1 files changed, 34 insertions, 8 deletions
diff --git a/src/AstGen.zig b/src/AstGen.zig
index 59878f940c..228937fffa 100644
--- a/src/AstGen.zig
+++ b/src/AstGen.zig
@@ -5118,8 +5118,10 @@ fn setCondBrPayloadElideBlockStorePtr(
const astgen = then_scope.astgen;
const then_body = then_scope.instructionsSliceUpto(else_scope);
const else_body = else_scope.instructionsSlice();
- const then_body_len = @intCast(u32, then_body.len + @boolToInt(then_break != 0));
- const else_body_len = @intCast(u32, else_body.len + @boolToInt(else_break != 0));
+ const has_then_break = then_break != 0;
+ const has_else_break = else_break != 0;
+ const then_body_len = @intCast(u32, then_body.len + @boolToInt(has_then_break));
+ const else_body_len = @intCast(u32, else_body.len + @boolToInt(has_else_break));
try astgen.extra.ensureUnusedCapacity(astgen.gpa, @typeInfo(Zir.Inst.CondBr).Struct.fields.len +
then_body_len + else_body_len);
@@ -5135,26 +5137,49 @@ fn setCondBrPayloadElideBlockStorePtr(
const then_body_len_index = condbr_pl + 1;
const else_body_len_index = condbr_pl + 2;
+ // The break instructions need to have their operands coerced if the
+ // switch's result location is a `ty`. In this case we overwrite the
+ // `store_to_block_ptr` instruction with an `as` instruction and repurpose
+ // it as the break operand.
for (then_body) |src_inst| {
- if (zir_tags[src_inst] == .store_to_block_ptr) {
- if (zir_datas[src_inst].bin.lhs == block_ptr) {
+ if (zir_tags[src_inst] == .store_to_block_ptr and
+ zir_datas[src_inst].bin.lhs == block_ptr)
+ {
+ if (then_scope.rl_ty_inst != .none and has_then_break) {
+ zir_tags[src_inst] = .as;
+ zir_datas[src_inst].bin = .{
+ .lhs = then_scope.rl_ty_inst,
+ .rhs = zir_datas[then_break].@"break".operand,
+ };
+ zir_datas[then_break].@"break".operand = indexToRef(src_inst);
+ } else {
astgen.extra.items[then_body_len_index] -= 1;
continue;
}
}
astgen.extra.appendAssumeCapacity(src_inst);
}
- if (then_break != 0) astgen.extra.appendAssumeCapacity(then_break);
+ if (has_then_break) astgen.extra.appendAssumeCapacity(then_break);
+
for (else_body) |src_inst| {
- if (zir_tags[src_inst] == .store_to_block_ptr) {
- if (zir_datas[src_inst].bin.lhs == block_ptr) {
+ if (zir_tags[src_inst] == .store_to_block_ptr and
+ zir_datas[src_inst].bin.lhs == block_ptr)
+ {
+ if (else_scope.rl_ty_inst != .none and has_else_break) {
+ zir_tags[src_inst] = .as;
+ zir_datas[src_inst].bin = .{
+ .lhs = else_scope.rl_ty_inst,
+ .rhs = zir_datas[else_break].@"break".operand,
+ };
+ zir_datas[else_break].@"break".operand = indexToRef(src_inst);
+ } else {
astgen.extra.items[else_body_len_index] -= 1;
continue;
}
}
astgen.extra.appendAssumeCapacity(src_inst);
}
- if (else_break != 0) astgen.extra.appendAssumeCapacity(else_break);
+ if (has_else_break) astgen.extra.appendAssumeCapacity(else_break);
}
fn whileExpr(
@@ -9460,6 +9485,7 @@ const GenZir = struct {
.decl_node_index = gz.decl_node_index,
.decl_line = gz.decl_line,
.parent = scope,
+ .rl_ty_inst = gz.rl_ty_inst,
.astgen = gz.astgen,
.suspend_node = gz.suspend_node,
.nosuspend_node = gz.nosuspend_node,