authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-11-27 01:22:30-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-11-27 01:22:30-05:00
logd9329ed389e4454c631772674beee459c7783069
tree97a126a50745427996f3ce8b14c57062451bf29c
parentbd4d4ee51efebb79ed7b563a10eec992a71220fd

IR: add ref instruction


4 files changed, 103 insertions(+), 16 deletions(-)

src/all_types.hpp+9-2
...@@ -1081,8 +1081,7 @@ struct FnTableEntry {...@@ -1081,8 +1081,7 @@ struct FnTableEntry {
1081 AstNode *fn_test_set_node;1081 AstNode *fn_test_set_node;
1082 AstNode *fn_static_eval_set_node;1082 AstNode *fn_static_eval_set_node;
10831083
1084 ZigList<IrInstructionCast *> cast_alloca_list;1084 ZigList<IrInstruction *> alloca_list;
1085 ZigList<StructValExprCodeGen *> struct_val_expr_alloca_list;
1086 ZigList<VariableTableEntry *> variable_list;1085 ZigList<VariableTableEntry *> variable_list;
1087};1086};
10881087
...@@ -1414,6 +1413,7 @@ enum IrInstructionId {...@@ -1414,6 +1413,7 @@ enum IrInstructionId {
1414 IrInstructionIdStaticEval,1413 IrInstructionIdStaticEval,
1415 IrInstructionIdImport,1414 IrInstructionIdImport,
1416 IrInstructionIdArrayLen,1415 IrInstructionIdArrayLen,
1416 IrInstructionIdRef,
1417};1417};
14181418
1419struct IrInstruction {1419struct IrInstruction {
...@@ -1771,6 +1771,13 @@ struct IrInstructionArrayLen {...@@ -1771,6 +1771,13 @@ struct IrInstructionArrayLen {
1771 IrInstruction *array_value;1771 IrInstruction *array_value;
1772};1772};
17731773
1774struct IrInstructionRef {
1775 IrInstruction base;
1776
1777 IrInstruction *value;
1778 LLVMValueRef tmp_ptr;
1779};
1780
1774enum LValPurpose {1781enum LValPurpose {
1775 LValPurposeNone,1782 LValPurposeNone,
1776 LValPurposeAssign,1783 LValPurposeAssign,
src/codegen.cpp+26-11
...@@ -1661,6 +1661,16 @@ static LLVMValueRef ir_render_phi(CodeGen *g, IrExecutable *executable, IrInstru...@@ -1661,6 +1661,16 @@ static LLVMValueRef ir_render_phi(CodeGen *g, IrExecutable *executable, IrInstru
1661 return phi;1661 return phi;
1662}1662}
16631663
1664static LLVMValueRef ir_render_ref(CodeGen *g, IrExecutable *executable, IrInstructionRef *instruction) {
1665 LLVMValueRef value = ir_llvm_value(g, instruction->value);
1666 if (handle_is_ptr(instruction->value->type_entry)) {
1667 return value;
1668 } else {
1669 LLVMBuildStore(g->builder, value, instruction->tmp_ptr);
1670 return instruction->tmp_ptr;
1671 }
1672}
1673
1664static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, IrInstruction *instruction) {1674static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, IrInstruction *instruction) {
1665 set_debug_source_node(g, instruction->source_node);1675 set_debug_source_node(g, instruction->source_node);
16661676
...@@ -1724,6 +1734,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,...@@ -1724,6 +1734,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
1724 return ir_render_switch_br(g, executable, (IrInstructionSwitchBr *)instruction);1734 return ir_render_switch_br(g, executable, (IrInstructionSwitchBr *)instruction);
1725 case IrInstructionIdPhi:1735 case IrInstructionIdPhi:
1726 return ir_render_phi(g, executable, (IrInstructionPhi *)instruction);1736 return ir_render_phi(g, executable, (IrInstructionPhi *)instruction);
1737 case IrInstructionIdRef:
1738 return ir_render_ref(g, executable, (IrInstructionRef *)instruction);
1727 case IrInstructionIdSwitchVar:1739 case IrInstructionIdSwitchVar:
1728 case IrInstructionIdContainerInitList:1740 case IrInstructionIdContainerInitList:
1729 case IrInstructionIdContainerInitFields:1741 case IrInstructionIdContainerInitFields:
...@@ -2317,17 +2329,20 @@ static void do_code_gen(CodeGen *g) {...@@ -2317,17 +2329,20 @@ static void do_code_gen(CodeGen *g) {
23172329
2318 clear_debug_source_node(g);2330 clear_debug_source_node(g);
23192331
2320 // allocate structs which are the result of casts2332 // allocate temporary stack data
2321 for (size_t cea_i = 0; cea_i < fn_table_entry->cast_alloca_list.length; cea_i += 1) {2333 for (size_t alloca_i = 0; alloca_i < fn_table_entry->alloca_list.length; alloca_i += 1) {
2322 IrInstructionCast *cast_instruction = fn_table_entry->cast_alloca_list.at(cea_i);2334 IrInstruction *instruction = fn_table_entry->alloca_list.at(alloca_i);
2323 cast_instruction->tmp_ptr = LLVMBuildAlloca(g->builder, cast_instruction->base.type_entry->type_ref, "");2335 LLVMValueRef *slot;
2324 }2336 if (instruction->id == IrInstructionIdCast) {
23252337 IrInstructionCast *cast_instruction = (IrInstructionCast *)instruction;
2326 // allocate structs which are struct value expressions2338 slot = &cast_instruction->tmp_ptr;
2327 for (size_t alloca_i = 0; alloca_i < fn_table_entry->struct_val_expr_alloca_list.length; alloca_i += 1) {2339 } else if (instruction->id == IrInstructionIdRef) {
2328 StructValExprCodeGen *struct_val_expr_node = fn_table_entry->struct_val_expr_alloca_list.at(alloca_i);2340 IrInstructionRef *ref_instruction = (IrInstructionRef *)instruction;
2329 struct_val_expr_node->ptr = LLVMBuildAlloca(g->builder,2341 slot = &ref_instruction->tmp_ptr;
2330 struct_val_expr_node->type_entry->type_ref, "");2342 } else {
2343 zig_unreachable();
2344 }
2345 *slot = LLVMBuildAlloca(g->builder, instruction->type_entry->type_ref, "");
2331 }2346 }
23322347
2333 // create debug variable declarations for variables and allocate all local variables2348 // create debug variable declarations for variables and allocate all local variables
src/ir.cpp+60-3
...@@ -272,6 +272,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionArrayLen *) {...@@ -272,6 +272,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionArrayLen *) {
272 return IrInstructionIdArrayLen;272 return IrInstructionIdArrayLen;
273}273}
274274
275static constexpr IrInstructionId ir_instruction_id(IrInstructionRef *) {
276 return IrInstructionIdRef;
277}
278
275template<typename T>279template<typename T>
276static T *ir_create_instruction(IrExecutable *exec, AstNode *source_node) {280static T *ir_create_instruction(IrExecutable *exec, AstNode *source_node) {
277 T *special_instruction = allocate<T>(1);281 T *special_instruction = allocate<T>(1);
...@@ -1112,6 +1116,21 @@ static IrInstruction *ir_build_array_len_from(IrBuilder *irb, IrInstruction *old...@@ -1112,6 +1116,21 @@ static IrInstruction *ir_build_array_len_from(IrBuilder *irb, IrInstruction *old
1112 return new_instruction;1116 return new_instruction;
1113}1117}
11141118
1119static IrInstruction *ir_build_ref(IrBuilder *irb, AstNode *source_node, IrInstruction *value) {
1120 IrInstructionRef *instruction = ir_build_instruction<IrInstructionRef>(irb, source_node);
1121 instruction->value = value;
1122
1123 ir_ref_instruction(value);
1124
1125 return &instruction->base;
1126}
1127
1128static IrInstruction *ir_build_ref_from(IrBuilder *irb, IrInstruction *old_instruction, IrInstruction *value) {
1129 IrInstruction *new_instruction = ir_build_ref(irb, old_instruction->source_node, value);
1130 ir_link_new_instruction(new_instruction, old_instruction);
1131 return new_instruction;
1132}
1133
1115static void ir_gen_defers_for_block(IrBuilder *irb, BlockContext *inner_block, BlockContext *outer_block,1134static void ir_gen_defers_for_block(IrBuilder *irb, BlockContext *inner_block, BlockContext *outer_block,
1116 bool gen_error_defers, bool gen_maybe_defers)1135 bool gen_error_defers, bool gen_maybe_defers)
1117{1136{
...@@ -2493,6 +2512,17 @@ static IrInstruction *ir_gen_goto(IrBuilder *irb, AstNode *node) {...@@ -2493,6 +2512,17 @@ static IrInstruction *ir_gen_goto(IrBuilder *irb, AstNode *node) {
2493 return ir_build_unreachable(irb, node);2512 return ir_build_unreachable(irb, node);
2494}2513}
24952514
2515static IrInstruction *ir_lval_wrap(IrBuilder *irb, IrInstruction *value, LValPurpose lval) {
2516 if (lval == LValPurposeNone)
2517 return value;
2518 if (value == irb->codegen->invalid_instruction)
2519 return value;
2520
2521 // We needed a pointer to a value, but we got a value. So we create
2522 // an instruction which just makes a const pointer of it.
2523 return ir_build_ref(irb, value->source_node, value);
2524}
2525
2496static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, BlockContext *block_context,2526static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, BlockContext *block_context,
2497 LValPurpose lval)2527 LValPurpose lval)
2498{2528{
...@@ -2509,7 +2539,7 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, BlockContex...@@ -2509,7 +2539,7 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, BlockContex
2509 case NodeTypeSymbol:2539 case NodeTypeSymbol:
2510 return ir_gen_symbol(irb, node, lval);2540 return ir_gen_symbol(irb, node, lval);
2511 case NodeTypeFnCallExpr:2541 case NodeTypeFnCallExpr:
2512 return ir_gen_fn_call(irb, node);2542 return ir_lval_wrap(irb, ir_gen_fn_call(irb, node), lval);
2513 case NodeTypeIfBoolExpr:2543 case NodeTypeIfBoolExpr:
2514 return ir_gen_if_bool_expr(irb, node);2544 return ir_gen_if_bool_expr(irb, node);
2515 case NodeTypePrefixOpExpr:2545 case NodeTypePrefixOpExpr:
...@@ -2898,8 +2928,7 @@ static IrInstruction *ir_resolve_cast(IrAnalyze *ira, IrInstruction *source_inst...@@ -2898,8 +2928,7 @@ static IrInstruction *ir_resolve_cast(IrAnalyze *ira, IrInstruction *source_inst
2898 dest_type, value, cast_op);2928 dest_type, value, cast_op);
2899 result->type_entry = wanted_type;2929 result->type_entry = wanted_type;
2900 if (need_alloca && source_instr->source_node->block_context->fn_entry) {2930 if (need_alloca && source_instr->source_node->block_context->fn_entry) {
2901 IrInstructionCast *cast_instruction = (IrInstructionCast *)result;2931 source_instr->source_node->block_context->fn_entry->alloca_list.append(result);
2902 source_instr->source_node->block_context->fn_entry->cast_alloca_list.append(cast_instruction);
2903 }2932 }
2904 return result;2933 return result;
2905 }2934 }
...@@ -5700,6 +5729,31 @@ static TypeTableEntry *ir_analyze_instruction_array_len(IrAnalyze *ira,...@@ -5700,6 +5729,31 @@ static TypeTableEntry *ir_analyze_instruction_array_len(IrAnalyze *ira,
5700 }5729 }
5701}5730}
57025731
5732static TypeTableEntry *ir_analyze_instruction_ref(IrAnalyze *ira, IrInstructionRef *ref_instruction) {
5733 IrInstruction *value = ref_instruction->value->other;
5734 if (value->type_entry->id == TypeTableEntryIdInvalid)
5735 return ira->codegen->builtin_types.entry_invalid;
5736
5737 FnTableEntry *fn_entry = ref_instruction->base.source_node->block_context->fn_entry;
5738 if (!fn_entry || value->static_value.special != ConstValSpecialRuntime) {
5739 ConstExprValue *val = ir_resolve_const(ira, value);
5740 if (!val)
5741 return ira->codegen->builtin_types.entry_invalid;
5742 return ir_analyze_const_ptr(ira, &ref_instruction->base, val, value->type_entry, false);
5743 }
5744
5745 TypeTableEntry *ptr_type = get_pointer_to_type(ira->codegen, value->type_entry, true);
5746 if (handle_is_ptr(value->type_entry)) {
5747 // this instruction is a noop - codegen can pass the pointer we already have as the result
5748 ir_link_new_instruction(value, &ref_instruction->base);
5749 return ptr_type;
5750 } else {
5751 fn_entry->alloca_list.append(&ref_instruction->base);
5752 ir_build_ref_from(&ira->new_irb, &ref_instruction->base, value);
5753 return ptr_type;
5754 }
5755}
5756
5703static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstruction *instruction) {5757static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstruction *instruction) {
5704 switch (instruction->id) {5758 switch (instruction->id) {
5705 case IrInstructionIdInvalid:5759 case IrInstructionIdInvalid:
...@@ -5778,6 +5832,8 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi...@@ -5778,6 +5832,8 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi
5778 return ir_analyze_instruction_import(ira, (IrInstructionImport *)instruction);5832 return ir_analyze_instruction_import(ira, (IrInstructionImport *)instruction);
5779 case IrInstructionIdArrayLen:5833 case IrInstructionIdArrayLen:
5780 return ir_analyze_instruction_array_len(ira, (IrInstructionArrayLen *)instruction);5834 return ir_analyze_instruction_array_len(ira, (IrInstructionArrayLen *)instruction);
5835 case IrInstructionIdRef:
5836 return ir_analyze_instruction_ref(ira, (IrInstructionRef *)instruction);
5781 case IrInstructionIdCast:5837 case IrInstructionIdCast:
5782 case IrInstructionIdContainerInitList:5838 case IrInstructionIdContainerInitList:
5783 case IrInstructionIdContainerInitFields:5839 case IrInstructionIdContainerInitFields:
...@@ -5901,6 +5957,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {...@@ -5901,6 +5957,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {
5901 case IrInstructionIdSwitchTarget:5957 case IrInstructionIdSwitchTarget:
5902 case IrInstructionIdEnumTag:5958 case IrInstructionIdEnumTag:
5903 case IrInstructionIdStaticEval:5959 case IrInstructionIdStaticEval:
5960 case IrInstructionIdRef:
5904 return false;5961 return false;
5905 case IrInstructionIdAsm:5962 case IrInstructionIdAsm:
5906 {5963 {
src/ir_print.cpp+8
...@@ -586,6 +586,11 @@ static void ir_print_array_len(IrPrint *irp, IrInstructionArrayLen *instruction)...@@ -586,6 +586,11 @@ static void ir_print_array_len(IrPrint *irp, IrInstructionArrayLen *instruction)
586 fprintf(irp->f, ".len");586 fprintf(irp->f, ".len");
587}587}
588588
589static void ir_print_ref(IrPrint *irp, IrInstructionRef *instruction) {
590 fprintf(irp->f, "ref ");
591 ir_print_other_instruction(irp, instruction->value);
592}
593
589static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {594static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
590 ir_print_prefix(irp, instruction);595 ir_print_prefix(irp, instruction);
591 switch (instruction->id) {596 switch (instruction->id) {
...@@ -714,6 +719,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {...@@ -714,6 +719,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
714 case IrInstructionIdArrayLen:719 case IrInstructionIdArrayLen:
715 ir_print_array_len(irp, (IrInstructionArrayLen *)instruction);720 ir_print_array_len(irp, (IrInstructionArrayLen *)instruction);
716 break;721 break;
722 case IrInstructionIdRef:
723 ir_print_ref(irp, (IrInstructionRef *)instruction);
724 break;
717 }725 }
718 fprintf(irp->f, "\n");726 fprintf(irp->f, "\n");
719}727}