| ... | ... | @@ -3759,7 +3759,17 @@ static ZigVar *ir_create_var(IrBuilder *irb, AstNode *node, Scope *scope, Buf *n |
| 3759 | 3759 | return var; |
| 3760 | 3760 | } |
| 3761 | 3761 | |
| 3762 | | static IrInstruction *ir_gen_block(IrBuilder *irb, Scope *parent_scope, AstNode *block_node) { |
| 3762 | static ResultLocPeer *create_peer_result(ResultLocPeerParent *peer_parent) { |
| 3763 | ResultLocPeer *result = allocate<ResultLocPeer>(1); |
| 3764 | result->base.id = ResultLocIdPeer; |
| 3765 | result->base.source_instruction = peer_parent->base.source_instruction; |
| 3766 | result->parent = peer_parent; |
| 3767 | return result; |
| 3768 | } |
| 3769 | |
| 3770 | static IrInstruction *ir_gen_block(IrBuilder *irb, Scope *parent_scope, AstNode *block_node, LVal lval, |
| 3771 | ResultLoc *result_loc) |
| 3772 | { |
| 3763 | 3773 | assert(block_node->type == NodeTypeBlock); |
| 3764 | 3774 | |
| 3765 | 3775 | ZigList<IrInstruction *> incoming_values = {0}; |
| ... | ... | @@ -3777,15 +3787,24 @@ static IrInstruction *ir_gen_block(IrBuilder *irb, Scope *parent_scope, AstNode |
| 3777 | 3787 | |
| 3778 | 3788 | if (block_node->data.block.statements.length == 0) { |
| 3779 | 3789 | // {} |
| 3780 | | return ir_build_const_void(irb, child_scope, block_node); |
| 3790 | return ir_lval_wrap(irb, parent_scope, ir_build_const_void(irb, child_scope, block_node), lval, result_loc); |
| 3781 | 3791 | } |
| 3782 | 3792 | |
| 3783 | 3793 | if (block_node->data.block.name != nullptr) { |
| 3794 | scope_block->lval = lval; |
| 3784 | 3795 | scope_block->incoming_blocks = &incoming_blocks; |
| 3785 | 3796 | scope_block->incoming_values = &incoming_values; |
| 3786 | 3797 | scope_block->end_block = ir_create_basic_block(irb, parent_scope, "BlockEnd"); |
| 3787 | 3798 | scope_block->is_comptime = ir_build_const_bool(irb, parent_scope, block_node, |
| 3788 | 3799 | ir_should_inline(irb->exec, parent_scope)); |
| 3800 | |
| 3801 | scope_block->peer_parent = allocate<ResultLocPeerParent>(1); |
| 3802 | scope_block->peer_parent->base.id = ResultLocIdPeerParent; |
| 3803 | scope_block->peer_parent->base.source_instruction = scope_block->is_comptime; |
| 3804 | scope_block->peer_parent->end_bb = scope_block->end_block; |
| 3805 | scope_block->peer_parent->is_comptime = scope_block->is_comptime; |
| 3806 | scope_block->peer_parent->parent = result_loc; |
| 3807 | ir_build_reset_result(irb, parent_scope, block_node, &scope_block->peer_parent->base); |
| 3789 | 3808 | } |
| 3790 | 3809 | |
| 3791 | 3810 | bool is_continuation_unreachable = false; |
| ... | ... | @@ -3821,23 +3840,41 @@ static IrInstruction *ir_gen_block(IrBuilder *irb, Scope *parent_scope, AstNode |
| 3821 | 3840 | return noreturn_return_value; |
| 3822 | 3841 | } |
| 3823 | 3842 | |
| 3843 | if (scope_block->peer_parent != nullptr && scope_block->peer_parent->peers.length != 0) { |
| 3844 | scope_block->peer_parent->peers.last()->next_bb = scope_block->end_block; |
| 3845 | } |
| 3824 | 3846 | ir_set_cursor_at_end_and_append_block(irb, scope_block->end_block); |
| 3825 | | return ir_build_phi(irb, parent_scope, block_node, incoming_blocks.length, |
| 3826 | | incoming_blocks.items, incoming_values.items, nullptr); |
| 3847 | IrInstruction *phi = ir_build_phi(irb, parent_scope, block_node, incoming_blocks.length, |
| 3848 | incoming_blocks.items, incoming_values.items, scope_block->peer_parent); |
| 3849 | return ir_expr_wrap(irb, parent_scope, phi, result_loc); |
| 3827 | 3850 | } else { |
| 3828 | 3851 | incoming_blocks.append(irb->current_basic_block); |
| 3829 | | incoming_values.append(ir_mark_gen(ir_build_const_void(irb, parent_scope, block_node))); |
| 3852 | IrInstruction *else_expr_result = ir_mark_gen(ir_build_const_void(irb, parent_scope, block_node)); |
| 3853 | |
| 3854 | if (scope_block->peer_parent != nullptr) { |
| 3855 | ResultLocPeer *peer_result = create_peer_result(scope_block->peer_parent); |
| 3856 | scope_block->peer_parent->peers.append(peer_result); |
| 3857 | ir_build_end_expr(irb, parent_scope, block_node, else_expr_result, &peer_result->base); |
| 3858 | |
| 3859 | if (scope_block->peer_parent->peers.length != 0) { |
| 3860 | scope_block->peer_parent->peers.last()->next_bb = scope_block->end_block; |
| 3861 | } |
| 3862 | } |
| 3863 | |
| 3864 | incoming_values.append(else_expr_result); |
| 3830 | 3865 | } |
| 3831 | 3866 | |
| 3832 | 3867 | if (block_node->data.block.name != nullptr) { |
| 3833 | 3868 | ir_gen_defers_for_block(irb, child_scope, outer_block_scope, false); |
| 3834 | 3869 | ir_mark_gen(ir_build_br(irb, parent_scope, block_node, scope_block->end_block, scope_block->is_comptime)); |
| 3835 | 3870 | ir_set_cursor_at_end_and_append_block(irb, scope_block->end_block); |
| 3836 | | return ir_build_phi(irb, parent_scope, block_node, incoming_blocks.length, |
| 3837 | | incoming_blocks.items, incoming_values.items, nullptr); |
| 3871 | IrInstruction *phi = ir_build_phi(irb, parent_scope, block_node, incoming_blocks.length, |
| 3872 | incoming_blocks.items, incoming_values.items, scope_block->peer_parent); |
| 3873 | return ir_expr_wrap(irb, parent_scope, phi, result_loc); |
| 3838 | 3874 | } else { |
| 3839 | 3875 | ir_gen_defers_for_block(irb, child_scope, outer_block_scope, false); |
| 3840 | | return ir_mark_gen(ir_mark_gen(ir_build_const_void(irb, child_scope, block_node))); |
| 3876 | IrInstruction *void_inst = ir_mark_gen(ir_build_const_void(irb, child_scope, block_node)); |
| 3877 | return ir_lval_wrap(irb, parent_scope, void_inst, lval, result_loc); |
| 3841 | 3878 | } |
| 3842 | 3879 | } |
| 3843 | 3880 | |
| ... | ... | @@ -3964,14 +4001,6 @@ static IrInstruction *ir_gen_bool_and(IrBuilder *irb, Scope *scope, AstNode *nod |
| 3964 | 4001 | return ir_build_phi(irb, scope, node, 2, incoming_blocks, incoming_values, nullptr); |
| 3965 | 4002 | } |
| 3966 | 4003 | |
| 3967 | | static ResultLocPeer *create_peer_result(ResultLocPeerParent *peer_parent) { |
| 3968 | | ResultLocPeer *result = allocate<ResultLocPeer>(1); |
| 3969 | | result->base.id = ResultLocIdPeer; |
| 3970 | | result->base.source_instruction = peer_parent->base.source_instruction; |
| 3971 | | result->parent = peer_parent; |
| 3972 | | return result; |
| 3973 | | } |
| 3974 | | |
| 3975 | 4004 | static ResultLocPeerParent *ir_build_result_peers(IrBuilder *irb, IrInstruction *cond_br_inst, |
| 3976 | 4005 | IrBasicBlock *end_block, ResultLoc *parent, IrInstruction *is_comptime) |
| 3977 | 4006 | { |
| ... | ... | @@ -7216,7 +7245,11 @@ static IrInstruction *ir_gen_return_from_block(IrBuilder *irb, Scope *break_scop |
| 7216 | 7245 | |
| 7217 | 7246 | IrInstruction *result_value; |
| 7218 | 7247 | if (node->data.break_expr.expr) { |
| 7219 | | result_value = ir_gen_node(irb, node->data.break_expr.expr, break_scope); |
| 7248 | ResultLocPeer *peer_result = create_peer_result(block_scope->peer_parent); |
| 7249 | block_scope->peer_parent->peers.append(peer_result); |
| 7250 | |
| 7251 | result_value = ir_gen_node_extra(irb, node->data.break_expr.expr, break_scope, block_scope->lval, |
| 7252 | &peer_result->base); |
| 7220 | 7253 | if (result_value == irb->codegen->invalid_instruction) |
| 7221 | 7254 | return irb->codegen->invalid_instruction; |
| 7222 | 7255 | } else { |
| ... | ... | @@ -8193,7 +8226,7 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop |
| 8193 | 8226 | case NodeTypeTestDecl: |
| 8194 | 8227 | zig_unreachable(); |
| 8195 | 8228 | case NodeTypeBlock: |
| 8196 | | return ir_lval_wrap(irb, scope, ir_gen_block(irb, scope, node), lval, result_loc); |
| 8229 | return ir_gen_block(irb, scope, node, lval, result_loc); |
| 8197 | 8230 | case NodeTypeGroupedExpr: |
| 8198 | 8231 | return ir_gen_node_raw(irb, node->data.grouped_expr, scope, lval, result_loc); |
| 8199 | 8232 | case NodeTypeBinOpExpr: |
| ... | ... | @@ -15066,6 +15099,21 @@ static IrInstruction *ir_resolve_result_raw(IrAnalyze *ira, IrInstruction *suspe |
| 15066 | 15099 | ResultLocPeer *result_peer = reinterpret_cast<ResultLocPeer *>(result_loc); |
| 15067 | 15100 | ResultLocPeerParent *peer_parent = result_peer->parent; |
| 15068 | 15101 | |
| 15102 | if (peer_parent->peers.length == 1) { |
| 15103 | IrInstruction *parent_result_loc = ir_resolve_result(ira, suspend_source_instr, peer_parent->parent, |
| 15104 | value_type, value, false, non_null_comptime); |
| 15105 | result_peer->suspend_pos.basic_block_index = SIZE_MAX; |
| 15106 | result_peer->suspend_pos.instruction_index = SIZE_MAX; |
| 15107 | if (parent_result_loc == nullptr || type_is_invalid(parent_result_loc->value.type) || |
| 15108 | parent_result_loc->value.type->id == ZigTypeIdUnreachable) |
| 15109 | { |
| 15110 | return parent_result_loc; |
| 15111 | } |
| 15112 | result_loc->written = true; |
| 15113 | result_loc->resolved_loc = parent_result_loc; |
| 15114 | return result_loc->resolved_loc; |
| 15115 | } |
| 15116 | |
| 15069 | 15117 | bool is_comptime; |
| 15070 | 15118 | if (!ir_resolve_comptime(ira, peer_parent->is_comptime->child, &is_comptime)) |
| 15071 | 15119 | return ira->codegen->invalid_instruction; |
| ... | ... | @@ -16670,7 +16718,7 @@ static IrInstruction *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionPh |
| 16670 | 16718 | |
| 16671 | 16719 | ResultLocPeerParent *peer_parent = phi_instruction->peer_parent; |
| 16672 | 16720 | if (peer_parent != nullptr && !peer_parent->skipped && !peer_parent->done_resuming && |
| 16673 | | peer_parent->peers.length != 0) |
| 16721 | peer_parent->peers.length >= 2) |
| 16674 | 16722 | { |
| 16675 | 16723 | if (peer_parent->resolved_type == nullptr) { |
| 16676 | 16724 | IrInstruction **instructions = allocate<IrInstruction *>(peer_parent->peers.length); |