| ... | ... | @@ -3964,25 +3964,23 @@ static IrInstruction *ir_gen_bool_and(IrBuilder *irb, Scope *scope, AstNode *nod |
| 3964 | 3964 | return ir_build_phi(irb, scope, node, 2, incoming_blocks, incoming_values, nullptr); |
| 3965 | 3965 | } |
| 3966 | 3966 | |
| 3967 | | static ResultLocPeerParent *ir_build_binary_result_peers(IrBuilder *irb, IrInstruction *cond_br_inst, |
| 3968 | | IrBasicBlock *else_block, IrBasicBlock *endif_block, ResultLoc *parent, IrInstruction *is_comptime) |
| 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, |
| 3976 | IrBasicBlock *end_block, ResultLoc *parent, IrInstruction *is_comptime) |
| 3969 | 3977 | { |
| 3970 | 3978 | ResultLocPeerParent *peer_parent = allocate<ResultLocPeerParent>(1); |
| 3971 | 3979 | peer_parent->base.id = ResultLocIdPeerParent; |
| 3972 | 3980 | peer_parent->base.source_instruction = cond_br_inst; |
| 3973 | | peer_parent->end_bb = endif_block; |
| 3981 | peer_parent->end_bb = end_block; |
| 3974 | 3982 | peer_parent->is_comptime = is_comptime; |
| 3975 | 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; |
| 3986 | 3984 | |
| 3987 | 3985 | IrInstruction *popped_inst = irb->current_basic_block->instruction_list.pop(); |
| 3988 | 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 | 3991 | return peer_parent; |
| 3994 | 3992 | } |
| 3995 | 3993 | |
| 3994 | static 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 | |
| 3996 | 4008 | static IrInstruction *ir_gen_orelse(IrBuilder *irb, Scope *parent_scope, AstNode *node, LVal lval, |
| 3997 | 4009 | ResultLoc *result_loc) |
| 3998 | 4010 | { |
| ... | ... | @@ -4024,7 +4036,8 @@ static IrInstruction *ir_gen_orelse(IrBuilder *irb, Scope *parent_scope, AstNode |
| 4024 | 4036 | result_loc, is_comptime); |
| 4025 | 4037 | |
| 4026 | 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 | 4041 | if (null_result == irb->codegen->invalid_instruction) |
| 4029 | 4042 | return irb->codegen->invalid_instruction; |
| 4030 | 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 | 4047 | ir_set_cursor_at_end_and_append_block(irb, ok_block); |
| 4035 | 4048 | IrInstruction *unwrapped_ptr = ir_build_optional_unwrap_ptr(irb, parent_scope, node, maybe_ptr, false, false); |
| 4036 | 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 | 4051 | IrBasicBlock *after_ok_block = irb->current_basic_block; |
| 4039 | 4052 | ir_build_br(irb, parent_scope, node, end_block, is_comptime); |
| 4040 | 4053 | |
| ... | ... | @@ -5545,7 +5558,7 @@ static IrInstruction *ir_gen_if_bool_expr(IrBuilder *irb, Scope *scope, AstNode |
| 5545 | 5558 | |
| 5546 | 5559 | Scope *subexpr_scope = create_runtime_scope(irb->codegen, node, scope, is_comptime); |
| 5547 | 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 | 5562 | if (then_expr_result == irb->codegen->invalid_instruction) |
| 5550 | 5563 | return irb->codegen->invalid_instruction; |
| 5551 | 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 | 5568 | ir_set_cursor_at_end_and_append_block(irb, else_block); |
| 5556 | 5569 | IrInstruction *else_expr_result; |
| 5557 | 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 | 5572 | if (else_expr_result == irb->codegen->invalid_instruction) |
| 5560 | 5573 | return irb->codegen->invalid_instruction; |
| 5561 | 5574 | } else { |
| 5562 | 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 | 5578 | IrBasicBlock *after_else_block = irb->current_basic_block; |
| 5566 | 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 | 6017 | else_block, body_block, is_comptime); |
| 6005 | 6018 | cond_br_inst->is_gen = true; |
| 6006 | 6019 | } else { |
| 6007 | | // for the purposes of the source instruction to ir_build_binary_result_peers |
| 6020 | // for the purposes of the source instruction to ir_build_result_peers |
| 6008 | 6021 | cond_br_inst = irb->current_basic_block->instruction_list.last(); |
| 6009 | 6022 | } |
| 6010 | 6023 | |
| 6011 | | ResultLocPeerParent *peer_parent = ir_build_binary_result_peers(irb, cond_br_inst, else_block, end_block, |
| 6012 | | result_loc, is_comptime); |
| 6024 | ResultLocPeerParent *peer_parent = ir_build_result_peers(irb, cond_br_inst, end_block, result_loc, |
| 6025 | is_comptime); |
| 6013 | 6026 | |
| 6014 | 6027 | ir_set_cursor_at_end_and_append_block(irb, body_block); |
| 6015 | 6028 | if (var_symbol) { |
| ... | ... | @@ -6030,7 +6043,7 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n |
| 6030 | 6043 | loop_scope->incoming_blocks = &incoming_blocks; |
| 6031 | 6044 | loop_scope->incoming_values = &incoming_values; |
| 6032 | 6045 | loop_scope->lval = lval; |
| 6033 | | loop_scope->result_loc = &peer_parent->peers[0].base; |
| 6046 | loop_scope->peer_parent = peer_parent; |
| 6034 | 6047 | |
| 6035 | 6048 | // Note the body block of the loop is not the place that lval and result_loc are used - |
| 6036 | 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 | 6079 | IrInstruction *err_ptr = ir_build_unwrap_err_code(irb, err_scope, err_symbol_node, err_val_ptr); |
| 6067 | 6080 | ir_build_var_decl_src(irb, err_scope, symbol_node, err_var, nullptr, err_ptr); |
| 6068 | 6081 | |
| 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 | 6088 | if (else_result == irb->codegen->invalid_instruction) |
| 6071 | 6089 | return else_result; |
| 6072 | 6090 | if (!instr_is_unreachable(else_result)) |
| ... | ... | @@ -6080,6 +6098,9 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n |
| 6080 | 6098 | incoming_blocks.append(after_cond_block); |
| 6081 | 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 | } |
| 6083 | 6104 | |
| 6084 | 6105 | IrInstruction *phi = ir_build_phi(irb, scope, node, incoming_blocks.length, |
| 6085 | 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 | 6128 | body_block, else_block, is_comptime); |
| 6108 | 6129 | cond_br_inst->is_gen = true; |
| 6109 | 6130 | } else { |
| 6110 | | // for the purposes of the source instruction to ir_build_binary_result_peers |
| 6131 | // for the purposes of the source instruction to ir_build_result_peers |
| 6111 | 6132 | cond_br_inst = irb->current_basic_block->instruction_list.last(); |
| 6112 | 6133 | } |
| 6113 | 6134 | |
| 6114 | | ResultLocPeerParent *peer_parent = ir_build_binary_result_peers(irb, cond_br_inst, else_block, end_block, |
| 6115 | | result_loc, is_comptime); |
| 6135 | ResultLocPeerParent *peer_parent = ir_build_result_peers(irb, cond_br_inst, end_block, result_loc, |
| 6136 | is_comptime); |
| 6116 | 6137 | |
| 6117 | 6138 | ir_set_cursor_at_end_and_append_block(irb, body_block); |
| 6118 | 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 | 6151 | loop_scope->incoming_blocks = &incoming_blocks; |
| 6131 | 6152 | loop_scope->incoming_values = &incoming_values; |
| 6132 | 6153 | loop_scope->lval = lval; |
| 6133 | | loop_scope->result_loc = &peer_parent->peers[0].base; |
| 6154 | loop_scope->peer_parent = peer_parent; |
| 6134 | 6155 | |
| 6135 | 6156 | // Note the body block of the loop is not the place that lval and result_loc are used - |
| 6136 | 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 | 6180 | if (else_node) { |
| 6160 | 6181 | ir_set_cursor_at_end_and_append_block(irb, else_block); |
| 6161 | 6182 | |
| 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 | 6189 | if (else_result == irb->codegen->invalid_instruction) |
| 6164 | 6190 | return else_result; |
| 6165 | 6191 | if (!instr_is_unreachable(else_result)) |
| ... | ... | @@ -6174,6 +6200,9 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n |
| 6174 | 6200 | incoming_blocks.append(after_cond_block); |
| 6175 | 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 | } |
| 6177 | 6206 | |
| 6178 | 6207 | IrInstruction *phi = ir_build_phi(irb, scope, node, incoming_blocks.length, |
| 6179 | 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 | 6220 | body_block, else_block, is_comptime); |
| 6192 | 6221 | cond_br_inst->is_gen = true; |
| 6193 | 6222 | } else { |
| 6194 | | // for the purposes of the source instruction to ir_build_binary_result_peers |
| 6223 | // for the purposes of the source instruction to ir_build_result_peers |
| 6195 | 6224 | cond_br_inst = irb->current_basic_block->instruction_list.last(); |
| 6196 | 6225 | } |
| 6197 | 6226 | |
| 6198 | | ResultLocPeerParent *peer_parent = ir_build_binary_result_peers(irb, cond_br_inst, else_block, end_block, |
| 6199 | | result_loc, is_comptime); |
| 6227 | ResultLocPeerParent *peer_parent = ir_build_result_peers(irb, cond_br_inst, end_block, result_loc, |
| 6228 | is_comptime); |
| 6200 | 6229 | ir_set_cursor_at_end_and_append_block(irb, body_block); |
| 6201 | 6230 | |
| 6202 | 6231 | ZigList<IrInstruction *> incoming_values = {0}; |
| ... | ... | @@ -6211,7 +6240,7 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n |
| 6211 | 6240 | loop_scope->incoming_blocks = &incoming_blocks; |
| 6212 | 6241 | loop_scope->incoming_values = &incoming_values; |
| 6213 | 6242 | loop_scope->lval = lval; |
| 6214 | | loop_scope->result_loc = &peer_parent->peers[0].base; |
| 6243 | loop_scope->peer_parent = peer_parent; |
| 6215 | 6244 | |
| 6216 | 6245 | // Note the body block of the loop is not the place that lval and result_loc are used - |
| 6217 | 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 | 6269 | if (else_node) { |
| 6241 | 6270 | ir_set_cursor_at_end_and_append_block(irb, else_block); |
| 6242 | 6271 | |
| 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 | 6279 | if (else_result == irb->codegen->invalid_instruction) |
| 6245 | 6280 | return else_result; |
| 6246 | 6281 | if (!instr_is_unreachable(else_result)) |
| ... | ... | @@ -6255,6 +6290,9 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n |
| 6255 | 6290 | incoming_blocks.append(after_cond_block); |
| 6256 | 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 | } |
| 6258 | 6296 | |
| 6259 | 6297 | IrInstruction *phi = ir_build_phi(irb, scope, node, incoming_blocks.length, |
| 6260 | 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 | 6365 | IrInstruction *cond_br_inst = ir_mark_gen(ir_build_cond_br(irb, parent_scope, node, cond, |
| 6328 | 6366 | body_block, else_block, is_comptime)); |
| 6329 | 6367 | |
| 6330 | | ResultLocPeerParent *peer_parent = ir_build_binary_result_peers(irb, cond_br_inst, else_block, end_block, |
| 6331 | | result_loc, is_comptime); |
| 6368 | ResultLocPeerParent *peer_parent = ir_build_result_peers(irb, cond_br_inst, end_block, result_loc, is_comptime); |
| 6332 | 6369 | |
| 6333 | 6370 | ir_set_cursor_at_end_and_append_block(irb, body_block); |
| 6334 | 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 | 6388 | loop_scope->incoming_blocks = &incoming_blocks; |
| 6352 | 6389 | loop_scope->incoming_values = &incoming_values; |
| 6353 | 6390 | loop_scope->lval = lval; |
| 6354 | | loop_scope->result_loc = &peer_parent->peers[0].base; |
| 6391 | loop_scope->peer_parent = peer_parent; |
| 6355 | 6392 | |
| 6356 | 6393 | // Note the body block of the loop is not the place that lval and result_loc are used - |
| 6357 | 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 | 6409 | if (else_node) { |
| 6373 | 6410 | ir_set_cursor_at_end_and_append_block(irb, else_block); |
| 6374 | 6411 | |
| 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 | 6418 | if (else_result == irb->codegen->invalid_instruction) |
| 6377 | 6419 | return else_result; |
| 6378 | 6420 | if (!instr_is_unreachable(else_result)) |
| ... | ... | @@ -6388,6 +6430,9 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, Scope *parent_scope, AstNo |
| 6388 | 6430 | incoming_blocks.append(after_cond_block); |
| 6389 | 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 | } |
| 6391 | 6436 | |
| 6392 | 6437 | IrInstruction *phi = ir_build_phi(irb, parent_scope, node, incoming_blocks.length, |
| 6393 | 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 | 6773 | var_scope = subexpr_scope; |
| 6729 | 6774 | } |
| 6730 | 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 | 6777 | if (then_expr_result == irb->codegen->invalid_instruction) |
| 6733 | 6778 | return then_expr_result; |
| 6734 | 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 | 6783 | ir_set_cursor_at_end_and_append_block(irb, else_block); |
| 6739 | 6784 | IrInstruction *else_expr_result; |
| 6740 | 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 | 6787 | if (else_expr_result == irb->codegen->invalid_instruction) |
| 6743 | 6788 | return else_expr_result; |
| 6744 | 6789 | } else { |
| 6745 | 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 | 6793 | IrBasicBlock *after_else_block = irb->current_basic_block; |
| 6749 | 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 | 6856 | var_scope = subexpr_scope; |
| 6812 | 6857 | } |
| 6813 | 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 | 6860 | if (then_expr_result == irb->codegen->invalid_instruction) |
| 6816 | 6861 | return then_expr_result; |
| 6817 | 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 | 6880 | } else { |
| 6836 | 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 | 6884 | if (else_expr_result == irb->codegen->invalid_instruction) |
| 6840 | 6885 | return else_expr_result; |
| 6841 | 6886 | } else { |
| 6842 | 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 | 6890 | IrBasicBlock *after_else_block = irb->current_basic_block; |
| 6846 | 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 | 6955 | return true; |
| 6911 | 6956 | } |
| 6912 | 6957 | |
| 6913 | | static 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 | | |
| 6920 | 6958 | static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode *node, LVal lval, |
| 6921 | 6959 | ResultLoc *result_loc) |
| 6922 | 6960 | { |
| ... | ... | @@ -6955,8 +6993,6 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode * |
| 6955 | 6993 | peer_parent->end_bb = end_block; |
| 6956 | 6994 | peer_parent->is_comptime = is_comptime; |
| 6957 | 6995 | peer_parent->parent = result_loc; |
| 6958 | | peer_parent->peers = allocate<ResultLocPeer>(prong_count); |
| 6959 | | peer_parent->peer_count = 0; |
| 6960 | 6996 | |
| 6961 | 6997 | ir_build_reset_result(irb, scope, node, &peer_parent->base); |
| 6962 | 6998 | |
| ... | ... | @@ -6968,9 +7004,7 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode * |
| 6968 | 7004 | AstNode *prong_node = node->data.switch_expr.prongs.at(prong_i); |
| 6969 | 7005 | size_t prong_item_count = prong_node->data.switch_prong.items.length; |
| 6970 | 7006 | if (prong_item_count == 0) { |
| 6971 | | ResultLocPeer *this_peer_result_loc = &peer_parent->peers[peer_parent->peer_count]; |
| 6972 | | this_peer_result_loc->base.id = ResultLocIdPeer; |
| 6973 | | this_peer_result_loc->parent = peer_parent; |
| 7007 | ResultLocPeer *this_peer_result_loc = create_peer_result(peer_parent); |
| 6974 | 7008 | if (else_prong) { |
| 6975 | 7009 | ErrorMsg *msg = add_node_error(irb->codegen, prong_node, |
| 6976 | 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 | 7015 | else_prong = prong_node; |
| 6982 | 7016 | |
| 6983 | 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 | 7022 | ir_set_cursor_at_end_and_append_block(irb, else_block); |
| 6986 | 7023 | if (!ir_gen_switch_prong_expr(irb, subexpr_scope, node, prong_node, end_block, |
| 6987 | 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 | 7028 | } |
| 6992 | 7029 | ir_set_cursor_at_end(irb, prev_block); |
| 6993 | 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]; |
| 6995 | | this_peer_result_loc->base.id = ResultLocIdPeer; |
| 6996 | | this_peer_result_loc->parent = peer_parent; |
| 7031 | ResultLocPeer *this_peer_result_loc = create_peer_result(peer_parent); |
| 6997 | 7032 | |
| 6998 | 7033 | IrInstruction *ok_bit = nullptr; |
| 6999 | 7034 | AstNode *last_item_node = nullptr; |
| ... | ... | @@ -7054,7 +7089,10 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode * |
| 7054 | 7089 | ir_mark_gen(ir_build_cond_br(irb, scope, last_item_node, ok_bit, range_block_yes, |
| 7055 | 7090 | range_block_no, is_comptime)); |
| 7056 | 7091 | |
| 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 | 7096 | ir_set_cursor_at_end_and_append_block(irb, range_block_yes); |
| 7059 | 7097 | if (!ir_gen_switch_prong_expr(irb, subexpr_scope, node, prong_node, end_block, |
| 7060 | 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 | 7114 | if (prong_node->data.switch_prong.any_items_are_range) |
| 7077 | 7115 | continue; |
| 7078 | 7116 | |
| 7079 | | ResultLocPeer *this_peer_result_loc = &peer_parent->peers[peer_parent->peer_count]; |
| 7080 | | this_peer_result_loc->base.id = ResultLocIdPeer; |
| 7081 | | this_peer_result_loc->parent = peer_parent; |
| 7117 | ResultLocPeer *this_peer_result_loc = create_peer_result(peer_parent); |
| 7082 | 7118 | |
| 7083 | 7119 | IrBasicBlock *prong_block = ir_create_basic_block(irb, scope, "SwitchProng"); |
| 7084 | 7120 | IrInstruction **items = allocate<IrInstruction *>(prong_item_count); |
| ... | ... | @@ -7103,7 +7139,10 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode * |
| 7103 | 7139 | } |
| 7104 | 7140 | |
| 7105 | 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 | 7146 | ir_set_cursor_at_end_and_append_block(irb, prong_block); |
| 7108 | 7147 | if (!ir_gen_switch_prong_expr(irb, subexpr_scope, node, prong_node, end_block, |
| 7109 | 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 | 7169 | } |
| 7131 | 7170 | br_instruction = &switch_br->base; |
| 7132 | 7171 | } |
| 7133 | | for (size_t i = 0; i < peer_parent->peer_count; i += 1) { |
| 7134 | | peer_parent->peers[i].base.source_instruction = br_instruction; |
| 7172 | for (size_t i = 0; i < peer_parent->peers.length; i += 1) { |
| 7173 | peer_parent->peers.at(i)->base.source_instruction = br_instruction; |
| 7135 | 7174 | } |
| 7136 | 7175 | peer_parent->base.source_instruction = br_instruction; |
| 7137 | 7176 | |
| 7138 | 7177 | if (!else_prong) { |
| 7139 | | if (peer_parent->peer_count != 0) { |
| 7140 | | peer_parent->peers[peer_parent->peer_count - 1].next_bb = else_block; |
| 7178 | if (peer_parent->peers.length != 0) { |
| 7179 | peer_parent->peers.last()->next_bb = else_block; |
| 7141 | 7180 | } |
| 7142 | 7181 | ir_set_cursor_at_end_and_append_block(irb, else_block); |
| 7143 | 7182 | ir_build_unreachable(irb, scope, node); |
| 7144 | 7183 | } else { |
| 7145 | | if (peer_parent->peer_count != 0) { |
| 7146 | | peer_parent->peers[peer_parent->peer_count - 1].next_bb = end_block; |
| 7184 | if (peer_parent->peers.length != 0) { |
| 7185 | peer_parent->peers.last()->next_bb = end_block; |
| 7147 | 7186 | } |
| 7148 | 7187 | } |
| 7149 | 7188 | |
| ... | ... | @@ -7247,8 +7286,11 @@ static IrInstruction *ir_gen_break(IrBuilder *irb, Scope *break_scope, AstNode * |
| 7247 | 7286 | |
| 7248 | 7287 | IrInstruction *result_value; |
| 7249 | 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 | 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 | 7294 | if (result_value == irb->codegen->invalid_instruction) |
| 7253 | 7295 | return irb->codegen->invalid_instruction; |
| 7254 | 7296 | } else { |
| ... | ... | @@ -7421,7 +7463,7 @@ static IrInstruction *ir_gen_catch(IrBuilder *irb, Scope *parent_scope, AstNode |
| 7421 | 7463 | } else { |
| 7422 | 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 | 7467 | if (err_result == irb->codegen->invalid_instruction) |
| 7426 | 7468 | return irb->codegen->invalid_instruction; |
| 7427 | 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 | 7473 | ir_set_cursor_at_end_and_append_block(irb, ok_block); |
| 7432 | 7474 | IrInstruction *unwrapped_ptr = ir_build_unwrap_err_payload(irb, parent_scope, node, err_union_ptr, false, false); |
| 7433 | 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 | 7477 | IrBasicBlock *after_ok_block = irb->current_basic_block; |
| 7436 | 7478 | ir_build_br(irb, parent_scope, node, end_block, is_comptime); |
| 7437 | 7479 | |
| ... | ... | @@ -10939,25 +10981,7 @@ static IrInstruction *ira_resume(IrAnalyze *ira) { |
| 10939 | 10981 | return ira->codegen->unreach_instruction; |
| 10940 | 10982 | } |
| 10941 | 10983 | |
| 10942 | | static void ir_finish_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 | | |
| 10984 | static void ir_start_next_bb(IrAnalyze *ira) { |
| 10961 | 10985 | ira->old_bb_index += 1; |
| 10962 | 10986 | |
| 10963 | 10987 | bool need_repeat = true; |
| ... | ... | @@ -11006,6 +11030,28 @@ static void ir_finish_bb(IrAnalyze *ira) { |
| 11006 | 11030 | } |
| 11007 | 11031 | } |
| 11008 | 11032 | |
| 11033 | static 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 | |
| 11009 | 11055 | static IrInstruction *ir_unreach_error(IrAnalyze *ira) { |
| 11010 | 11056 | ira->old_bb_index = SIZE_MAX; |
| 11011 | 11057 | ira->new_irb.exec->invalid = true; |
| ... | ... | @@ -15036,7 +15082,12 @@ static IrInstruction *ir_resolve_result_raw(IrAnalyze *ira, IrInstruction *suspe |
| 15036 | 15082 | if (peer_parent->end_bb->suspend_instruction_ref == nullptr) { |
| 15037 | 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 | } |
| 15041 | 15092 | |
| 15042 | 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 | 15245 | peer_parent->skipped = false; |
| 15195 | 15246 | peer_parent->done_resuming = false; |
| 15196 | 15247 | peer_parent->resolved_type = nullptr; |
| 15197 | | for (size_t i = 0; i < peer_parent->peer_count; i += 1) { |
| 15198 | | ir_reset_result(&peer_parent->peers[i].base); |
| 15248 | for (size_t i = 0; i < peer_parent->peers.length; i += 1) { |
| 15249 | ir_reset_result(&peer_parent->peers.at(i)->base); |
| 15199 | 15250 | } |
| 15200 | 15251 | break; |
| 15201 | 15252 | } |
| ... | ... | @@ -16615,11 +16666,13 @@ static IrInstruction *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionPh |
| 16615 | 16666 | } |
| 16616 | 16667 | |
| 16617 | 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 | 16672 | if (peer_parent->resolved_type == nullptr) { |
| 16620 | | IrInstruction **instructions = allocate<IrInstruction *>(peer_parent->peer_count); |
| 16621 | | for (size_t i = 0; i < peer_parent->peer_count; i += 1) { |
| 16622 | | ResultLocPeer *this_peer = &peer_parent->peers[i]; |
| 16673 | IrInstruction **instructions = allocate<IrInstruction *>(peer_parent->peers.length); |
| 16674 | for (size_t i = 0; i < peer_parent->peers.length; i += 1) { |
| 16675 | ResultLocPeer *this_peer = peer_parent->peers.at(i); |
| 16623 | 16676 | |
| 16624 | 16677 | IrInstruction *gen_instruction = this_peer->base.gen_instruction; |
| 16625 | 16678 | if (gen_instruction == nullptr) { |
| ... | ... | @@ -16639,7 +16692,7 @@ static IrInstruction *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionPh |
| 16639 | 16692 | ZigType *expected_type = ir_result_loc_expected_type(ira, &phi_instruction->base, peer_parent->parent); |
| 16640 | 16693 | peer_parent->resolved_type = ir_resolve_peer_types(ira, |
| 16641 | 16694 | peer_parent->base.source_instruction->source_node, expected_type, instructions, |
| 16642 | | peer_parent->peer_count); |
| 16695 | peer_parent->peers.length); |
| 16643 | 16696 | |
| 16644 | 16697 | // the logic below assumes there are no instructions in the new current basic block yet |
| 16645 | 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 | 16726 | ira_suspend(ira, &phi_instruction->base, nullptr, &suspend_pos); |
| 16674 | 16727 | ir_push_resume(ira, suspend_pos); |
| 16675 | 16728 | |
| 16676 | | for (size_t i = 0; i < peer_parent->peer_count; i += 1) { |
| 16677 | | ResultLocPeer *opposite_peer = &peer_parent->peers[peer_parent->peer_count - i - 1]; |
| 16729 | for (size_t i = 0; i < peer_parent->peers.length; i += 1) { |
| 16730 | ResultLocPeer *opposite_peer = peer_parent->peers.at(peer_parent->peers.length - i - 1); |
| 16678 | 16731 | if (opposite_peer->base.implicit_elem_type != nullptr && |
| 16679 | 16732 | opposite_peer->base.implicit_elem_type->id != ZigTypeIdUnreachable) |
| 16680 | 16733 | { |