| ... | @@ -286,6 +286,7 @@ static IrInstGen *ir_analyze_struct_value_field_value(IrAnalyze *ira, IrInst* so | ... | @@ -286,6 +286,7 @@ static IrInstGen *ir_analyze_struct_value_field_value(IrAnalyze *ira, IrInst* so |
| 286 | IrInstGen *struct_operand, TypeStructField *field); | 286 | IrInstGen *struct_operand, TypeStructField *field); |
| 287 | static bool value_cmp_numeric_val_any(ZigValue *left, Cmp predicate, ZigValue *right); | 287 | static bool value_cmp_numeric_val_any(ZigValue *left, Cmp predicate, ZigValue *right); |
| 288 | static bool value_cmp_numeric_val_all(ZigValue *left, Cmp predicate, ZigValue *right); | 288 | static bool value_cmp_numeric_val_all(ZigValue *left, Cmp predicate, ZigValue *right); |
| | 289 | static void memoize_field_init_val(CodeGen *codegen, ZigType *container_type, TypeStructField *field); |
| 289 | | 290 | |
| 290 | #define ir_assert(OK, SOURCE_INSTRUCTION) ir_assert_impl((OK), (SOURCE_INSTRUCTION), __FILE__, __LINE__) | 291 | #define ir_assert(OK, SOURCE_INSTRUCTION) ir_assert_impl((OK), (SOURCE_INSTRUCTION), __FILE__, __LINE__) |
| 291 | #define ir_assert_gen(OK, SOURCE_INSTRUCTION) ir_assert_gen_impl((OK), (SOURCE_INSTRUCTION), __FILE__, __LINE__) | 292 | #define ir_assert_gen(OK, SOURCE_INSTRUCTION) ir_assert_gen_impl((OK), (SOURCE_INSTRUCTION), __FILE__, __LINE__) |
| ... | @@ -14703,10 +14704,139 @@ static IrInstGen *ir_analyze_struct_literal_to_array(IrAnalyze *ira, IrInst* sou | ... | @@ -14703,10 +14704,139 @@ static IrInstGen *ir_analyze_struct_literal_to_array(IrAnalyze *ira, IrInst* sou |
| 14703 | } | 14704 | } |
| 14704 | | 14705 | |
| 14705 | static IrInstGen *ir_analyze_struct_literal_to_struct(IrAnalyze *ira, IrInst* source_instr, | 14706 | static IrInstGen *ir_analyze_struct_literal_to_struct(IrAnalyze *ira, IrInst* source_instr, |
| 14706 | IrInstGen *value, ZigType *wanted_type) | 14707 | IrInstGen *struct_operand, ZigType *wanted_type) |
| 14707 | { | 14708 | { |
| 14708 | ir_add_error(ira, source_instr, buf_sprintf("TODO: type coercion of anon struct literal to struct")); | 14709 | Error err; |
| 14709 | return ira->codegen->invalid_inst_gen; | 14710 | |
| | 14711 | IrInstGen *struct_ptr = ir_get_ref(ira, source_instr, struct_operand, true, false); |
| | 14712 | if (type_is_invalid(struct_ptr->value->type)) |
| | 14713 | return ira->codegen->invalid_inst_gen; |
| | 14714 | |
| | 14715 | if (wanted_type->data.structure.resolve_status == ResolveStatusBeingInferred) { |
| | 14716 | ir_add_error(ira, source_instr, buf_sprintf("type coercion of anon struct literal to inferred struct")); |
| | 14717 | return ira->codegen->invalid_inst_gen; |
| | 14718 | } |
| | 14719 | |
| | 14720 | if ((err = type_resolve(ira->codegen, wanted_type, ResolveStatusSizeKnown))) |
| | 14721 | return ira->codegen->invalid_inst_gen; |
| | 14722 | |
| | 14723 | size_t actual_field_count = wanted_type->data.structure.src_field_count; |
| | 14724 | size_t instr_field_count = struct_operand->value->type->data.structure.src_field_count; |
| | 14725 | |
| | 14726 | bool need_comptime = ir_should_inline(ira->old_irb.exec, source_instr->scope) |
| | 14727 | || type_requires_comptime(ira->codegen, wanted_type) == ReqCompTimeYes; |
| | 14728 | bool is_comptime = true; |
| | 14729 | |
| | 14730 | // Determine if the struct_operand will be comptime. |
| | 14731 | // Also emit compile errors for missing fields and duplicate fields. |
| | 14732 | AstNode **field_assign_nodes = heap::c_allocator.allocate<AstNode *>(actual_field_count); |
| | 14733 | ZigValue **field_values = heap::c_allocator.allocate<ZigValue *>(actual_field_count); |
| | 14734 | IrInstGen **casted_fields = heap::c_allocator.allocate<IrInstGen *>(actual_field_count); |
| | 14735 | IrInstGen *const_result = ir_const(ira, source_instr, wanted_type); |
| | 14736 | |
| | 14737 | for (size_t i = 0; i < instr_field_count; i += 1) { |
| | 14738 | TypeStructField *src_field = struct_operand->value->type->data.structure.fields[i]; |
| | 14739 | TypeStructField *dst_field = find_struct_type_field(wanted_type, src_field->name); |
| | 14740 | if (dst_field == nullptr) { |
| | 14741 | ErrorMsg *msg = ir_add_error(ira, source_instr, buf_sprintf("no field named '%s' in struct '%s'", |
| | 14742 | buf_ptr(src_field->name), buf_ptr(&wanted_type->name))); |
| | 14743 | if (wanted_type->data.structure.decl_node) { |
| | 14744 | add_error_note(ira->codegen, msg, wanted_type->data.structure.decl_node, |
| | 14745 | buf_sprintf("struct '%s' declared here", buf_ptr(&wanted_type->name))); |
| | 14746 | } |
| | 14747 | add_error_note(ira->codegen, msg, src_field->decl_node, |
| | 14748 | buf_sprintf("field '%s' declared here", buf_ptr(src_field->name))); |
| | 14749 | return ira->codegen->invalid_inst_gen; |
| | 14750 | } |
| | 14751 | |
| | 14752 | ir_assert(src_field->decl_node != nullptr, source_instr); |
| | 14753 | AstNode *existing_assign_node = field_assign_nodes[dst_field->src_index]; |
| | 14754 | if (existing_assign_node != nullptr) { |
| | 14755 | ErrorMsg *msg = ir_add_error(ira, source_instr, buf_sprintf("duplicate field")); |
| | 14756 | add_error_note(ira->codegen, msg, existing_assign_node, buf_sprintf("other field here")); |
| | 14757 | return ira->codegen->invalid_inst_gen; |
| | 14758 | } |
| | 14759 | field_assign_nodes[dst_field->src_index] = src_field->decl_node; |
| | 14760 | |
| | 14761 | IrInstGen *field_ptr = ir_analyze_struct_field_ptr(ira, source_instr, src_field, struct_ptr, |
| | 14762 | struct_operand->value->type, false); |
| | 14763 | if (type_is_invalid(field_ptr->value->type)) |
| | 14764 | return ira->codegen->invalid_inst_gen; |
| | 14765 | IrInstGen *field_value = ir_get_deref(ira, source_instr, field_ptr, nullptr); |
| | 14766 | if (type_is_invalid(field_value->value->type)) |
| | 14767 | return ira->codegen->invalid_inst_gen; |
| | 14768 | IrInstGen *casted_value = ir_implicit_cast(ira, field_value, dst_field->type_entry); |
| | 14769 | if (type_is_invalid(casted_value->value->type)) |
| | 14770 | return ira->codegen->invalid_inst_gen; |
| | 14771 | |
| | 14772 | casted_fields[dst_field->src_index] = casted_value; |
| | 14773 | if (need_comptime || instr_is_comptime(casted_value)) { |
| | 14774 | ZigValue *field_val = ir_resolve_const(ira, casted_value, UndefOk); |
| | 14775 | if (field_val == nullptr) |
| | 14776 | return ira->codegen->invalid_inst_gen; |
| | 14777 | field_val->parent.id = ConstParentIdStruct; |
| | 14778 | field_val->parent.data.p_struct.struct_val = const_result->value; |
| | 14779 | field_val->parent.data.p_struct.field_index = dst_field->src_index; |
| | 14780 | field_values[dst_field->src_index] = field_val; |
| | 14781 | } else { |
| | 14782 | is_comptime = false; |
| | 14783 | } |
| | 14784 | } |
| | 14785 | |
| | 14786 | bool any_missing = false; |
| | 14787 | for (size_t i = 0; i < actual_field_count; i += 1) { |
| | 14788 | if (field_assign_nodes[i] != nullptr) continue; |
| | 14789 | |
| | 14790 | // look for a default field value |
| | 14791 | TypeStructField *field = wanted_type->data.structure.fields[i]; |
| | 14792 | memoize_field_init_val(ira->codegen, wanted_type, field); |
| | 14793 | if (field->init_val == nullptr) { |
| | 14794 | ir_add_error(ira, source_instr, |
| | 14795 | buf_sprintf("missing field: '%s'", buf_ptr(field->name))); |
| | 14796 | any_missing = true; |
| | 14797 | continue; |
| | 14798 | } |
| | 14799 | if (type_is_invalid(field->init_val->type)) |
| | 14800 | return ira->codegen->invalid_inst_gen; |
| | 14801 | ZigValue *init_val_copy = ira->codegen->pass1_arena->create<ZigValue>(); |
| | 14802 | copy_const_val(ira->codegen, init_val_copy, field->init_val); |
| | 14803 | init_val_copy->parent.id = ConstParentIdStruct; |
| | 14804 | init_val_copy->parent.data.p_struct.struct_val = const_result->value; |
| | 14805 | init_val_copy->parent.data.p_struct.field_index = i; |
| | 14806 | field_values[i] = init_val_copy; |
| | 14807 | casted_fields[i] = ir_const_move(ira, source_instr, init_val_copy); |
| | 14808 | } |
| | 14809 | if (any_missing) |
| | 14810 | return ira->codegen->invalid_inst_gen; |
| | 14811 | |
| | 14812 | if (is_comptime) { |
| | 14813 | heap::c_allocator.deallocate(field_assign_nodes, actual_field_count); |
| | 14814 | IrInstGen *const_result = ir_const(ira, source_instr, wanted_type); |
| | 14815 | const_result->value->data.x_struct.fields = field_values; |
| | 14816 | return const_result; |
| | 14817 | } |
| | 14818 | |
| | 14819 | IrInstGen *result_loc_inst = ir_resolve_result(ira, source_instr, no_result_loc(), |
| | 14820 | wanted_type, nullptr, true, true); |
| | 14821 | if (type_is_invalid(result_loc_inst->value->type) || result_loc_inst->value->type->id == ZigTypeIdUnreachable) { |
| | 14822 | return ira->codegen->invalid_inst_gen; |
| | 14823 | } |
| | 14824 | |
| | 14825 | for (size_t i = 0; i < actual_field_count; i += 1) { |
| | 14826 | TypeStructField *field = wanted_type->data.structure.fields[i]; |
| | 14827 | IrInstGen *field_ptr = ir_analyze_struct_field_ptr(ira, source_instr, field, result_loc_inst, wanted_type, true); |
| | 14828 | if (type_is_invalid(field_ptr->value->type)) |
| | 14829 | return ira->codegen->invalid_inst_gen; |
| | 14830 | IrInstGen *store_ptr_inst = ir_analyze_store_ptr(ira, source_instr, field_ptr, casted_fields[i], true); |
| | 14831 | if (type_is_invalid(store_ptr_inst->value->type)) |
| | 14832 | return ira->codegen->invalid_inst_gen; |
| | 14833 | } |
| | 14834 | |
| | 14835 | heap::c_allocator.deallocate(field_assign_nodes, actual_field_count); |
| | 14836 | heap::c_allocator.deallocate(field_values, actual_field_count); |
| | 14837 | heap::c_allocator.deallocate(casted_fields, actual_field_count); |
| | 14838 | |
| | 14839 | return ir_get_deref(ira, source_instr, result_loc_inst, nullptr); |
| 14710 | } | 14840 | } |
| 14711 | | 14841 | |
| 14712 | static IrInstGen *ir_analyze_struct_literal_to_union(IrAnalyze *ira, IrInst* source_instr, | 14842 | static IrInstGen *ir_analyze_struct_literal_to_union(IrAnalyze *ira, IrInst* source_instr, |
| ... | @@ -14727,7 +14857,7 @@ static IrInstGen *ir_analyze_struct_literal_to_union(IrAnalyze *ira, IrInst* sou | ... | @@ -14727,7 +14857,7 @@ static IrInstGen *ir_analyze_struct_literal_to_union(IrAnalyze *ira, IrInst* sou |
| 14727 | TypeUnionField *union_field = find_union_type_field(union_type, only_field->name); | 14857 | TypeUnionField *union_field = find_union_type_field(union_type, only_field->name); |
| 14728 | if (union_field == nullptr) { | 14858 | if (union_field == nullptr) { |
| 14729 | ir_add_error_node(ira, only_field->decl_node, | 14859 | ir_add_error_node(ira, only_field->decl_node, |
| 14730 | buf_sprintf("no member named '%s' in union '%s'", | 14860 | buf_sprintf("no field named '%s' in union '%s'", |
| 14731 | buf_ptr(only_field->name), buf_ptr(&union_type->name))); | 14861 | buf_ptr(only_field->name), buf_ptr(&union_type->name))); |
| 14732 | return ira->codegen->invalid_inst_gen; | 14862 | return ira->codegen->invalid_inst_gen; |
| 14733 | } | 14863 | } |
| ... | @@ -22407,7 +22537,7 @@ static IrInstGen *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstSrcFiel | ... | @@ -22407,7 +22537,7 @@ static IrInstGen *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstSrcFiel |
| 22407 | usize, ConstPtrMutComptimeConst, ptr_is_const, ptr_is_volatile, 0); | 22537 | usize, ConstPtrMutComptimeConst, ptr_is_const, ptr_is_volatile, 0); |
| 22408 | } else { | 22538 | } else { |
| 22409 | ir_add_error_node(ira, source_node, | 22539 | ir_add_error_node(ira, source_node, |
| 22410 | buf_sprintf("no member named '%s' in '%s'", buf_ptr(field_name), | 22540 | buf_sprintf("no field named '%s' in '%s'", buf_ptr(field_name), |
| 22411 | buf_ptr(&container_type->name))); | 22541 | buf_ptr(&container_type->name))); |
| 22412 | return ira->codegen->invalid_inst_gen; | 22542 | return ira->codegen->invalid_inst_gen; |
| 22413 | } | 22543 | } |
| ... | @@ -23834,7 +23964,7 @@ static IrInstGen *ir_analyze_union_init(IrAnalyze *ira, IrInst* source_instructi | ... | @@ -23834,7 +23964,7 @@ static IrInstGen *ir_analyze_union_init(IrAnalyze *ira, IrInst* source_instructi |
| 23834 | TypeUnionField *type_field = find_union_type_field(union_type, field_name); | 23964 | TypeUnionField *type_field = find_union_type_field(union_type, field_name); |
| 23835 | if (type_field == nullptr) { | 23965 | if (type_field == nullptr) { |
| 23836 | ir_add_error_node(ira, field_source_node, | 23966 | ir_add_error_node(ira, field_source_node, |
| 23837 | buf_sprintf("no member named '%s' in union '%s'", | 23967 | buf_sprintf("no field named '%s' in union '%s'", |
| 23838 | buf_ptr(field_name), buf_ptr(&union_type->name))); | 23968 | buf_ptr(field_name), buf_ptr(&union_type->name))); |
| 23839 | return ira->codegen->invalid_inst_gen; | 23969 | return ira->codegen->invalid_inst_gen; |
| 23840 | } | 23970 | } |
| ... | @@ -23930,7 +24060,7 @@ static IrInstGen *ir_analyze_container_init_fields(IrAnalyze *ira, IrInst *sourc | ... | @@ -23930,7 +24060,7 @@ static IrInstGen *ir_analyze_container_init_fields(IrAnalyze *ira, IrInst *sourc |
| 23930 | TypeStructField *type_field = find_struct_type_field(container_type, field->name); | 24060 | TypeStructField *type_field = find_struct_type_field(container_type, field->name); |
| 23931 | if (!type_field) { | 24061 | if (!type_field) { |
| 23932 | ir_add_error_node(ira, field->source_node, | 24062 | ir_add_error_node(ira, field->source_node, |
| 23933 | buf_sprintf("no member named '%s' in struct '%s'", | 24063 | buf_sprintf("no field named '%s' in struct '%s'", |
| 23934 | buf_ptr(field->name), buf_ptr(&container_type->name))); | 24064 | buf_ptr(field->name), buf_ptr(&container_type->name))); |
| 23935 | return ira->codegen->invalid_inst_gen; | 24065 | return ira->codegen->invalid_inst_gen; |
| 23936 | } | 24066 | } |
| ... | @@ -23965,7 +24095,7 @@ static IrInstGen *ir_analyze_container_init_fields(IrAnalyze *ira, IrInst *sourc | ... | @@ -23965,7 +24095,7 @@ static IrInstGen *ir_analyze_container_init_fields(IrAnalyze *ira, IrInst *sourc |
| 23965 | memoize_field_init_val(ira->codegen, container_type, field); | 24095 | memoize_field_init_val(ira->codegen, container_type, field); |
| 23966 | if (field->init_val == nullptr) { | 24096 | if (field->init_val == nullptr) { |
| 23967 | ir_add_error(ira, source_instr, | 24097 | ir_add_error(ira, source_instr, |
| 23968 | buf_sprintf("missing field: '%s'", buf_ptr(container_type->data.structure.fields[i]->name))); | 24098 | buf_sprintf("missing field: '%s'", buf_ptr(field->name))); |
| 23969 | any_missing = true; | 24099 | any_missing = true; |
| 23970 | continue; | 24100 | continue; |
| 23971 | } | 24101 | } |