authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-06-20 22:38:40-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-06-20 22:38:40-04:00
log0498bd40d9bb941454c9008c566a3599ea8f6f6b
treebbb261cd9a629a6c69e2d010bf2688ff4a509592
parent237233b04bdbbb82a5ce881a074fdd4ca55fe58f
signaturelock-open Commit is signed but in an unrecognized format.

fix loops with multiple break statements


6 files changed, 224 insertions(+), 112 deletions(-)

BRANCH_TODO+1-6
...@@ -1,12 +1,7 @@...@@ -1,12 +1,7 @@
1Scratch pad for stuff to do before merging master1Scratch pad for stuff to do before merging master
2=================================================2=================================================
33
4uncomment all the behavior tests4labeled break from a block
5diff master branch to make sure
6
7restore bootstrap.zig to master
8
9get an empty file compiling successfully (with no panic fn override)
105
11better behavior for implicit casts. for example these introduce an extra allocation/memcpy:6better behavior for implicit casts. for example these introduce an extra allocation/memcpy:
12 var x: [1]i32 = [_]i32{1};7 var x: [1]i32 = [_]i32{1};
src/all_types.hpp+2-3
...@@ -2065,7 +2065,7 @@ struct ScopeLoop {...@@ -2065,7 +2065,7 @@ struct ScopeLoop {
2065 IrInstruction *is_comptime;2065 IrInstruction *is_comptime;
2066 ZigList<IrInstruction *> *incoming_values;2066 ZigList<IrInstruction *> *incoming_values;
2067 ZigList<IrBasicBlock *> *incoming_blocks;2067 ZigList<IrBasicBlock *> *incoming_blocks;
2068 ResultLoc *result_loc;2068 ResultLocPeerParent *peer_parent;
2069};2069};
20702070
2071// This scope blocks certain things from working such as comptime continue2071// This scope blocks certain things from working such as comptime continue
...@@ -3682,8 +3682,7 @@ struct ResultLocPeerParent {...@@ -3682,8 +3682,7 @@ struct ResultLocPeerParent {
3682 bool done_resuming;3682 bool done_resuming;
3683 IrBasicBlock *end_bb;3683 IrBasicBlock *end_bb;
3684 ResultLoc *parent;3684 ResultLoc *parent;
3685 ResultLocPeer *peers;3685 ZigList<ResultLocPeer *> peers;
3686 size_t peer_count;
3687 ZigType *resolved_type;3686 ZigType *resolved_type;
3688 IrInstruction *is_comptime;3687 IrInstruction *is_comptime;
3689};3688};
src/ir.cpp+155-102
...@@ -3964,25 +3964,23 @@ static IrInstruction *ir_gen_bool_and(IrBuilder *irb, Scope *scope, AstNode *nod...@@ -3964,25 +3964,23 @@ 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);3964 return ir_build_phi(irb, scope, node, 2, incoming_blocks, incoming_values, nullptr);
3965}3965}
39663966
3967static ResultLocPeerParent *ir_build_binary_result_peers(IrBuilder *irb, IrInstruction *cond_br_inst,3967static ResultLocPeer *create_peer_result(ResultLocPeerParent *peer_parent) {
3968 IrBasicBlock *else_block, IrBasicBlock *endif_block, ResultLoc *parent, IrInstruction *is_comptime)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
3975static ResultLocPeerParent *ir_build_result_peers(IrBuilder *irb, IrInstruction *cond_br_inst,
3976 IrBasicBlock *end_block, ResultLoc *parent, IrInstruction *is_comptime)
3969{3977{
3970 ResultLocPeerParent *peer_parent = allocate<ResultLocPeerParent>(1);3978 ResultLocPeerParent *peer_parent = allocate<ResultLocPeerParent>(1);
3971 peer_parent->base.id = ResultLocIdPeerParent;3979 peer_parent->base.id = ResultLocIdPeerParent;
3972 peer_parent->base.source_instruction = cond_br_inst;3980 peer_parent->base.source_instruction = cond_br_inst;
3973 peer_parent->end_bb = endif_block;3981 peer_parent->end_bb = end_block;
3974 peer_parent->is_comptime = is_comptime;3982 peer_parent->is_comptime = is_comptime;
3975 peer_parent->parent = parent;3983 peer_parent->parent = parent;
3976 peer_parent->peer_count = 2;
3977 peer_parent->peers = allocate<ResultLocPeer>(2);
3978 peer_parent->peers[0].base.id = ResultLocIdPeer;
3979 peer_parent->peers[0].base.source_instruction = cond_br_inst;
3980 peer_parent->peers[0].parent = peer_parent;
3981 peer_parent->peers[0].next_bb = else_block;
3982 peer_parent->peers[1].base.id = ResultLocIdPeer;
3983 peer_parent->peers[1].base.source_instruction = cond_br_inst;
3984 peer_parent->peers[1].parent = peer_parent;
3985 peer_parent->peers[1].next_bb = endif_block;
39863984
3987 IrInstruction *popped_inst = irb->current_basic_block->instruction_list.pop();3985 IrInstruction *popped_inst = irb->current_basic_block->instruction_list.pop();
3988 ir_assert(popped_inst == cond_br_inst, cond_br_inst);3986 ir_assert(popped_inst == cond_br_inst, cond_br_inst);
...@@ -3993,6 +3991,20 @@ static ResultLocPeerParent *ir_build_binary_result_peers(IrBuilder *irb, IrInstr...@@ -3993,6 +3991,20 @@ static ResultLocPeerParent *ir_build_binary_result_peers(IrBuilder *irb, IrInstr
3993 return peer_parent;3991 return peer_parent;
3994}3992}
39953993
3994static ResultLocPeerParent *ir_build_binary_result_peers(IrBuilder *irb, IrInstruction *cond_br_inst,
3995 IrBasicBlock *else_block, IrBasicBlock *end_block, ResultLoc *parent, IrInstruction *is_comptime)
3996{
3997 ResultLocPeerParent *peer_parent = ir_build_result_peers(irb, cond_br_inst, end_block, parent, is_comptime);
3998
3999 peer_parent->peers.append(create_peer_result(peer_parent));
4000 peer_parent->peers.last()->next_bb = else_block;
4001
4002 peer_parent->peers.append(create_peer_result(peer_parent));
4003 peer_parent->peers.last()->next_bb = end_block;
4004
4005 return peer_parent;
4006}
4007
3996static IrInstruction *ir_gen_orelse(IrBuilder *irb, Scope *parent_scope, AstNode *node, LVal lval,4008static IrInstruction *ir_gen_orelse(IrBuilder *irb, Scope *parent_scope, AstNode *node, LVal lval,
3997 ResultLoc *result_loc)4009 ResultLoc *result_loc)
3998{4010{
...@@ -4024,7 +4036,8 @@ static IrInstruction *ir_gen_orelse(IrBuilder *irb, Scope *parent_scope, AstNode...@@ -4024,7 +4036,8 @@ static IrInstruction *ir_gen_orelse(IrBuilder *irb, Scope *parent_scope, AstNode
4024 result_loc, is_comptime);4036 result_loc, is_comptime);
40254037
4026 ir_set_cursor_at_end_and_append_block(irb, null_block);4038 ir_set_cursor_at_end_and_append_block(irb, null_block);
4027 IrInstruction *null_result = ir_gen_node_extra(irb, op2_node, parent_scope, lval, &peer_parent->peers[0].base);4039 IrInstruction *null_result = ir_gen_node_extra(irb, op2_node, parent_scope, lval,
4040 &peer_parent->peers.at(0)->base);
4028 if (null_result == irb->codegen->invalid_instruction)4041 if (null_result == irb->codegen->invalid_instruction)
4029 return irb->codegen->invalid_instruction;4042 return irb->codegen->invalid_instruction;
4030 IrBasicBlock *after_null_block = irb->current_basic_block;4043 IrBasicBlock *after_null_block = irb->current_basic_block;
...@@ -4034,7 +4047,7 @@ static IrInstruction *ir_gen_orelse(IrBuilder *irb, Scope *parent_scope, AstNode...@@ -4034,7 +4047,7 @@ static IrInstruction *ir_gen_orelse(IrBuilder *irb, Scope *parent_scope, AstNode
4034 ir_set_cursor_at_end_and_append_block(irb, ok_block);4047 ir_set_cursor_at_end_and_append_block(irb, ok_block);
4035 IrInstruction *unwrapped_ptr = ir_build_optional_unwrap_ptr(irb, parent_scope, node, maybe_ptr, false, false);4048 IrInstruction *unwrapped_ptr = ir_build_optional_unwrap_ptr(irb, parent_scope, node, maybe_ptr, false, false);
4036 IrInstruction *unwrapped_payload = ir_build_load_ptr(irb, parent_scope, node, unwrapped_ptr);4049 IrInstruction *unwrapped_payload = ir_build_load_ptr(irb, parent_scope, node, unwrapped_ptr);
4037 ir_build_end_expr(irb, parent_scope, node, unwrapped_payload, &peer_parent->peers[1].base);4050 ir_build_end_expr(irb, parent_scope, node, unwrapped_payload, &peer_parent->peers.at(1)->base);
4038 IrBasicBlock *after_ok_block = irb->current_basic_block;4051 IrBasicBlock *after_ok_block = irb->current_basic_block;
4039 ir_build_br(irb, parent_scope, node, end_block, is_comptime);4052 ir_build_br(irb, parent_scope, node, end_block, is_comptime);
40404053
...@@ -5545,7 +5558,7 @@ static IrInstruction *ir_gen_if_bool_expr(IrBuilder *irb, Scope *scope, AstNode...@@ -5545,7 +5558,7 @@ static IrInstruction *ir_gen_if_bool_expr(IrBuilder *irb, Scope *scope, AstNode
55455558
5546 Scope *subexpr_scope = create_runtime_scope(irb->codegen, node, scope, is_comptime);5559 Scope *subexpr_scope = create_runtime_scope(irb->codegen, node, scope, is_comptime);
5547 IrInstruction *then_expr_result = ir_gen_node_extra(irb, then_node, subexpr_scope, lval,5560 IrInstruction *then_expr_result = ir_gen_node_extra(irb, then_node, subexpr_scope, lval,
5548 &peer_parent->peers[0].base);5561 &peer_parent->peers.at(0)->base);
5549 if (then_expr_result == irb->codegen->invalid_instruction)5562 if (then_expr_result == irb->codegen->invalid_instruction)
5550 return irb->codegen->invalid_instruction;5563 return irb->codegen->invalid_instruction;
5551 IrBasicBlock *after_then_block = irb->current_basic_block;5564 IrBasicBlock *after_then_block = irb->current_basic_block;
...@@ -5555,12 +5568,12 @@ static IrInstruction *ir_gen_if_bool_expr(IrBuilder *irb, Scope *scope, AstNode...@@ -5555,12 +5568,12 @@ static IrInstruction *ir_gen_if_bool_expr(IrBuilder *irb, Scope *scope, AstNode
5555 ir_set_cursor_at_end_and_append_block(irb, else_block);5568 ir_set_cursor_at_end_and_append_block(irb, else_block);
5556 IrInstruction *else_expr_result;5569 IrInstruction *else_expr_result;
5557 if (else_node) {5570 if (else_node) {
5558 else_expr_result = ir_gen_node_extra(irb, else_node, subexpr_scope, lval, &peer_parent->peers[1].base);5571 else_expr_result = ir_gen_node_extra(irb, else_node, subexpr_scope, lval, &peer_parent->peers.at(1)->base);
5559 if (else_expr_result == irb->codegen->invalid_instruction)5572 if (else_expr_result == irb->codegen->invalid_instruction)
5560 return irb->codegen->invalid_instruction;5573 return irb->codegen->invalid_instruction;
5561 } else {5574 } else {
5562 else_expr_result = ir_build_const_void(irb, scope, node);5575 else_expr_result = ir_build_const_void(irb, scope, node);
5563 ir_build_end_expr(irb, scope, node, else_expr_result, &peer_parent->peers[1].base);5576 ir_build_end_expr(irb, scope, node, else_expr_result, &peer_parent->peers.at(1)->base);
5564 }5577 }
5565 IrBasicBlock *after_else_block = irb->current_basic_block;5578 IrBasicBlock *after_else_block = irb->current_basic_block;
5566 if (!instr_is_unreachable(else_expr_result))5579 if (!instr_is_unreachable(else_expr_result))
...@@ -6004,12 +6017,12 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n...@@ -6004,12 +6017,12 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n
6004 else_block, body_block, is_comptime);6017 else_block, body_block, is_comptime);
6005 cond_br_inst->is_gen = true;6018 cond_br_inst->is_gen = true;
6006 } else {6019 } else {
6007 // for the purposes of the source instruction to ir_build_binary_result_peers6020 // for the purposes of the source instruction to ir_build_result_peers
6008 cond_br_inst = irb->current_basic_block->instruction_list.last();6021 cond_br_inst = irb->current_basic_block->instruction_list.last();
6009 }6022 }
60106023
6011 ResultLocPeerParent *peer_parent = ir_build_binary_result_peers(irb, cond_br_inst, else_block, end_block,6024 ResultLocPeerParent *peer_parent = ir_build_result_peers(irb, cond_br_inst, end_block, result_loc,
6012 result_loc, is_comptime);6025 is_comptime);
60136026
6014 ir_set_cursor_at_end_and_append_block(irb, body_block);6027 ir_set_cursor_at_end_and_append_block(irb, body_block);
6015 if (var_symbol) {6028 if (var_symbol) {
...@@ -6030,7 +6043,7 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n...@@ -6030,7 +6043,7 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n
6030 loop_scope->incoming_blocks = &incoming_blocks;6043 loop_scope->incoming_blocks = &incoming_blocks;
6031 loop_scope->incoming_values = &incoming_values;6044 loop_scope->incoming_values = &incoming_values;
6032 loop_scope->lval = lval;6045 loop_scope->lval = lval;
6033 loop_scope->result_loc = &peer_parent->peers[0].base;6046 loop_scope->peer_parent = peer_parent;
60346047
6035 // Note the body block of the loop is not the place that lval and result_loc are used -6048 // Note the body block of the loop is not the place that lval and result_loc are used -
6036 // it's actually in break statements, handled similarly to return statements.6049 // it's actually in break statements, handled similarly to return statements.
...@@ -6066,7 +6079,12 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n...@@ -6066,7 +6079,12 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n
6066 IrInstruction *err_ptr = ir_build_unwrap_err_code(irb, err_scope, err_symbol_node, err_val_ptr);6079 IrInstruction *err_ptr = ir_build_unwrap_err_code(irb, err_scope, err_symbol_node, err_val_ptr);
6067 ir_build_var_decl_src(irb, err_scope, symbol_node, err_var, nullptr, err_ptr);6080 ir_build_var_decl_src(irb, err_scope, symbol_node, err_var, nullptr, err_ptr);
60686081
6069 IrInstruction *else_result = ir_gen_node_extra(irb, else_node, err_scope, lval, &peer_parent->peers[1].base);6082 if (peer_parent->peers.length != 0) {
6083 peer_parent->peers.last()->next_bb = else_block;
6084 }
6085 ResultLocPeer *peer_result = create_peer_result(peer_parent);
6086 peer_parent->peers.append(peer_result);
6087 IrInstruction *else_result = ir_gen_node_extra(irb, else_node, err_scope, lval, &peer_result->base);
6070 if (else_result == irb->codegen->invalid_instruction)6088 if (else_result == irb->codegen->invalid_instruction)
6071 return else_result;6089 return else_result;
6072 if (!instr_is_unreachable(else_result))6090 if (!instr_is_unreachable(else_result))
...@@ -6080,6 +6098,9 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n...@@ -6080,6 +6098,9 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n
6080 incoming_blocks.append(after_cond_block);6098 incoming_blocks.append(after_cond_block);
6081 incoming_values.append(void_else_result);6099 incoming_values.append(void_else_result);
6082 }6100 }
6101 if (peer_parent->peers.length != 0) {
6102 peer_parent->peers.last()->next_bb = end_block;
6103 }
60836104
6084 IrInstruction *phi = ir_build_phi(irb, scope, node, incoming_blocks.length,6105 IrInstruction *phi = ir_build_phi(irb, scope, node, incoming_blocks.length,
6085 incoming_blocks.items, incoming_values.items, peer_parent);6106 incoming_blocks.items, incoming_values.items, peer_parent);
...@@ -6107,12 +6128,12 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n...@@ -6107,12 +6128,12 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n
6107 body_block, else_block, is_comptime);6128 body_block, else_block, is_comptime);
6108 cond_br_inst->is_gen = true;6129 cond_br_inst->is_gen = true;
6109 } else {6130 } else {
6110 // for the purposes of the source instruction to ir_build_binary_result_peers6131 // for the purposes of the source instruction to ir_build_result_peers
6111 cond_br_inst = irb->current_basic_block->instruction_list.last();6132 cond_br_inst = irb->current_basic_block->instruction_list.last();
6112 }6133 }
61136134
6114 ResultLocPeerParent *peer_parent = ir_build_binary_result_peers(irb, cond_br_inst, else_block, end_block,6135 ResultLocPeerParent *peer_parent = ir_build_result_peers(irb, cond_br_inst, end_block, result_loc,
6115 result_loc, is_comptime);6136 is_comptime);
61166137
6117 ir_set_cursor_at_end_and_append_block(irb, body_block);6138 ir_set_cursor_at_end_and_append_block(irb, body_block);
6118 IrInstruction *payload_ptr = ir_build_optional_unwrap_ptr(irb, child_scope, symbol_node, maybe_val_ptr, false, false);6139 IrInstruction *payload_ptr = ir_build_optional_unwrap_ptr(irb, child_scope, symbol_node, maybe_val_ptr, false, false);
...@@ -6130,7 +6151,7 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n...@@ -6130,7 +6151,7 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n
6130 loop_scope->incoming_blocks = &incoming_blocks;6151 loop_scope->incoming_blocks = &incoming_blocks;
6131 loop_scope->incoming_values = &incoming_values;6152 loop_scope->incoming_values = &incoming_values;
6132 loop_scope->lval = lval;6153 loop_scope->lval = lval;
6133 loop_scope->result_loc = &peer_parent->peers[0].base;6154 loop_scope->peer_parent = peer_parent;
61346155
6135 // Note the body block of the loop is not the place that lval and result_loc are used -6156 // Note the body block of the loop is not the place that lval and result_loc are used -
6136 // it's actually in break statements, handled similarly to return statements.6157 // it's actually in break statements, handled similarly to return statements.
...@@ -6159,7 +6180,12 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n...@@ -6159,7 +6180,12 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n
6159 if (else_node) {6180 if (else_node) {
6160 ir_set_cursor_at_end_and_append_block(irb, else_block);6181 ir_set_cursor_at_end_and_append_block(irb, else_block);
61616182
6162 else_result = ir_gen_node_extra(irb, else_node, scope, lval, &peer_parent->peers[1].base);6183 if (peer_parent->peers.length != 0) {
6184 peer_parent->peers.last()->next_bb = else_block;
6185 }
6186 ResultLocPeer *peer_result = create_peer_result(peer_parent);
6187 peer_parent->peers.append(peer_result);
6188 else_result = ir_gen_node_extra(irb, else_node, scope, lval, &peer_result->base);
6163 if (else_result == irb->codegen->invalid_instruction)6189 if (else_result == irb->codegen->invalid_instruction)
6164 return else_result;6190 return else_result;
6165 if (!instr_is_unreachable(else_result))6191 if (!instr_is_unreachable(else_result))
...@@ -6174,6 +6200,9 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n...@@ -6174,6 +6200,9 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n
6174 incoming_blocks.append(after_cond_block);6200 incoming_blocks.append(after_cond_block);
6175 incoming_values.append(void_else_result);6201 incoming_values.append(void_else_result);
6176 }6202 }
6203 if (peer_parent->peers.length != 0) {
6204 peer_parent->peers.last()->next_bb = end_block;
6205 }
61776206
6178 IrInstruction *phi = ir_build_phi(irb, scope, node, incoming_blocks.length,6207 IrInstruction *phi = ir_build_phi(irb, scope, node, incoming_blocks.length,
6179 incoming_blocks.items, incoming_values.items, peer_parent);6208 incoming_blocks.items, incoming_values.items, peer_parent);
...@@ -6191,12 +6220,12 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n...@@ -6191,12 +6220,12 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n
6191 body_block, else_block, is_comptime);6220 body_block, else_block, is_comptime);
6192 cond_br_inst->is_gen = true;6221 cond_br_inst->is_gen = true;
6193 } else {6222 } else {
6194 // for the purposes of the source instruction to ir_build_binary_result_peers6223 // for the purposes of the source instruction to ir_build_result_peers
6195 cond_br_inst = irb->current_basic_block->instruction_list.last();6224 cond_br_inst = irb->current_basic_block->instruction_list.last();
6196 }6225 }
61976226
6198 ResultLocPeerParent *peer_parent = ir_build_binary_result_peers(irb, cond_br_inst, else_block, end_block,6227 ResultLocPeerParent *peer_parent = ir_build_result_peers(irb, cond_br_inst, end_block, result_loc,
6199 result_loc, is_comptime);6228 is_comptime);
6200 ir_set_cursor_at_end_and_append_block(irb, body_block);6229 ir_set_cursor_at_end_and_append_block(irb, body_block);
62016230
6202 ZigList<IrInstruction *> incoming_values = {0};6231 ZigList<IrInstruction *> incoming_values = {0};
...@@ -6211,7 +6240,7 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n...@@ -6211,7 +6240,7 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n
6211 loop_scope->incoming_blocks = &incoming_blocks;6240 loop_scope->incoming_blocks = &incoming_blocks;
6212 loop_scope->incoming_values = &incoming_values;6241 loop_scope->incoming_values = &incoming_values;
6213 loop_scope->lval = lval;6242 loop_scope->lval = lval;
6214 loop_scope->result_loc = &peer_parent->peers[0].base;6243 loop_scope->peer_parent = peer_parent;
62156244
6216 // Note the body block of the loop is not the place that lval and result_loc are used -6245 // Note the body block of the loop is not the place that lval and result_loc are used -
6217 // it's actually in break statements, handled similarly to return statements.6246 // it's actually in break statements, handled similarly to return statements.
...@@ -6240,7 +6269,13 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n...@@ -6240,7 +6269,13 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n
6240 if (else_node) {6269 if (else_node) {
6241 ir_set_cursor_at_end_and_append_block(irb, else_block);6270 ir_set_cursor_at_end_and_append_block(irb, else_block);
62426271
6243 else_result = ir_gen_node_extra(irb, else_node, subexpr_scope, lval, &peer_parent->peers[1].base);6272 if (peer_parent->peers.length != 0) {
6273 peer_parent->peers.last()->next_bb = else_block;
6274 }
6275 ResultLocPeer *peer_result = create_peer_result(peer_parent);
6276 peer_parent->peers.append(peer_result);
6277
6278 else_result = ir_gen_node_extra(irb, else_node, subexpr_scope, lval, &peer_result->base);
6244 if (else_result == irb->codegen->invalid_instruction)6279 if (else_result == irb->codegen->invalid_instruction)
6245 return else_result;6280 return else_result;
6246 if (!instr_is_unreachable(else_result))6281 if (!instr_is_unreachable(else_result))
...@@ -6255,6 +6290,9 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n...@@ -6255,6 +6290,9 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n
6255 incoming_blocks.append(after_cond_block);6290 incoming_blocks.append(after_cond_block);
6256 incoming_values.append(void_else_result);6291 incoming_values.append(void_else_result);
6257 }6292 }
6293 if (peer_parent->peers.length != 0) {
6294 peer_parent->peers.last()->next_bb = end_block;
6295 }
62586296
6259 IrInstruction *phi = ir_build_phi(irb, scope, node, incoming_blocks.length,6297 IrInstruction *phi = ir_build_phi(irb, scope, node, incoming_blocks.length,
6260 incoming_blocks.items, incoming_values.items, peer_parent);6298 incoming_blocks.items, incoming_values.items, peer_parent);
...@@ -6327,8 +6365,7 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, Scope *parent_scope, AstNo...@@ -6327,8 +6365,7 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, Scope *parent_scope, AstNo
6327 IrInstruction *cond_br_inst = ir_mark_gen(ir_build_cond_br(irb, parent_scope, node, cond,6365 IrInstruction *cond_br_inst = ir_mark_gen(ir_build_cond_br(irb, parent_scope, node, cond,
6328 body_block, else_block, is_comptime));6366 body_block, else_block, is_comptime));
63296367
6330 ResultLocPeerParent *peer_parent = ir_build_binary_result_peers(irb, cond_br_inst, else_block, end_block,6368 ResultLocPeerParent *peer_parent = ir_build_result_peers(irb, cond_br_inst, end_block, result_loc, is_comptime);
6331 result_loc, is_comptime);
63326369
6333 ir_set_cursor_at_end_and_append_block(irb, body_block);6370 ir_set_cursor_at_end_and_append_block(irb, body_block);
6334 IrInstruction *elem_ptr = ir_build_elem_ptr(irb, parent_scope, node, array_val_ptr, index_val, false,6371 IrInstruction *elem_ptr = ir_build_elem_ptr(irb, parent_scope, node, array_val_ptr, index_val, false,
...@@ -6351,7 +6388,7 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, Scope *parent_scope, AstNo...@@ -6351,7 +6388,7 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, Scope *parent_scope, AstNo
6351 loop_scope->incoming_blocks = &incoming_blocks;6388 loop_scope->incoming_blocks = &incoming_blocks;
6352 loop_scope->incoming_values = &incoming_values;6389 loop_scope->incoming_values = &incoming_values;
6353 loop_scope->lval = lval;6390 loop_scope->lval = lval;
6354 loop_scope->result_loc = &peer_parent->peers[0].base;6391 loop_scope->peer_parent = peer_parent;
63556392
6356 // Note the body block of the loop is not the place that lval and result_loc are used -6393 // Note the body block of the loop is not the place that lval and result_loc are used -
6357 // it's actually in break statements, handled similarly to return statements.6394 // it's actually in break statements, handled similarly to return statements.
...@@ -6372,7 +6409,12 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, Scope *parent_scope, AstNo...@@ -6372,7 +6409,12 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, Scope *parent_scope, AstNo
6372 if (else_node) {6409 if (else_node) {
6373 ir_set_cursor_at_end_and_append_block(irb, else_block);6410 ir_set_cursor_at_end_and_append_block(irb, else_block);
63746411
6375 else_result = ir_gen_node_extra(irb, else_node, parent_scope, lval, &peer_parent->peers[1].base);6412 if (peer_parent->peers.length != 0) {
6413 peer_parent->peers.last()->next_bb = else_block;
6414 }
6415 ResultLocPeer *peer_result = create_peer_result(peer_parent);
6416 peer_parent->peers.append(peer_result);
6417 else_result = ir_gen_node_extra(irb, else_node, parent_scope, lval, &peer_result->base);
6376 if (else_result == irb->codegen->invalid_instruction)6418 if (else_result == irb->codegen->invalid_instruction)
6377 return else_result;6419 return else_result;
6378 if (!instr_is_unreachable(else_result))6420 if (!instr_is_unreachable(else_result))
...@@ -6388,6 +6430,9 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, Scope *parent_scope, AstNo...@@ -6388,6 +6430,9 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, Scope *parent_scope, AstNo
6388 incoming_blocks.append(after_cond_block);6430 incoming_blocks.append(after_cond_block);
6389 incoming_values.append(void_else_value);6431 incoming_values.append(void_else_value);
6390 }6432 }
6433 if (peer_parent->peers.length != 0) {
6434 peer_parent->peers.last()->next_bb = end_block;
6435 }
63916436
6392 IrInstruction *phi = ir_build_phi(irb, parent_scope, node, incoming_blocks.length,6437 IrInstruction *phi = ir_build_phi(irb, parent_scope, node, incoming_blocks.length,
6393 incoming_blocks.items, incoming_values.items, peer_parent);6438 incoming_blocks.items, incoming_values.items, peer_parent);
...@@ -6728,7 +6773,7 @@ static IrInstruction *ir_gen_if_optional_expr(IrBuilder *irb, Scope *scope, AstN...@@ -6728,7 +6773,7 @@ static IrInstruction *ir_gen_if_optional_expr(IrBuilder *irb, Scope *scope, AstN
6728 var_scope = subexpr_scope;6773 var_scope = subexpr_scope;
6729 }6774 }
6730 IrInstruction *then_expr_result = ir_gen_node_extra(irb, then_node, var_scope, lval,6775 IrInstruction *then_expr_result = ir_gen_node_extra(irb, then_node, var_scope, lval,
6731 &peer_parent->peers[0].base);6776 &peer_parent->peers.at(0)->base);
6732 if (then_expr_result == irb->codegen->invalid_instruction)6777 if (then_expr_result == irb->codegen->invalid_instruction)
6733 return then_expr_result;6778 return then_expr_result;
6734 IrBasicBlock *after_then_block = irb->current_basic_block;6779 IrBasicBlock *after_then_block = irb->current_basic_block;
...@@ -6738,12 +6783,12 @@ static IrInstruction *ir_gen_if_optional_expr(IrBuilder *irb, Scope *scope, AstN...@@ -6738,12 +6783,12 @@ static IrInstruction *ir_gen_if_optional_expr(IrBuilder *irb, Scope *scope, AstN
6738 ir_set_cursor_at_end_and_append_block(irb, else_block);6783 ir_set_cursor_at_end_and_append_block(irb, else_block);
6739 IrInstruction *else_expr_result;6784 IrInstruction *else_expr_result;
6740 if (else_node) {6785 if (else_node) {
6741 else_expr_result = ir_gen_node_extra(irb, else_node, subexpr_scope, lval, &peer_parent->peers[1].base);6786 else_expr_result = ir_gen_node_extra(irb, else_node, subexpr_scope, lval, &peer_parent->peers.at(1)->base);
6742 if (else_expr_result == irb->codegen->invalid_instruction)6787 if (else_expr_result == irb->codegen->invalid_instruction)
6743 return else_expr_result;6788 return else_expr_result;
6744 } else {6789 } else {
6745 else_expr_result = ir_build_const_void(irb, scope, node);6790 else_expr_result = ir_build_const_void(irb, scope, node);
6746 ir_build_end_expr(irb, scope, node, else_expr_result, &peer_parent->peers[1].base);6791 ir_build_end_expr(irb, scope, node, else_expr_result, &peer_parent->peers.at(1)->base);
6747 }6792 }
6748 IrBasicBlock *after_else_block = irb->current_basic_block;6793 IrBasicBlock *after_else_block = irb->current_basic_block;
6749 if (!instr_is_unreachable(else_expr_result))6794 if (!instr_is_unreachable(else_expr_result))
...@@ -6811,7 +6856,7 @@ static IrInstruction *ir_gen_if_err_expr(IrBuilder *irb, Scope *scope, AstNode *...@@ -6811,7 +6856,7 @@ static IrInstruction *ir_gen_if_err_expr(IrBuilder *irb, Scope *scope, AstNode *
6811 var_scope = subexpr_scope;6856 var_scope = subexpr_scope;
6812 }6857 }
6813 IrInstruction *then_expr_result = ir_gen_node_extra(irb, then_node, var_scope, lval,6858 IrInstruction *then_expr_result = ir_gen_node_extra(irb, then_node, var_scope, lval,
6814 &peer_parent->peers[0].base);6859 &peer_parent->peers.at(0)->base);
6815 if (then_expr_result == irb->codegen->invalid_instruction)6860 if (then_expr_result == irb->codegen->invalid_instruction)
6816 return then_expr_result;6861 return then_expr_result;
6817 IrBasicBlock *after_then_block = irb->current_basic_block;6862 IrBasicBlock *after_then_block = irb->current_basic_block;
...@@ -6835,12 +6880,12 @@ static IrInstruction *ir_gen_if_err_expr(IrBuilder *irb, Scope *scope, AstNode *...@@ -6835,12 +6880,12 @@ static IrInstruction *ir_gen_if_err_expr(IrBuilder *irb, Scope *scope, AstNode *
6835 } else {6880 } else {
6836 err_var_scope = subexpr_scope;6881 err_var_scope = subexpr_scope;
6837 }6882 }
6838 else_expr_result = ir_gen_node_extra(irb, else_node, err_var_scope, lval, &peer_parent->peers[1].base);6883 else_expr_result = ir_gen_node_extra(irb, else_node, err_var_scope, lval, &peer_parent->peers.at(1)->base);
6839 if (else_expr_result == irb->codegen->invalid_instruction)6884 if (else_expr_result == irb->codegen->invalid_instruction)
6840 return else_expr_result;6885 return else_expr_result;
6841 } else {6886 } else {
6842 else_expr_result = ir_build_const_void(irb, scope, node);6887 else_expr_result = ir_build_const_void(irb, scope, node);
6843 ir_build_end_expr(irb, scope, node, else_expr_result, &peer_parent->peers[1].base);6888 ir_build_end_expr(irb, scope, node, else_expr_result, &peer_parent->peers.at(1)->base);
6844 }6889 }
6845 IrBasicBlock *after_else_block = irb->current_basic_block;6890 IrBasicBlock *after_else_block = irb->current_basic_block;
6846 if (!instr_is_unreachable(else_expr_result))6891 if (!instr_is_unreachable(else_expr_result))
...@@ -6910,13 +6955,6 @@ static bool ir_gen_switch_prong_expr(IrBuilder *irb, Scope *scope, AstNode *swit...@@ -6910,13 +6955,6 @@ static bool ir_gen_switch_prong_expr(IrBuilder *irb, Scope *scope, AstNode *swit
6910 return true;6955 return true;
6911}6956}
69126957
6913static void next_peer_block(ResultLocPeerParent *peer_parent, IrBasicBlock *next_bb) {
6914 if (peer_parent->peer_count > 0) {
6915 peer_parent->peers[peer_parent->peer_count - 1].next_bb = next_bb;
6916 }
6917 peer_parent->peer_count += 1;
6918}
6919
6920static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode *node, LVal lval,6958static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode *node, LVal lval,
6921 ResultLoc *result_loc)6959 ResultLoc *result_loc)
6922{6960{
...@@ -6955,8 +6993,6 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode *...@@ -6955,8 +6993,6 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode *
6955 peer_parent->end_bb = end_block;6993 peer_parent->end_bb = end_block;
6956 peer_parent->is_comptime = is_comptime;6994 peer_parent->is_comptime = is_comptime;
6957 peer_parent->parent = result_loc;6995 peer_parent->parent = result_loc;
6958 peer_parent->peers = allocate<ResultLocPeer>(prong_count);
6959 peer_parent->peer_count = 0;
69606996
6961 ir_build_reset_result(irb, scope, node, &peer_parent->base);6997 ir_build_reset_result(irb, scope, node, &peer_parent->base);
69626998
...@@ -6968,9 +7004,7 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode *...@@ -6968,9 +7004,7 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode *
6968 AstNode *prong_node = node->data.switch_expr.prongs.at(prong_i);7004 AstNode *prong_node = node->data.switch_expr.prongs.at(prong_i);
6969 size_t prong_item_count = prong_node->data.switch_prong.items.length;7005 size_t prong_item_count = prong_node->data.switch_prong.items.length;
6970 if (prong_item_count == 0) {7006 if (prong_item_count == 0) {
6971 ResultLocPeer *this_peer_result_loc = &peer_parent->peers[peer_parent->peer_count];7007 ResultLocPeer *this_peer_result_loc = create_peer_result(peer_parent);
6972 this_peer_result_loc->base.id = ResultLocIdPeer;
6973 this_peer_result_loc->parent = peer_parent;
6974 if (else_prong) {7008 if (else_prong) {
6975 ErrorMsg *msg = add_node_error(irb->codegen, prong_node,7009 ErrorMsg *msg = add_node_error(irb->codegen, prong_node,
6976 buf_sprintf("multiple else prongs in switch expression"));7010 buf_sprintf("multiple else prongs in switch expression"));
...@@ -6981,7 +7015,10 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode *...@@ -6981,7 +7015,10 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode *
6981 else_prong = prong_node;7015 else_prong = prong_node;
69827016
6983 IrBasicBlock *prev_block = irb->current_basic_block;7017 IrBasicBlock *prev_block = irb->current_basic_block;
6984 next_peer_block(peer_parent, else_block);7018 if (peer_parent->peers.length > 0) {
7019 peer_parent->peers.last()->next_bb = else_block;
7020 }
7021 peer_parent->peers.append(this_peer_result_loc);
6985 ir_set_cursor_at_end_and_append_block(irb, else_block);7022 ir_set_cursor_at_end_and_append_block(irb, else_block);
6986 if (!ir_gen_switch_prong_expr(irb, subexpr_scope, node, prong_node, end_block,7023 if (!ir_gen_switch_prong_expr(irb, subexpr_scope, node, prong_node, end_block,
6987 is_comptime, var_is_comptime, target_value_ptr, nullptr, 0, &incoming_blocks, &incoming_values,7024 is_comptime, var_is_comptime, target_value_ptr, nullptr, 0, &incoming_blocks, &incoming_values,
...@@ -6991,9 +7028,7 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode *...@@ -6991,9 +7028,7 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode *
6991 }7028 }
6992 ir_set_cursor_at_end(irb, prev_block);7029 ir_set_cursor_at_end(irb, prev_block);
6993 } else if (prong_node->data.switch_prong.any_items_are_range) {7030 } else if (prong_node->data.switch_prong.any_items_are_range) {
6994 ResultLocPeer *this_peer_result_loc = &peer_parent->peers[peer_parent->peer_count];7031 ResultLocPeer *this_peer_result_loc = create_peer_result(peer_parent);
6995 this_peer_result_loc->base.id = ResultLocIdPeer;
6996 this_peer_result_loc->parent = peer_parent;
69977032
6998 IrInstruction *ok_bit = nullptr;7033 IrInstruction *ok_bit = nullptr;
6999 AstNode *last_item_node = nullptr;7034 AstNode *last_item_node = nullptr;
...@@ -7054,7 +7089,10 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode *...@@ -7054,7 +7089,10 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode *
7054 ir_mark_gen(ir_build_cond_br(irb, scope, last_item_node, ok_bit, range_block_yes,7089 ir_mark_gen(ir_build_cond_br(irb, scope, last_item_node, ok_bit, range_block_yes,
7055 range_block_no, is_comptime));7090 range_block_no, is_comptime));
70567091
7057 next_peer_block(peer_parent, range_block_yes);7092 if (peer_parent->peers.length > 0) {
7093 peer_parent->peers.last()->next_bb = range_block_yes;
7094 }
7095 peer_parent->peers.append(this_peer_result_loc);
7058 ir_set_cursor_at_end_and_append_block(irb, range_block_yes);7096 ir_set_cursor_at_end_and_append_block(irb, range_block_yes);
7059 if (!ir_gen_switch_prong_expr(irb, subexpr_scope, node, prong_node, end_block,7097 if (!ir_gen_switch_prong_expr(irb, subexpr_scope, node, prong_node, end_block,
7060 is_comptime, var_is_comptime, target_value_ptr, nullptr, 0,7098 is_comptime, var_is_comptime, target_value_ptr, nullptr, 0,
...@@ -7076,9 +7114,7 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode *...@@ -7076,9 +7114,7 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode *
7076 if (prong_node->data.switch_prong.any_items_are_range)7114 if (prong_node->data.switch_prong.any_items_are_range)
7077 continue;7115 continue;
70787116
7079 ResultLocPeer *this_peer_result_loc = &peer_parent->peers[peer_parent->peer_count];7117 ResultLocPeer *this_peer_result_loc = create_peer_result(peer_parent);
7080 this_peer_result_loc->base.id = ResultLocIdPeer;
7081 this_peer_result_loc->parent = peer_parent;
70827118
7083 IrBasicBlock *prong_block = ir_create_basic_block(irb, scope, "SwitchProng");7119 IrBasicBlock *prong_block = ir_create_basic_block(irb, scope, "SwitchProng");
7084 IrInstruction **items = allocate<IrInstruction *>(prong_item_count);7120 IrInstruction **items = allocate<IrInstruction *>(prong_item_count);
...@@ -7103,7 +7139,10 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode *...@@ -7103,7 +7139,10 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode *
7103 }7139 }
71047140
7105 IrBasicBlock *prev_block = irb->current_basic_block;7141 IrBasicBlock *prev_block = irb->current_basic_block;
7106 next_peer_block(peer_parent, prong_block);7142 if (peer_parent->peers.length > 0) {
7143 peer_parent->peers.last()->next_bb = prong_block;
7144 }
7145 peer_parent->peers.append(this_peer_result_loc);
7107 ir_set_cursor_at_end_and_append_block(irb, prong_block);7146 ir_set_cursor_at_end_and_append_block(irb, prong_block);
7108 if (!ir_gen_switch_prong_expr(irb, subexpr_scope, node, prong_node, end_block,7147 if (!ir_gen_switch_prong_expr(irb, subexpr_scope, node, prong_node, end_block,
7109 is_comptime, var_is_comptime, target_value_ptr, items, prong_item_count,7148 is_comptime, var_is_comptime, target_value_ptr, items, prong_item_count,
...@@ -7130,20 +7169,20 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode *...@@ -7130,20 +7169,20 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode *
7130 }7169 }
7131 br_instruction = &switch_br->base;7170 br_instruction = &switch_br->base;
7132 }7171 }
7133 for (size_t i = 0; i < peer_parent->peer_count; i += 1) {7172 for (size_t i = 0; i < peer_parent->peers.length; i += 1) {
7134 peer_parent->peers[i].base.source_instruction = br_instruction;7173 peer_parent->peers.at(i)->base.source_instruction = br_instruction;
7135 }7174 }
7136 peer_parent->base.source_instruction = br_instruction;7175 peer_parent->base.source_instruction = br_instruction;
71377176
7138 if (!else_prong) {7177 if (!else_prong) {
7139 if (peer_parent->peer_count != 0) {7178 if (peer_parent->peers.length != 0) {
7140 peer_parent->peers[peer_parent->peer_count - 1].next_bb = else_block;7179 peer_parent->peers.last()->next_bb = else_block;
7141 }7180 }
7142 ir_set_cursor_at_end_and_append_block(irb, else_block);7181 ir_set_cursor_at_end_and_append_block(irb, else_block);
7143 ir_build_unreachable(irb, scope, node);7182 ir_build_unreachable(irb, scope, node);
7144 } else {7183 } else {
7145 if (peer_parent->peer_count != 0) {7184 if (peer_parent->peers.length != 0) {
7146 peer_parent->peers[peer_parent->peer_count - 1].next_bb = end_block;7185 peer_parent->peers.last()->next_bb = end_block;
7147 }7186 }
7148 }7187 }
71497188
...@@ -7247,8 +7286,11 @@ static IrInstruction *ir_gen_break(IrBuilder *irb, Scope *break_scope, AstNode *...@@ -7247,8 +7286,11 @@ static IrInstruction *ir_gen_break(IrBuilder *irb, Scope *break_scope, AstNode *
72477286
7248 IrInstruction *result_value;7287 IrInstruction *result_value;
7249 if (node->data.break_expr.expr) {7288 if (node->data.break_expr.expr) {
7289 ResultLocPeer *peer_result = create_peer_result(loop_scope->peer_parent);
7290 loop_scope->peer_parent->peers.append(peer_result);
7291
7250 result_value = ir_gen_node_extra(irb, node->data.break_expr.expr, break_scope,7292 result_value = ir_gen_node_extra(irb, node->data.break_expr.expr, break_scope,
7251 loop_scope->lval, loop_scope->result_loc);7293 loop_scope->lval, &peer_result->base);
7252 if (result_value == irb->codegen->invalid_instruction)7294 if (result_value == irb->codegen->invalid_instruction)
7253 return irb->codegen->invalid_instruction;7295 return irb->codegen->invalid_instruction;
7254 } else {7296 } else {
...@@ -7421,7 +7463,7 @@ static IrInstruction *ir_gen_catch(IrBuilder *irb, Scope *parent_scope, AstNode...@@ -7421,7 +7463,7 @@ static IrInstruction *ir_gen_catch(IrBuilder *irb, Scope *parent_scope, AstNode
7421 } else {7463 } else {
7422 err_scope = parent_scope;7464 err_scope = parent_scope;
7423 }7465 }
7424 IrInstruction *err_result = ir_gen_node_extra(irb, op2_node, err_scope, lval, &peer_parent->peers[0].base);7466 IrInstruction *err_result = ir_gen_node_extra(irb, op2_node, err_scope, lval, &peer_parent->peers.at(0)->base);
7425 if (err_result == irb->codegen->invalid_instruction)7467 if (err_result == irb->codegen->invalid_instruction)
7426 return irb->codegen->invalid_instruction;7468 return irb->codegen->invalid_instruction;
7427 IrBasicBlock *after_err_block = irb->current_basic_block;7469 IrBasicBlock *after_err_block = irb->current_basic_block;
...@@ -7431,7 +7473,7 @@ static IrInstruction *ir_gen_catch(IrBuilder *irb, Scope *parent_scope, AstNode...@@ -7431,7 +7473,7 @@ static IrInstruction *ir_gen_catch(IrBuilder *irb, Scope *parent_scope, AstNode
7431 ir_set_cursor_at_end_and_append_block(irb, ok_block);7473 ir_set_cursor_at_end_and_append_block(irb, ok_block);
7432 IrInstruction *unwrapped_ptr = ir_build_unwrap_err_payload(irb, parent_scope, node, err_union_ptr, false, false);7474 IrInstruction *unwrapped_ptr = ir_build_unwrap_err_payload(irb, parent_scope, node, err_union_ptr, false, false);
7433 IrInstruction *unwrapped_payload = ir_build_load_ptr(irb, parent_scope, node, unwrapped_ptr);7475 IrInstruction *unwrapped_payload = ir_build_load_ptr(irb, parent_scope, node, unwrapped_ptr);
7434 ir_build_end_expr(irb, parent_scope, node, unwrapped_payload, &peer_parent->peers[1].base);7476 ir_build_end_expr(irb, parent_scope, node, unwrapped_payload, &peer_parent->peers.at(1)->base);
7435 IrBasicBlock *after_ok_block = irb->current_basic_block;7477 IrBasicBlock *after_ok_block = irb->current_basic_block;
7436 ir_build_br(irb, parent_scope, node, end_block, is_comptime);7478 ir_build_br(irb, parent_scope, node, end_block, is_comptime);
74377479
...@@ -10939,25 +10981,7 @@ static IrInstruction *ira_resume(IrAnalyze *ira) {...@@ -10939,25 +10981,7 @@ static IrInstruction *ira_resume(IrAnalyze *ira) {
10939 return ira->codegen->unreach_instruction;10981 return ira->codegen->unreach_instruction;
10940}10982}
1094110983
10942static void ir_finish_bb(IrAnalyze *ira) {10984static void ir_start_next_bb(IrAnalyze *ira) {
10943 if (!ira->new_irb.current_basic_block->already_appended) {
10944 ira->new_irb.current_basic_block->already_appended = true;
10945 if (ira->codegen->verbose_ir) {
10946 fprintf(stderr, "append new bb %s_%zu\n", ira->new_irb.current_basic_block->name_hint,
10947 ira->new_irb.current_basic_block->debug_id);
10948 }
10949 ira->new_irb.exec->basic_block_list.append(ira->new_irb.current_basic_block);
10950 }
10951 ira->instruction_index += 1;
10952 while (ira->instruction_index < ira->old_irb.current_basic_block->instruction_list.length) {
10953 IrInstruction *next_instruction = ira->old_irb.current_basic_block->instruction_list.at(ira->instruction_index);
10954 if (!next_instruction->is_gen) {
10955 ir_add_error(ira, next_instruction, buf_sprintf("unreachable code"));
10956 break;
10957 }
10958 ira->instruction_index += 1;
10959 }
10960
10961 ira->old_bb_index += 1;10985 ira->old_bb_index += 1;
1096210986
10963 bool need_repeat = true;10987 bool need_repeat = true;
...@@ -11006,6 +11030,28 @@ static void ir_finish_bb(IrAnalyze *ira) {...@@ -11006,6 +11030,28 @@ static void ir_finish_bb(IrAnalyze *ira) {
11006 }11030 }
11007}11031}
1100811032
11033static void ir_finish_bb(IrAnalyze *ira) {
11034 if (!ira->new_irb.current_basic_block->already_appended) {
11035 ira->new_irb.current_basic_block->already_appended = true;
11036 if (ira->codegen->verbose_ir) {
11037 fprintf(stderr, "append new bb %s_%zu\n", ira->new_irb.current_basic_block->name_hint,
11038 ira->new_irb.current_basic_block->debug_id);
11039 }
11040 ira->new_irb.exec->basic_block_list.append(ira->new_irb.current_basic_block);
11041 }
11042 ira->instruction_index += 1;
11043 while (ira->instruction_index < ira->old_irb.current_basic_block->instruction_list.length) {
11044 IrInstruction *next_instruction = ira->old_irb.current_basic_block->instruction_list.at(ira->instruction_index);
11045 if (!next_instruction->is_gen) {
11046 ir_add_error(ira, next_instruction, buf_sprintf("unreachable code"));
11047 break;
11048 }
11049 ira->instruction_index += 1;
11050 }
11051
11052 ir_start_next_bb(ira);
11053}
11054
11009static IrInstruction *ir_unreach_error(IrAnalyze *ira) {11055static IrInstruction *ir_unreach_error(IrAnalyze *ira) {
11010 ira->old_bb_index = SIZE_MAX;11056 ira->old_bb_index = SIZE_MAX;
11011 ira->new_irb.exec->invalid = true;11057 ira->new_irb.exec->invalid = true;
...@@ -15036,7 +15082,12 @@ static IrInstruction *ir_resolve_result_raw(IrAnalyze *ira, IrInstruction *suspe...@@ -15036,7 +15082,12 @@ static IrInstruction *ir_resolve_result_raw(IrAnalyze *ira, IrInstruction *suspe
15036 if (peer_parent->end_bb->suspend_instruction_ref == nullptr) {15082 if (peer_parent->end_bb->suspend_instruction_ref == nullptr) {
15037 peer_parent->end_bb->suspend_instruction_ref = suspend_source_instr;15083 peer_parent->end_bb->suspend_instruction_ref = suspend_source_instr;
15038 }15084 }
15039 return ira_suspend(ira, suspend_source_instr, result_peer->next_bb, &result_peer->suspend_pos);15085 IrInstruction *unreach_inst = ira_suspend(ira, suspend_source_instr, result_peer->next_bb,
15086 &result_peer->suspend_pos);
15087 if (result_peer->next_bb == nullptr) {
15088 ir_start_next_bb(ira);
15089 }
15090 return unreach_inst;
15040 }15091 }
1504115092
15042 IrInstruction *parent_result_loc = ir_resolve_result(ira, suspend_source_instr, peer_parent->parent,15093 IrInstruction *parent_result_loc = ir_resolve_result(ira, suspend_source_instr, peer_parent->parent,
...@@ -15194,8 +15245,8 @@ static void ir_reset_result(ResultLoc *result_loc) {...@@ -15194,8 +15245,8 @@ static void ir_reset_result(ResultLoc *result_loc) {
15194 peer_parent->skipped = false;15245 peer_parent->skipped = false;
15195 peer_parent->done_resuming = false;15246 peer_parent->done_resuming = false;
15196 peer_parent->resolved_type = nullptr;15247 peer_parent->resolved_type = nullptr;
15197 for (size_t i = 0; i < peer_parent->peer_count; i += 1) {15248 for (size_t i = 0; i < peer_parent->peers.length; i += 1) {
15198 ir_reset_result(&peer_parent->peers[i].base);15249 ir_reset_result(&peer_parent->peers.at(i)->base);
15199 }15250 }
15200 break;15251 break;
15201 }15252 }
...@@ -16615,11 +16666,13 @@ static IrInstruction *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionPh...@@ -16615,11 +16666,13 @@ static IrInstruction *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionPh
16615 }16666 }
1661616667
16617 ResultLocPeerParent *peer_parent = phi_instruction->peer_parent;16668 ResultLocPeerParent *peer_parent = phi_instruction->peer_parent;
16618 if (peer_parent != nullptr && !peer_parent->skipped && !peer_parent->done_resuming) {16669 if (peer_parent != nullptr && !peer_parent->skipped && !peer_parent->done_resuming &&
16670 peer_parent->peers.length != 0)
16671 {
16619 if (peer_parent->resolved_type == nullptr) {16672 if (peer_parent->resolved_type == nullptr) {
16620 IrInstruction **instructions = allocate<IrInstruction *>(peer_parent->peer_count);16673 IrInstruction **instructions = allocate<IrInstruction *>(peer_parent->peers.length);
16621 for (size_t i = 0; i < peer_parent->peer_count; i += 1) {16674 for (size_t i = 0; i < peer_parent->peers.length; i += 1) {
16622 ResultLocPeer *this_peer = &peer_parent->peers[i];16675 ResultLocPeer *this_peer = peer_parent->peers.at(i);
1662316676
16624 IrInstruction *gen_instruction = this_peer->base.gen_instruction;16677 IrInstruction *gen_instruction = this_peer->base.gen_instruction;
16625 if (gen_instruction == nullptr) {16678 if (gen_instruction == nullptr) {
...@@ -16639,7 +16692,7 @@ static IrInstruction *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionPh...@@ -16639,7 +16692,7 @@ static IrInstruction *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionPh
16639 ZigType *expected_type = ir_result_loc_expected_type(ira, &phi_instruction->base, peer_parent->parent);16692 ZigType *expected_type = ir_result_loc_expected_type(ira, &phi_instruction->base, peer_parent->parent);
16640 peer_parent->resolved_type = ir_resolve_peer_types(ira,16693 peer_parent->resolved_type = ir_resolve_peer_types(ira,
16641 peer_parent->base.source_instruction->source_node, expected_type, instructions,16694 peer_parent->base.source_instruction->source_node, expected_type, instructions,
16642 peer_parent->peer_count);16695 peer_parent->peers.length);
1664316696
16644 // the logic below assumes there are no instructions in the new current basic block yet16697 // the logic below assumes there are no instructions in the new current basic block yet
16645 ir_assert(ira->new_irb.current_basic_block->instruction_list.length == 0, &phi_instruction->base);16698 ir_assert(ira->new_irb.current_basic_block->instruction_list.length == 0, &phi_instruction->base);
...@@ -16673,8 +16726,8 @@ static IrInstruction *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionPh...@@ -16673,8 +16726,8 @@ static IrInstruction *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionPh
16673 ira_suspend(ira, &phi_instruction->base, nullptr, &suspend_pos);16726 ira_suspend(ira, &phi_instruction->base, nullptr, &suspend_pos);
16674 ir_push_resume(ira, suspend_pos);16727 ir_push_resume(ira, suspend_pos);
1667516728
16676 for (size_t i = 0; i < peer_parent->peer_count; i += 1) {16729 for (size_t i = 0; i < peer_parent->peers.length; i += 1) {
16677 ResultLocPeer *opposite_peer = &peer_parent->peers[peer_parent->peer_count - i - 1];16730 ResultLocPeer *opposite_peer = peer_parent->peers.at(peer_parent->peers.length - i - 1);
16678 if (opposite_peer->base.implicit_elem_type != nullptr &&16731 if (opposite_peer->base.implicit_elem_type != nullptr &&
16679 opposite_peer->base.implicit_elem_type->id != ZigTypeIdUnreachable)16732 opposite_peer->base.implicit_elem_type->id != ZigTypeIdUnreachable)
16680 {16733 {
src/ir_print.cpp+5-1
...@@ -57,7 +57,11 @@ static void ir_print_other_instruction(IrPrint *irp, IrInstruction *instruction)...@@ -57,7 +57,11 @@ static void ir_print_other_instruction(IrPrint *irp, IrInstruction *instruction)
57}57}
5858
59static void ir_print_other_block(IrPrint *irp, IrBasicBlock *bb) {59static void ir_print_other_block(IrPrint *irp, IrBasicBlock *bb) {
60 fprintf(irp->f, "$%s_%" ZIG_PRI_usize "", bb->name_hint, bb->debug_id);60 if (bb == nullptr) {
61 fprintf(irp->f, "(null block)");
62 } else {
63 fprintf(irp->f, "$%s_%" ZIG_PRI_usize "", bb->name_hint, bb->debug_id);
64 }
61}65}
6266
63static void ir_print_return(IrPrint *irp, IrInstructionReturn *return_instruction) {67static void ir_print_return(IrPrint *irp, IrInstructionReturn *return_instruction) {
test/stage1/behavior/for.zig+16
...@@ -110,3 +110,19 @@ fn testContinueOuter() void {...@@ -110,3 +110,19 @@ fn testContinueOuter() void {
110 }110 }
111 expect(counter == array.len);111 expect(counter == array.len);
112}112}
113
114test "2 break statements and an else" {
115 const S = struct {
116 fn entry(t: bool, f: bool) void {
117 var buf: [10]u8 = undefined;
118 var ok = false;
119 ok = for (buf) |item| {
120 if (f) break false;
121 if (t) break true;
122 } else false;
123 expect(ok);
124 }
125 };
126 S.entry(true, false);
127 comptime S.entry(true, false);
128}
test/stage1/behavior/while.zig+45
...@@ -226,3 +226,48 @@ fn returnFalse() bool {...@@ -226,3 +226,48 @@ fn returnFalse() bool {
226fn returnTrue() bool {226fn returnTrue() bool {
227 return true;227 return true;
228}228}
229
230test "while bool 2 break statements and an else" {
231 const S = struct {
232 fn entry(t: bool, f: bool) void {
233 var ok = false;
234 ok = while (t) {
235 if (f) break false;
236 if (t) break true;
237 } else false;
238 expect(ok);
239 }
240 };
241 S.entry(true, false);
242 comptime S.entry(true, false);
243}
244
245test "while optional 2 break statements and an else" {
246 const S = struct {
247 fn entry(opt_t: ?bool, f: bool) void {
248 var ok = false;
249 ok = while (opt_t) |t| {
250 if (f) break false;
251 if (t) break true;
252 } else false;
253 expect(ok);
254 }
255 };
256 S.entry(true, false);
257 comptime S.entry(true, false);
258}
259
260test "while error 2 break statements and an else" {
261 const S = struct {
262 fn entry(opt_t: anyerror!bool, f: bool) void {
263 var ok = false;
264 ok = while (opt_t) |t| {
265 if (f) break false;
266 if (t) break true;
267 } else |_| false;
268 expect(ok);
269 }
270 };
271 S.entry(true, false);
272 comptime S.entry(true, false);
273}