| ... | @@ -1709,6 +1709,24 @@ static IrInstruction *ir_build_alignof(IrBuilder *irb, Scope *scope, AstNode *so | ... | @@ -1709,6 +1709,24 @@ static IrInstruction *ir_build_alignof(IrBuilder *irb, Scope *scope, AstNode *so |
| 1709 | return &instruction->base; | 1709 | return &instruction->base; |
| 1710 | } | 1710 | } |
| 1711 | | 1711 | |
| | 1712 | static void ir_count_defers(IrBuilder *irb, Scope *inner_scope, Scope *outer_scope, size_t *results) { |
| | 1713 | results[ReturnKindUnconditional] = 0; |
| | 1714 | results[ReturnKindError] = 0; |
| | 1715 | results[ReturnKindMaybe] = 0; |
| | 1716 | |
| | 1717 | while (inner_scope != outer_scope) { |
| | 1718 | assert(inner_scope); |
| | 1719 | if (inner_scope->id == ScopeIdDefer) { |
| | 1720 | AstNode *defer_node = inner_scope->source_node; |
| | 1721 | assert(defer_node->type == NodeTypeDefer); |
| | 1722 | ReturnKind defer_kind = defer_node->data.defer.kind; |
| | 1723 | results[defer_kind] += 1; |
| | 1724 | |
| | 1725 | } |
| | 1726 | inner_scope = inner_scope->parent; |
| | 1727 | } |
| | 1728 | } |
| | 1729 | |
| 1712 | static void ir_gen_defers_for_block(IrBuilder *irb, Scope *inner_scope, Scope *outer_scope, | 1730 | static void ir_gen_defers_for_block(IrBuilder *irb, Scope *inner_scope, Scope *outer_scope, |
| 1713 | bool gen_error_defers, bool gen_maybe_defers) | 1731 | bool gen_error_defers, bool gen_maybe_defers) |
| 1714 | { | 1732 | { |
| ... | @@ -1762,8 +1780,22 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node, | ... | @@ -1762,8 +1780,22 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node, |
| 1762 | return_value = ir_build_const_void(irb, scope, node); | 1780 | return_value = ir_build_const_void(irb, scope, node); |
| 1763 | } | 1781 | } |
| 1764 | | 1782 | |
| 1765 | // TODO conditionally gen maybe defers and error defers | 1783 | size_t defer_counts[3]; |
| 1766 | ir_gen_defers_for_block(irb, scope, outer_scope, false, false); | 1784 | ir_count_defers(irb, scope, outer_scope, defer_counts); |
| | 1785 | if (defer_counts[ReturnKindError] > 0) { |
| | 1786 | // TODO in this situation we need to make a conditional |
| | 1787 | // branch on the return value. we potentially must make multiple conditional branches, |
| | 1788 | // if unconditional defers are interleaved with error defers. |
| | 1789 | zig_panic("TODO handle error defers"); |
| | 1790 | } else if (defer_counts[ReturnKindMaybe] > 0) { |
| | 1791 | // TODO in this situation we need to make a conditional |
| | 1792 | // branch on the maybe value. we potentially must make multiple conditional branches, |
| | 1793 | // if unconditional defers are interleaved with error defers. |
| | 1794 | zig_panic("TODO handle maybe defers"); |
| | 1795 | } else { |
| | 1796 | // generate unconditional defers |
| | 1797 | ir_gen_defers_for_block(irb, scope, outer_scope, false, false); |
| | 1798 | } |
| 1767 | return ir_build_return(irb, scope, node, return_value); | 1799 | return ir_build_return(irb, scope, node, return_value); |
| 1768 | } | 1800 | } |
| 1769 | case ReturnKindError: | 1801 | case ReturnKindError: |