authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-10-27 01:52:06-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-10-27 01:52:06-04:00
log78e6314422bda10440dccf7e7fcfe294193cdca7
tree99fe95b73ebc28bd31e2ff08e06f96ea09919f88
parentbfcd6648e70bfe647b6fea9d6d9a024c4a9169d4

IR: phi instruction works at compile time


1 files changed, 34 insertions(+), 2 deletions(-)

src/ir.cpp+34-2
......@@ -26,6 +26,7 @@ struct IrAnalyze {
2626 size_t instruction_index;
2727 TypeTableEntry *explicit_return_type;
2828 ZigList<IrInstruction *> implicit_return_type_list;
29 IrBasicBlock *const_predecessor_bb;
2930};
3031
3132static IrInstruction *ir_gen_node(IrBuilder *irb, AstNode *node, BlockContext *scope);
......@@ -397,6 +398,8 @@ static IrInstruction *ir_build_phi_from(IrBuilder *irb, IrInstruction *old_instr
397398
398399static IrInstruction *ir_build_br(IrBuilder *irb, AstNode *source_node, IrBasicBlock *dest_block) {
399400 IrInstructionBr *br_instruction = ir_build_instruction<IrInstructionBr>(irb, source_node);
401 br_instruction->base.type_entry = irb->codegen->builtin_types.entry_unreachable;
402 br_instruction->base.static_value.ok = true;
400403 br_instruction->dest_block = dest_block;
401404
402405 ir_ref_bb(dest_block);
......@@ -1618,12 +1621,13 @@ static void ir_finish_bb(IrAnalyze *ira) {
16181621 ira->instruction_index = 0;
16191622 ira->new_irb.current_basic_block = ir_get_new_bb(ira, old_bb);
16201623 ira->old_irb.current_basic_block = old_bb;
1624 ira->const_predecessor_bb = nullptr;
16211625 }
16221626}
16231627
16241628static void ir_inline_bb(IrAnalyze *ira, IrBasicBlock *old_bb) {
16251629 ira->instruction_index = 0;
1626
1630 ira->const_predecessor_bb = ira->old_irb.current_basic_block;
16271631 ira->old_irb.current_basic_block = old_bb;
16281632}
16291633
......@@ -2470,7 +2474,10 @@ static TypeTableEntry *ir_analyze_instruction_call(IrAnalyze *ira, IrInstruction
24702474
24712475 ir_build_call_from(&ira->new_irb, &call_instruction->base,
24722476 call_instruction->fn, call_instruction->arg_count, call_instruction->args);
2473 return fn_table_entry->type_entry;
2477
2478 TypeTableEntry *fn_type = fn_table_entry->type_entry;
2479 TypeTableEntry *return_type = fn_type->data.fn.fn_type_id.return_type;
2480 return return_type;
24742481 } else {
24752482 zig_panic("TODO analyze more fn call types");
24762483 }
......@@ -3946,6 +3953,24 @@ static TypeTableEntry *ir_analyze_instruction_unreachable(IrAnalyze *ira,
39463953}
39473954
39483955static TypeTableEntry *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionPhi *phi_instruction) {
3956 if (ira->const_predecessor_bb) {
3957 for (size_t i = 0; i < phi_instruction->incoming_count; i += 1) {
3958 IrBasicBlock *predecessor = phi_instruction->incoming_blocks[i];
3959 if (predecessor != ira->const_predecessor_bb)
3960 continue;
3961 IrInstruction *value = phi_instruction->incoming_values[i]->other;
3962 assert(value->type_entry);
3963 if (value->static_value.ok) {
3964 ConstExprValue *out_val = ir_get_out_val(&phi_instruction->base);
3965 *out_val = value->static_value;
3966 } else {
3967 phi_instruction->base.other = value;
3968 }
3969 return value->type_entry;
3970 }
3971 zig_unreachable();
3972 }
3973
39493974 ZigList<IrBasicBlock*> new_incoming_blocks = {0};
39503975 ZigList<IrInstruction*> new_incoming_values = {0};
39513976
......@@ -4094,6 +4119,8 @@ static TypeTableEntry *ir_analyze_instruction(IrAnalyze *ira, IrInstruction *ins
40944119{
40954120 TypeTableEntry *instruction_type = ir_analyze_instruction_nocast(ira, instruction);
40964121 instruction->type_entry = instruction_type;
4122 if (instruction->other)
4123 instruction->other->type_entry = instruction_type;
40974124
40984125 IrInstruction *casted_instruction = ir_get_casted_value(ira, instruction, expected_type);
40994126 return casted_instruction->type_entry;
......@@ -4128,6 +4155,11 @@ TypeTableEntry *ir_analyze(CodeGen *codegen, IrExecutable *old_exec, IrExecutabl
41284155
41294156 while (ira->block_queue_index < ira->block_queue.length) {
41304157 IrInstruction *old_instruction = ira->old_irb.current_basic_block->instruction_list.at(ira->instruction_index);
4158 if (old_instruction->ref_count == 0 && !ir_has_side_effects(old_instruction)) {
4159 ira->instruction_index += 1;
4160 continue;
4161 }
4162
41314163 TypeTableEntry *return_type = ir_analyze_instruction(ira, old_instruction, nullptr);
41324164
41334165 // unreachable instructions do their own control flow.