| ... | ... | @@ -272,6 +272,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionArrayLen *) { |
| 272 | 272 | return IrInstructionIdArrayLen; |
| 273 | 273 | } |
| 274 | 274 | |
| 275 | static constexpr IrInstructionId ir_instruction_id(IrInstructionRef *) { |
| 276 | return IrInstructionIdRef; |
| 277 | } |
| 278 | |
| 275 | 279 | template<typename T> |
| 276 | 280 | static T *ir_create_instruction(IrExecutable *exec, AstNode *source_node) { |
| 277 | 281 | T *special_instruction = allocate<T>(1); |
| ... | ... | @@ -1112,6 +1116,21 @@ static IrInstruction *ir_build_array_len_from(IrBuilder *irb, IrInstruction *old |
| 1112 | 1116 | return new_instruction; |
| 1113 | 1117 | } |
| 1114 | 1118 | |
| 1119 | static 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 | |
| 1128 | static 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 | |
| 1115 | 1134 | static void ir_gen_defers_for_block(IrBuilder *irb, BlockContext *inner_block, BlockContext *outer_block, |
| 1116 | 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 | 2512 | return ir_build_unreachable(irb, node); |
| 2494 | 2513 | } |
| 2495 | 2514 | |
| 2515 | static 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 | |
| 2496 | 2526 | static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, BlockContext *block_context, |
| 2497 | 2527 | LValPurpose lval) |
| 2498 | 2528 | { |
| ... | ... | @@ -2509,7 +2539,7 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, BlockContex |
| 2509 | 2539 | case NodeTypeSymbol: |
| 2510 | 2540 | return ir_gen_symbol(irb, node, lval); |
| 2511 | 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 | 2543 | case NodeTypeIfBoolExpr: |
| 2514 | 2544 | return ir_gen_if_bool_expr(irb, node); |
| 2515 | 2545 | case NodeTypePrefixOpExpr: |
| ... | ... | @@ -2898,8 +2928,7 @@ static IrInstruction *ir_resolve_cast(IrAnalyze *ira, IrInstruction *source_inst |
| 2898 | 2928 | dest_type, value, cast_op); |
| 2899 | 2929 | result->type_entry = wanted_type; |
| 2900 | 2930 | if (need_alloca && source_instr->source_node->block_context->fn_entry) { |
| 2901 | | IrInstructionCast *cast_instruction = (IrInstructionCast *)result; |
| 2902 | | source_instr->source_node->block_context->fn_entry->cast_alloca_list.append(cast_instruction); |
| 2931 | source_instr->source_node->block_context->fn_entry->alloca_list.append(result); |
| 2903 | 2932 | } |
| 2904 | 2933 | return result; |
| 2905 | 2934 | } |
| ... | ... | @@ -5700,6 +5729,31 @@ static TypeTableEntry *ir_analyze_instruction_array_len(IrAnalyze *ira, |
| 5700 | 5729 | } |
| 5701 | 5730 | } |
| 5702 | 5731 | |
| 5732 | static 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 | |
| 5703 | 5757 | static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstruction *instruction) { |
| 5704 | 5758 | switch (instruction->id) { |
| 5705 | 5759 | case IrInstructionIdInvalid: |
| ... | ... | @@ -5778,6 +5832,8 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi |
| 5778 | 5832 | return ir_analyze_instruction_import(ira, (IrInstructionImport *)instruction); |
| 5779 | 5833 | case IrInstructionIdArrayLen: |
| 5780 | 5834 | return ir_analyze_instruction_array_len(ira, (IrInstructionArrayLen *)instruction); |
| 5835 | case IrInstructionIdRef: |
| 5836 | return ir_analyze_instruction_ref(ira, (IrInstructionRef *)instruction); |
| 5781 | 5837 | case IrInstructionIdCast: |
| 5782 | 5838 | case IrInstructionIdContainerInitList: |
| 5783 | 5839 | case IrInstructionIdContainerInitFields: |
| ... | ... | @@ -5901,6 +5957,7 @@ bool ir_has_side_effects(IrInstruction *instruction) { |
| 5901 | 5957 | case IrInstructionIdSwitchTarget: |
| 5902 | 5958 | case IrInstructionIdEnumTag: |
| 5903 | 5959 | case IrInstructionIdStaticEval: |
| 5960 | case IrInstructionIdRef: |
| 5904 | 5961 | return false; |
| 5905 | 5962 | case IrInstructionIdAsm: |
| 5906 | 5963 | { |