| ... | @@ -3759,7 +3759,17 @@ static ZigVar *ir_create_var(IrBuilder *irb, AstNode *node, Scope *scope, Buf *n | ... | @@ -3759,7 +3759,17 @@ static ZigVar *ir_create_var(IrBuilder *irb, AstNode *node, Scope *scope, Buf *n |
| 3759 | return var; | 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 | assert(block_node->type == NodeTypeBlock); | 3773 | assert(block_node->type == NodeTypeBlock); |
| 3764 | | 3774 | |
| 3765 | ZigList<IrInstruction *> incoming_values = {0}; | 3775 | ZigList<IrInstruction *> incoming_values = {0}; |
| ... | @@ -3777,15 +3787,24 @@ static IrInstruction *ir_gen_block(IrBuilder *irb, Scope *parent_scope, AstNode | ... | @@ -3777,15 +3787,24 @@ static IrInstruction *ir_gen_block(IrBuilder *irb, Scope *parent_scope, AstNode |
| 3777 | | 3787 | |
| 3778 | if (block_node->data.block.statements.length == 0) { | 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 | if (block_node->data.block.name != nullptr) { | 3793 | if (block_node->data.block.name != nullptr) { |
| | 3794 | scope_block->lval = lval; |
| 3784 | scope_block->incoming_blocks = &incoming_blocks; | 3795 | scope_block->incoming_blocks = &incoming_blocks; |
| 3785 | scope_block->incoming_values = &incoming_values; | 3796 | scope_block->incoming_values = &incoming_values; |
| 3786 | scope_block->end_block = ir_create_basic_block(irb, parent_scope, "BlockEnd"); | 3797 | scope_block->end_block = ir_create_basic_block(irb, parent_scope, "BlockEnd"); |
| 3787 | scope_block->is_comptime = ir_build_const_bool(irb, parent_scope, block_node, | 3798 | scope_block->is_comptime = ir_build_const_bool(irb, parent_scope, block_node, |
| 3788 | ir_should_inline(irb->exec, parent_scope)); | 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 | bool is_continuation_unreachable = false; | 3810 | bool is_continuation_unreachable = false; |
| ... | @@ -3821,23 +3840,41 @@ static IrInstruction *ir_gen_block(IrBuilder *irb, Scope *parent_scope, AstNode | ... | @@ -3821,23 +3840,41 @@ static IrInstruction *ir_gen_block(IrBuilder *irb, Scope *parent_scope, AstNode |
| 3821 | return noreturn_return_value; | 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 | ir_set_cursor_at_end_and_append_block(irb, scope_block->end_block); | 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, | 3847 | IrInstruction *phi = ir_build_phi(irb, parent_scope, block_node, incoming_blocks.length, |
| 3826 | incoming_blocks.items, incoming_values.items, nullptr); | 3848 | incoming_blocks.items, incoming_values.items, scope_block->peer_parent); |
| | 3849 | return ir_expr_wrap(irb, parent_scope, phi, result_loc); |
| 3827 | } else { | 3850 | } else { |
| 3828 | incoming_blocks.append(irb->current_basic_block); | 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 | if (block_node->data.block.name != nullptr) { | 3867 | if (block_node->data.block.name != nullptr) { |
| 3833 | ir_gen_defers_for_block(irb, child_scope, outer_block_scope, false); | 3868 | ir_gen_defers_for_block(irb, child_scope, outer_block_scope, false); |
| 3834 | ir_mark_gen(ir_build_br(irb, parent_scope, block_node, scope_block->end_block, scope_block->is_comptime)); | 3869 | ir_mark_gen(ir_build_br(irb, parent_scope, block_node, scope_block->end_block, scope_block->is_comptime)); |
| 3835 | ir_set_cursor_at_end_and_append_block(irb, scope_block->end_block); | 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, | 3871 | IrInstruction *phi = ir_build_phi(irb, parent_scope, block_node, incoming_blocks.length, |
| 3837 | incoming_blocks.items, incoming_values.items, nullptr); | 3872 | incoming_blocks.items, incoming_values.items, scope_block->peer_parent); |
| | 3873 | return ir_expr_wrap(irb, parent_scope, phi, result_loc); |
| 3838 | } else { | 3874 | } else { |
| 3839 | ir_gen_defers_for_block(irb, child_scope, outer_block_scope, false); | 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,14 +4001,6 @@ static IrInstruction *ir_gen_bool_and(IrBuilder *irb, Scope *scope, AstNode *nod |
| 3964 | return ir_build_phi(irb, scope, node, 2, incoming_blocks, incoming_values, nullptr); | 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 | static ResultLocPeerParent *ir_build_result_peers(IrBuilder *irb, IrInstruction *cond_br_inst, | 4004 | static ResultLocPeerParent *ir_build_result_peers(IrBuilder *irb, IrInstruction *cond_br_inst, |
| 3976 | IrBasicBlock *end_block, ResultLoc *parent, IrInstruction *is_comptime) | 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,7 +7245,11 @@ static IrInstruction *ir_gen_return_from_block(IrBuilder *irb, Scope *break_scop |
| 7216 | | 7245 | |
| 7217 | IrInstruction *result_value; | 7246 | IrInstruction *result_value; |
| 7218 | if (node->data.break_expr.expr) { | 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 | if (result_value == irb->codegen->invalid_instruction) | 7253 | if (result_value == irb->codegen->invalid_instruction) |
| 7221 | return irb->codegen->invalid_instruction; | 7254 | return irb->codegen->invalid_instruction; |
| 7222 | } else { | 7255 | } else { |
| ... | @@ -8193,7 +8226,7 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop | ... | @@ -8193,7 +8226,7 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop |
| 8193 | case NodeTypeTestDecl: | 8226 | case NodeTypeTestDecl: |
| 8194 | zig_unreachable(); | 8227 | zig_unreachable(); |
| 8195 | case NodeTypeBlock: | 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 | case NodeTypeGroupedExpr: | 8230 | case NodeTypeGroupedExpr: |
| 8198 | return ir_gen_node_raw(irb, node->data.grouped_expr, scope, lval, result_loc); | 8231 | return ir_gen_node_raw(irb, node->data.grouped_expr, scope, lval, result_loc); |
| 8199 | case NodeTypeBinOpExpr: | 8232 | case NodeTypeBinOpExpr: |
| ... | @@ -15066,6 +15099,21 @@ static IrInstruction *ir_resolve_result_raw(IrAnalyze *ira, IrInstruction *suspe | ... | @@ -15066,6 +15099,21 @@ static IrInstruction *ir_resolve_result_raw(IrAnalyze *ira, IrInstruction *suspe |
| 15066 | ResultLocPeer *result_peer = reinterpret_cast<ResultLocPeer *>(result_loc); | 15099 | ResultLocPeer *result_peer = reinterpret_cast<ResultLocPeer *>(result_loc); |
| 15067 | ResultLocPeerParent *peer_parent = result_peer->parent; | 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 | bool is_comptime; | 15117 | bool is_comptime; |
| 15070 | if (!ir_resolve_comptime(ira, peer_parent->is_comptime->child, &is_comptime)) | 15118 | if (!ir_resolve_comptime(ira, peer_parent->is_comptime->child, &is_comptime)) |
| 15071 | return ira->codegen->invalid_instruction; | 15119 | return ira->codegen->invalid_instruction; |
| ... | @@ -16670,7 +16718,7 @@ static IrInstruction *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionPh | ... | @@ -16670,7 +16718,7 @@ static IrInstruction *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionPh |
| 16670 | | 16718 | |
| 16671 | ResultLocPeerParent *peer_parent = phi_instruction->peer_parent; | 16719 | ResultLocPeerParent *peer_parent = phi_instruction->peer_parent; |
| 16672 | if (peer_parent != nullptr && !peer_parent->skipped && !peer_parent->done_resuming && | 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 | if (peer_parent->resolved_type == nullptr) { | 16723 | if (peer_parent->resolved_type == nullptr) { |
| 16676 | IrInstruction **instructions = allocate<IrInstruction *>(peer_parent->peers.length); | 16724 | IrInstruction **instructions = allocate<IrInstruction *>(peer_parent->peers.length); |