| ... | ... | @@ -196,6 +196,8 @@ static IrInstruction *ir_analyze_unwrap_error_payload(IrAnalyze *ira, IrInstruct |
| 196 | 196 | IrInstruction *base_ptr, bool safety_check_on, bool initializing); |
| 197 | 197 | static IrInstruction *ir_analyze_unwrap_err_code(IrAnalyze *ira, IrInstruction *source_instr, |
| 198 | 198 | IrInstruction *base_ptr, bool initializing); |
| 199 | static IrInstruction *ir_analyze_store_ptr(IrAnalyze *ira, IrInstruction *source_instr, |
| 200 | IrInstruction *ptr, IrInstruction *uncasted_value); |
| 199 | 201 | |
| 200 | 202 | static ConstExprValue *const_ptr_pointee_unchecked(CodeGen *g, ConstExprValue *const_val) { |
| 201 | 203 | assert(get_src_ptr_type(const_val->type) != nullptr); |
| ... | ... | @@ -3363,7 +3365,6 @@ static void ir_count_defers(IrBuilder *irb, Scope *inner_scope, Scope *outer_sco |
| 3363 | 3365 | case ScopeIdSuspend: |
| 3364 | 3366 | case ScopeIdCompTime: |
| 3365 | 3367 | case ScopeIdRuntime: |
| 3366 | | case ScopeIdElide: |
| 3367 | 3368 | scope = scope->parent; |
| 3368 | 3369 | continue; |
| 3369 | 3370 | case ScopeIdDeferExpr: |
| ... | ... | @@ -3420,7 +3421,6 @@ static bool ir_gen_defers_for_block(IrBuilder *irb, Scope *inner_scope, Scope *o |
| 3420 | 3421 | case ScopeIdSuspend: |
| 3421 | 3422 | case ScopeIdCompTime: |
| 3422 | 3423 | case ScopeIdRuntime: |
| 3423 | | case ScopeIdElide: |
| 3424 | 3424 | scope = scope->parent; |
| 3425 | 3425 | continue; |
| 3426 | 3426 | case ScopeIdDeferExpr: |
| ... | ... | @@ -5758,15 +5758,8 @@ static IrInstruction *ir_gen_container_init_expr(IrBuilder *irb, Scope *scope, A |
| 5758 | 5758 | return irb->codegen->invalid_instruction; |
| 5759 | 5759 | } |
| 5760 | 5760 | |
| 5761 | | IrInstruction *container_ptr = nullptr; |
| 5762 | | if (!ir_should_inline(irb->exec, scope)) { |
| 5763 | | src_assert(parent_result_loc->scope_elide == nullptr, node); |
| 5764 | | parent_result_loc->scope_elide = create_elide_scope(irb->codegen, node, scope); |
| 5765 | | |
| 5766 | | src_assert(parent_result_loc != nullptr, node); |
| 5767 | | container_ptr = ir_build_resolve_result(irb, &parent_result_loc->scope_elide->base, |
| 5768 | | node, parent_result_loc, container_type); |
| 5769 | | } |
| 5761 | IrInstruction *container_ptr = ir_build_resolve_result(irb, scope, node, parent_result_loc, |
| 5762 | container_type); |
| 5770 | 5763 | |
| 5771 | 5764 | size_t field_count = container_init_expr->entries.length; |
| 5772 | 5765 | IrInstructionContainerInitFieldsField *fields = allocate<IrInstructionContainerInitFieldsField>(field_count); |
| ... | ... | @@ -5777,27 +5770,22 @@ static IrInstruction *ir_gen_container_init_expr(IrBuilder *irb, Scope *scope, A |
| 5777 | 5770 | Buf *name = entry_node->data.struct_val_field.name; |
| 5778 | 5771 | AstNode *expr_node = entry_node->data.struct_val_field.expr; |
| 5779 | 5772 | |
| 5780 | | Scope *val_scope = scope; |
| 5781 | | ResultLoc *child_result_loc = nullptr; |
| 5782 | | if (container_ptr != nullptr) { |
| 5783 | | IrInstruction *field_ptr = ir_build_field_ptr(irb, &parent_result_loc->scope_elide->base, |
| 5784 | | expr_node, container_ptr, name, true); |
| 5785 | | ResultLocInstruction *result_loc_inst = allocate<ResultLocInstruction>(1); |
| 5786 | | result_loc_inst->base.id = ResultLocIdInstruction; |
| 5787 | | result_loc_inst->base.source_instruction = field_ptr; |
| 5788 | | ir_ref_instruction(field_ptr, irb->current_basic_block); |
| 5789 | | child_result_loc = &result_loc_inst->base; |
| 5790 | | val_scope = &parent_result_loc->scope_elide->base; |
| 5791 | | } |
| 5773 | IrInstruction *field_ptr = ir_build_field_ptr(irb, scope, expr_node, container_ptr, name, true); |
| 5774 | ResultLocInstruction *result_loc_inst = allocate<ResultLocInstruction>(1); |
| 5775 | result_loc_inst->base.id = ResultLocIdInstruction; |
| 5776 | result_loc_inst->base.source_instruction = field_ptr; |
| 5777 | ir_ref_instruction(field_ptr, irb->current_basic_block); |
| 5778 | ir_build_reset_result(irb, scope, expr_node, &result_loc_inst->base); |
| 5792 | 5779 | |
| 5793 | | IrInstruction *expr_value = ir_gen_node_extra(irb, expr_node, val_scope, LValNone, |
| 5794 | | child_result_loc); |
| 5780 | IrInstruction *expr_value = ir_gen_node_extra(irb, expr_node, scope, LValNone, |
| 5781 | &result_loc_inst->base); |
| 5795 | 5782 | if (expr_value == irb->codegen->invalid_instruction) |
| 5796 | 5783 | return expr_value; |
| 5797 | 5784 | |
| 5798 | 5785 | fields[i].name = name; |
| 5799 | 5786 | fields[i].value = expr_value; |
| 5800 | 5787 | fields[i].source_node = entry_node; |
| 5788 | fields[i].result_loc = field_ptr; |
| 5801 | 5789 | } |
| 5802 | 5790 | IrInstruction *init_fields = ir_build_container_init_fields(irb, scope, node, container_type, |
| 5803 | 5791 | field_count, fields, container_ptr); |
| ... | ... | @@ -5812,36 +5800,23 @@ static IrInstruction *ir_gen_container_init_expr(IrBuilder *irb, Scope *scope, A |
| 5812 | 5800 | container_type = ir_build_array_type(irb, scope, node, item_count_inst, elem_type); |
| 5813 | 5801 | } |
| 5814 | 5802 | |
| 5815 | | IrInstruction *container_ptr = nullptr; |
| 5816 | | if (!ir_should_inline(irb->exec, scope)) { |
| 5817 | | src_assert(parent_result_loc->scope_elide == nullptr, node); |
| 5818 | | parent_result_loc->scope_elide = create_elide_scope(irb->codegen, node, scope); |
| 5819 | | |
| 5820 | | container_ptr = ir_build_resolve_result(irb, &parent_result_loc->scope_elide->base, |
| 5821 | | node, parent_result_loc, container_type); |
| 5822 | | } |
| 5803 | IrInstruction *container_ptr = ir_build_resolve_result(irb, scope, node, parent_result_loc, |
| 5804 | container_type); |
| 5823 | 5805 | |
| 5824 | 5806 | IrInstruction **values = allocate<IrInstruction *>(item_count); |
| 5825 | 5807 | for (size_t i = 0; i < item_count; i += 1) { |
| 5826 | 5808 | AstNode *expr_node = container_init_expr->entries.at(i); |
| 5827 | 5809 | |
| 5828 | | ResultLoc *child_result_loc = nullptr; |
| 5829 | | Scope *val_scope = scope; |
| 5830 | | if (container_ptr != nullptr) { |
| 5831 | | IrInstruction *elem_index = ir_build_const_usize(irb, &parent_result_loc->scope_elide->base, |
| 5832 | | expr_node, i); |
| 5833 | | IrInstruction *elem_ptr = ir_build_elem_ptr(irb, &parent_result_loc->scope_elide->base, |
| 5834 | | expr_node, container_ptr, elem_index, false, PtrLenSingle, true); |
| 5835 | | ResultLocInstruction *result_loc_inst = allocate<ResultLocInstruction>(1); |
| 5836 | | result_loc_inst->base.id = ResultLocIdInstruction; |
| 5837 | | result_loc_inst->base.source_instruction = elem_ptr; |
| 5838 | | ir_ref_instruction(elem_ptr, irb->current_basic_block); |
| 5839 | | child_result_loc = &result_loc_inst->base; |
| 5840 | | val_scope = &parent_result_loc->scope_elide->base; |
| 5841 | | } |
| 5810 | IrInstruction *elem_index = ir_build_const_usize(irb, scope, expr_node, i); |
| 5811 | IrInstruction *elem_ptr = ir_build_elem_ptr(irb, scope, expr_node, container_ptr, elem_index, |
| 5812 | false, PtrLenSingle, true); |
| 5813 | ResultLocInstruction *result_loc_inst = allocate<ResultLocInstruction>(1); |
| 5814 | result_loc_inst->base.id = ResultLocIdInstruction; |
| 5815 | result_loc_inst->base.source_instruction = elem_ptr; |
| 5816 | ir_ref_instruction(elem_ptr, irb->current_basic_block); |
| 5842 | 5817 | |
| 5843 | | IrInstruction *expr_value = ir_gen_node_extra(irb, expr_node, val_scope, LValNone, |
| 5844 | | child_result_loc); |
| 5818 | IrInstruction *expr_value = ir_gen_node_extra(irb, expr_node, scope, LValNone, |
| 5819 | &result_loc_inst->base); |
| 5845 | 5820 | if (expr_value == irb->codegen->invalid_instruction) |
| 5846 | 5821 | return expr_value; |
| 5847 | 5822 | |
| ... | ... | @@ -8651,8 +8626,6 @@ static ConstExprValue *ir_exec_const_result(CodeGen *codegen, IrExecutable *exec |
| 8651 | 8626 | IrBasicBlock *bb = exec->basic_block_list.at(0); |
| 8652 | 8627 | for (size_t i = 0; i < bb->instruction_list.length; i += 1) { |
| 8653 | 8628 | IrInstruction *instruction = bb->instruction_list.at(i); |
| 8654 | | if (scope_is_elided(instruction->scope)) |
| 8655 | | continue; |
| 8656 | 8629 | if (instruction->id == IrInstructionIdReturn) { |
| 8657 | 8630 | IrInstructionReturn *ret_inst = (IrInstructionReturn *)instruction; |
| 8658 | 8631 | IrInstruction *value = ret_inst->value; |
| ... | ... | @@ -12745,9 +12718,7 @@ static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruc |
| 12745 | 12718 | ir_add_error(ira, ptr, buf_sprintf("attempt to dereference undefined value")); |
| 12746 | 12719 | return ira->codegen->invalid_instruction; |
| 12747 | 12720 | } |
| 12748 | | if (ptr->value.data.x_ptr.mut == ConstPtrMutComptimeConst || |
| 12749 | | ptr->value.data.x_ptr.mut == ConstPtrMutComptimeVar) |
| 12750 | | { |
| 12721 | if (ptr->value.data.x_ptr.mut != ConstPtrMutRuntimeVar) { |
| 12751 | 12722 | ConstExprValue *pointee = const_ptr_pointee_unchecked(ira->codegen, &ptr->value); |
| 12752 | 12723 | if (pointee->special != ConstValSpecialRuntime) { |
| 12753 | 12724 | IrInstruction *result = ir_const(ira, source_instruction, child_type); |
| ... | ... | @@ -14487,7 +14458,25 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira, |
| 14487 | 14458 | } |
| 14488 | 14459 | |
| 14489 | 14460 | if (init_val != nullptr && init_val->special != ConstValSpecialRuntime) { |
| 14490 | | if (var->mem_slot_index != SIZE_MAX) { |
| 14461 | // Resolve ConstPtrMutInfer |
| 14462 | if (var->gen_is_const) { |
| 14463 | var_ptr->value.data.x_ptr.mut = ConstPtrMutComptimeConst; |
| 14464 | } else if (is_comptime_var) { |
| 14465 | var_ptr->value.data.x_ptr.mut = ConstPtrMutComptimeVar; |
| 14466 | } else { |
| 14467 | // we need a runtime ptr but we have a comptime val. |
| 14468 | // since it's a comptime val there are no instructions for it. |
| 14469 | // we memcpy the init value here |
| 14470 | IrInstruction *deref = ir_get_deref(ira, var_ptr, var_ptr, nullptr); |
| 14471 | // If this assertion trips, something is wrong with the IR instructions, because |
| 14472 | // we expected the above deref to return a constant value, but it created a runtime |
| 14473 | // instruction. |
| 14474 | assert(deref->value.special != ConstValSpecialRuntime); |
| 14475 | var_ptr->value.special = ConstValSpecialRuntime; |
| 14476 | ir_analyze_store_ptr(ira, var_ptr, var_ptr, deref); |
| 14477 | } |
| 14478 | |
| 14479 | if (var_ptr->value.special == ConstValSpecialStatic && var->mem_slot_index != SIZE_MAX) { |
| 14491 | 14480 | assert(var->mem_slot_index < ira->exec_context.mem_slot_list.length); |
| 14492 | 14481 | ConstExprValue *mem_slot = ira->exec_context.mem_slot_list.at(var->mem_slot_index); |
| 14493 | 14482 | copy_const_val(mem_slot, init_val, !is_comptime_var || var->gen_is_const); |
| ... | ... | @@ -14818,9 +14807,9 @@ static IrInstruction *ir_analyze_alloca(IrAnalyze *ira, IrInstruction *source_in |
| 14818 | 14807 | pointee->special = ConstValSpecialUndef; |
| 14819 | 14808 | |
| 14820 | 14809 | IrInstructionAllocaGen *result = ir_create_alloca_gen(ira, source_inst, align, name_hint); |
| 14821 | | result->base.value.special = force_comptime ? ConstValSpecialStatic : ConstValSpecialRuntime; |
| 14810 | result->base.value.special = ConstValSpecialStatic; |
| 14822 | 14811 | result->base.value.data.x_ptr.special = ConstPtrSpecialRef; |
| 14823 | | result->base.value.data.x_ptr.mut = force_comptime ? ConstPtrMutComptimeVar : ConstPtrMutRuntimeVar; |
| 14812 | result->base.value.data.x_ptr.mut = force_comptime ? ConstPtrMutComptimeVar : ConstPtrMutInfer; |
| 14824 | 14813 | result->base.value.data.x_ptr.data.ref.pointee = pointee; |
| 14825 | 14814 | |
| 14826 | 14815 | if ((err = type_resolve(ira->codegen, var_type, ResolveStatusZeroBitsKnown))) |
| ... | ... | @@ -15109,7 +15098,10 @@ static IrInstruction *ir_analyze_instruction_resolve_result(IrAnalyze *ira, IrIn |
| 15109 | 15098 | ZigType *implicit_elem_type = ir_resolve_type(ira, instruction->ty->child); |
| 15110 | 15099 | if (type_is_invalid(implicit_elem_type)) |
| 15111 | 15100 | return ira->codegen->invalid_instruction; |
| 15112 | | return ir_resolve_result(ira, &instruction->base, instruction->result_loc, implicit_elem_type, nullptr); |
| 15101 | IrInstruction *result_loc = ir_resolve_result(ira, &instruction->base, instruction->result_loc, implicit_elem_type, nullptr); |
| 15102 | if (result_loc != nullptr) |
| 15103 | return result_loc; |
| 15104 | zig_panic("TODO"); |
| 15113 | 15105 | } |
| 15114 | 15106 | |
| 15115 | 15107 | static void ir_reset_result(ResultLoc *result_loc) { |
| ... | ... | @@ -15431,7 +15423,9 @@ static IrInstruction *ir_analyze_store_ptr(IrAnalyze *ira, IrInstruction *source |
| 15431 | 15423 | ir_add_error(ira, source_instr, buf_sprintf("cannot assign to constant")); |
| 15432 | 15424 | return ira->codegen->invalid_instruction; |
| 15433 | 15425 | } |
| 15434 | | if (ptr->value.data.x_ptr.mut == ConstPtrMutComptimeVar) { |
| 15426 | if (ptr->value.data.x_ptr.mut == ConstPtrMutComptimeVar || |
| 15427 | ptr->value.data.x_ptr.mut == ConstPtrMutInfer) |
| 15428 | { |
| 15435 | 15429 | if (instr_is_comptime(value)) { |
| 15436 | 15430 | ConstExprValue *dest_val = const_ptr_pointee(ira, ira->codegen, &ptr->value, source_instr->source_node); |
| 15437 | 15431 | if (dest_val == nullptr) |
| ... | ... | @@ -15451,12 +15445,16 @@ static IrInstruction *ir_analyze_store_ptr(IrAnalyze *ira, IrInstruction *source |
| 15451 | 15445 | return ir_const_void(ira, source_instr); |
| 15452 | 15446 | } |
| 15453 | 15447 | } |
| 15454 | | ir_add_error(ira, source_instr, |
| 15455 | | buf_sprintf("cannot store runtime value in compile time variable")); |
| 15456 | | ConstExprValue *dest_val = const_ptr_pointee_unchecked(ira->codegen, &ptr->value); |
| 15457 | | dest_val->type = ira->codegen->builtin_types.entry_invalid; |
| 15448 | if (ptr->value.data.x_ptr.mut == ConstPtrMutInfer) { |
| 15449 | ptr->value.special = ConstValSpecialRuntime; |
| 15450 | } else { |
| 15451 | ir_add_error(ira, source_instr, |
| 15452 | buf_sprintf("cannot store runtime value in compile time variable")); |
| 15453 | ConstExprValue *dest_val = const_ptr_pointee_unchecked(ira->codegen, &ptr->value); |
| 15454 | dest_val->type = ira->codegen->builtin_types.entry_invalid; |
| 15458 | 15455 | |
| 15459 | | return ira->codegen->invalid_instruction; |
| 15456 | return ira->codegen->invalid_instruction; |
| 15457 | } |
| 15460 | 15458 | } |
| 15461 | 15459 | } |
| 15462 | 15460 | |
| ... | ... | @@ -17091,6 +17089,81 @@ static IrInstruction *ir_analyze_container_member_access_inner(IrAnalyze *ira, |
| 17091 | 17089 | return ira->codegen->invalid_instruction; |
| 17092 | 17090 | } |
| 17093 | 17091 | |
| 17092 | static IrInstruction *ir_analyze_struct_field_ptr(IrAnalyze *ira, IrInstruction *source_instr, |
| 17093 | TypeStructField *field, IrInstruction *struct_ptr, ZigType *struct_type, bool initializing) |
| 17094 | { |
| 17095 | switch (type_has_one_possible_value(ira->codegen, field->type_entry)) { |
| 17096 | case OnePossibleValueInvalid: |
| 17097 | return ira->codegen->invalid_instruction; |
| 17098 | case OnePossibleValueYes: { |
| 17099 | IrInstruction *elem = ir_const(ira, source_instr, field->type_entry); |
| 17100 | return ir_get_ref(ira, source_instr, elem, false, false); |
| 17101 | } |
| 17102 | case OnePossibleValueNo: |
| 17103 | break; |
| 17104 | } |
| 17105 | assert(struct_ptr->value.type->id == ZigTypeIdPointer); |
| 17106 | bool is_packed = (struct_type->data.structure.layout == ContainerLayoutPacked); |
| 17107 | uint32_t align_bytes = is_packed ? 1 : get_abi_alignment(ira->codegen, field->type_entry); |
| 17108 | uint32_t ptr_bit_offset = struct_ptr->value.type->data.pointer.bit_offset_in_host; |
| 17109 | uint32_t ptr_host_int_bytes = struct_ptr->value.type->data.pointer.host_int_bytes; |
| 17110 | uint32_t host_int_bytes_for_result_type = (ptr_host_int_bytes == 0) ? |
| 17111 | get_host_int_bytes(ira->codegen, struct_type, field) : ptr_host_int_bytes; |
| 17112 | bool is_const = struct_ptr->value.type->data.pointer.is_const; |
| 17113 | bool is_volatile = struct_ptr->value.type->data.pointer.is_volatile; |
| 17114 | ZigType *ptr_type = get_pointer_to_type_extra(ira->codegen, field->type_entry, |
| 17115 | is_const, is_volatile, PtrLenSingle, align_bytes, |
| 17116 | (uint32_t)(ptr_bit_offset + field->bit_offset_in_host), |
| 17117 | (uint32_t)host_int_bytes_for_result_type, false); |
| 17118 | if (instr_is_comptime(struct_ptr)) { |
| 17119 | ConstExprValue *ptr_val = ir_resolve_const(ira, struct_ptr, UndefBad); |
| 17120 | if (!ptr_val) |
| 17121 | return ira->codegen->invalid_instruction; |
| 17122 | |
| 17123 | if (ptr_val->data.x_ptr.special != ConstPtrSpecialHardCodedAddr) { |
| 17124 | ConstExprValue *struct_val = const_ptr_pointee(ira, ira->codegen, ptr_val, source_instr->source_node); |
| 17125 | if (struct_val == nullptr) |
| 17126 | return ira->codegen->invalid_instruction; |
| 17127 | if (type_is_invalid(struct_val->type)) |
| 17128 | return ira->codegen->invalid_instruction; |
| 17129 | if (struct_val->special == ConstValSpecialUndef && initializing) { |
| 17130 | struct_val->data.x_struct.fields = create_const_vals(struct_type->data.structure.src_field_count); |
| 17131 | struct_val->special = ConstValSpecialStatic; |
| 17132 | for (size_t i = 0; i < struct_type->data.structure.src_field_count; i += 1) { |
| 17133 | ConstExprValue *field_val = &struct_val->data.x_struct.fields[i]; |
| 17134 | field_val->special = ConstValSpecialUndef; |
| 17135 | field_val->type = struct_type->data.structure.fields[i].type_entry; |
| 17136 | ConstParent *parent = get_const_val_parent(ira->codegen, field_val); |
| 17137 | if (parent != nullptr) { |
| 17138 | parent->id = ConstParentIdStruct; |
| 17139 | parent->data.p_struct.struct_val = struct_val; |
| 17140 | parent->data.p_struct.field_index = i; |
| 17141 | } |
| 17142 | } |
| 17143 | } |
| 17144 | IrInstruction *result; |
| 17145 | if (ptr_val->data.x_ptr.mut == ConstPtrMutInfer) { |
| 17146 | result = ir_build_struct_field_ptr(&ira->new_irb, source_instr->scope, |
| 17147 | source_instr->source_node, struct_ptr, field); |
| 17148 | result->value.type = ptr_type; |
| 17149 | result->value.special = ConstValSpecialStatic; |
| 17150 | } else { |
| 17151 | result = ir_const(ira, source_instr, ptr_type); |
| 17152 | } |
| 17153 | ConstExprValue *const_val = &result->value; |
| 17154 | const_val->data.x_ptr.special = ConstPtrSpecialBaseStruct; |
| 17155 | const_val->data.x_ptr.mut = struct_ptr->value.data.x_ptr.mut; |
| 17156 | const_val->data.x_ptr.data.base_struct.struct_val = struct_val; |
| 17157 | const_val->data.x_ptr.data.base_struct.field_index = field->src_index; |
| 17158 | return result; |
| 17159 | } |
| 17160 | } |
| 17161 | IrInstruction *result = ir_build_struct_field_ptr(&ira->new_irb, source_instr->scope, source_instr->source_node, |
| 17162 | struct_ptr, field); |
| 17163 | result->value.type = ptr_type; |
| 17164 | return result; |
| 17165 | } |
| 17166 | |
| 17094 | 17167 | static IrInstruction *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_name, |
| 17095 | 17168 | IrInstruction *source_instr, IrInstruction *container_ptr, ZigType *container_type, bool initializing) |
| 17096 | 17169 | { |
| ... | ... | @@ -17101,59 +17174,10 @@ static IrInstruction *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_ |
| 17101 | 17174 | return ira->codegen->invalid_instruction; |
| 17102 | 17175 | |
| 17103 | 17176 | assert(container_ptr->value.type->id == ZigTypeIdPointer); |
| 17104 | | bool is_const = container_ptr->value.type->data.pointer.is_const; |
| 17105 | | bool is_volatile = container_ptr->value.type->data.pointer.is_volatile; |
| 17106 | 17177 | if (bare_type->id == ZigTypeIdStruct) { |
| 17107 | 17178 | TypeStructField *field = find_struct_type_field(bare_type, field_name); |
| 17108 | | if (field) { |
| 17109 | | switch (type_has_one_possible_value(ira->codegen, field->type_entry)) { |
| 17110 | | case OnePossibleValueInvalid: |
| 17111 | | return ira->codegen->invalid_instruction; |
| 17112 | | case OnePossibleValueYes: { |
| 17113 | | IrInstruction *elem = ir_const(ira, source_instr, field->type_entry); |
| 17114 | | return ir_get_ref(ira, source_instr, elem, false, false); |
| 17115 | | } |
| 17116 | | case OnePossibleValueNo: |
| 17117 | | break; |
| 17118 | | } |
| 17119 | | bool is_packed = (bare_type->data.structure.layout == ContainerLayoutPacked); |
| 17120 | | uint32_t align_bytes = is_packed ? 1 : get_abi_alignment(ira->codegen, field->type_entry); |
| 17121 | | uint32_t ptr_bit_offset = container_ptr->value.type->data.pointer.bit_offset_in_host; |
| 17122 | | uint32_t ptr_host_int_bytes = container_ptr->value.type->data.pointer.host_int_bytes; |
| 17123 | | uint32_t host_int_bytes_for_result_type = (ptr_host_int_bytes == 0) ? |
| 17124 | | get_host_int_bytes(ira->codegen, bare_type, field) : ptr_host_int_bytes; |
| 17125 | | if (instr_is_comptime(container_ptr)) { |
| 17126 | | ConstExprValue *ptr_val = ir_resolve_const(ira, container_ptr, UndefBad); |
| 17127 | | if (!ptr_val) |
| 17128 | | return ira->codegen->invalid_instruction; |
| 17129 | | |
| 17130 | | if (ptr_val->data.x_ptr.special != ConstPtrSpecialHardCodedAddr) { |
| 17131 | | ConstExprValue *struct_val = const_ptr_pointee(ira, ira->codegen, ptr_val, source_instr->source_node); |
| 17132 | | if (struct_val == nullptr) |
| 17133 | | return ira->codegen->invalid_instruction; |
| 17134 | | if (type_is_invalid(struct_val->type)) |
| 17135 | | return ira->codegen->invalid_instruction; |
| 17136 | | ZigType *ptr_type = get_pointer_to_type_extra(ira->codegen, field->type_entry, |
| 17137 | | is_const, is_volatile, PtrLenSingle, align_bytes, |
| 17138 | | (uint32_t)(ptr_bit_offset + field->bit_offset_in_host), |
| 17139 | | (uint32_t)host_int_bytes_for_result_type, false); |
| 17140 | | IrInstruction *result = ir_const(ira, source_instr, ptr_type); |
| 17141 | | ConstExprValue *const_val = &result->value; |
| 17142 | | const_val->data.x_ptr.special = ConstPtrSpecialBaseStruct; |
| 17143 | | const_val->data.x_ptr.mut = container_ptr->value.data.x_ptr.mut; |
| 17144 | | const_val->data.x_ptr.data.base_struct.struct_val = struct_val; |
| 17145 | | const_val->data.x_ptr.data.base_struct.field_index = field->src_index; |
| 17146 | | return result; |
| 17147 | | } |
| 17148 | | } |
| 17149 | | IrInstruction *result = ir_build_struct_field_ptr(&ira->new_irb, source_instr->scope, source_instr->source_node, |
| 17150 | | container_ptr, field); |
| 17151 | | result->value.type = get_pointer_to_type_extra(ira->codegen, field->type_entry, is_const, is_volatile, |
| 17152 | | PtrLenSingle, |
| 17153 | | align_bytes, |
| 17154 | | (uint32_t)(ptr_bit_offset + field->bit_offset_in_host), |
| 17155 | | host_int_bytes_for_result_type, false); |
| 17156 | | return result; |
| 17179 | if (field != nullptr) { |
| 17180 | return ir_analyze_struct_field_ptr(ira, source_instr, field, container_ptr, bare_type, initializing); |
| 17157 | 17181 | } else { |
| 17158 | 17182 | return ir_analyze_container_member_access_inner(ira, bare_type, field_name, |
| 17159 | 17183 | source_instr, container_ptr, container_type); |
| ... | ... | @@ -17162,6 +17186,9 @@ static IrInstruction *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_ |
| 17162 | 17186 | return ir_analyze_container_member_access_inner(ira, bare_type, field_name, |
| 17163 | 17187 | source_instr, container_ptr, container_type); |
| 17164 | 17188 | } else if (bare_type->id == ZigTypeIdUnion) { |
| 17189 | bool is_const = container_ptr->value.type->data.pointer.is_const; |
| 17190 | bool is_volatile = container_ptr->value.type->data.pointer.is_volatile; |
| 17191 | |
| 17165 | 17192 | TypeUnionField *field = find_union_type_field(bare_type, field_name); |
| 17166 | 17193 | if (field) { |
| 17167 | 17194 | if (instr_is_comptime(container_ptr)) { |
| ... | ... | @@ -18849,7 +18876,7 @@ static IrInstruction *ir_analyze_instruction_ref(IrAnalyze *ira, IrInstructionRe |
| 18849 | 18876 | |
| 18850 | 18877 | static IrInstruction *ir_analyze_container_init_fields_union(IrAnalyze *ira, IrInstruction *instruction, |
| 18851 | 18878 | ZigType *container_type, size_t instr_field_count, IrInstructionContainerInitFieldsField *fields, |
| 18852 | | IrInstruction *old_result_loc) |
| 18879 | IrInstruction *result_loc) |
| 18853 | 18880 | { |
| 18854 | 18881 | Error err; |
| 18855 | 18882 | assert(container_type->id == ZigTypeIdUnion); |
| ... | ... | @@ -18905,21 +18932,17 @@ static IrInstruction *ir_analyze_container_init_fields_union(IrAnalyze *ira, IrI |
| 18905 | 18932 | return result; |
| 18906 | 18933 | } |
| 18907 | 18934 | |
| 18908 | | ir_assert(old_result_loc != nullptr, instruction); |
| 18909 | | IrInstruction *result_loc = old_result_loc->child; |
| 18910 | | if (type_is_invalid(result_loc->value.type)) |
| 18911 | | return result_loc; |
| 18912 | 18935 | return ir_get_deref(ira, instruction, result_loc, nullptr); |
| 18913 | 18936 | } |
| 18914 | 18937 | |
| 18915 | 18938 | static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruction *instruction, |
| 18916 | 18939 | ZigType *container_type, size_t instr_field_count, IrInstructionContainerInitFieldsField *fields, |
| 18917 | | IrInstruction *old_result_loc) |
| 18940 | IrInstruction *result_loc) |
| 18918 | 18941 | { |
| 18919 | 18942 | Error err; |
| 18920 | 18943 | if (container_type->id == ZigTypeIdUnion) { |
| 18921 | 18944 | return ir_analyze_container_init_fields_union(ira, instruction, container_type, instr_field_count, |
| 18922 | | fields, old_result_loc); |
| 18945 | fields, result_loc); |
| 18923 | 18946 | } |
| 18924 | 18947 | if (container_type->id != ZigTypeIdStruct || is_slice(container_type)) { |
| 18925 | 18948 | ir_add_error(ira, instruction, |
| ... | ... | @@ -18936,20 +18959,28 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc |
| 18936 | 18959 | IrInstruction *first_non_const_instruction = nullptr; |
| 18937 | 18960 | |
| 18938 | 18961 | AstNode **field_assign_nodes = allocate<AstNode *>(actual_field_count); |
| 18962 | ZigList<IrInstruction *> const_ptrs = {}; |
| 18939 | 18963 | |
| 18940 | 18964 | bool is_comptime = ir_should_inline(ira->new_irb.exec, instruction->scope) |
| 18941 | 18965 | || type_requires_comptime(ira->codegen, container_type) == ReqCompTimeYes; |
| 18942 | 18966 | |
| 18943 | | ConstExprValue const_val = {}; |
| 18944 | | const_val.special = ConstValSpecialStatic; |
| 18945 | | const_val.type = container_type; |
| 18946 | | // const_val.global_refs = allocate<ConstGlobalRefs>(1); |
| 18947 | | const_val.data.x_struct.fields = create_const_vals(actual_field_count); |
| 18967 | |
| 18968 | // Here we iterate over the fields that have been initialized, and emit |
| 18969 | // compile errors for missing fields and duplicate fields. |
| 18970 | // It is only now that we find out whether the struct initialization can be a comptime |
| 18971 | // value, but we have already emitted runtime instructions for the fields that |
| 18972 | // were initialized with runtime values, and have omitted instructions that would have |
| 18973 | // initialized fields with comptime values. |
| 18974 | // So now we must clean up this situation. If it turns out the struct initialization can |
| 18975 | // be a comptime value, overwrite ConstPtrMutInfer with ConstPtrMutComptimeConst. |
| 18976 | // Otherwise, we must emit instructions to runtime-initialize the fields that have |
| 18977 | // comptime-known values. |
| 18978 | |
| 18948 | 18979 | for (size_t i = 0; i < instr_field_count; i += 1) { |
| 18949 | 18980 | IrInstructionContainerInitFieldsField *field = &fields[i]; |
| 18950 | 18981 | |
| 18951 | | IrInstruction *field_value = field->value->child; |
| 18952 | | if (type_is_invalid(field_value->value.type)) |
| 18982 | IrInstruction *field_result_loc = field->result_loc->child; |
| 18983 | if (type_is_invalid(field_result_loc->value.type)) |
| 18953 | 18984 | return ira->codegen->invalid_instruction; |
| 18954 | 18985 | |
| 18955 | 18986 | TypeStructField *type_field = find_struct_type_field(container_type, field->name); |
| ... | ... | @@ -18963,10 +18994,6 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc |
| 18963 | 18994 | if (type_is_invalid(type_field->type_entry)) |
| 18964 | 18995 | return ira->codegen->invalid_instruction; |
| 18965 | 18996 | |
| 18966 | | IrInstruction *casted_field_value = ir_implicit_cast(ira, field_value, type_field->type_entry); |
| 18967 | | if (casted_field_value == ira->codegen->invalid_instruction) |
| 18968 | | return ira->codegen->invalid_instruction; |
| 18969 | | |
| 18970 | 18997 | size_t field_index = type_field->src_index; |
| 18971 | 18998 | AstNode *existing_assign_node = field_assign_nodes[field_index]; |
| 18972 | 18999 | if (existing_assign_node) { |
| ... | ... | @@ -18976,23 +19003,18 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc |
| 18976 | 19003 | } |
| 18977 | 19004 | field_assign_nodes[field_index] = field->source_node; |
| 18978 | 19005 | |
| 18979 | | if (const_val.special == ConstValSpecialStatic) { |
| 18980 | | if (is_comptime || casted_field_value->value.special != ConstValSpecialRuntime) { |
| 18981 | | ConstExprValue *field_val = ir_resolve_const(ira, casted_field_value, UndefOk); |
| 18982 | | if (!field_val) |
| 18983 | | return ira->codegen->invalid_instruction; |
| 18984 | | |
| 18985 | | copy_const_val(&const_val.data.x_struct.fields[field_index], field_val, true); |
| 18986 | | } else { |
| 18987 | | first_non_const_instruction = casted_field_value; |
| 18988 | | const_val.special = ConstValSpecialRuntime; |
| 18989 | | } |
| 19006 | if (instr_is_comptime(field_result_loc) && |
| 19007 | field_result_loc->value.data.x_ptr.mut != ConstPtrMutRuntimeVar) |
| 19008 | { |
| 19009 | const_ptrs.append(field_result_loc); |
| 19010 | } else { |
| 19011 | first_non_const_instruction = field_result_loc; |
| 18990 | 19012 | } |
| 18991 | 19013 | } |
| 18992 | 19014 | |
| 18993 | 19015 | bool any_missing = false; |
| 18994 | 19016 | for (size_t i = 0; i < actual_field_count; i += 1) { |
| 18995 | | if (field_assign_nodes[i]) continue; |
| 19017 | if (field_assign_nodes[i] != nullptr) continue; |
| 18996 | 19018 | |
| 18997 | 19019 | // look for a default field value |
| 18998 | 19020 | TypeStructField *field = &container_type->data.structure.fields[i]; |
| ... | ... | @@ -19018,44 +19040,41 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc |
| 19018 | 19040 | IrInstruction *runtime_inst = ir_const(ira, instruction, field->init_val->type); |
| 19019 | 19041 | copy_const_val(&runtime_inst->value, field->init_val, true); |
| 19020 | 19042 | |
| 19021 | | if (const_val.special == ConstValSpecialStatic) { |
| 19022 | | copy_const_val(&const_val.data.x_struct.fields[i], field->init_val, true); |
| 19043 | IrInstruction *field_ptr = ir_analyze_struct_field_ptr(ira, instruction, field, result_loc, |
| 19044 | container_type, true); |
| 19045 | ir_analyze_store_ptr(ira, instruction, field_ptr, runtime_inst); |
| 19046 | if (instr_is_comptime(field_ptr) && field_ptr->value.data.x_ptr.mut != ConstPtrMutRuntimeVar) { |
| 19047 | const_ptrs.append(field_ptr); |
| 19048 | } else { |
| 19049 | first_non_const_instruction = result_loc; |
| 19023 | 19050 | } |
| 19024 | 19051 | } |
| 19025 | 19052 | if (any_missing) |
| 19026 | 19053 | return ira->codegen->invalid_instruction; |
| 19027 | 19054 | |
| 19028 | | if (const_val.special == ConstValSpecialStatic) { |
| 19029 | | IrInstruction *result = ir_const(ira, instruction, nullptr); |
| 19030 | | ConstExprValue *out_val = &result->value; |
| 19031 | | copy_const_val(out_val, &const_val, false); |
| 19032 | | out_val->type = container_type; |
| 19033 | | |
| 19034 | | for (size_t i = 0; i < instr_field_count; i += 1) { |
| 19035 | | ConstExprValue *field_val = &out_val->data.x_struct.fields[i]; |
| 19036 | | ConstParent *parent = get_const_val_parent(ira->codegen, field_val); |
| 19037 | | if (parent != nullptr) { |
| 19038 | | parent->id = ConstParentIdStruct; |
| 19039 | | parent->data.p_struct.field_index = i; |
| 19040 | | parent->data.p_struct.struct_val = out_val; |
| 19055 | if (result_loc->value.data.x_ptr.mut == ConstPtrMutInfer) { |
| 19056 | if (const_ptrs.length == actual_field_count) { |
| 19057 | result_loc->value.data.x_ptr.mut = ConstPtrMutComptimeConst; |
| 19058 | } else { |
| 19059 | result_loc->value.special = ConstValSpecialRuntime; |
| 19060 | for (size_t i = 0; i < const_ptrs.length; i += 1) { |
| 19061 | IrInstruction *field_result_loc = const_ptrs.at(i); |
| 19062 | IrInstruction *deref = ir_get_deref(ira, field_result_loc, field_result_loc, nullptr); |
| 19063 | field_result_loc->value.special = ConstValSpecialRuntime; |
| 19064 | ir_analyze_store_ptr(ira, field_result_loc, field_result_loc, deref); |
| 19041 | 19065 | } |
| 19042 | 19066 | } |
| 19043 | | |
| 19044 | | return result; |
| 19045 | 19067 | } |
| 19046 | 19068 | |
| 19047 | | if (is_comptime) { |
| 19069 | IrInstruction *result = ir_get_deref(ira, instruction, result_loc, nullptr); |
| 19070 | |
| 19071 | if (is_comptime && !instr_is_comptime(result)) { |
| 19048 | 19072 | ir_add_error_node(ira, first_non_const_instruction->source_node, |
| 19049 | 19073 | buf_sprintf("unable to evaluate constant expression")); |
| 19050 | 19074 | return ira->codegen->invalid_instruction; |
| 19051 | 19075 | } |
| 19052 | 19076 | |
| 19053 | | |
| 19054 | | ir_assert(old_result_loc != nullptr, instruction); |
| 19055 | | IrInstruction *result_loc = old_result_loc->child; |
| 19056 | | if (type_is_invalid(result_loc->value.type)) |
| 19057 | | return result_loc; |
| 19058 | | return ir_get_deref(ira, instruction, result_loc, nullptr); |
| 19077 | return result; |
| 19059 | 19078 | } |
| 19060 | 19079 | |
| 19061 | 19080 | static IrInstruction *ir_analyze_instruction_container_init_list(IrAnalyze *ira, |
| ... | ... | @@ -19074,8 +19093,11 @@ static IrInstruction *ir_analyze_instruction_container_init_list(IrAnalyze *ira, |
| 19074 | 19093 | buf_sprintf("expected array type or [_], found slice")); |
| 19075 | 19094 | return ira->codegen->invalid_instruction; |
| 19076 | 19095 | } else if (container_type->id == ZigTypeIdStruct && !is_slice(container_type) && elem_count == 0) { |
| 19077 | | return ir_analyze_container_init_fields(ira, &instruction->base, container_type, 0, nullptr, |
| 19078 | | instruction->result_loc); |
| 19096 | ir_assert(instruction->result_loc != nullptr, &instruction->base); |
| 19097 | IrInstruction *result_loc = instruction->result_loc->child; |
| 19098 | if (type_is_invalid(result_loc->value.type)) |
| 19099 | return result_loc; |
| 19100 | return ir_analyze_container_init_fields(ira, &instruction->base, container_type, 0, nullptr, result_loc); |
| 19079 | 19101 | } else if (container_type->id == ZigTypeIdArray) { |
| 19080 | 19102 | // array is same as slice init but we make a compile error if the length is wrong |
| 19081 | 19103 | ZigType *child_type; |
| ... | ... | @@ -19199,8 +19221,13 @@ static IrInstruction *ir_analyze_instruction_container_init_fields(IrAnalyze *ir |
| 19199 | 19221 | if (type_is_invalid(container_type)) |
| 19200 | 19222 | return ira->codegen->invalid_instruction; |
| 19201 | 19223 | |
| 19224 | ir_assert(instruction->result_loc != nullptr, &instruction->base); |
| 19225 | IrInstruction *result_loc = instruction->result_loc->child; |
| 19226 | if (type_is_invalid(result_loc->value.type)) |
| 19227 | return result_loc; |
| 19228 | |
| 19202 | 19229 | return ir_analyze_container_init_fields(ira, &instruction->base, container_type, |
| 19203 | | instruction->field_count, instruction->fields, instruction->result_loc); |
| 19230 | instruction->field_count, instruction->fields, result_loc); |
| 19204 | 19231 | } |
| 19205 | 19232 | |
| 19206 | 19233 | static IrInstruction *ir_analyze_instruction_compile_err(IrAnalyze *ira, |
| ... | ... | @@ -24390,17 +24417,7 @@ static IrInstruction *ir_analyze_instruction_end_expr(IrAnalyze *ira, IrInstruct |
| 24390 | 24417 | if (type_is_invalid(value->value.type)) |
| 24391 | 24418 | return ira->codegen->invalid_instruction; |
| 24392 | 24419 | |
| 24393 | | bool want_resolve_result; |
| 24394 | | if (instruction->result_loc->written) { |
| 24395 | | if (instruction->result_loc->scope_elide != nullptr && instr_is_comptime(value)) { |
| 24396 | | want_resolve_result = true; |
| 24397 | | instruction->result_loc->scope_elide->activated = true; |
| 24398 | | } else { |
| 24399 | | want_resolve_result = false; |
| 24400 | | } |
| 24401 | | } else { |
| 24402 | | want_resolve_result = true; |
| 24403 | | } |
| 24420 | bool want_resolve_result = !instruction->result_loc->written; |
| 24404 | 24421 | if (want_resolve_result) { |
| 24405 | 24422 | IrInstruction *result_loc = ir_resolve_result(ira, &instruction->base, instruction->result_loc, |
| 24406 | 24423 | value->value.type, value); |