| author | |
| committer | |
| log | ca2a788a240bbc3fa8060471bcda845e543dac70 |
| tree | 2a6d173cf7a90e20ad5bce72ca099307265c1d29 |
| parent | 1bca8e693d42256d575c76fbab5c68d86c0c4bc3 |
| signature |
5 files changed, 271 insertions(+), 63 deletions(-)
src/all_types.hpp+13| ... | @@ -1187,10 +1187,22 @@ bool fn_type_id_eql(FnTypeId *a, FnTypeId *b); | ... | @@ -1187,10 +1187,22 @@ bool fn_type_id_eql(FnTypeId *a, FnTypeId *b); |
| 1187 | static const uint32_t VECTOR_INDEX_NONE = UINT32_MAX; | 1187 | static const uint32_t VECTOR_INDEX_NONE = UINT32_MAX; |
| 1188 | static const uint32_t VECTOR_INDEX_RUNTIME = UINT32_MAX - 1; | 1188 | static const uint32_t VECTOR_INDEX_RUNTIME = UINT32_MAX - 1; |
| 1189 | 1189 | ||
| 1190 | struct InferredStructField { | ||
| 1191 | ZigType *inferred_struct_type; | ||
| 1192 | Buf *field_name; | ||
| 1193 | }; | ||
| 1194 | |||
| 1190 | struct ZigTypePointer { | 1195 | struct ZigTypePointer { |
| 1191 | ZigType *child_type; | 1196 | ZigType *child_type; |
| 1192 | ZigType *slice_parent; | 1197 | ZigType *slice_parent; |
| 1193 | 1198 | ||
| 1199 | // Anonymous struct literal syntax uses this when the result location has | ||
| 1200 | // no type in it. This field is null if this pointer does not refer to | ||
| 1201 | // a field of a currently-being-inferred struct type. | ||
| 1202 | // When this is non-null, the pointer is pointing to the base of the inferred | ||
| 1203 | // struct. | ||
| 1204 | InferredStructField *inferred_struct_field; | ||
| 1205 | |||
| 1194 | PtrLen ptr_len; | 1206 | PtrLen ptr_len; |
| 1195 | uint32_t explicit_alignment; // 0 means use ABI alignment | 1207 | uint32_t explicit_alignment; // 0 means use ABI alignment |
| 1196 | 1208 | ||
| ... | @@ -1743,6 +1755,7 @@ struct TypeId { | ... | @@ -1743,6 +1755,7 @@ struct TypeId { |
| 1743 | union { | 1755 | union { |
| 1744 | struct { | 1756 | struct { |
| 1745 | ZigType *child_type; | 1757 | ZigType *child_type; |
| 1758 | InferredStructField *inferred_struct_field; | ||
| 1746 | PtrLen ptr_len; | 1759 | PtrLen ptr_len; |
| 1747 | uint32_t alignment; | 1760 | uint32_t alignment; |
| 1748 | 1761 |
src/analyze.cpp+92-41| ... | @@ -486,7 +486,7 @@ ZigType *get_fn_frame_type(CodeGen *g, ZigFn *fn) { | ... | @@ -486,7 +486,7 @@ ZigType *get_fn_frame_type(CodeGen *g, ZigFn *fn) { |
| 486 | ZigType *get_pointer_to_type_extra2(CodeGen *g, ZigType *child_type, bool is_const, | 486 | ZigType *get_pointer_to_type_extra2(CodeGen *g, ZigType *child_type, bool is_const, |
| 487 | bool is_volatile, PtrLen ptr_len, uint32_t byte_alignment, | 487 | bool is_volatile, PtrLen ptr_len, uint32_t byte_alignment, |
| 488 | uint32_t bit_offset_in_host, uint32_t host_int_bytes, bool allow_zero, | 488 | uint32_t bit_offset_in_host, uint32_t host_int_bytes, bool allow_zero, |
| 489 | uint32_t vector_index) | 489 | uint32_t vector_index, InferredStructField *inferred_struct_field) |
| 490 | { | 490 | { |
| 491 | assert(ptr_len != PtrLenC || allow_zero); | 491 | assert(ptr_len != PtrLenC || allow_zero); |
| 492 | assert(!type_is_invalid(child_type)); | 492 | assert(!type_is_invalid(child_type)); |
| ... | @@ -509,7 +509,7 @@ ZigType *get_pointer_to_type_extra2(CodeGen *g, ZigType *child_type, bool is_con | ... | @@ -509,7 +509,7 @@ ZigType *get_pointer_to_type_extra2(CodeGen *g, ZigType *child_type, bool is_con |
| 509 | TypeId type_id = {}; | 509 | TypeId type_id = {}; |
| 510 | ZigType **parent_pointer = nullptr; | 510 | ZigType **parent_pointer = nullptr; |
| 511 | if (host_int_bytes != 0 || is_volatile || byte_alignment != 0 || ptr_len != PtrLenSingle || | 511 | if (host_int_bytes != 0 || is_volatile || byte_alignment != 0 || ptr_len != PtrLenSingle || |
| 512 | allow_zero || vector_index != VECTOR_INDEX_NONE) | 512 | allow_zero || vector_index != VECTOR_INDEX_NONE || inferred_struct_field != nullptr) |
| 513 | { | 513 | { |
| 514 | type_id.id = ZigTypeIdPointer; | 514 | type_id.id = ZigTypeIdPointer; |
| 515 | type_id.data.pointer.child_type = child_type; | 515 | type_id.data.pointer.child_type = child_type; |
| ... | @@ -521,6 +521,7 @@ ZigType *get_pointer_to_type_extra2(CodeGen *g, ZigType *child_type, bool is_con | ... | @@ -521,6 +521,7 @@ ZigType *get_pointer_to_type_extra2(CodeGen *g, ZigType *child_type, bool is_con |
| 521 | type_id.data.pointer.ptr_len = ptr_len; | 521 | type_id.data.pointer.ptr_len = ptr_len; |
| 522 | type_id.data.pointer.allow_zero = allow_zero; | 522 | type_id.data.pointer.allow_zero = allow_zero; |
| 523 | type_id.data.pointer.vector_index = vector_index; | 523 | type_id.data.pointer.vector_index = vector_index; |
| 524 | type_id.data.pointer.inferred_struct_field = inferred_struct_field; | ||
| 524 | 525 | ||
| 525 | auto existing_entry = g->type_table.maybe_get(type_id); | 526 | auto existing_entry = g->type_table.maybe_get(type_id); |
| 526 | if (existing_entry) | 527 | if (existing_entry) |
| ... | @@ -548,8 +549,15 @@ ZigType *get_pointer_to_type_extra2(CodeGen *g, ZigType *child_type, bool is_con | ... | @@ -548,8 +549,15 @@ ZigType *get_pointer_to_type_extra2(CodeGen *g, ZigType *child_type, bool is_con |
| 548 | } | 549 | } |
| 549 | buf_resize(&entry->name, 0); | 550 | buf_resize(&entry->name, 0); |
| 550 | if (host_int_bytes == 0 && byte_alignment == 0 && vector_index == VECTOR_INDEX_NONE) { | 551 | if (host_int_bytes == 0 && byte_alignment == 0 && vector_index == VECTOR_INDEX_NONE) { |
| 551 | buf_appendf(&entry->name, "%s%s%s%s%s", | 552 | if (inferred_struct_field == nullptr) { |
| 552 | star_str, const_str, volatile_str, allow_zero_str, buf_ptr(&child_type->name)); | 553 | buf_appendf(&entry->name, "%s%s%s%s%s", |
| 554 | star_str, const_str, volatile_str, allow_zero_str, buf_ptr(&child_type->name)); | ||
| 555 | } else { | ||
| 556 | buf_appendf(&entry->name, "(%s%s%s%s field '%s' of %s)", | ||
| 557 | star_str, const_str, volatile_str, allow_zero_str, | ||
| 558 | buf_ptr(inferred_struct_field->field_name), | ||
| 559 | buf_ptr(&inferred_struct_field->inferred_struct_type->name)); | ||
| 560 | } | ||
| 553 | } else if (host_int_bytes == 0 && vector_index == VECTOR_INDEX_NONE) { | 561 | } else if (host_int_bytes == 0 && vector_index == VECTOR_INDEX_NONE) { |
| 554 | buf_appendf(&entry->name, "%salign(%" PRIu32 ") %s%s%s%s", star_str, byte_alignment, | 562 | buf_appendf(&entry->name, "%salign(%" PRIu32 ") %s%s%s%s", star_str, byte_alignment, |
| 555 | const_str, volatile_str, allow_zero_str, buf_ptr(&child_type->name)); | 563 | const_str, volatile_str, allow_zero_str, buf_ptr(&child_type->name)); |
| ... | @@ -606,6 +614,7 @@ ZigType *get_pointer_to_type_extra2(CodeGen *g, ZigType *child_type, bool is_con | ... | @@ -606,6 +614,7 @@ ZigType *get_pointer_to_type_extra2(CodeGen *g, ZigType *child_type, bool is_con |
| 606 | entry->data.pointer.host_int_bytes = host_int_bytes; | 614 | entry->data.pointer.host_int_bytes = host_int_bytes; |
| 607 | entry->data.pointer.allow_zero = allow_zero; | 615 | entry->data.pointer.allow_zero = allow_zero; |
| 608 | entry->data.pointer.vector_index = vector_index; | 616 | entry->data.pointer.vector_index = vector_index; |
| 617 | entry->data.pointer.inferred_struct_field = inferred_struct_field; | ||
| 609 | 618 | ||
| 610 | if (parent_pointer) { | 619 | if (parent_pointer) { |
| 611 | *parent_pointer = entry; | 620 | *parent_pointer = entry; |
| ... | @@ -620,12 +629,12 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons | ... | @@ -620,12 +629,12 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons |
| 620 | uint32_t bit_offset_in_host, uint32_t host_int_bytes, bool allow_zero) | 629 | uint32_t bit_offset_in_host, uint32_t host_int_bytes, bool allow_zero) |
| 621 | { | 630 | { |
| 622 | return get_pointer_to_type_extra2(g, child_type, is_const, is_volatile, ptr_len, | 631 | return get_pointer_to_type_extra2(g, child_type, is_const, is_volatile, ptr_len, |
| 623 | byte_alignment, bit_offset_in_host, host_int_bytes, allow_zero, VECTOR_INDEX_NONE); | 632 | byte_alignment, bit_offset_in_host, host_int_bytes, allow_zero, VECTOR_INDEX_NONE, nullptr); |
| 624 | } | 633 | } |
| 625 | 634 | ||
| 626 | ZigType *get_pointer_to_type(CodeGen *g, ZigType *child_type, bool is_const) { | 635 | ZigType *get_pointer_to_type(CodeGen *g, ZigType *child_type, bool is_const) { |
| 627 | return get_pointer_to_type_extra2(g, child_type, is_const, false, PtrLenSingle, 0, 0, 0, false, | 636 | return get_pointer_to_type_extra2(g, child_type, is_const, false, PtrLenSingle, 0, 0, 0, false, |
| 628 | VECTOR_INDEX_NONE); | 637 | VECTOR_INDEX_NONE, nullptr); |
| 629 | } | 638 | } |
| 630 | 639 | ||
| 631 | ZigType *get_optional_type(CodeGen *g, ZigType *child_type) { | 640 | ZigType *get_optional_type(CodeGen *g, ZigType *child_type) { |
| ... | @@ -2082,7 +2091,7 @@ static Error resolve_struct_type(CodeGen *g, ZigType *struct_type) { | ... | @@ -2082,7 +2091,7 @@ static Error resolve_struct_type(CodeGen *g, ZigType *struct_type) { |
| 2082 | } | 2091 | } |
| 2083 | 2092 | ||
| 2084 | assert(struct_type->data.structure.fields || struct_type->data.structure.src_field_count == 0); | 2093 | assert(struct_type->data.structure.fields || struct_type->data.structure.src_field_count == 0); |
| 2085 | assert(decl_node->type == NodeTypeContainerDecl); | 2094 | assert(decl_node->type == NodeTypeContainerDecl || decl_node->type == NodeTypeContainerInitExpr); |
| 2086 | 2095 | ||
| 2087 | size_t field_count = struct_type->data.structure.src_field_count; | 2096 | size_t field_count = struct_type->data.structure.src_field_count; |
| 2088 | 2097 | ||
| ... | @@ -2670,7 +2679,6 @@ static Error resolve_struct_zero_bits(CodeGen *g, ZigType *struct_type) { | ... | @@ -2670,7 +2679,6 @@ static Error resolve_struct_zero_bits(CodeGen *g, ZigType *struct_type) { |
| 2670 | return ErrorNone; | 2679 | return ErrorNone; |
| 2671 | 2680 | ||
| 2672 | AstNode *decl_node = struct_type->data.structure.decl_node; | 2681 | AstNode *decl_node = struct_type->data.structure.decl_node; |
| 2673 | assert(decl_node->type == NodeTypeContainerDecl); | ||
| 2674 | 2682 | ||
| 2675 | if (struct_type->data.structure.resolve_loop_flag_zero_bits) { | 2683 | if (struct_type->data.structure.resolve_loop_flag_zero_bits) { |
| 2676 | if (struct_type->data.structure.resolve_status != ResolveStatusInvalid) { | 2684 | if (struct_type->data.structure.resolve_status != ResolveStatusInvalid) { |
| ... | @@ -2681,29 +2689,46 @@ static Error resolve_struct_zero_bits(CodeGen *g, ZigType *struct_type) { | ... | @@ -2681,29 +2689,46 @@ static Error resolve_struct_zero_bits(CodeGen *g, ZigType *struct_type) { |
| 2681 | } | 2689 | } |
| 2682 | return ErrorSemanticAnalyzeFail; | 2690 | return ErrorSemanticAnalyzeFail; |
| 2683 | } | 2691 | } |
| 2684 | |||
| 2685 | struct_type->data.structure.resolve_loop_flag_zero_bits = true; | 2692 | struct_type->data.structure.resolve_loop_flag_zero_bits = true; |
| 2686 | 2693 | ||
| 2687 | assert(!struct_type->data.structure.fields); | 2694 | size_t field_count; |
| 2688 | size_t field_count = decl_node->data.container_decl.fields.length; | 2695 | if (decl_node->type == NodeTypeContainerDecl) { |
| 2689 | struct_type->data.structure.src_field_count = (uint32_t)field_count; | 2696 | field_count = decl_node->data.container_decl.fields.length; |
| 2690 | struct_type->data.structure.fields = allocate<TypeStructField>(field_count); | 2697 | struct_type->data.structure.src_field_count = (uint32_t)field_count; |
| 2698 | |||
| 2699 | src_assert(struct_type->data.structure.fields == nullptr, decl_node); | ||
| 2700 | struct_type->data.structure.fields = allocate<TypeStructField>(field_count); | ||
| 2701 | } else if (decl_node->type == NodeTypeContainerInitExpr) { | ||
| 2702 | src_assert(struct_type->data.structure.is_inferred, decl_node); | ||
| 2703 | src_assert(struct_type->data.structure.fields != nullptr, decl_node); | ||
| 2704 | |||
| 2705 | field_count = struct_type->data.structure.src_field_count; | ||
| 2706 | } else zig_unreachable(); | ||
| 2707 | |||
| 2691 | struct_type->data.structure.fields_by_name.init(field_count); | 2708 | struct_type->data.structure.fields_by_name.init(field_count); |
| 2692 | 2709 | ||
| 2693 | Scope *scope = &struct_type->data.structure.decls_scope->base; | 2710 | Scope *scope = &struct_type->data.structure.decls_scope->base; |
| 2694 | 2711 | ||
| 2695 | size_t gen_field_index = 0; | 2712 | size_t gen_field_index = 0; |
| 2696 | for (size_t i = 0; i < field_count; i += 1) { | 2713 | for (size_t i = 0; i < field_count; i += 1) { |
| 2697 | AstNode *field_node = decl_node->data.container_decl.fields.at(i); | ||
| 2698 | TypeStructField *type_struct_field = &struct_type->data.structure.fields[i]; | 2714 | TypeStructField *type_struct_field = &struct_type->data.structure.fields[i]; |
| 2699 | type_struct_field->name = field_node->data.struct_field.name; | ||
| 2700 | type_struct_field->decl_node = field_node; | ||
| 2701 | 2715 | ||
| 2702 | if (field_node->data.struct_field.type == nullptr) { | 2716 | AstNode *field_node; |
| 2703 | add_node_error(g, field_node, buf_sprintf("struct field missing type")); | 2717 | if (decl_node->type == NodeTypeContainerDecl) { |
| 2704 | struct_type->data.structure.resolve_status = ResolveStatusInvalid; | 2718 | field_node = decl_node->data.container_decl.fields.at(i); |
| 2705 | return ErrorSemanticAnalyzeFail; | 2719 | type_struct_field->name = field_node->data.struct_field.name; |
| 2706 | } | 2720 | type_struct_field->decl_node = field_node; |
| 2721 | |||
| 2722 | if (field_node->data.struct_field.type == nullptr) { | ||
| 2723 | add_node_error(g, field_node, buf_sprintf("struct field missing type")); | ||
| 2724 | struct_type->data.structure.resolve_status = ResolveStatusInvalid; | ||
| 2725 | return ErrorSemanticAnalyzeFail; | ||
| 2726 | } | ||
| 2727 | } else if (decl_node->type == NodeTypeContainerInitExpr) { | ||
| 2728 | field_node = type_struct_field->decl_node; | ||
| 2729 | |||
| 2730 | src_assert(type_struct_field->type_entry != nullptr, field_node); | ||
| 2731 | } else zig_unreachable(); | ||
| 2707 | 2732 | ||
| 2708 | auto field_entry = struct_type->data.structure.fields_by_name.put_unique(type_struct_field->name, type_struct_field); | 2733 | auto field_entry = struct_type->data.structure.fields_by_name.put_unique(type_struct_field->name, type_struct_field); |
| 2709 | if (field_entry != nullptr) { | 2734 | if (field_entry != nullptr) { |
| ... | @@ -2714,16 +2739,21 @@ static Error resolve_struct_zero_bits(CodeGen *g, ZigType *struct_type) { | ... | @@ -2714,16 +2739,21 @@ static Error resolve_struct_zero_bits(CodeGen *g, ZigType *struct_type) { |
| 2714 | return ErrorSemanticAnalyzeFail; | 2739 | return ErrorSemanticAnalyzeFail; |
| 2715 | } | 2740 | } |
| 2716 | 2741 | ||
| 2717 | ConstExprValue *field_type_val = analyze_const_value(g, scope, | 2742 | ConstExprValue *field_type_val; |
| 2718 | field_node->data.struct_field.type, g->builtin_types.entry_type, nullptr, LazyOkNoUndef); | 2743 | if (decl_node->type == NodeTypeContainerDecl) { |
| 2719 | if (type_is_invalid(field_type_val->type)) { | 2744 | field_type_val = analyze_const_value(g, scope, |
| 2720 | struct_type->data.structure.resolve_status = ResolveStatusInvalid; | 2745 | field_node->data.struct_field.type, g->builtin_types.entry_type, nullptr, LazyOkNoUndef); |
| 2721 | return ErrorSemanticAnalyzeFail; | 2746 | if (type_is_invalid(field_type_val->type)) { |
| 2722 | } | 2747 | struct_type->data.structure.resolve_status = ResolveStatusInvalid; |
| 2723 | assert(field_type_val->special != ConstValSpecialRuntime); | 2748 | return ErrorSemanticAnalyzeFail; |
| 2724 | type_struct_field->type_val = field_type_val; | 2749 | } |
| 2725 | if (struct_type->data.structure.resolve_status == ResolveStatusInvalid) | 2750 | assert(field_type_val->special != ConstValSpecialRuntime); |
| 2726 | return ErrorSemanticAnalyzeFail; | 2751 | type_struct_field->type_val = field_type_val; |
| 2752 | if (struct_type->data.structure.resolve_status == ResolveStatusInvalid) | ||
| 2753 | return ErrorSemanticAnalyzeFail; | ||
| 2754 | } else if (decl_node->type == NodeTypeContainerInitExpr) { | ||
| 2755 | field_type_val = type_struct_field->type_val; | ||
| 2756 | } else zig_unreachable(); | ||
| 2727 | 2757 | ||
| 2728 | bool field_is_opaque_type; | 2758 | bool field_is_opaque_type; |
| 2729 | if ((err = type_val_resolve_is_opaque_type(g, field_type_val, &field_is_opaque_type))) { | 2759 | if ((err = type_val_resolve_is_opaque_type(g, field_type_val, &field_is_opaque_type))) { |
| ... | @@ -2807,7 +2837,7 @@ static Error resolve_struct_alignment(CodeGen *g, ZigType *struct_type) { | ... | @@ -2807,7 +2837,7 @@ static Error resolve_struct_alignment(CodeGen *g, ZigType *struct_type) { |
| 2807 | } | 2837 | } |
| 2808 | 2838 | ||
| 2809 | struct_type->data.structure.resolve_loop_flag_other = true; | 2839 | struct_type->data.structure.resolve_loop_flag_other = true; |
| 2810 | assert(decl_node->type == NodeTypeContainerDecl); | 2840 | assert(decl_node->type == NodeTypeContainerDecl || decl_node->type == NodeTypeContainerInitExpr); |
| 2811 | 2841 | ||
| 2812 | size_t field_count = struct_type->data.structure.src_field_count; | 2842 | size_t field_count = struct_type->data.structure.src_field_count; |
| 2813 | bool packed = struct_type->data.structure.layout == ContainerLayoutPacked; | 2843 | bool packed = struct_type->data.structure.layout == ContainerLayoutPacked; |
| ... | @@ -2817,7 +2847,8 @@ static Error resolve_struct_alignment(CodeGen *g, ZigType *struct_type) { | ... | @@ -2817,7 +2847,8 @@ static Error resolve_struct_alignment(CodeGen *g, ZigType *struct_type) { |
| 2817 | if (field->gen_index == SIZE_MAX) | 2847 | if (field->gen_index == SIZE_MAX) |
| 2818 | continue; | 2848 | continue; |
| 2819 | 2849 | ||
| 2820 | AstNode *align_expr = field->decl_node->data.struct_field.align_expr; | 2850 | AstNode *align_expr = (field->decl_node->type == NodeTypeStructField) ? |
| 2851 | field->decl_node->data.struct_field.align_expr : nullptr; | ||
| 2821 | if (align_expr != nullptr) { | 2852 | if (align_expr != nullptr) { |
| 2822 | if (!analyze_const_align(g, &struct_type->data.structure.decls_scope->base, align_expr, | 2853 | if (!analyze_const_align(g, &struct_type->data.structure.decls_scope->base, align_expr, |
| 2823 | &field->align)) | 2854 | &field->align)) |
| ... | @@ -5416,6 +5447,12 @@ OnePossibleValue type_has_one_possible_value(CodeGen *g, ZigType *type_entry) { | ... | @@ -5416,6 +5447,12 @@ OnePossibleValue type_has_one_possible_value(CodeGen *g, ZigType *type_entry) { |
| 5416 | if (type_entry->one_possible_value != OnePossibleValueInvalid) | 5447 | if (type_entry->one_possible_value != OnePossibleValueInvalid) |
| 5417 | return type_entry->one_possible_value; | 5448 | return type_entry->one_possible_value; |
| 5418 | 5449 | ||
| 5450 | if (type_entry->id == ZigTypeIdStruct && | ||
| 5451 | type_entry->data.structure.resolve_status == ResolveStatusBeingInferred) | ||
| 5452 | { | ||
| 5453 | return OnePossibleValueNo; | ||
| 5454 | } | ||
| 5455 | |||
| 5419 | Error err; | 5456 | Error err; |
| 5420 | if ((err = type_resolve(g, type_entry, ResolveStatusZeroBitsKnown))) | 5457 | if ((err = type_resolve(g, type_entry, ResolveStatusZeroBitsKnown))) |
| 5421 | return OnePossibleValueInvalid; | 5458 | return OnePossibleValueInvalid; |
| ... | @@ -5820,9 +5857,15 @@ ConstExprValue *create_const_arg_tuple(CodeGen *g, size_t arg_index_start, size_ | ... | @@ -5820,9 +5857,15 @@ ConstExprValue *create_const_arg_tuple(CodeGen *g, size_t arg_index_start, size_ |
| 5820 | 5857 | ||
| 5821 | 5858 | ||
| 5822 | ConstExprValue *create_const_vals(size_t count) { | 5859 | ConstExprValue *create_const_vals(size_t count) { |
| 5823 | ConstGlobalRefs *global_refs = allocate<ConstGlobalRefs>(count, "ConstGlobalRefs"); | 5860 | return realloc_const_vals(nullptr, 0, count); |
| 5824 | ConstExprValue *vals = allocate<ConstExprValue>(count, "ConstExprValue"); | 5861 | } |
| 5825 | for (size_t i = 0; i < count; i += 1) { | 5862 | |
| 5863 | ConstExprValue *realloc_const_vals(ConstExprValue *base, size_t old_count, size_t new_count) { | ||
| 5864 | ConstGlobalRefs *old_global_refs = (base == nullptr) ? nullptr : base->global_refs; | ||
| 5865 | ConstGlobalRefs *global_refs = reallocate<ConstGlobalRefs>(old_global_refs, old_count, | ||
| 5866 | new_count, "ConstGlobalRefs"); | ||
| 5867 | ConstExprValue *vals = reallocate<ConstExprValue>(base, old_count, new_count, "ConstExprValue"); | ||
| 5868 | for (size_t i = old_count; i < new_count; i += 1) { | ||
| 5826 | vals[i].global_refs = &global_refs[i]; | 5869 | vals[i].global_refs = &global_refs[i]; |
| 5827 | } | 5870 | } |
| 5828 | return vals; | 5871 | return vals; |
| ... | @@ -7002,7 +7045,16 @@ bool type_id_eql(TypeId a, TypeId b) { | ... | @@ -7002,7 +7045,16 @@ bool type_id_eql(TypeId a, TypeId b) { |
| 7002 | a.data.pointer.alignment == b.data.pointer.alignment && | 7045 | a.data.pointer.alignment == b.data.pointer.alignment && |
| 7003 | a.data.pointer.bit_offset_in_host == b.data.pointer.bit_offset_in_host && | 7046 | a.data.pointer.bit_offset_in_host == b.data.pointer.bit_offset_in_host && |
| 7004 | a.data.pointer.vector_index == b.data.pointer.vector_index && | 7047 | a.data.pointer.vector_index == b.data.pointer.vector_index && |
| 7005 | a.data.pointer.host_int_bytes == b.data.pointer.host_int_bytes; | 7048 | a.data.pointer.host_int_bytes == b.data.pointer.host_int_bytes && |
| 7049 | ( | ||
| 7050 | a.data.pointer.inferred_struct_field == b.data.pointer.inferred_struct_field || | ||
| 7051 | (a.data.pointer.inferred_struct_field != nullptr && | ||
| 7052 | b.data.pointer.inferred_struct_field != nullptr && | ||
| 7053 | a.data.pointer.inferred_struct_field->inferred_struct_type == | ||
| 7054 | b.data.pointer.inferred_struct_field->inferred_struct_type && | ||
| 7055 | buf_eql_buf(a.data.pointer.inferred_struct_field->field_name, | ||
| 7056 | b.data.pointer.inferred_struct_field->field_name)) | ||
| 7057 | ); | ||
| 7006 | case ZigTypeIdArray: | 7058 | case ZigTypeIdArray: |
| 7007 | return a.data.array.child_type == b.data.array.child_type && | 7059 | return a.data.array.child_type == b.data.array.child_type && |
| 7008 | a.data.array.size == b.data.array.size; | 7060 | a.data.array.size == b.data.array.size; |
| ... | @@ -7815,7 +7867,6 @@ static void resolve_llvm_types_struct(CodeGen *g, ZigType *struct_type, ResolveS | ... | @@ -7815,7 +7867,6 @@ static void resolve_llvm_types_struct(CodeGen *g, ZigType *struct_type, ResolveS |
| 7815 | ZigLLVMDIScope *di_scope; | 7867 | ZigLLVMDIScope *di_scope; |
| 7816 | unsigned line; | 7868 | unsigned line; |
| 7817 | if (decl_node != nullptr) { | 7869 | if (decl_node != nullptr) { |
| 7818 | assert(decl_node->type == NodeTypeContainerDecl); | ||
| 7819 | Scope *scope = &struct_type->data.structure.decls_scope->base; | 7870 | Scope *scope = &struct_type->data.structure.decls_scope->base; |
| 7820 | ZigType *import = get_scope_import(scope); | 7871 | ZigType *import = get_scope_import(scope); |
| 7821 | di_file = import->data.structure.root_struct->di_file; | 7872 | di_file = import->data.structure.root_struct->di_file; |
| ... | @@ -8018,7 +8069,7 @@ static void resolve_llvm_types_struct(CodeGen *g, ZigType *struct_type, ResolveS | ... | @@ -8018,7 +8069,7 @@ static void resolve_llvm_types_struct(CodeGen *g, ZigType *struct_type, ResolveS |
| 8018 | } | 8069 | } |
| 8019 | unsigned line; | 8070 | unsigned line; |
| 8020 | if (decl_node != nullptr) { | 8071 | if (decl_node != nullptr) { |
| 8021 | AstNode *field_node = decl_node->data.container_decl.fields.at(i); | 8072 | AstNode *field_node = field->decl_node; |
| 8022 | line = field_node->line + 1; | 8073 | line = field_node->line + 1; |
| 8023 | } else { | 8074 | } else { |
| 8024 | line = 0; | 8075 | line = 0; |
| ... | @@ -8314,12 +8365,12 @@ static void resolve_llvm_types_pointer(CodeGen *g, ZigType *type, ResolveStatus | ... | @@ -8314,12 +8365,12 @@ static void resolve_llvm_types_pointer(CodeGen *g, ZigType *type, ResolveStatus |
| 8314 | if (type->data.pointer.vector_index == VECTOR_INDEX_NONE) { | 8365 | if (type->data.pointer.vector_index == VECTOR_INDEX_NONE) { |
| 8315 | peer_type = get_pointer_to_type_extra2(g, elem_type, false, false, | 8366 | peer_type = get_pointer_to_type_extra2(g, elem_type, false, false, |
| 8316 | PtrLenSingle, 0, 0, type->data.pointer.host_int_bytes, false, | 8367 | PtrLenSingle, 0, 0, type->data.pointer.host_int_bytes, false, |
| 8317 | VECTOR_INDEX_NONE); | 8368 | VECTOR_INDEX_NONE, nullptr); |
| 8318 | } else { | 8369 | } else { |
| 8319 | uint32_t host_vec_len = type->data.pointer.host_int_bytes; | 8370 | uint32_t host_vec_len = type->data.pointer.host_int_bytes; |
| 8320 | ZigType *host_vec_type = get_vector_type(g, host_vec_len, elem_type); | 8371 | ZigType *host_vec_type = get_vector_type(g, host_vec_len, elem_type); |
| 8321 | peer_type = get_pointer_to_type_extra2(g, host_vec_type, false, false, | 8372 | peer_type = get_pointer_to_type_extra2(g, host_vec_type, false, false, |
| 8322 | PtrLenSingle, 0, 0, 0, false, VECTOR_INDEX_NONE); | 8373 | PtrLenSingle, 0, 0, 0, false, VECTOR_INDEX_NONE, nullptr); |
| 8323 | } | 8374 | } |
| 8324 | type->llvm_type = get_llvm_type(g, peer_type); | 8375 | type->llvm_type = get_llvm_type(g, peer_type); |
| 8325 | type->llvm_di_type = get_llvm_di_type(g, peer_type); | 8376 | type->llvm_di_type = get_llvm_di_type(g, peer_type); |
src/analyze.hpp+2-1| ... | @@ -24,7 +24,7 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, | ... | @@ -24,7 +24,7 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, |
| 24 | ZigType *get_pointer_to_type_extra2(CodeGen *g, ZigType *child_type, | 24 | ZigType *get_pointer_to_type_extra2(CodeGen *g, ZigType *child_type, |
| 25 | bool is_const, bool is_volatile, PtrLen ptr_len, | 25 | bool is_const, bool is_volatile, PtrLen ptr_len, |
| 26 | uint32_t byte_alignment, uint32_t bit_offset, uint32_t unaligned_bit_count, | 26 | uint32_t byte_alignment, uint32_t bit_offset, uint32_t unaligned_bit_count, |
| 27 | bool allow_zero, uint32_t vector_index); | 27 | bool allow_zero, uint32_t vector_index, InferredStructField *inferred_struct_field); |
| 28 | uint64_t type_size(CodeGen *g, ZigType *type_entry); | 28 | uint64_t type_size(CodeGen *g, ZigType *type_entry); |
| 29 | uint64_t type_size_bits(CodeGen *g, ZigType *type_entry); | 29 | uint64_t type_size_bits(CodeGen *g, ZigType *type_entry); |
| 30 | ZigType *get_int_type(CodeGen *g, bool is_signed, uint32_t size_in_bits); | 30 | ZigType *get_int_type(CodeGen *g, bool is_signed, uint32_t size_in_bits); |
| ... | @@ -175,6 +175,7 @@ void init_const_arg_tuple(CodeGen *g, ConstExprValue *const_val, size_t arg_inde | ... | @@ -175,6 +175,7 @@ void init_const_arg_tuple(CodeGen *g, ConstExprValue *const_val, size_t arg_inde |
| 175 | ConstExprValue *create_const_arg_tuple(CodeGen *g, size_t arg_index_start, size_t arg_index_end); | 175 | ConstExprValue *create_const_arg_tuple(CodeGen *g, size_t arg_index_start, size_t arg_index_end); |
| 176 | 176 | ||
| 177 | ConstExprValue *create_const_vals(size_t count); | 177 | ConstExprValue *create_const_vals(size_t count); |
| 178 | ConstExprValue *realloc_const_vals(ConstExprValue *base, size_t old_count, size_t new_count); | ||
| 178 | 179 | ||
| 179 | ZigType *make_int_type(CodeGen *g, bool is_signed, uint32_t size_in_bits); | 180 | ZigType *make_int_type(CodeGen *g, bool is_signed, uint32_t size_in_bits); |
| 180 | void expand_undef_array(CodeGen *g, ConstExprValue *const_val); | 181 | void expand_undef_array(CodeGen *g, ConstExprValue *const_val); |
src/ir.cpp+142-21| ... | @@ -202,6 +202,8 @@ static Buf *get_anon_type_name(CodeGen *codegen, IrExecutable *exec, const char | ... | @@ -202,6 +202,8 @@ static Buf *get_anon_type_name(CodeGen *codegen, IrExecutable *exec, const char |
| 202 | Scope *scope, AstNode *source_node, Buf *out_bare_name); | 202 | Scope *scope, AstNode *source_node, Buf *out_bare_name); |
| 203 | static ResultLocCast *ir_build_cast_result_loc(IrBuilder *irb, IrInstruction *dest_type, | 203 | static ResultLocCast *ir_build_cast_result_loc(IrBuilder *irb, IrInstruction *dest_type, |
| 204 | ResultLoc *parent_result_loc); | 204 | ResultLoc *parent_result_loc); |
| 205 | static IrInstruction *ir_analyze_struct_field_ptr(IrAnalyze *ira, IrInstruction *source_instr, | ||
| 206 | TypeStructField *field, IrInstruction *struct_ptr, ZigType *struct_type, bool initializing); | ||
| 205 | 207 | ||
| 206 | static ConstExprValue *const_ptr_pointee_unchecked(CodeGen *g, ConstExprValue *const_val) { | 208 | static ConstExprValue *const_ptr_pointee_unchecked(CodeGen *g, ConstExprValue *const_val) { |
| 207 | assert(get_src_ptr_type(const_val->type) != nullptr); | 209 | assert(get_src_ptr_type(const_val->type) != nullptr); |
| ... | @@ -16321,13 +16323,81 @@ static IrInstruction *ir_analyze_store_ptr(IrAnalyze *ira, IrInstruction *source | ... | @@ -16321,13 +16323,81 @@ static IrInstruction *ir_analyze_store_ptr(IrAnalyze *ira, IrInstruction *source |
| 16321 | return ir_const_void(ira, source_instr); | 16323 | return ir_const_void(ira, source_instr); |
| 16322 | } | 16324 | } |
| 16323 | 16325 | ||
| 16324 | ZigType *child_type = ptr->value.type->data.pointer.child_type; | 16326 | InferredStructField *isf = ptr->value.type->data.pointer.inferred_struct_field; |
| 16327 | if (allow_write_through_const && isf != nullptr) { | ||
| 16328 | // Now it's time to add the field to the struct type. | ||
| 16329 | uint32_t old_field_count = isf->inferred_struct_type->data.structure.src_field_count; | ||
| 16330 | uint32_t new_field_count = old_field_count + 1; | ||
| 16331 | isf->inferred_struct_type->data.structure.src_field_count = new_field_count; | ||
| 16332 | // This thing with max(x, 16) is a hack to allow this functionality to work without | ||
| 16333 | // modifying the ConstExprValue layout of structs. That reworking needs to be | ||
| 16334 | // done, but this hack lets us do it separately, in the future. | ||
| 16335 | TypeStructField *prev_ptr = isf->inferred_struct_type->data.structure.fields; | ||
| 16336 | isf->inferred_struct_type->data.structure.fields = reallocate( | ||
| 16337 | isf->inferred_struct_type->data.structure.fields, | ||
| 16338 | (old_field_count == 0) ? 0 : max(old_field_count, 16u), | ||
| 16339 | max(new_field_count, 16u)); | ||
| 16340 | if (prev_ptr != nullptr && prev_ptr != isf->inferred_struct_type->data.structure.fields) { | ||
| 16341 | zig_panic("TODO need to rework the layout of ZigTypeStruct. this realloc would have caused invalid pointer references"); | ||
| 16342 | } | ||
| 16343 | |||
| 16344 | // This reference can't live long, don't keep it around outside this block. | ||
| 16345 | TypeStructField *field = &isf->inferred_struct_type->data.structure.fields[old_field_count]; | ||
| 16346 | field->name = isf->field_name; | ||
| 16347 | field->type_entry = uncasted_value->value.type; | ||
| 16348 | field->type_val = create_const_type(ira->codegen, field->type_entry); | ||
| 16349 | field->src_index = old_field_count; | ||
| 16350 | field->decl_node = uncasted_value->source_node; | ||
| 16351 | |||
| 16352 | ZigType *struct_ptr_type = get_pointer_to_type(ira->codegen, isf->inferred_struct_type, false); | ||
| 16353 | IrInstruction *casted_ptr; | ||
| 16354 | if (instr_is_comptime(ptr)) { | ||
| 16355 | casted_ptr = ir_const(ira, source_instr, struct_ptr_type); | ||
| 16356 | copy_const_val(&casted_ptr->value, &ptr->value, false); | ||
| 16357 | casted_ptr->value.type = struct_ptr_type; | ||
| 16358 | } else { | ||
| 16359 | casted_ptr = ir_build_cast(&ira->new_irb, source_instr->scope, | ||
| 16360 | source_instr->source_node, struct_ptr_type, ptr, CastOpNoop); | ||
| 16361 | casted_ptr->value.type = struct_ptr_type; | ||
| 16362 | } | ||
| 16363 | if (instr_is_comptime(casted_ptr)) { | ||
| 16364 | ConstExprValue *ptr_val = ir_resolve_const(ira, casted_ptr, UndefBad); | ||
| 16365 | if (!ptr_val) | ||
| 16366 | return ira->codegen->invalid_instruction; | ||
| 16367 | if (ptr_val->data.x_ptr.special != ConstPtrSpecialHardCodedAddr) { | ||
| 16368 | ConstExprValue *struct_val = const_ptr_pointee(ira, ira->codegen, ptr_val, | ||
| 16369 | source_instr->source_node); | ||
| 16370 | struct_val->special = ConstValSpecialStatic; | ||
| 16371 | ConstExprValue *prev_ptr = struct_val->data.x_struct.fields; | ||
| 16372 | // This thing with max(x, 16) is a hack to allow this functionality to work without | ||
| 16373 | // modifying the ConstExprValue layout of structs. That reworking needs to be | ||
| 16374 | // done, but this hack lets us do it separately, in the future. | ||
| 16375 | struct_val->data.x_struct.fields = realloc_const_vals(struct_val->data.x_struct.fields, | ||
| 16376 | (old_field_count == 0) ? 0 : max(old_field_count, 16u), | ||
| 16377 | max(new_field_count, 16u)); | ||
| 16378 | if (prev_ptr != nullptr && prev_ptr != struct_val->data.x_struct.fields) { | ||
| 16379 | zig_panic("TODO need to rework the layout of ConstExprValue for structs. this realloc would have caused invalid pointer references"); | ||
| 16380 | } | ||
| 16381 | |||
| 16382 | ConstExprValue *field_val = &struct_val->data.x_struct.fields[old_field_count]; | ||
| 16383 | field_val->special = ConstValSpecialUndef; | ||
| 16384 | field_val->type = field->type_entry; | ||
| 16385 | field_val->parent.id = ConstParentIdStruct; | ||
| 16386 | field_val->parent.data.p_struct.struct_val = struct_val; | ||
| 16387 | field_val->parent.data.p_struct.field_index = old_field_count; | ||
| 16388 | } | ||
| 16389 | } | ||
| 16390 | |||
| 16391 | ptr = ir_analyze_struct_field_ptr(ira, source_instr, field, casted_ptr, | ||
| 16392 | isf->inferred_struct_type, true); | ||
| 16393 | } | ||
| 16325 | 16394 | ||
| 16326 | if (ptr->value.type->data.pointer.is_const && !allow_write_through_const) { | 16395 | if (ptr->value.type->data.pointer.is_const && !allow_write_through_const) { |
| 16327 | ir_add_error(ira, source_instr, buf_sprintf("cannot assign to constant")); | 16396 | ir_add_error(ira, source_instr, buf_sprintf("cannot assign to constant")); |
| 16328 | return ira->codegen->invalid_instruction; | 16397 | return ira->codegen->invalid_instruction; |
| 16329 | } | 16398 | } |
| 16330 | 16399 | ||
| 16400 | ZigType *child_type = ptr->value.type->data.pointer.child_type; | ||
| 16331 | IrInstruction *value = ir_implicit_cast(ira, uncasted_value, child_type); | 16401 | IrInstruction *value = ir_implicit_cast(ira, uncasted_value, child_type); |
| 16332 | if (value == ira->codegen->invalid_instruction) | 16402 | if (value == ira->codegen->invalid_instruction) |
| 16333 | return ira->codegen->invalid_instruction; | 16403 | return ira->codegen->invalid_instruction; |
| ... | @@ -17853,7 +17923,8 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct | ... | @@ -17853,7 +17923,8 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct |
| 17853 | return_type = get_pointer_to_type_extra2(ira->codegen, elem_type, | 17923 | return_type = get_pointer_to_type_extra2(ira->codegen, elem_type, |
| 17854 | ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile, | 17924 | ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile, |
| 17855 | elem_ptr_instruction->ptr_len, | 17925 | elem_ptr_instruction->ptr_len, |
| 17856 | get_ptr_align(ira->codegen, ptr_type), 0, host_vec_len, false, (uint32_t)index); | 17926 | get_ptr_align(ira->codegen, ptr_type), 0, host_vec_len, false, (uint32_t)index, |
| 17927 | nullptr); | ||
| 17857 | } else if (return_type->data.pointer.explicit_alignment != 0) { | 17928 | } else if (return_type->data.pointer.explicit_alignment != 0) { |
| 17858 | // figure out the largest alignment possible | 17929 | // figure out the largest alignment possible |
| 17859 | 17930 | ||
| ... | @@ -18094,7 +18165,8 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct | ... | @@ -18094,7 +18165,8 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct |
| 18094 | return_type = get_pointer_to_type_extra2(ira->codegen, elem_type, | 18165 | return_type = get_pointer_to_type_extra2(ira->codegen, elem_type, |
| 18095 | ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile, | 18166 | ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile, |
| 18096 | elem_ptr_instruction->ptr_len, | 18167 | elem_ptr_instruction->ptr_len, |
| 18097 | get_ptr_align(ira->codegen, ptr_type), 0, host_vec_len, false, VECTOR_INDEX_RUNTIME); | 18168 | get_ptr_align(ira->codegen, ptr_type), 0, host_vec_len, false, VECTOR_INDEX_RUNTIME, |
| 18169 | nullptr); | ||
| 18098 | } else { | 18170 | } else { |
| 18099 | // runtime known element index | 18171 | // runtime known element index |
| 18100 | switch (type_requires_comptime(ira->codegen, return_type)) { | 18172 | switch (type_requires_comptime(ira->codegen, return_type)) { |
| ... | @@ -18210,31 +18282,34 @@ static IrInstruction *ir_analyze_struct_field_ptr(IrAnalyze *ira, IrInstruction | ... | @@ -18210,31 +18282,34 @@ static IrInstruction *ir_analyze_struct_field_ptr(IrAnalyze *ira, IrInstruction |
| 18210 | case OnePossibleValueNo: | 18282 | case OnePossibleValueNo: |
| 18211 | break; | 18283 | break; |
| 18212 | } | 18284 | } |
| 18213 | ResolveStatus needed_resolve_status = | ||
| 18214 | (struct_type->data.structure.layout == ContainerLayoutAuto) ? | ||
| 18215 | ResolveStatusZeroBitsKnown : ResolveStatusSizeKnown; | ||
| 18216 | if ((err = type_resolve(ira->codegen, struct_type, needed_resolve_status))) | ||
| 18217 | return ira->codegen->invalid_instruction; | ||
| 18218 | assert(struct_ptr->value.type->id == ZigTypeIdPointer); | ||
| 18219 | uint32_t ptr_bit_offset = struct_ptr->value.type->data.pointer.bit_offset_in_host; | ||
| 18220 | uint32_t ptr_host_int_bytes = struct_ptr->value.type->data.pointer.host_int_bytes; | ||
| 18221 | uint32_t host_int_bytes_for_result_type = (ptr_host_int_bytes == 0) ? | ||
| 18222 | get_host_int_bytes(ira->codegen, struct_type, field) : ptr_host_int_bytes; | ||
| 18223 | bool is_const = struct_ptr->value.type->data.pointer.is_const; | 18285 | bool is_const = struct_ptr->value.type->data.pointer.is_const; |
| 18224 | bool is_volatile = struct_ptr->value.type->data.pointer.is_volatile; | 18286 | bool is_volatile = struct_ptr->value.type->data.pointer.is_volatile; |
| 18225 | ZigType *ptr_type = get_pointer_to_type_extra(ira->codegen, field_type, | 18287 | ZigType *ptr_type; |
| 18226 | is_const, is_volatile, PtrLenSingle, field->align, | 18288 | if (struct_type->data.structure.is_inferred) { |
| 18227 | (uint32_t)(ptr_bit_offset + field->bit_offset_in_host), | 18289 | ptr_type = get_pointer_to_type_extra(ira->codegen, field_type, |
| 18228 | (uint32_t)host_int_bytes_for_result_type, false); | 18290 | is_const, is_volatile, PtrLenSingle, 0, 0, 0, false); |
| 18291 | } else { | ||
| 18292 | ResolveStatus needed_resolve_status = | ||
| 18293 | (struct_type->data.structure.layout == ContainerLayoutAuto) ? | ||
| 18294 | ResolveStatusZeroBitsKnown : ResolveStatusSizeKnown; | ||
| 18295 | if ((err = type_resolve(ira->codegen, struct_type, needed_resolve_status))) | ||
| 18296 | return ira->codegen->invalid_instruction; | ||
| 18297 | assert(struct_ptr->value.type->id == ZigTypeIdPointer); | ||
| 18298 | uint32_t ptr_bit_offset = struct_ptr->value.type->data.pointer.bit_offset_in_host; | ||
| 18299 | uint32_t ptr_host_int_bytes = struct_ptr->value.type->data.pointer.host_int_bytes; | ||
| 18300 | uint32_t host_int_bytes_for_result_type = (ptr_host_int_bytes == 0) ? | ||
| 18301 | get_host_int_bytes(ira->codegen, struct_type, field) : ptr_host_int_bytes; | ||
| 18302 | ptr_type = get_pointer_to_type_extra(ira->codegen, field_type, | ||
| 18303 | is_const, is_volatile, PtrLenSingle, field->align, | ||
| 18304 | (uint32_t)(ptr_bit_offset + field->bit_offset_in_host), | ||
| 18305 | (uint32_t)host_int_bytes_for_result_type, false); | ||
| 18306 | } | ||
| 18229 | if (instr_is_comptime(struct_ptr)) { | 18307 | if (instr_is_comptime(struct_ptr)) { |
| 18230 | ConstExprValue *ptr_val = ir_resolve_const(ira, struct_ptr, UndefBad); | 18308 | ConstExprValue *ptr_val = ir_resolve_const(ira, struct_ptr, UndefBad); |
| 18231 | if (!ptr_val) | 18309 | if (!ptr_val) |
| 18232 | return ira->codegen->invalid_instruction; | 18310 | return ira->codegen->invalid_instruction; |
| 18233 | 18311 | ||
| 18234 | if (ptr_val->data.x_ptr.special != ConstPtrSpecialHardCodedAddr) { | 18312 | if (ptr_val->data.x_ptr.special != ConstPtrSpecialHardCodedAddr) { |
| 18235 | if ((err = type_resolve(ira->codegen, struct_type, ResolveStatusSizeKnown))) | ||
| 18236 | return ira->codegen->invalid_instruction; | ||
| 18237 | |||
| 18238 | ConstExprValue *struct_val = const_ptr_pointee(ira, ira->codegen, ptr_val, source_instr->source_node); | 18313 | ConstExprValue *struct_val = const_ptr_pointee(ira, ira->codegen, ptr_val, source_instr->source_node); |
| 18239 | if (struct_val == nullptr) | 18314 | if (struct_val == nullptr) |
| 18240 | return ira->codegen->invalid_instruction; | 18315 | return ira->codegen->invalid_instruction; |
| ... | @@ -18246,7 +18321,8 @@ static IrInstruction *ir_analyze_struct_field_ptr(IrAnalyze *ira, IrInstruction | ... | @@ -18246,7 +18321,8 @@ static IrInstruction *ir_analyze_struct_field_ptr(IrAnalyze *ira, IrInstruction |
| 18246 | for (size_t i = 0; i < struct_type->data.structure.src_field_count; i += 1) { | 18321 | for (size_t i = 0; i < struct_type->data.structure.src_field_count; i += 1) { |
| 18247 | ConstExprValue *field_val = &struct_val->data.x_struct.fields[i]; | 18322 | ConstExprValue *field_val = &struct_val->data.x_struct.fields[i]; |
| 18248 | field_val->special = ConstValSpecialUndef; | 18323 | field_val->special = ConstValSpecialUndef; |
| 18249 | field_val->type = struct_type->data.structure.fields[i].type_entry; | 18324 | field_val->type = resolve_struct_field_type(ira->codegen, |
| 18325 | &struct_type->data.structure.fields[i]); | ||
| 18250 | field_val->parent.id = ConstParentIdStruct; | 18326 | field_val->parent.id = ConstParentIdStruct; |
| 18251 | field_val->parent.data.p_struct.struct_val = struct_val; | 18327 | field_val->parent.data.p_struct.struct_val = struct_val; |
| 18252 | field_val->parent.data.p_struct.field_index = i; | 18328 | field_val->parent.data.p_struct.field_index = i; |
| ... | @@ -18275,6 +18351,40 @@ static IrInstruction *ir_analyze_struct_field_ptr(IrAnalyze *ira, IrInstruction | ... | @@ -18275,6 +18351,40 @@ static IrInstruction *ir_analyze_struct_field_ptr(IrAnalyze *ira, IrInstruction |
| 18275 | return result; | 18351 | return result; |
| 18276 | } | 18352 | } |
| 18277 | 18353 | ||
| 18354 | static IrInstruction *ir_analyze_inferred_field_ptr(IrAnalyze *ira, Buf *field_name, | ||
| 18355 | IrInstruction *source_instr, IrInstruction *container_ptr, ZigType *container_type) | ||
| 18356 | { | ||
| 18357 | // The type of the field is not available until a store using this pointer happens. | ||
| 18358 | // So, here we create a special pointer type which has the inferred struct type and | ||
| 18359 | // field name encoded in the type. Later, when there is a store via this pointer, | ||
| 18360 | // the field type will then be available, and the field will be added to the inferred | ||
| 18361 | // struct. | ||
| 18362 | |||
| 18363 | ZigType *container_ptr_type = container_ptr->value.type; | ||
| 18364 | ir_assert(container_ptr_type->id == ZigTypeIdPointer, source_instr); | ||
| 18365 | |||
| 18366 | InferredStructField *inferred_struct_field = allocate<InferredStructField>(1, "InferredStructField"); | ||
| 18367 | inferred_struct_field->inferred_struct_type = container_type; | ||
| 18368 | inferred_struct_field->field_name = field_name; | ||
| 18369 | |||
| 18370 | ZigType *elem_type = ira->codegen->builtin_types.entry_c_void; | ||
| 18371 | ZigType *field_ptr_type = get_pointer_to_type_extra2(ira->codegen, elem_type, | ||
| 18372 | container_ptr_type->data.pointer.is_const, container_ptr_type->data.pointer.is_volatile, | ||
| 18373 | PtrLenSingle, 0, 0, 0, false, VECTOR_INDEX_NONE, inferred_struct_field); | ||
| 18374 | |||
| 18375 | if (instr_is_comptime(container_ptr)) { | ||
| 18376 | IrInstruction *result = ir_const(ira, source_instr, field_ptr_type); | ||
| 18377 | copy_const_val(&result->value, &container_ptr->value, false); | ||
| 18378 | result->value.type = field_ptr_type; | ||
| 18379 | return result; | ||
| 18380 | } | ||
| 18381 | |||
| 18382 | IrInstruction *result = ir_build_cast(&ira->new_irb, source_instr->scope, | ||
| 18383 | source_instr->source_node, field_ptr_type, container_ptr, CastOpNoop); | ||
| 18384 | result->value.type = field_ptr_type; | ||
| 18385 | return result; | ||
| 18386 | } | ||
| 18387 | |||
| 18278 | static IrInstruction *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_name, | 18388 | static IrInstruction *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_name, |
| 18279 | IrInstruction *source_instr, IrInstruction *container_ptr, ZigType *container_type, bool initializing) | 18389 | IrInstruction *source_instr, IrInstruction *container_ptr, ZigType *container_type, bool initializing) |
| 18280 | { | 18390 | { |
| ... | @@ -18282,6 +18392,12 @@ static IrInstruction *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_ | ... | @@ -18282,6 +18392,12 @@ static IrInstruction *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_ |
| 18282 | 18392 | ||
| 18283 | ZigType *bare_type = container_ref_type(container_type); | 18393 | ZigType *bare_type = container_ref_type(container_type); |
| 18284 | 18394 | ||
| 18395 | if (initializing && bare_type->id == ZigTypeIdStruct && | ||
| 18396 | bare_type->data.structure.resolve_status == ResolveStatusBeingInferred) | ||
| 18397 | { | ||
| 18398 | return ir_analyze_inferred_field_ptr(ira, field_name, source_instr, container_ptr, bare_type); | ||
| 18399 | } | ||
| 18400 | |||
| 18285 | if ((err = type_resolve(ira->codegen, bare_type, ResolveStatusZeroBitsKnown))) | 18401 | if ((err = type_resolve(ira->codegen, bare_type, ResolveStatusZeroBitsKnown))) |
| 18286 | return ira->codegen->invalid_instruction; | 18402 | return ira->codegen->invalid_instruction; |
| 18287 | 18403 | ||
| ... | @@ -20056,6 +20172,11 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc | ... | @@ -20056,6 +20172,11 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc |
| 20056 | return ira->codegen->invalid_instruction; | 20172 | return ira->codegen->invalid_instruction; |
| 20057 | } | 20173 | } |
| 20058 | 20174 | ||
| 20175 | if (container_type->data.structure.resolve_status == ResolveStatusBeingInferred) { | ||
| 20176 | // We're now done inferring the type. | ||
| 20177 | container_type->data.structure.resolve_status = ResolveStatusUnstarted; | ||
| 20178 | } | ||
| 20179 | |||
| 20059 | if ((err = type_resolve(ira->codegen, container_type, ResolveStatusSizeKnown))) | 20180 | if ((err = type_resolve(ira->codegen, container_type, ResolveStatusSizeKnown))) |
| 20060 | return ira->codegen->invalid_instruction; | 20181 | return ira->codegen->invalid_instruction; |
| 20061 | 20182 |
test/stage1/behavior/struct.zig+22| ... | @@ -729,3 +729,25 @@ test "anonymous struct literal syntax" { | ... | @@ -729,3 +729,25 @@ test "anonymous struct literal syntax" { |
| 729 | S.doTheTest(); | 729 | S.doTheTest(); |
| 730 | comptime S.doTheTest(); | 730 | comptime S.doTheTest(); |
| 731 | } | 731 | } |
| 732 | |||
| 733 | test "fully anonymous struct" { | ||
| 734 | const S = struct { | ||
| 735 | fn doTheTest() void { | ||
| 736 | dump(.{ | ||
| 737 | .int = @as(u32, 1234), | ||
| 738 | .float = @as(f64, 12.34), | ||
| 739 | .b = true, | ||
| 740 | .s = "hi", | ||
| 741 | }); | ||
| 742 | } | ||
| 743 | fn dump(args: var) void { | ||
| 744 | expect(args.int == 1234); | ||
| 745 | expect(args.float == 12.34); | ||
| 746 | expect(args.b); | ||
| 747 | expect(args.s[0] == 'h'); | ||
| 748 | expect(args.s[1] == 'i'); | ||
| 749 | } | ||
| 750 | }; | ||
| 751 | S.doTheTest(); | ||
| 752 | comptime S.doTheTest(); | ||
| 753 | } |