| ... | ... | @@ -5287,33 +5287,51 @@ fn resolveBlockBody( |
| 5287 | 5287 | return sema.resolveAnalyzedBlock(parent_block, src, child_block, merges, need_debug_scope); |
| 5288 | 5288 | } else |err| switch (err) { |
| 5289 | 5289 | error.ComptimeBreak => { |
| 5290 | const break_inst = sema.comptime_break_inst; |
| 5291 | const break_data = sema.code.instructions.items(.data)[@intFromEnum(break_inst)].@"break"; |
| 5292 | const extra = sema.code.extraData(Zir.Inst.Break, break_data.payload_index).data; |
| 5293 | const breaks_to_body = extra.block_inst == body_inst; |
| 5294 | |
| 5290 | 5295 | // Comptime control flow is happening, however child_block may still contain |
| 5291 | 5296 | // runtime instructions which need to be copied to the parent block. |
| 5292 | 5297 | if (need_debug_scope and child_block.instructions.items.len > 0) { |
| 5293 | | // We need a runtime block for scoping reasons. |
| 5294 | | _ = try child_block.addBr(merges.block_inst, .void_value); |
| 5298 | // We need a runtime block for scoping reasons. The break |
| 5299 | // operand may have been produced by a runtime instruction |
| 5300 | // inside `child_blocks`. |
| 5301 | const operand = sema.resolveInst(break_data.operand); |
| 5302 | const operand_ty = sema.typeOf(operand); |
| 5303 | _ = try child_block.addBr(merges.block_inst, operand); |
| 5295 | 5304 | try parent_block.instructions.append(sema.gpa, merges.block_inst); |
| 5296 | 5305 | try sema.air_extra.ensureUnusedCapacity(sema.gpa, @typeInfo(Air.Block).@"struct".field_names.len + |
| 5297 | 5306 | child_block.instructions.items.len); |
| 5298 | 5307 | sema.air_instructions.items(.data)[@intFromEnum(merges.block_inst)] = .{ .ty_pl = .{ |
| 5299 | | .ty = .void_type, |
| 5308 | .ty = Air.internedToRef(operand_ty.toIntern()), |
| 5300 | 5309 | .payload = sema.addExtraAssumeCapacity(Air.Block{ |
| 5301 | 5310 | .body_len = @intCast(child_block.instructions.items.len), |
| 5302 | 5311 | }), |
| 5303 | 5312 | } }; |
| 5304 | 5313 | sema.air_extra.appendSliceAssumeCapacity(@ptrCast(child_block.instructions.items)); |
| 5314 | |
| 5315 | // The block result now holds the operand value, so we remap |
| 5316 | // the operand such that an enclosing scope which resolves |
| 5317 | // it picks up the block result rather than the internal |
| 5318 | // block instruction. |
| 5319 | if (break_data.operand.toIndex()) |operand_zir| { |
| 5320 | sema.inst_map.putAssumeCapacity(operand_zir, merges.block_inst.toRef()); |
| 5321 | } |
| 5322 | if (breaks_to_body) { |
| 5323 | return merges.block_inst.toRef(); |
| 5324 | } else { |
| 5325 | return error.ComptimeBreak; |
| 5326 | } |
| 5305 | 5327 | } else { |
| 5306 | 5328 | // We can copy instructions directly to the parent block. |
| 5307 | 5329 | try parent_block.instructions.appendSlice(sema.gpa, child_block.instructions.items); |
| 5308 | | } |
| 5309 | | |
| 5310 | | const break_inst = sema.comptime_break_inst; |
| 5311 | | const break_data = sema.code.instructions.items(.data)[@intFromEnum(break_inst)].@"break"; |
| 5312 | | const extra = sema.code.extraData(Zir.Inst.Break, break_data.payload_index).data; |
| 5313 | | if (extra.block_inst == body_inst) { |
| 5314 | | return sema.resolveInst(break_data.operand); |
| 5315 | | } else { |
| 5316 | | return error.ComptimeBreak; |
| 5330 | if (breaks_to_body) { |
| 5331 | return sema.resolveInst(break_data.operand); |
| 5332 | } else { |
| 5333 | return error.ComptimeBreak; |
| 5334 | } |
| 5317 | 5335 | } |
| 5318 | 5336 | }, |
| 5319 | 5337 | else => |e| return e, |