| ... | @@ -5290,6 +5290,26 @@ static IrInstruction *ir_gen_fn_call(IrBuilder *irb, Scope *scope, AstNode *node | ... | @@ -5290,6 +5290,26 @@ static IrInstruction *ir_gen_fn_call(IrBuilder *irb, Scope *scope, AstNode *node |
| 5290 | return ir_lval_wrap(irb, scope, fn_call, lval, result_loc); | 5290 | return ir_lval_wrap(irb, scope, fn_call, lval, result_loc); |
| 5291 | } | 5291 | } |
| 5292 | | 5292 | |
| | 5293 | static ResultLocPeerParent *create_binary_result_peers(IrInstruction *cond_br_inst, |
| | 5294 | IrBasicBlock *else_block, IrBasicBlock *endif_block, ResultLoc *parent) |
| | 5295 | { |
| | 5296 | ResultLocPeerParent *peer_parent = allocate<ResultLocPeerParent>(1); |
| | 5297 | peer_parent->base.id = ResultLocIdPeerParent; |
| | 5298 | peer_parent->base.source_instruction = cond_br_inst; |
| | 5299 | peer_parent->parent = parent; |
| | 5300 | peer_parent->peer_count = 2; |
| | 5301 | peer_parent->peers = allocate<ResultLocPeer>(2); |
| | 5302 | peer_parent->peers[0].base.id = ResultLocIdPeer; |
| | 5303 | peer_parent->peers[0].base.source_instruction = cond_br_inst; |
| | 5304 | peer_parent->peers[0].parent = peer_parent; |
| | 5305 | peer_parent->peers[0].next_bb = else_block; |
| | 5306 | peer_parent->peers[1].base.id = ResultLocIdPeer; |
| | 5307 | peer_parent->peers[1].base.source_instruction = cond_br_inst; |
| | 5308 | peer_parent->peers[1].parent = peer_parent; |
| | 5309 | peer_parent->peers[1].next_bb = endif_block; |
| | 5310 | return peer_parent; |
| | 5311 | } |
| | 5312 | |
| 5293 | static IrInstruction *ir_gen_if_bool_expr(IrBuilder *irb, Scope *scope, AstNode *node, LVal lval, | 5313 | static IrInstruction *ir_gen_if_bool_expr(IrBuilder *irb, Scope *scope, AstNode *node, LVal lval, |
| 5294 | ResultLoc *result_loc) | 5314 | ResultLoc *result_loc) |
| 5295 | { | 5315 | { |
| ... | @@ -5316,20 +5336,7 @@ static IrInstruction *ir_gen_if_bool_expr(IrBuilder *irb, Scope *scope, AstNode | ... | @@ -5316,20 +5336,7 @@ static IrInstruction *ir_gen_if_bool_expr(IrBuilder *irb, Scope *scope, AstNode |
| 5316 | IrInstruction *cond_br_inst = ir_build_cond_br(irb, scope, condition->source_node, condition, | 5336 | IrInstruction *cond_br_inst = ir_build_cond_br(irb, scope, condition->source_node, condition, |
| 5317 | then_block, else_block, is_comptime); | 5337 | then_block, else_block, is_comptime); |
| 5318 | | 5338 | |
| 5319 | ResultLocPeerParent *peer_parent = allocate<ResultLocPeerParent>(1); | 5339 | ResultLocPeerParent *peer_parent = create_binary_result_peers(cond_br_inst, else_block, endif_block, result_loc); |
| 5320 | peer_parent->base.id = ResultLocIdPeerParent; | | |
| 5321 | peer_parent->base.source_instruction = cond_br_inst; | | |
| 5322 | peer_parent->parent = result_loc; | | |
| 5323 | peer_parent->peer_count = 2; | | |
| 5324 | peer_parent->peers = allocate<ResultLocPeer>(2); | | |
| 5325 | peer_parent->peers[0].base.id = ResultLocIdPeer; | | |
| 5326 | peer_parent->peers[0].base.source_instruction = cond_br_inst; | | |
| 5327 | peer_parent->peers[0].parent = peer_parent; | | |
| 5328 | peer_parent->peers[0].next_bb = else_block; | | |
| 5329 | peer_parent->peers[1].base.id = ResultLocIdPeer; | | |
| 5330 | peer_parent->peers[1].base.source_instruction = cond_br_inst; | | |
| 5331 | peer_parent->peers[1].parent = peer_parent; | | |
| 5332 | peer_parent->peers[1].next_bb = endif_block; | | |
| 5333 | | 5340 | |
| 5334 | ir_set_cursor_at_end_and_append_block(irb, then_block); | 5341 | ir_set_cursor_at_end_and_append_block(irb, then_block); |
| 5335 | | 5342 | |
| ... | @@ -5676,7 +5683,9 @@ static IrInstruction *ir_gen_var_decl(IrBuilder *irb, Scope *scope, AstNode *nod | ... | @@ -5676,7 +5683,9 @@ static IrInstruction *ir_gen_var_decl(IrBuilder *irb, Scope *scope, AstNode *nod |
| 5676 | return ir_build_var_decl_src(irb, scope, node, var, align_value, alloca); | 5683 | return ir_build_var_decl_src(irb, scope, node, var, align_value, alloca); |
| 5677 | } | 5684 | } |
| 5678 | | 5685 | |
| 5679 | static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *node) { | 5686 | static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *node, LVal lval, |
| | 5687 | ResultLoc *result_loc) |
| | 5688 | { |
| 5680 | assert(node->type == NodeTypeWhileExpr); | 5689 | assert(node->type == NodeTypeWhileExpr); |
| 5681 | | 5690 | |
| 5682 | AstNode *continue_expr_node = node->data.while_expr.continue_expr; | 5691 | AstNode *continue_expr_node = node->data.while_expr.continue_expr; |
| ... | @@ -5719,11 +5728,16 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n | ... | @@ -5719,11 +5728,16 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n |
| 5719 | IrInstruction *is_err = ir_build_test_err(irb, scope, node->data.while_expr.condition, err_val); | 5728 | IrInstruction *is_err = ir_build_test_err(irb, scope, node->data.while_expr.condition, err_val); |
| 5720 | IrBasicBlock *after_cond_block = irb->current_basic_block; | 5729 | IrBasicBlock *after_cond_block = irb->current_basic_block; |
| 5721 | IrInstruction *void_else_result = else_node ? nullptr : ir_mark_gen(ir_build_const_void(irb, scope, node)); | 5730 | IrInstruction *void_else_result = else_node ? nullptr : ir_mark_gen(ir_build_const_void(irb, scope, node)); |
| | 5731 | IrInstruction *cond_br_inst; |
| 5722 | if (!instr_is_unreachable(is_err)) { | 5732 | if (!instr_is_unreachable(is_err)) { |
| 5723 | ir_mark_gen(ir_build_cond_br(irb, scope, node->data.while_expr.condition, is_err, | 5733 | cond_br_inst = ir_build_cond_br(irb, scope, node->data.while_expr.condition, is_err, |
| 5724 | else_block, body_block, is_comptime)); | 5734 | else_block, body_block, is_comptime); |
| | 5735 | } else { |
| | 5736 | cond_br_inst = is_err; // for the purposes of the source instruction to create_binary_result_peers |
| 5725 | } | 5737 | } |
| 5726 | | 5738 | |
| | 5739 | ResultLocPeerParent *peer_parent = create_binary_result_peers(cond_br_inst, else_block, end_block, result_loc); |
| | 5740 | |
| 5727 | ir_set_cursor_at_end_and_append_block(irb, body_block); | 5741 | ir_set_cursor_at_end_and_append_block(irb, body_block); |
| 5728 | if (var_symbol) { | 5742 | if (var_symbol) { |
| 5729 | IrInstruction *payload_ptr = ir_build_unwrap_err_payload(irb, payload_scope, symbol_node, | 5743 | IrInstruction *payload_ptr = ir_build_unwrap_err_payload(irb, payload_scope, symbol_node, |
| ... | @@ -5742,7 +5756,12 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n | ... | @@ -5742,7 +5756,12 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n |
| 5742 | loop_scope->is_comptime = is_comptime; | 5756 | loop_scope->is_comptime = is_comptime; |
| 5743 | loop_scope->incoming_blocks = &incoming_blocks; | 5757 | loop_scope->incoming_blocks = &incoming_blocks; |
| 5744 | loop_scope->incoming_values = &incoming_values; | 5758 | loop_scope->incoming_values = &incoming_values; |
| | 5759 | loop_scope->lval = lval; |
| | 5760 | loop_scope->result_loc = &peer_parent->peers[0].base; |
| 5745 | | 5761 | |
| | 5762 | // Note the body block of the loop is not the place that lval and result_loc are used - |
| | 5763 | // it's actually in break statements, handled similarly to return statements. |
| | 5764 | // That is why we set those values in loop_scope above and not in this ir_gen_node call. |
| 5746 | IrInstruction *body_result = ir_gen_node(irb, node->data.while_expr.body, &loop_scope->base); | 5765 | IrInstruction *body_result = ir_gen_node(irb, node->data.while_expr.body, &loop_scope->base); |
| 5747 | if (body_result == irb->codegen->invalid_instruction) | 5766 | if (body_result == irb->codegen->invalid_instruction) |
| 5748 | return body_result; | 5767 | return body_result; |
| ... | @@ -5774,7 +5793,7 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n | ... | @@ -5774,7 +5793,7 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n |
| 5774 | IrInstruction *err_ptr = ir_build_unwrap_err_code(irb, err_scope, err_symbol_node, err_val_ptr); | 5793 | IrInstruction *err_ptr = ir_build_unwrap_err_code(irb, err_scope, err_symbol_node, err_val_ptr); |
| 5775 | ir_build_var_decl_src(irb, err_scope, symbol_node, err_var, nullptr, err_ptr); | 5794 | ir_build_var_decl_src(irb, err_scope, symbol_node, err_var, nullptr, err_ptr); |
| 5776 | | 5795 | |
| 5777 | IrInstruction *else_result = ir_gen_node(irb, else_node, err_scope); | 5796 | IrInstruction *else_result = ir_gen_node_extra(irb, else_node, err_scope, lval, &peer_parent->peers[1].base); |
| 5778 | if (else_result == irb->codegen->invalid_instruction) | 5797 | if (else_result == irb->codegen->invalid_instruction) |
| 5779 | return else_result; | 5798 | return else_result; |
| 5780 | if (!instr_is_unreachable(else_result)) | 5799 | if (!instr_is_unreachable(else_result)) |
| ... | @@ -5789,7 +5808,8 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n | ... | @@ -5789,7 +5808,8 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n |
| 5789 | incoming_values.append(void_else_result); | 5808 | incoming_values.append(void_else_result); |
| 5790 | } | 5809 | } |
| 5791 | | 5810 | |
| 5792 | return ir_build_phi(irb, scope, node, incoming_blocks.length, incoming_blocks.items, incoming_values.items); | 5811 | IrInstruction *phi = ir_build_phi(irb, scope, node, incoming_blocks.length, incoming_blocks.items, incoming_values.items); |
| | 5812 | return ir_expr_wrap(irb, scope, phi, result_loc); |
| 5793 | } else if (var_symbol != nullptr) { | 5813 | } else if (var_symbol != nullptr) { |
| 5794 | ir_set_cursor_at_end_and_append_block(irb, cond_block); | 5814 | ir_set_cursor_at_end_and_append_block(irb, cond_block); |
| 5795 | Scope *subexpr_scope = create_runtime_scope(irb->codegen, node, scope, is_comptime); | 5815 | Scope *subexpr_scope = create_runtime_scope(irb->codegen, node, scope, is_comptime); |
| ... | @@ -6370,20 +6390,7 @@ static IrInstruction *ir_gen_if_optional_expr(IrBuilder *irb, Scope *scope, AstN | ... | @@ -6370,20 +6390,7 @@ static IrInstruction *ir_gen_if_optional_expr(IrBuilder *irb, Scope *scope, AstN |
| 6370 | IrInstruction *cond_br_inst = ir_build_cond_br(irb, scope, node, is_non_null, | 6390 | IrInstruction *cond_br_inst = ir_build_cond_br(irb, scope, node, is_non_null, |
| 6371 | then_block, else_block, is_comptime); | 6391 | then_block, else_block, is_comptime); |
| 6372 | | 6392 | |
| 6373 | ResultLocPeerParent *peer_parent = allocate<ResultLocPeerParent>(1); | 6393 | ResultLocPeerParent *peer_parent = create_binary_result_peers(cond_br_inst, else_block, endif_block, result_loc); |
| 6374 | peer_parent->base.id = ResultLocIdPeerParent; | | |
| 6375 | peer_parent->base.source_instruction = cond_br_inst; | | |
| 6376 | peer_parent->parent = result_loc; | | |
| 6377 | peer_parent->peer_count = 2; | | |
| 6378 | peer_parent->peers = allocate<ResultLocPeer>(2); | | |
| 6379 | peer_parent->peers[0].base.id = ResultLocIdPeer; | | |
| 6380 | peer_parent->peers[0].base.source_instruction = cond_br_inst; | | |
| 6381 | peer_parent->peers[0].parent = peer_parent; | | |
| 6382 | peer_parent->peers[0].next_bb = else_block; | | |
| 6383 | peer_parent->peers[1].base.id = ResultLocIdPeer; | | |
| 6384 | peer_parent->peers[1].base.source_instruction = cond_br_inst; | | |
| 6385 | peer_parent->peers[1].parent = peer_parent; | | |
| 6386 | peer_parent->peers[1].next_bb = endif_block; | | |
| 6387 | | 6394 | |
| 6388 | ir_set_cursor_at_end_and_append_block(irb, then_block); | 6395 | ir_set_cursor_at_end_and_append_block(irb, then_block); |
| 6389 | | 6396 | |
| ... | @@ -6463,20 +6470,7 @@ static IrInstruction *ir_gen_if_err_expr(IrBuilder *irb, Scope *scope, AstNode * | ... | @@ -6463,20 +6470,7 @@ static IrInstruction *ir_gen_if_err_expr(IrBuilder *irb, Scope *scope, AstNode * |
| 6463 | IrInstruction *is_comptime = force_comptime ? ir_build_const_bool(irb, scope, node, true) : ir_build_test_comptime(irb, scope, node, is_err); | 6470 | IrInstruction *is_comptime = force_comptime ? ir_build_const_bool(irb, scope, node, true) : ir_build_test_comptime(irb, scope, node, is_err); |
| 6464 | IrInstruction *cond_br_inst = ir_build_cond_br(irb, scope, node, is_err, else_block, ok_block, is_comptime); | 6471 | IrInstruction *cond_br_inst = ir_build_cond_br(irb, scope, node, is_err, else_block, ok_block, is_comptime); |
| 6465 | | 6472 | |
| 6466 | ResultLocPeerParent *peer_parent = allocate<ResultLocPeerParent>(1); | 6473 | ResultLocPeerParent *peer_parent = create_binary_result_peers(cond_br_inst, else_block, endif_block, result_loc); |
| 6467 | peer_parent->base.id = ResultLocIdPeerParent; | | |
| 6468 | peer_parent->base.source_instruction = cond_br_inst; | | |
| 6469 | peer_parent->parent = result_loc; | | |
| 6470 | peer_parent->peer_count = 2; | | |
| 6471 | peer_parent->peers = allocate<ResultLocPeer>(2); | | |
| 6472 | peer_parent->peers[0].base.id = ResultLocIdPeer; | | |
| 6473 | peer_parent->peers[0].base.source_instruction = cond_br_inst; | | |
| 6474 | peer_parent->peers[0].parent = peer_parent; | | |
| 6475 | peer_parent->peers[0].next_bb = else_block; | | |
| 6476 | peer_parent->peers[1].base.id = ResultLocIdPeer; | | |
| 6477 | peer_parent->peers[1].base.source_instruction = cond_br_inst; | | |
| 6478 | peer_parent->peers[1].parent = peer_parent; | | |
| 6479 | peer_parent->peers[1].next_bb = endif_block; | | |
| 6480 | | 6474 | |
| 6481 | ir_set_cursor_at_end_and_append_block(irb, ok_block); | 6475 | ir_set_cursor_at_end_and_append_block(irb, ok_block); |
| 6482 | | 6476 | |
| ... | @@ -6926,7 +6920,8 @@ static IrInstruction *ir_gen_break(IrBuilder *irb, Scope *break_scope, AstNode * | ... | @@ -6926,7 +6920,8 @@ static IrInstruction *ir_gen_break(IrBuilder *irb, Scope *break_scope, AstNode * |
| 6926 | | 6920 | |
| 6927 | IrInstruction *result_value; | 6921 | IrInstruction *result_value; |
| 6928 | if (node->data.break_expr.expr) { | 6922 | if (node->data.break_expr.expr) { |
| 6929 | result_value = ir_gen_node(irb, node->data.break_expr.expr, break_scope); | 6923 | result_value = ir_gen_node_extra(irb, node->data.break_expr.expr, break_scope, |
| | 6924 | loop_scope->lval, loop_scope->result_loc); |
| 6930 | if (result_value == irb->codegen->invalid_instruction) | 6925 | if (result_value == irb->codegen->invalid_instruction) |
| 6931 | return irb->codegen->invalid_instruction; | 6926 | return irb->codegen->invalid_instruction; |
| 6932 | } else { | 6927 | } else { |
| ... | @@ -7845,7 +7840,7 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop | ... | @@ -7845,7 +7840,7 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop |
| 7845 | case NodeTypeVariableDeclaration: | 7840 | case NodeTypeVariableDeclaration: |
| 7846 | return ir_lval_wrap(irb, scope, ir_gen_var_decl(irb, scope, node), lval, result_loc); | 7841 | return ir_lval_wrap(irb, scope, ir_gen_var_decl(irb, scope, node), lval, result_loc); |
| 7847 | case NodeTypeWhileExpr: | 7842 | case NodeTypeWhileExpr: |
| 7848 | return ir_lval_wrap(irb, scope, ir_gen_while_expr(irb, scope, node), lval, result_loc); | 7843 | return ir_gen_while_expr(irb, scope, node, lval, result_loc); |
| 7849 | case NodeTypeForExpr: | 7844 | case NodeTypeForExpr: |
| 7850 | return ir_lval_wrap(irb, scope, ir_gen_for_expr(irb, scope, node), lval, result_loc); | 7845 | return ir_lval_wrap(irb, scope, ir_gen_for_expr(irb, scope, node), lval, result_loc); |
| 7851 | case NodeTypeArrayAccessExpr: | 7846 | case NodeTypeArrayAccessExpr: |