| ... | ... | @@ -672,62 +672,62 @@ fn breakExpr( |
| 672 | 672 | rl: ResultLoc, |
| 673 | 673 | node: ast.Node.Index, |
| 674 | 674 | ) InnerError!zir.Inst.Ref { |
| 675 | | if (true) @panic("TODO update for zir-memory-layout"); |
| 676 | 675 | const tree = parent_scope.tree(); |
| 677 | 676 | const node_datas = tree.nodes.items(.data); |
| 678 | 677 | const main_tokens = tree.nodes.items(.main_token); |
| 679 | 678 | |
| 679 | const break_token = main_tokens[node]; |
| 680 | 680 | const break_label = node_datas[node].lhs; |
| 681 | 681 | const rhs = node_datas[node].rhs; |
| 682 | 682 | |
| 683 | const parent_gz = parent_scope.getGenZir(); |
| 684 | |
| 683 | 685 | // Look for the label in the scope. |
| 684 | 686 | var scope = parent_scope; |
| 685 | 687 | while (true) { |
| 686 | 688 | switch (scope.tag) { |
| 687 | 689 | .gen_zir => { |
| 688 | | const gen_zir = scope.cast(Scope.GenZir).?; |
| 690 | const block_gz = scope.getGenZir(); |
| 689 | 691 | |
| 690 | 692 | const block_inst = blk: { |
| 691 | 693 | if (break_label != 0) { |
| 692 | | if (gen_zir.label) |*label| { |
| 694 | if (block_gz.label) |*label| { |
| 693 | 695 | if (try tokenIdentEql(mod, parent_scope, label.token, break_label)) { |
| 694 | 696 | label.used = true; |
| 695 | 697 | break :blk label.block_inst; |
| 696 | 698 | } |
| 697 | 699 | } |
| 698 | | } else if (gen_zir.break_block) |inst| { |
| 699 | | break :blk inst; |
| 700 | } else if (block_gz.break_block != 0) { |
| 701 | break :blk block_gz.break_block; |
| 700 | 702 | } |
| 701 | | scope = gen_zir.parent; |
| 703 | scope = block_gz.parent; |
| 702 | 704 | continue; |
| 703 | 705 | }; |
| 704 | 706 | |
| 705 | 707 | if (rhs == 0) { |
| 706 | | const result = try addZirInstTag(mod, parent_scope, src, .break_void, .{ |
| 707 | | .block = block_inst, |
| 708 | | }); |
| 709 | | return rvalue(mod, parent_scope, rl, result); |
| 708 | const result = try parent_gz.addBreakVoid(block_gz, block_inst, node); |
| 709 | return rvalue(mod, parent_scope, rl, result, node); |
| 710 | 710 | } |
| 711 | | gen_zir.break_count += 1; |
| 712 | | const prev_rvalue_rl_count = gen_zir.rvalue_rl_count; |
| 713 | | const operand = try expr(mod, parent_scope, gen_zir.break_result_loc, rhs); |
| 714 | | const have_store_to_block = gen_zir.rvalue_rl_count != prev_rvalue_rl_count; |
| 715 | | const br = try addZirInstTag(mod, parent_scope, src, .@"break", .{ |
| 716 | | .block = block_inst, |
| 717 | | .operand = operand, |
| 718 | | }); |
| 719 | | if (gen_zir.break_result_loc == .block_ptr) { |
| 720 | | try gen_zir.labeled_breaks.append(mod.gpa, br.castTag(.@"break").?); |
| 711 | block_gz.break_count += 1; |
| 712 | const prev_rvalue_rl_count = block_gz.rvalue_rl_count; |
| 713 | const operand = try expr(mod, parent_scope, block_gz.break_result_loc, rhs); |
| 714 | const have_store_to_block = block_gz.rvalue_rl_count != prev_rvalue_rl_count; |
| 715 | |
| 716 | const br = try parent_gz.addBreak(block_inst, operand); |
| 717 | |
| 718 | if (block_gz.break_result_loc == .block_ptr) { |
| 719 | try block_gz.labeled_breaks.append(mod.gpa, br); |
| 721 | 720 | |
| 722 | 721 | if (have_store_to_block) { |
| 723 | | const inst_list = parent_scope.getGenZir().instructions.items; |
| 724 | | const last_inst = inst_list[inst_list.len - 2]; |
| 725 | | const store_inst = last_inst.castTag(.store_to_block_ptr).?; |
| 726 | | assert(store_inst.positionals.lhs == gen_zir.rl_ptr.?); |
| 727 | | try gen_zir.labeled_store_to_block_ptr_list.append(mod.gpa, store_inst); |
| 722 | const zir_tags = parent_gz.zir_code.instructions.items(.tag); |
| 723 | const zir_datas = parent_gz.zir_code.instructions.items(.data); |
| 724 | const last_inst = zir_tags.len - 2; |
| 725 | assert(zir_tags[last_inst] == .store_to_block_ptr); |
| 726 | assert(zir_datas[last_inst].bin.lhs == block_gz.rl_ptr); |
| 727 | try block_gz.labeled_store_to_block_ptr_list.append(mod.gpa, @intCast(zir.Inst.Ref, last_inst)); |
| 728 | 728 | } |
| 729 | 729 | } |
| 730 | | return rvalue(mod, parent_scope, rl, br); |
| 730 | return rvalue(mod, parent_scope, rl, br, node); |
| 731 | 731 | }, |
| 732 | 732 | .local_val => scope = scope.cast(Scope.LocalVal).?.parent, |
| 733 | 733 | .local_ptr => scope = scope.cast(Scope.LocalPtr).?.parent, |
| ... | ... | @@ -735,7 +735,7 @@ fn breakExpr( |
| 735 | 735 | const label_name = try mod.identifierTokenString(parent_scope, break_label); |
| 736 | 736 | return mod.failTok(parent_scope, break_label, "label not found: '{s}'", .{label_name}); |
| 737 | 737 | } else { |
| 738 | | return mod.failTok(parent_scope, src, "break expression outside loop", .{}); |
| 738 | return mod.failTok(parent_scope, break_token, "break expression outside loop", .{}); |
| 739 | 739 | }, |
| 740 | 740 | } |
| 741 | 741 | } |
| ... | ... | @@ -1769,23 +1769,11 @@ fn finishThenElseBlock( |
| 1769 | 1769 | switch (strat.tag) { |
| 1770 | 1770 | .break_void => { |
| 1771 | 1771 | if (!wzc.refIsNoReturn(then_result)) { |
| 1772 | | _ = try then_scope.add(.{ |
| 1773 | | .tag = .break_void_node, |
| 1774 | | .data = .{ .break_void_node = .{ |
| 1775 | | .src_node = wzc.decl.nodeIndexToRelative(then_src), |
| 1776 | | .block_inst = then_break_block, |
| 1777 | | } }, |
| 1778 | | }); |
| 1772 | _ = try then_scope.addBreakVoid(block_scope, then_break_block, then_src); |
| 1779 | 1773 | } |
| 1780 | 1774 | const elide_else = if (else_result != .none) wzc.refIsNoReturn(else_result) else false; |
| 1781 | 1775 | if (!elide_else) { |
| 1782 | | _ = try else_scope.add(.{ |
| 1783 | | .tag = .break_void_node, |
| 1784 | | .data = .{ .break_void_node = .{ |
| 1785 | | .src_node = wzc.decl.nodeIndexToRelative(else_src), |
| 1786 | | .block_inst = main_block, |
| 1787 | | } }, |
| 1788 | | }); |
| 1776 | _ = try else_scope.addBreakVoid(block_scope, main_block, else_src); |
| 1789 | 1777 | } |
| 1790 | 1778 | assert(!strat.elide_store_to_block_ptr_instructions); |
| 1791 | 1779 | try setCondBrPayload(condbr, cond, then_scope, else_scope); |
| ... | ... | @@ -1793,32 +1781,14 @@ fn finishThenElseBlock( |
| 1793 | 1781 | }, |
| 1794 | 1782 | .break_operand => { |
| 1795 | 1783 | if (!wzc.refIsNoReturn(then_result)) { |
| 1796 | | _ = try then_scope.add(.{ |
| 1797 | | .tag = .@"break", |
| 1798 | | .data = .{ .@"break" = .{ |
| 1799 | | .block_inst = then_break_block, |
| 1800 | | .operand = then_result, |
| 1801 | | } }, |
| 1802 | | }); |
| 1784 | _ = try then_scope.addBreak(then_break_block, then_result); |
| 1803 | 1785 | } |
| 1804 | 1786 | if (else_result != .none) { |
| 1805 | 1787 | if (!wzc.refIsNoReturn(else_result)) { |
| 1806 | | _ = try else_scope.add(.{ |
| 1807 | | .tag = .@"break", |
| 1808 | | .data = .{ .@"break" = .{ |
| 1809 | | .block_inst = main_block, |
| 1810 | | .operand = else_result, |
| 1811 | | } }, |
| 1812 | | }); |
| 1788 | _ = try else_scope.addBreak(main_block, else_result); |
| 1813 | 1789 | } |
| 1814 | 1790 | } else { |
| 1815 | | _ = try else_scope.add(.{ |
| 1816 | | .tag = .break_void_node, |
| 1817 | | .data = .{ .break_void_node = .{ |
| 1818 | | .src_node = wzc.decl.nodeIndexToRelative(else_src), |
| 1819 | | .block_inst = main_block, |
| 1820 | | } }, |
| 1821 | | }); |
| 1791 | _ = try else_scope.addBreakVoid(block_scope, main_block, else_src); |
| 1822 | 1792 | } |
| 1823 | 1793 | if (strat.elide_store_to_block_ptr_instructions) { |
| 1824 | 1794 | try setCondBrPayloadElideBlockStorePtr(condbr, cond, then_scope, else_scope); |