@@ -22,6 +22,8 @@ struct LoopStackItem {
22
22
IrBasicBlock *break_block;
23
23
IrBasicBlock *continue_block;
24
24
IrInstruction *is_comptime;
25
+ ZigList<IrInstruction *> *incoming_values;
26
+ ZigList<IrBasicBlock *> *incoming_blocks;
25
27
};
26
28
27
29
struct IrBuilder {
@@ -56,6 +58,18 @@ static IrInstruction *ir_gen_node_extra(IrBuilder *irb, AstNode *node, Scope *sc
56
58
static TypeTableEntry *ir_analyze_instruction(IrAnalyze *ira, IrInstruction *instruction);
57
59
static IrInstruction *ir_implicit_cast(IrAnalyze *ira, IrInstruction *value, TypeTableEntry *expected_type);
58
60
61
+ static LoopStackItem *add_loop_stack_item(IrBuilder *irb, IrBasicBlock *break_block, IrBasicBlock *continue_block,
62
+ IrInstruction *is_comptime, ZigList<IrBasicBlock *> *incoming_blocks, ZigList<IrInstruction *> *incoming_values)
63
+ {
64
+ LoopStackItem *loop_stack_item = irb->loop_stack.add_one();
65
+ loop_stack_item->break_block = break_block;
66
+ loop_stack_item->continue_block = continue_block;
67
+ loop_stack_item->is_comptime = is_comptime;
68
+ loop_stack_item->incoming_blocks = incoming_blocks;
69
+ loop_stack_item->incoming_values = incoming_values;
70
+ return loop_stack_item;
71
+ }
72
+
59
73
ConstExprValue *const_ptr_pointee(CodeGen *g, ConstExprValue *const_val) {
60
74
assert(const_val->type->id == TypeTableEntryIdPointer);
61
75
assert(const_val->special == ConstValSpecialStatic);
@@ -4693,6 +4707,8 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n
4693
4707
return err_val_ptr;
4694
4708
IrInstruction *err_val = ir_build_load_ptr(irb, scope, node->data.while_expr.condition, err_val_ptr);
4695
4709
IrInstruction *is_err = ir_build_test_err(irb, scope, node->data.while_expr.condition, err_val);
4710
+ IrBasicBlock *after_cond_block = irb->current_basic_block;
4711
+ IrInstruction *void_else_result = else_node ? nullptr : ir_mark_gen(ir_build_const_void(irb, scope, node));
4696
4712
if (!instr_is_unreachable(is_err)) {
4697
4713
ir_mark_gen(ir_build_cond_br(irb, scope, node->data.while_expr.condition, is_err,
4698
4714
else_block, body_block, is_comptime));
@@ -4706,10 +4722,9 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n
4706
4722
var_ptr_value : ir_build_load_ptr(irb, payload_scope, symbol_node, var_ptr_value);
4707
4723
ir_build_var_decl(irb, payload_scope, symbol_node, payload_var, nullptr, var_value);
4708
4724
}
4709
- LoopStackItem *loop_stack_item = irb->loop_stack.add_one();
4710
- loop_stack_item->break_block = end_block;
4711
- loop_stack_item->continue_block = continue_block;
4712
- loop_stack_item->is_comptime = is_comptime;
4725
+ ZigList<IrInstruction *> incoming_values = {0};
4726
+ ZigList<IrBasicBlock *> incoming_blocks = {0};
4727
+ add_loop_stack_item(irb, end_block, continue_block, is_comptime, &incoming_blocks, &incoming_values);
4713
4728
IrInstruction *body_result = ir_gen_node(irb, node->data.while_expr.body, payload_scope);
4714
4729
if (body_result == irb->codegen->invalid_instruction)
4715
4730
return body_result;
@@ -4727,6 +4742,7 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n
4727
4742
ir_mark_gen(ir_build_br(irb, payload_scope, node, cond_block, is_comptime));
4728
4743
}
4729
4744
4745
+ IrInstruction *else_result = nullptr;
4730
4746
if (else_node) {
4731
4747
ir_set_cursor_at_end(irb, else_block);
4732
4748
@@ -4738,15 +4754,23 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n
4738
4754
IrInstruction *err_var_value = ir_build_unwrap_err_code(irb, err_scope, err_symbol_node, err_val_ptr);
4739
4755
ir_build_var_decl(irb, err_scope, symbol_node, err_var, nullptr, err_var_value);
4740
4756
4741
- IrInstruction * else_result = ir_gen_node(irb, else_node, err_scope);
4757
+ else_result = ir_gen_node(irb, else_node, err_scope);
4742
4758
if (else_result == irb->codegen->invalid_instruction)
4743
4759
return else_result;
4744
4760
if (!instr_is_unreachable(else_result))
4745
4761
ir_mark_gen(ir_build_br(irb, scope, node, end_block, is_comptime));
4746
4762
}
4747
-
4763
+ IrBasicBlock *after_else_block = irb->current_basic_block;
4748
4764
ir_set_cursor_at_end(irb, end_block);
4749
- return ir_build_const_void(irb, scope, node);
4765
+ if (else_result) {
4766
+ incoming_blocks.append(after_else_block);
4767
+ incoming_values.append(else_result);
4768
+ } else {
4769
+ incoming_blocks.append(after_cond_block);
4770
+ incoming_values.append(void_else_result);
4771
+ }
4772
+
4773
+ return ir_build_phi(irb, scope, node, incoming_blocks.length, incoming_blocks.items, incoming_values.items);
4750
4774
} else if (var_symbol != nullptr) {
4751
4775
ir_set_cursor_at_end(irb, cond_block);
4752
4776
// TODO make it an error to write to payload variable
@@ -4759,6 +4783,8 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n
4759
4783
return maybe_val_ptr;
4760
4784
IrInstruction *maybe_val = ir_build_load_ptr(irb, scope, node->data.while_expr.condition, maybe_val_ptr);
4761
4785
IrInstruction *is_non_null = ir_build_test_nonnull(irb, scope, node->data.while_expr.condition, maybe_val);
4786
+ IrBasicBlock *after_cond_block = irb->current_basic_block;
4787
+ IrInstruction *void_else_result = else_node ? nullptr : ir_mark_gen(ir_build_const_void(irb, scope, node));
4762
4788
if (!instr_is_unreachable(is_non_null)) {
4763
4789
ir_mark_gen(ir_build_cond_br(irb, scope, node->data.while_expr.condition, is_non_null,
4764
4790
body_block, else_block, is_comptime));
@@ -4769,10 +4795,9 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n
4769
4795
IrInstruction *var_value = node->data.while_expr.var_is_ptr ?
4770
4796
var_ptr_value : ir_build_load_ptr(irb, child_scope, symbol_node, var_ptr_value);
4771
4797
ir_build_var_decl(irb, child_scope, symbol_node, payload_var, nullptr, var_value);
4772
- LoopStackItem *loop_stack_item = irb->loop_stack.add_one();
4773
- loop_stack_item->break_block = end_block;
4774
- loop_stack_item->continue_block = continue_block;
4775
- loop_stack_item->is_comptime = is_comptime;
4798
+ ZigList<IrInstruction *> incoming_values = {0};
4799
+ ZigList<IrBasicBlock *> incoming_blocks = {0};
4800
+ add_loop_stack_item(irb, end_block, continue_block, is_comptime, &incoming_blocks, &incoming_values);
4776
4801
IrInstruction *body_result = ir_gen_node(irb, node->data.while_expr.body, child_scope);
4777
4802
if (body_result == irb->codegen->invalid_instruction)
4778
4803
return body_result;
@@ -4790,18 +4815,27 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n
4790
4815
ir_mark_gen(ir_build_br(irb, child_scope, node, cond_block, is_comptime));
4791
4816
}
4792
4817
4818
+ IrInstruction *else_result = nullptr;
4793
4819
if (else_node) {
4794
4820
ir_set_cursor_at_end(irb, else_block);
4795
4821
4796
- IrInstruction * else_result = ir_gen_node(irb, else_node, scope);
4822
+ else_result = ir_gen_node(irb, else_node, scope);
4797
4823
if (else_result == irb->codegen->invalid_instruction)
4798
4824
return else_result;
4799
4825
if (!instr_is_unreachable(else_result))
4800
4826
ir_mark_gen(ir_build_br(irb, scope, node, end_block, is_comptime));
4801
4827
}
4802
-
4828
+ IrBasicBlock *after_else_block = irb->current_basic_block;
4803
4829
ir_set_cursor_at_end(irb, end_block);
4804
- return ir_build_const_void(irb, scope, node);
4830
+ if (else_result) {
4831
+ incoming_blocks.append(after_else_block);
4832
+ incoming_values.append(else_result);
4833
+ } else {
4834
+ incoming_blocks.append(after_cond_block);
4835
+ incoming_values.append(void_else_result);
4836
+ }
4837
+
4838
+ return ir_build_phi(irb, scope, node, incoming_blocks.length, incoming_blocks.items, incoming_values.items);
4805
4839
} else {
4806
4840
if (continue_expr_node) {
4807
4841
ir_set_cursor_at_end(irb, continue_block);
@@ -4816,17 +4850,18 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n
4816
4850
IrInstruction *cond_val = ir_gen_node(irb, node->data.while_expr.condition, scope);
4817
4851
if (cond_val == irb->codegen->invalid_instruction)
4818
4852
return cond_val;
4853
+ IrBasicBlock *after_cond_block = irb->current_basic_block;
4854
+ IrInstruction *void_else_result = else_node ? nullptr : ir_mark_gen(ir_build_const_void(irb, scope, node));
4819
4855
if (!instr_is_unreachable(cond_val)) {
4820
4856
ir_mark_gen(ir_build_cond_br(irb, scope, node->data.while_expr.condition, cond_val,
4821
4857
body_block, else_block, is_comptime));
4822
4858
}
4823
4859
4824
4860
ir_set_cursor_at_end(irb, body_block);
4825
4861
4826
- LoopStackItem *loop_stack_item = irb->loop_stack.add_one();
4827
- loop_stack_item->break_block = end_block;
4828
- loop_stack_item->continue_block = continue_block;
4829
- loop_stack_item->is_comptime = is_comptime;
4862
+ ZigList<IrInstruction *> incoming_values = {0};
4863
+ ZigList<IrBasicBlock *> incoming_blocks = {0};
4864
+ add_loop_stack_item(irb, end_block, continue_block, is_comptime, &incoming_blocks, &incoming_values);
4830
4865
IrInstruction *body_result = ir_gen_node(irb, node->data.while_expr.body, scope);
4831
4866
if (body_result == irb->codegen->invalid_instruction)
4832
4867
return body_result;
@@ -4835,19 +4870,27 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n
4835
4870
if (!instr_is_unreachable(body_result))
4836
4871
ir_mark_gen(ir_build_br(irb, scope, node, continue_block, is_comptime));
4837
4872
4873
+ IrInstruction *else_result = nullptr;
4838
4874
if (else_node) {
4839
4875
ir_set_cursor_at_end(irb, else_block);
4840
4876
4841
- IrInstruction * else_result = ir_gen_node(irb, else_node, scope);
4877
+ else_result = ir_gen_node(irb, else_node, scope);
4842
4878
if (else_result == irb->codegen->invalid_instruction)
4843
4879
return else_result;
4844
4880
if (!instr_is_unreachable(else_result))
4845
4881
ir_mark_gen(ir_build_br(irb, scope, node, end_block, is_comptime));
4846
4882
}
4847
-
4883
+ IrBasicBlock *after_else_block = irb->current_basic_block;
4848
4884
ir_set_cursor_at_end(irb, end_block);
4885
+ if (else_result) {
4886
+ incoming_blocks.append(after_else_block);
4887
+ incoming_values.append(else_result);
4888
+ } else {
4889
+ incoming_blocks.append(after_cond_block);
4890
+ incoming_values.append(void_else_result);
4891
+ }
4849
4892
4850
- return ir_build_const_void (irb, scope, node);
4893
+ return ir_build_phi (irb, scope, node, incoming_blocks.length, incoming_blocks.items, incoming_values.items );
4851
4894
}
4852
4895
}
4853
4896
@@ -4858,6 +4901,7 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, Scope *parent_scope, AstNo
4858
4901
AstNode *elem_node = node->data.for_expr.elem_node;
4859
4902
AstNode *index_node = node->data.for_expr.index_node;
4860
4903
AstNode *body_node = node->data.for_expr.body;
4904
+ AstNode *else_node = node->data.for_expr.else_node;
4861
4905
4862
4906
if (!elem_node) {
4863
4907
add_node_error(irb->codegen, node, buf_sprintf("for loop expression missing element parameter"));
@@ -4915,6 +4959,7 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, Scope *parent_scope, AstNo
4915
4959
IrBasicBlock *cond_block = ir_build_basic_block(irb, child_scope, "ForCond");
4916
4960
IrBasicBlock *body_block = ir_build_basic_block(irb, child_scope, "ForBody");
4917
4961
IrBasicBlock *end_block = ir_build_basic_block(irb, child_scope, "ForEnd");
4962
+ IrBasicBlock *else_block = else_node ? ir_build_basic_block(irb, child_scope, "ForElse") : end_block;
4918
4963
IrBasicBlock *continue_block = ir_build_basic_block(irb, child_scope, "ForContinue");
4919
4964
4920
4965
IrInstruction *len_val = ir_build_array_len(irb, child_scope, node, array_val);
@@ -4923,7 +4968,9 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, Scope *parent_scope, AstNo
4923
4968
ir_set_cursor_at_end(irb, cond_block);
4924
4969
IrInstruction *index_val = ir_build_load_ptr(irb, child_scope, node, index_ptr);
4925
4970
IrInstruction *cond = ir_build_bin_op(irb, child_scope, node, IrBinOpCmpLessThan, index_val, len_val, false);
4926
- ir_mark_gen(ir_build_cond_br(irb, child_scope, node, cond, body_block, end_block, is_comptime));
4971
+ IrBasicBlock *after_cond_block = irb->current_basic_block;
4972
+ IrInstruction *void_else_value = else_node ? nullptr : ir_mark_gen(ir_build_const_void(irb, parent_scope, node));
4973
+ ir_mark_gen(ir_build_cond_br(irb, child_scope, node, cond, body_block, else_block, is_comptime));
4927
4974
4928
4975
ir_set_cursor_at_end(irb, body_block);
4929
4976
IrInstruction *elem_ptr = ir_build_elem_ptr(irb, child_scope, node, array_val_ptr, index_val, false);
@@ -4935,10 +4982,9 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, Scope *parent_scope, AstNo
4935
4982
}
4936
4983
ir_mark_gen(ir_build_store_ptr(irb, child_scope, node, elem_var_ptr, elem_val));
4937
4984
4938
- LoopStackItem *loop_stack_item = irb->loop_stack.add_one();
4939
- loop_stack_item->break_block = end_block;
4940
- loop_stack_item->continue_block = continue_block;
4941
- loop_stack_item->is_comptime = is_comptime;
4985
+ ZigList<IrInstruction *> incoming_values = {0};
4986
+ ZigList<IrBasicBlock *> incoming_blocks = {0};
4987
+ add_loop_stack_item(irb, end_block, continue_block, is_comptime, &incoming_blocks, &incoming_values);
4942
4988
IrInstruction *body_result = ir_gen_node(irb, body_node, child_scope);
4943
4989
irb->loop_stack.pop();
4944
4990
@@ -4950,9 +4996,28 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, Scope *parent_scope, AstNo
4950
4996
ir_mark_gen(ir_build_store_ptr(irb, child_scope, node, index_ptr, new_index_val));
4951
4997
ir_build_br(irb, child_scope, node, cond_block, is_comptime);
4952
4998
4999
+ IrInstruction *else_result = nullptr;
5000
+ if (else_node) {
5001
+ ir_set_cursor_at_end(irb, else_block);
5002
+
5003
+ else_result = ir_gen_node(irb, else_node, parent_scope);
5004
+ if (else_result == irb->codegen->invalid_instruction)
5005
+ return else_result;
5006
+ if (!instr_is_unreachable(else_result))
5007
+ ir_mark_gen(ir_build_br(irb, parent_scope, node, end_block, is_comptime));
5008
+ }
5009
+ IrBasicBlock *after_else_block = irb->current_basic_block;
4953
5010
ir_set_cursor_at_end(irb, end_block);
4954
- return ir_build_const_void(irb, child_scope, node);
4955
5011
5012
+ if (else_result) {
5013
+ incoming_blocks.append(after_else_block);
5014
+ incoming_values.append(else_result);
5015
+ } else {
5016
+ incoming_blocks.append(after_cond_block);
5017
+ incoming_values.append(void_else_value);
5018
+ }
5019
+
5020
+ return ir_build_phi(irb, parent_scope, node, incoming_blocks.length, incoming_blocks.items, incoming_values.items);
4956
5021
}
4957
5022
4958
5023
static IrInstruction *ir_gen_this_literal(IrBuilder *irb, Scope *scope, AstNode *node) {
@@ -5512,8 +5577,20 @@ static IrInstruction *ir_gen_break(IrBuilder *irb, Scope *scope, AstNode *node)
5512
5577
is_comptime = loop_stack_item->is_comptime;
5513
5578
}
5514
5579
5580
+ IrInstruction *result_value;
5581
+ if (node->data.break_expr.expr) {
5582
+ result_value = ir_gen_node(irb, node->data.break_expr.expr, scope);
5583
+ if (result_value == irb->codegen->invalid_instruction)
5584
+ return irb->codegen->invalid_instruction;
5585
+ } else {
5586
+ result_value = ir_build_const_void(irb, scope, node);
5587
+ }
5588
+
5515
5589
IrBasicBlock *dest_block = loop_stack_item->break_block;
5516
5590
ir_gen_defers_for_block(irb, scope, dest_block->scope, false);
5591
+
5592
+ loop_stack_item->incoming_blocks->append(irb->current_basic_block);
5593
+ loop_stack_item->incoming_values->append(result_value);
5517
5594
return ir_build_br(irb, scope, node, dest_block, is_comptime);
5518
5595
}
5519
5596
0 commit comments