| ... | @@ -2681,48 +2681,50 @@ static Error resolve_struct_alignment(CodeGen *g, ZigType *struct_type) { | ... | @@ -2681,48 +2681,50 @@ static Error resolve_struct_alignment(CodeGen *g, ZigType *struct_type) { |
| 2681 | assert(decl_node->type == NodeTypeContainerDecl); | 2681 | assert(decl_node->type == NodeTypeContainerDecl); |
| 2682 | assert(struct_type->di_type); | 2682 | assert(struct_type->di_type); |
| 2683 | | 2683 | |
| | 2684 | size_t field_count = struct_type->data.structure.src_field_count; |
| 2684 | if (struct_type->data.structure.layout == ContainerLayoutPacked) { | 2685 | if (struct_type->data.structure.layout == ContainerLayoutPacked) { |
| 2685 | struct_type->data.structure.abi_alignment = 1; | 2686 | struct_type->data.structure.abi_alignment = 1; |
| 2686 | } | 2687 | for (size_t i = 0; i < field_count; i += 1) { |
| 2687 | | 2688 | TypeStructField *field = &struct_type->data.structure.fields[i]; |
| 2688 | size_t field_count = struct_type->data.structure.src_field_count; | 2689 | if (field->type_entry != nullptr && type_is_invalid(field->type_entry)) { |
| 2689 | bool self_resolving = false; | 2690 | struct_type->data.structure.resolve_status = ResolveStatusInvalid; |
| 2690 | for (size_t i = 0; i < field_count; i += 1) { | 2691 | break; |
| 2691 | TypeStructField *field = &struct_type->data.structure.fields[i]; | 2692 | } |
| 2692 | | | |
| 2693 | // If we have no type_entry for the field, assume that we are in the | | |
| 2694 | // midst of resolving this struct. We further assume that since the | | |
| 2695 | // resolved alignment of the other fields of this struct is ultimately | | |
| 2696 | // equal to the resolved alignment of this struct, we can safely ignore. | | |
| 2697 | // | | |
| 2698 | // If this struct is used down-stream in aligning a sub-struct, ignoring | | |
| 2699 | // this struct in the context of a sub struct has the same effect since | | |
| 2700 | // the other fields will be calculated and bubble-up. | | |
| 2701 | if (nullptr == field->type_entry) { | | |
| 2702 | self_resolving = true; | | |
| 2703 | continue; | | |
| 2704 | } | | |
| 2705 | | | |
| 2706 | if (type_is_invalid(field->type_entry)) { | | |
| 2707 | struct_type->data.structure.resolve_status = ResolveStatusInvalid; | | |
| 2708 | break; | | |
| 2709 | } | 2693 | } |
| | 2694 | } else for (size_t i = 0; i < field_count; i += 1) { |
| | 2695 | TypeStructField *field = &struct_type->data.structure.fields[i]; |
| | 2696 | uint32_t this_field_align; |
| | 2697 | |
| | 2698 | // TODO If we have no type_entry for the field, we've already failed to |
| | 2699 | // compile the program correctly. This stage1 compiler needs a deeper |
| | 2700 | // reworking to make this correct, or we can ignore the problem |
| | 2701 | // and make sure it is fixed in stage2. This workaround is for when |
| | 2702 | // there is a false positive of a dependency loop, of alignment depending |
| | 2703 | // on itself. When this false positive happens we assume a pointer-aligned |
| | 2704 | // field, which is usually fine but could be incorrectly over-aligned or |
| | 2705 | // even under-aligned. See https://github.com/ziglang/zig/issues/1512 |
| | 2706 | if (field->type_entry == nullptr) { |
| | 2707 | this_field_align = LLVMABIAlignmentOfType(g->target_data_ref, LLVMPointerType(LLVMInt8Type(), 0)); |
| | 2708 | } else { |
| | 2709 | if (type_is_invalid(field->type_entry)) { |
| | 2710 | struct_type->data.structure.resolve_status = ResolveStatusInvalid; |
| | 2711 | break; |
| | 2712 | } |
| 2710 | | 2713 | |
| 2711 | if (!type_has_bits(field->type_entry)) | 2714 | if (!type_has_bits(field->type_entry)) |
| 2712 | continue; | 2715 | continue; |
| 2713 | | 2716 | |
| 2714 | // alignment of structs is the alignment of the most-aligned field | | |
| 2715 | if (struct_type->data.structure.layout != ContainerLayoutPacked) { | | |
| 2716 | if ((err = type_resolve(g, field->type_entry, ResolveStatusAlignmentKnown))) { | 2717 | if ((err = type_resolve(g, field->type_entry, ResolveStatusAlignmentKnown))) { |
| 2717 | struct_type->data.structure.resolve_status = ResolveStatusInvalid; | 2718 | struct_type->data.structure.resolve_status = ResolveStatusInvalid; |
| 2718 | break; | 2719 | break; |
| 2719 | } | 2720 | } |
| 2720 | | 2721 | |
| 2721 | uint32_t this_field_align = get_abi_alignment(g, field->type_entry); | 2722 | this_field_align = get_abi_alignment(g, field->type_entry); |
| 2722 | assert(this_field_align != 0); | 2723 | assert(this_field_align != 0); |
| 2723 | if (this_field_align > struct_type->data.structure.abi_alignment) { | 2724 | } |
| 2724 | struct_type->data.structure.abi_alignment = this_field_align; | 2725 | // alignment of structs is the alignment of the most-aligned field |
| 2725 | } | 2726 | if (this_field_align > struct_type->data.structure.abi_alignment) { |
| | 2727 | struct_type->data.structure.abi_alignment = this_field_align; |
| 2726 | } | 2728 | } |
| 2727 | } | 2729 | } |
| 2728 | | 2730 | |
| ... | @@ -2732,14 +2734,6 @@ static Error resolve_struct_alignment(CodeGen *g, ZigType *struct_type) { | ... | @@ -2732,14 +2734,6 @@ static Error resolve_struct_alignment(CodeGen *g, ZigType *struct_type) { |
| 2732 | return ErrorSemanticAnalyzeFail; | 2734 | return ErrorSemanticAnalyzeFail; |
| 2733 | } | 2735 | } |
| 2734 | | 2736 | |
| 2735 | if ( self_resolving | | |
| 2736 | && field_count > 0 | | |
| 2737 | ) { | | |
| 2738 | // If we get here it's due to self-referencing this struct before it has been fully resolved. | | |
| 2739 | // In this case, set alignment to target pointer default. | | |
| 2740 | struct_type->data.structure.abi_alignment = LLVMABIAlignmentOfType(g->target_data_ref, | | |
| 2741 | LLVMPointerType(LLVMInt8Type(), 0)); | | |
| 2742 | } | | |
| 2743 | struct_type->data.structure.resolve_status = ResolveStatusAlignmentKnown; | 2737 | struct_type->data.structure.resolve_status = ResolveStatusAlignmentKnown; |
| 2744 | return ErrorNone; | 2738 | return ErrorNone; |
| 2745 | } | 2739 | } |