| ... | @@ -1713,84 +1713,16 @@ static void resolve_union_type(CodeGen *g, TypeTableEntry *union_type) { | ... | @@ -1713,84 +1713,16 @@ static void resolve_union_type(CodeGen *g, TypeTableEntry *union_type) { |
| 1713 | uint64_t biggest_align_in_bits = 0; | 1713 | uint64_t biggest_align_in_bits = 0; |
| 1714 | uint64_t biggest_size_in_bits = 0; | 1714 | uint64_t biggest_size_in_bits = 0; |
| 1715 | | 1715 | |
| 1716 | ZigLLVMDIEnumerator **di_enumerators; | | |
| 1717 | | | |
| 1718 | Scope *scope = &union_type->data.unionation.decls_scope->base; | 1716 | Scope *scope = &union_type->data.unionation.decls_scope->base; |
| 1719 | ImportTableEntry *import = get_scope_import(scope); | 1717 | ImportTableEntry *import = get_scope_import(scope); |
| 1720 | | 1718 | |
| 1721 | // set temporary flag | 1719 | // set temporary flag |
| 1722 | union_type->data.unionation.embedded_in_current = true; | 1720 | union_type->data.unionation.embedded_in_current = true; |
| 1723 | | 1721 | |
| 1724 | HashMap<BigInt, AstNode *, bigint_hash, bigint_eql> occupied_tag_values = {}; | | |
| 1725 | | | |
| 1726 | AstNode *enum_type_node = decl_node->data.container_decl.init_arg_expr; | | |
| 1727 | bool auto_layout = (union_type->data.unionation.layout == ContainerLayoutAuto); | | |
| 1728 | bool want_safety = (field_count >= 2) && (auto_layout || enum_type_node != nullptr); | | |
| 1729 | TypeTableEntry *tag_type; | | |
| 1730 | bool create_enum_type = decl_node->data.container_decl.auto_enum || (enum_type_node == nullptr && want_safety); | | |
| 1731 | bool *covered_enum_fields; | | |
| 1732 | if (create_enum_type) { | | |
| 1733 | occupied_tag_values.init(field_count); | | |
| 1734 | | | |
| 1735 | di_enumerators = allocate<ZigLLVMDIEnumerator*>(field_count); | | |
| 1736 | | | |
| 1737 | TypeTableEntry *tag_int_type; | | |
| 1738 | if (enum_type_node != nullptr) { | | |
| 1739 | tag_int_type = analyze_type_expr(g, scope, enum_type_node); | | |
| 1740 | if (type_is_invalid(tag_int_type)) { | | |
| 1741 | union_type->data.unionation.is_invalid = true; | | |
| 1742 | return; | | |
| 1743 | } | | |
| 1744 | if (tag_int_type->id != TypeTableEntryIdInt) { | | |
| 1745 | add_node_error(g, enum_type_node, | | |
| 1746 | buf_sprintf("expected integer tag type, found '%s'", buf_ptr(&tag_int_type->name))); | | |
| 1747 | union_type->data.unionation.is_invalid = true; | | |
| 1748 | return; | | |
| 1749 | } | | |
| 1750 | } else { | | |
| 1751 | tag_int_type = get_smallest_unsigned_int_type(g, field_count - 1); | | |
| 1752 | } | | |
| 1753 | | | |
| 1754 | tag_type = new_type_table_entry(TypeTableEntryIdEnum); | | |
| 1755 | buf_resize(&tag_type->name, 0); | | |
| 1756 | buf_appendf(&tag_type->name, "@EnumTagType(%s)", buf_ptr(&union_type->name)); | | |
| 1757 | tag_type->is_copyable = true; | | |
| 1758 | tag_type->type_ref = tag_int_type->type_ref; | | |
| 1759 | tag_type->zero_bits = tag_int_type->zero_bits; | | |
| 1760 | | | |
| 1761 | tag_type->data.enumeration.tag_int_type = tag_int_type; | | |
| 1762 | tag_type->data.enumeration.zero_bits_known = true; | | |
| 1763 | tag_type->data.enumeration.decl_node = decl_node; | | |
| 1764 | tag_type->data.enumeration.layout = ContainerLayoutAuto; | | |
| 1765 | tag_type->data.enumeration.src_field_count = field_count; | | |
| 1766 | tag_type->data.enumeration.fields = allocate<TypeEnumField>(field_count); | | |
| 1767 | tag_type->data.enumeration.decls_scope = union_type->data.unionation.decls_scope; | | |
| 1768 | tag_type->data.enumeration.complete = true; | | |
| 1769 | } else if (enum_type_node != nullptr) { | | |
| 1770 | TypeTableEntry *enum_type = analyze_type_expr(g, scope, enum_type_node); | | |
| 1771 | if (type_is_invalid(enum_type)) { | | |
| 1772 | union_type->data.unionation.is_invalid = true; | | |
| 1773 | union_type->data.unionation.embedded_in_current = false; | | |
| 1774 | return; | | |
| 1775 | } | | |
| 1776 | if (enum_type->id != TypeTableEntryIdEnum) { | | |
| 1777 | union_type->data.unionation.is_invalid = true; | | |
| 1778 | union_type->data.unionation.embedded_in_current = false; | | |
| 1779 | add_node_error(g, enum_type_node, | | |
| 1780 | buf_sprintf("expected enum tag type, found '%s'", buf_ptr(&enum_type->name))); | | |
| 1781 | return; | | |
| 1782 | } | | |
| 1783 | tag_type = enum_type; | | |
| 1784 | covered_enum_fields = allocate<bool>(enum_type->data.enumeration.src_field_count); | | |
| 1785 | } else { | | |
| 1786 | tag_type = nullptr; | | |
| 1787 | } | | |
| 1788 | union_type->data.unionation.tag_type = tag_type; | | |
| 1789 | | 1722 | |
| 1790 | for (uint32_t i = 0; i < field_count; i += 1) { | 1723 | for (uint32_t i = 0; i < field_count; i += 1) { |
| 1791 | AstNode *field_node = decl_node->data.container_decl.fields.at(i); | 1724 | AstNode *field_node = decl_node->data.container_decl.fields.at(i); |
| 1792 | TypeUnionField *union_field = &union_type->data.unionation.fields[i]; | 1725 | TypeUnionField *union_field = &union_type->data.unionation.fields[i]; |
| 1793 | Buf *field_name = field_node->data.struct_field.name; | | |
| 1794 | TypeTableEntry *field_type = union_field->type_entry; | 1726 | TypeTableEntry *field_type = union_field->type_entry; |
| 1795 | | 1727 | |
| 1796 | ensure_complete_type(g, field_type); | 1728 | ensure_complete_type(g, field_type); |
| ... | @@ -1799,57 +1731,6 @@ static void resolve_union_type(CodeGen *g, TypeTableEntry *union_type) { | ... | @@ -1799,57 +1731,6 @@ static void resolve_union_type(CodeGen *g, TypeTableEntry *union_type) { |
| 1799 | continue; | 1731 | continue; |
| 1800 | } | 1732 | } |
| 1801 | | 1733 | |
| 1802 | if (create_enum_type) { | | |
| 1803 | di_enumerators[i] = ZigLLVMCreateDebugEnumerator(g->dbuilder, buf_ptr(field_name), i); | | |
| 1804 | union_field->enum_field = &tag_type->data.enumeration.fields[i]; | | |
| 1805 | union_field->enum_field->name = field_name; | | |
| 1806 | union_field->enum_field->decl_index = i; | | |
| 1807 | | | |
| 1808 | AstNode *tag_value = field_node->data.struct_field.value; | | |
| 1809 | // In this first pass we resolve explicit tag values. | | |
| 1810 | // In a second pass we will fill in the unspecified ones. | | |
| 1811 | if (tag_value != nullptr) { | | |
| 1812 | TypeTableEntry *tag_int_type = tag_type->data.enumeration.tag_int_type; | | |
| 1813 | IrInstruction *result_inst = analyze_const_value(g, scope, tag_value, tag_int_type, nullptr); | | |
| 1814 | if (result_inst->value.type->id == TypeTableEntryIdInvalid) { | | |
| 1815 | union_type->data.unionation.is_invalid = true; | | |
| 1816 | continue; | | |
| 1817 | } | | |
| 1818 | assert(result_inst->value.special != ConstValSpecialRuntime); | | |
| 1819 | assert(result_inst->value.type->id == TypeTableEntryIdInt); | | |
| 1820 | auto entry = occupied_tag_values.put_unique(result_inst->value.data.x_bigint, tag_value); | | |
| 1821 | if (entry == nullptr) { | | |
| 1822 | bigint_init_bigint(&union_field->enum_field->value, &result_inst->value.data.x_bigint); | | |
| 1823 | } else { | | |
| 1824 | Buf *val_buf = buf_alloc(); | | |
| 1825 | bigint_append_buf(val_buf, &result_inst->value.data.x_bigint, 10); | | |
| 1826 | | | |
| 1827 | ErrorMsg *msg = add_node_error(g, tag_value, | | |
| 1828 | buf_sprintf("enum tag value %s already taken", buf_ptr(val_buf))); | | |
| 1829 | add_error_note(g, msg, entry->value, | | |
| 1830 | buf_sprintf("other occurrence here")); | | |
| 1831 | union_type->data.unionation.is_invalid = true; | | |
| 1832 | continue; | | |
| 1833 | } | | |
| 1834 | } | | |
| 1835 | } else if (enum_type_node != nullptr) { | | |
| 1836 | union_field->enum_field = find_enum_type_field(tag_type, field_name); | | |
| 1837 | if (union_field->enum_field == nullptr) { | | |
| 1838 | ErrorMsg *msg = add_node_error(g, field_node, | | |
| 1839 | buf_sprintf("enum field not found: '%s'", buf_ptr(field_name))); | | |
| 1840 | add_error_note(g, msg, tag_type->data.enumeration.decl_node, | | |
| 1841 | buf_sprintf("enum declared here")); | | |
| 1842 | union_type->data.unionation.is_invalid = true; | | |
| 1843 | continue; | | |
| 1844 | } | | |
| 1845 | covered_enum_fields[union_field->enum_field->decl_index] = true; | | |
| 1846 | } else { | | |
| 1847 | union_field->enum_field = allocate<TypeEnumField>(1); | | |
| 1848 | union_field->enum_field->name = field_name; | | |
| 1849 | union_field->enum_field->decl_index = i; | | |
| 1850 | bigint_init_unsigned(&union_field->enum_field->value, i); | | |
| 1851 | } | | |
| 1852 | | | |
| 1853 | if (!type_has_bits(field_type)) | 1734 | if (!type_has_bits(field_type)) |
| 1854 | continue; | 1735 | continue; |
| 1855 | | 1736 | |
| ... | @@ -1876,48 +1757,6 @@ static void resolve_union_type(CodeGen *g, TypeTableEntry *union_type) { | ... | @@ -1876,48 +1757,6 @@ static void resolve_union_type(CodeGen *g, TypeTableEntry *union_type) { |
| 1876 | } | 1757 | } |
| 1877 | } | 1758 | } |
| 1878 | | 1759 | |
| 1879 | if (create_enum_type) { | | |
| 1880 | // Now iterate again and populate the unspecified tag values | | |
| 1881 | uint32_t next_maybe_unoccupied_index = 0; | | |
| 1882 | | | |
| 1883 | for (uint32_t field_i = 0; field_i < field_count; field_i += 1) { | | |
| 1884 | AstNode *field_node = decl_node->data.container_decl.fields.at(field_i); | | |
| 1885 | TypeUnionField *union_field = &union_type->data.unionation.fields[field_i]; | | |
| 1886 | AstNode *tag_value = field_node->data.struct_field.value; | | |
| 1887 | | | |
| 1888 | if (tag_value == nullptr) { | | |
| 1889 | if (occupied_tag_values.size() == 0) { | | |
| 1890 | bigint_init_unsigned(&union_field->enum_field->value, next_maybe_unoccupied_index); | | |
| 1891 | next_maybe_unoccupied_index += 1; | | |
| 1892 | } else { | | |
| 1893 | BigInt proposed_value; | | |
| 1894 | for (;;) { | | |
| 1895 | bigint_init_unsigned(&proposed_value, next_maybe_unoccupied_index); | | |
| 1896 | next_maybe_unoccupied_index += 1; | | |
| 1897 | auto entry = occupied_tag_values.put_unique(proposed_value, field_node); | | |
| 1898 | if (entry != nullptr) { | | |
| 1899 | continue; | | |
| 1900 | } | | |
| 1901 | break; | | |
| 1902 | } | | |
| 1903 | bigint_init_bigint(&union_field->enum_field->value, &proposed_value); | | |
| 1904 | } | | |
| 1905 | } | | |
| 1906 | } | | |
| 1907 | } else if (enum_type_node != nullptr) { | | |
| 1908 | for (uint32_t i = 0; i < tag_type->data.enumeration.src_field_count; i += 1) { | | |
| 1909 | TypeEnumField *enum_field = &tag_type->data.enumeration.fields[i]; | | |
| 1910 | if (!covered_enum_fields[i]) { | | |
| 1911 | AstNode *enum_decl_node = tag_type->data.enumeration.decl_node; | | |
| 1912 | AstNode *field_node = enum_decl_node->data.container_decl.fields.at(i); | | |
| 1913 | ErrorMsg *msg = add_node_error(g, decl_node, | | |
| 1914 | buf_sprintf("enum field missing: '%s'", buf_ptr(enum_field->name))); | | |
| 1915 | add_error_note(g, msg, field_node, | | |
| 1916 | buf_sprintf("declared here")); | | |
| 1917 | union_type->data.unionation.is_invalid = true; | | |
| 1918 | } | | |
| 1919 | } | | |
| 1920 | } | | |
| 1921 | | 1760 | |
| 1922 | // unset temporary flag | 1761 | // unset temporary flag |
| 1923 | union_type->data.unionation.embedded_in_current = false; | 1762 | union_type->data.unionation.embedded_in_current = false; |
| ... | @@ -1948,11 +1787,12 @@ static void resolve_union_type(CodeGen *g, TypeTableEntry *union_type) { | ... | @@ -1948,11 +1787,12 @@ static void resolve_union_type(CodeGen *g, TypeTableEntry *union_type) { |
| 1948 | return; | 1787 | return; |
| 1949 | } | 1788 | } |
| 1950 | | 1789 | |
| 1951 | assert(most_aligned_union_member != nullptr); | | |
| 1952 | | | |
| 1953 | uint64_t padding_in_bits = biggest_size_in_bits - size_of_most_aligned_member_in_bits; | 1790 | uint64_t padding_in_bits = biggest_size_in_bits - size_of_most_aligned_member_in_bits; |
| 1954 | | 1791 | |
| | 1792 | TypeTableEntry *tag_type = union_type->data.unionation.tag_type; |
| 1955 | if (tag_type == nullptr) { | 1793 | if (tag_type == nullptr) { |
| | 1794 | assert(most_aligned_union_member != nullptr); |
| | 1795 | |
| 1956 | if (padding_in_bits > 0) { | 1796 | if (padding_in_bits > 0) { |
| 1957 | TypeTableEntry *u8_type = get_int_type(g, false, 8); | 1797 | TypeTableEntry *u8_type = get_int_type(g, false, 8); |
| 1958 | TypeTableEntry *padding_array = get_array_type(g, u8_type, padding_in_bits / 8); | 1798 | TypeTableEntry *padding_array = get_array_type(g, u8_type, padding_in_bits / 8); |
| ... | @@ -1993,7 +1833,13 @@ static void resolve_union_type(CodeGen *g, TypeTableEntry *union_type) { | ... | @@ -1993,7 +1833,13 @@ static void resolve_union_type(CodeGen *g, TypeTableEntry *union_type) { |
| 1993 | }; | 1833 | }; |
| 1994 | union_type_ref = LLVMStructType(union_element_types, 2, false); | 1834 | union_type_ref = LLVMStructType(union_element_types, 2, false); |
| 1995 | } else if (most_aligned_union_member == nullptr) { | 1835 | } else if (most_aligned_union_member == nullptr) { |
| 1996 | zig_panic("TODO zero bit payload"); | 1836 | union_type->data.unionation.gen_tag_index = SIZE_MAX; |
| | 1837 | union_type->data.unionation.gen_union_index = SIZE_MAX; |
| | 1838 | union_type->type_ref = tag_type->type_ref; |
| | 1839 | |
| | 1840 | ZigLLVMReplaceTemporary(g->dbuilder, union_type->di_type, tag_type->di_type); |
| | 1841 | union_type->di_type = tag_type->di_type; |
| | 1842 | return; |
| 1997 | } else { | 1843 | } else { |
| 1998 | union_type_ref = most_aligned_union_member->type_ref; | 1844 | union_type_ref = most_aligned_union_member->type_ref; |
| 1999 | } | 1845 | } |
| ... | @@ -2020,20 +1866,6 @@ static void resolve_union_type(CodeGen *g, TypeTableEntry *union_type) { | ... | @@ -2020,20 +1866,6 @@ static void resolve_union_type(CodeGen *g, TypeTableEntry *union_type) { |
| 2020 | LLVMStructSetBody(union_type->type_ref, root_struct_element_types, 2, false); | 1866 | LLVMStructSetBody(union_type->type_ref, root_struct_element_types, 2, false); |
| 2021 | | 1867 | |
| 2022 | | 1868 | |
| 2023 | // create debug type for root struct | | |
| 2024 | | | |
| 2025 | uint64_t tag_debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, tag_type->type_ref); | | |
| 2026 | uint64_t tag_debug_align_in_bits = 8*LLVMABIAlignmentOfType(g->target_data_ref, tag_type->type_ref); | | |
| 2027 | if (create_enum_type) { | | |
| 2028 | // create debug type for tag | | |
| 2029 | ZigLLVMDIType *tag_di_type = ZigLLVMCreateDebugEnumerationType(g->dbuilder, | | |
| 2030 | ZigLLVMTypeToScope(union_type->di_type), "AnonEnum", | | |
| 2031 | import->di_file, (unsigned)(decl_node->line + 1), | | |
| 2032 | tag_debug_size_in_bits, tag_debug_align_in_bits, di_enumerators, field_count, | | |
| 2033 | tag_type->di_type, ""); | | |
| 2034 | tag_type->di_type = tag_di_type; | | |
| 2035 | } | | |
| 2036 | | | |
| 2037 | // create debug type for union | 1869 | // create debug type for union |
| 2038 | ZigLLVMDIType *union_di_type = ZigLLVMCreateDebugUnionType(g->dbuilder, | 1870 | ZigLLVMDIType *union_di_type = ZigLLVMCreateDebugUnionType(g->dbuilder, |
| 2039 | ZigLLVMTypeToScope(union_type->di_type), "AnonUnion", | 1871 | ZigLLVMTypeToScope(union_type->di_type), "AnonUnion", |
| ... | @@ -2053,6 +1885,10 @@ static void resolve_union_type(CodeGen *g, TypeTableEntry *union_type) { | ... | @@ -2053,6 +1885,10 @@ static void resolve_union_type(CodeGen *g, TypeTableEntry *union_type) { |
| 2053 | biggest_align_in_bits, | 1885 | biggest_align_in_bits, |
| 2054 | union_offset_in_bits, | 1886 | union_offset_in_bits, |
| 2055 | 0, union_di_type); | 1887 | 0, union_di_type); |
| | 1888 | |
| | 1889 | uint64_t tag_debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, tag_type->type_ref); |
| | 1890 | uint64_t tag_debug_align_in_bits = 8*LLVMABIAlignmentOfType(g->target_data_ref, tag_type->type_ref); |
| | 1891 | |
| 2056 | ZigLLVMDIType *tag_member_di_type = ZigLLVMCreateDebugMemberType(g->dbuilder, | 1892 | ZigLLVMDIType *tag_member_di_type = ZigLLVMCreateDebugMemberType(g->dbuilder, |
| 2057 | ZigLLVMTypeToScope(union_type->di_type), "tag", | 1893 | ZigLLVMTypeToScope(union_type->di_type), "tag", |
| 2058 | import->di_file, (unsigned)(decl_node->line + 1), | 1894 | import->di_file, (unsigned)(decl_node->line + 1), |
| ... | @@ -2312,8 +2148,23 @@ static void resolve_union_zero_bits(CodeGen *g, TypeTableEntry *union_type) { | ... | @@ -2312,8 +2148,23 @@ static void resolve_union_zero_bits(CodeGen *g, TypeTableEntry *union_type) { |
| 2312 | if (union_type->data.unionation.zero_bits_known) | 2148 | if (union_type->data.unionation.zero_bits_known) |
| 2313 | return; | 2149 | return; |
| 2314 | | 2150 | |
| | 2151 | if (type_is_invalid(union_type)) |
| | 2152 | return; |
| | 2153 | |
| 2315 | if (union_type->data.unionation.zero_bits_loop_flag) { | 2154 | if (union_type->data.unionation.zero_bits_loop_flag) { |
| | 2155 | // If we get here it's due to recursion. From this we conclude that the struct is |
| | 2156 | // not zero bits, and if abi_alignment == 0 we further conclude that the first field |
| | 2157 | // is a pointer to this very struct, or a function pointer with parameters that |
| | 2158 | // reference such a type. |
| 2316 | union_type->data.unionation.zero_bits_known = true; | 2159 | union_type->data.unionation.zero_bits_known = true; |
| | 2160 | if (union_type->data.unionation.abi_alignment == 0) { |
| | 2161 | if (union_type->data.unionation.layout == ContainerLayoutPacked) { |
| | 2162 | union_type->data.unionation.abi_alignment = 1; |
| | 2163 | } else { |
| | 2164 | union_type->data.unionation.abi_alignment = LLVMABIAlignmentOfType(g->target_data_ref, |
| | 2165 | LLVMPointerType(LLVMInt8Type(), 0)); |
| | 2166 | } |
| | 2167 | } |
| 2317 | return; | 2168 | return; |
| 2318 | } | 2169 | } |
| 2319 | | 2170 | |
| ... | @@ -2342,19 +2193,99 @@ static void resolve_union_zero_bits(CodeGen *g, TypeTableEntry *union_type) { | ... | @@ -2342,19 +2193,99 @@ static void resolve_union_zero_bits(CodeGen *g, TypeTableEntry *union_type) { |
| 2342 | | 2193 | |
| 2343 | Scope *scope = &union_type->data.unionation.decls_scope->base; | 2194 | Scope *scope = &union_type->data.unionation.decls_scope->base; |
| 2344 | | 2195 | |
| | 2196 | HashMap<BigInt, AstNode *, bigint_hash, bigint_eql> occupied_tag_values = {}; |
| | 2197 | |
| | 2198 | AstNode *enum_type_node = decl_node->data.container_decl.init_arg_expr; |
| | 2199 | bool auto_layout = (union_type->data.unionation.layout == ContainerLayoutAuto); |
| | 2200 | bool want_safety = (field_count >= 2) && (auto_layout || enum_type_node != nullptr); |
| | 2201 | TypeTableEntry *tag_type; |
| | 2202 | bool create_enum_type = decl_node->data.container_decl.auto_enum || (enum_type_node == nullptr && want_safety); |
| | 2203 | bool *covered_enum_fields; |
| | 2204 | ZigLLVMDIEnumerator **di_enumerators; |
| | 2205 | if (create_enum_type) { |
| | 2206 | occupied_tag_values.init(field_count); |
| | 2207 | |
| | 2208 | di_enumerators = allocate<ZigLLVMDIEnumerator*>(field_count); |
| | 2209 | |
| | 2210 | TypeTableEntry *tag_int_type; |
| | 2211 | if (enum_type_node != nullptr) { |
| | 2212 | tag_int_type = analyze_type_expr(g, scope, enum_type_node); |
| | 2213 | if (type_is_invalid(tag_int_type)) { |
| | 2214 | union_type->data.unionation.is_invalid = true; |
| | 2215 | return; |
| | 2216 | } |
| | 2217 | if (tag_int_type->id != TypeTableEntryIdInt) { |
| | 2218 | add_node_error(g, enum_type_node, |
| | 2219 | buf_sprintf("expected integer tag type, found '%s'", buf_ptr(&tag_int_type->name))); |
| | 2220 | union_type->data.unionation.is_invalid = true; |
| | 2221 | return; |
| | 2222 | } |
| | 2223 | } else { |
| | 2224 | tag_int_type = get_smallest_unsigned_int_type(g, field_count - 1); |
| | 2225 | } |
| | 2226 | union_type->data.unionation.abi_alignment = get_abi_alignment(g, tag_int_type); |
| | 2227 | |
| | 2228 | tag_type = new_type_table_entry(TypeTableEntryIdEnum); |
| | 2229 | buf_resize(&tag_type->name, 0); |
| | 2230 | buf_appendf(&tag_type->name, "@EnumTagType(%s)", buf_ptr(&union_type->name)); |
| | 2231 | tag_type->is_copyable = true; |
| | 2232 | tag_type->type_ref = tag_int_type->type_ref; |
| | 2233 | tag_type->zero_bits = tag_int_type->zero_bits; |
| | 2234 | |
| | 2235 | tag_type->data.enumeration.tag_int_type = tag_int_type; |
| | 2236 | tag_type->data.enumeration.zero_bits_known = true; |
| | 2237 | tag_type->data.enumeration.decl_node = decl_node; |
| | 2238 | tag_type->data.enumeration.layout = ContainerLayoutAuto; |
| | 2239 | tag_type->data.enumeration.src_field_count = field_count; |
| | 2240 | tag_type->data.enumeration.fields = allocate<TypeEnumField>(field_count); |
| | 2241 | tag_type->data.enumeration.decls_scope = union_type->data.unionation.decls_scope; |
| | 2242 | tag_type->data.enumeration.complete = true; |
| | 2243 | } else if (enum_type_node != nullptr) { |
| | 2244 | TypeTableEntry *enum_type = analyze_type_expr(g, scope, enum_type_node); |
| | 2245 | if (type_is_invalid(enum_type)) { |
| | 2246 | union_type->data.unionation.is_invalid = true; |
| | 2247 | union_type->data.unionation.embedded_in_current = false; |
| | 2248 | return; |
| | 2249 | } |
| | 2250 | if (enum_type->id != TypeTableEntryIdEnum) { |
| | 2251 | union_type->data.unionation.is_invalid = true; |
| | 2252 | union_type->data.unionation.embedded_in_current = false; |
| | 2253 | add_node_error(g, enum_type_node, |
| | 2254 | buf_sprintf("expected enum tag type, found '%s'", buf_ptr(&enum_type->name))); |
| | 2255 | return; |
| | 2256 | } |
| | 2257 | tag_type = enum_type; |
| | 2258 | covered_enum_fields = allocate<bool>(enum_type->data.enumeration.src_field_count); |
| | 2259 | union_type->data.unionation.abi_alignment = get_abi_alignment(g, enum_type); |
| | 2260 | } else { |
| | 2261 | tag_type = nullptr; |
| | 2262 | } |
| | 2263 | union_type->data.unionation.tag_type = tag_type; |
| | 2264 | |
| 2345 | uint32_t gen_field_index = 0; | 2265 | uint32_t gen_field_index = 0; |
| 2346 | for (uint32_t i = 0; i < field_count; i += 1) { | 2266 | for (uint32_t i = 0; i < field_count; i += 1) { |
| 2347 | AstNode *field_node = decl_node->data.container_decl.fields.at(i); | 2267 | AstNode *field_node = decl_node->data.container_decl.fields.at(i); |
| | 2268 | Buf *field_name = field_node->data.struct_field.name; |
| 2348 | TypeUnionField *union_field = &union_type->data.unionation.fields[i]; | 2269 | TypeUnionField *union_field = &union_type->data.unionation.fields[i]; |
| 2349 | union_field->name = field_node->data.struct_field.name; | 2270 | union_field->name = field_node->data.struct_field.name; |
| 2350 | | 2271 | |
| | 2272 | TypeTableEntry *field_type; |
| 2351 | if (field_node->data.struct_field.type == nullptr) { | 2273 | if (field_node->data.struct_field.type == nullptr) { |
| 2352 | add_node_error(g, field_node, buf_sprintf("union field missing type")); | 2274 | if (decl_node->data.container_decl.auto_enum || decl_node->data.container_decl.init_arg_expr != nullptr) { |
| 2353 | union_type->data.unionation.is_invalid = true; | 2275 | field_type = g->builtin_types.entry_void; |
| 2354 | continue; | 2276 | } else { |
| | 2277 | add_node_error(g, field_node, buf_sprintf("union field missing type")); |
| | 2278 | union_type->data.unionation.is_invalid = true; |
| | 2279 | continue; |
| | 2280 | } |
| | 2281 | } else { |
| | 2282 | field_type = analyze_type_expr(g, scope, field_node->data.struct_field.type); |
| | 2283 | type_ensure_zero_bits_known(g, field_type); |
| | 2284 | if (type_is_invalid(field_type)) { |
| | 2285 | union_type->data.unionation.is_invalid = true; |
| | 2286 | continue; |
| | 2287 | } |
| 2355 | } | 2288 | } |
| 2356 | | | |
| 2357 | TypeTableEntry *field_type = analyze_type_expr(g, scope, field_node->data.struct_field.type); | | |
| 2358 | union_field->type_entry = field_type; | 2289 | union_field->type_entry = field_type; |
| 2359 | | 2290 | |
| 2360 | if (field_node->data.struct_field.value != nullptr && !decl_node->data.container_decl.auto_enum) { | 2291 | if (field_node->data.struct_field.value != nullptr && !decl_node->data.container_decl.auto_enum) { |
| ... | @@ -2364,11 +2295,57 @@ static void resolve_union_zero_bits(CodeGen *g, TypeTableEntry *union_type) { | ... | @@ -2364,11 +2295,57 @@ static void resolve_union_zero_bits(CodeGen *g, TypeTableEntry *union_type) { |
| 2364 | buf_sprintf("consider 'union(enum)' here")); | 2295 | buf_sprintf("consider 'union(enum)' here")); |
| 2365 | } | 2296 | } |
| 2366 | | 2297 | |
| 2367 | type_ensure_zero_bits_known(g, field_type); | 2298 | if (create_enum_type) { |
| 2368 | if (type_is_invalid(field_type)) { | 2299 | di_enumerators[i] = ZigLLVMCreateDebugEnumerator(g->dbuilder, buf_ptr(field_name), i); |
| 2369 | union_type->data.unionation.is_invalid = true; | 2300 | union_field->enum_field = &tag_type->data.enumeration.fields[i]; |
| 2370 | continue; | 2301 | union_field->enum_field->name = field_name; |
| | 2302 | union_field->enum_field->decl_index = i; |
| | 2303 | |
| | 2304 | AstNode *tag_value = field_node->data.struct_field.value; |
| | 2305 | // In this first pass we resolve explicit tag values. |
| | 2306 | // In a second pass we will fill in the unspecified ones. |
| | 2307 | if (tag_value != nullptr) { |
| | 2308 | TypeTableEntry *tag_int_type = tag_type->data.enumeration.tag_int_type; |
| | 2309 | IrInstruction *result_inst = analyze_const_value(g, scope, tag_value, tag_int_type, nullptr); |
| | 2310 | if (result_inst->value.type->id == TypeTableEntryIdInvalid) { |
| | 2311 | union_type->data.unionation.is_invalid = true; |
| | 2312 | continue; |
| | 2313 | } |
| | 2314 | assert(result_inst->value.special != ConstValSpecialRuntime); |
| | 2315 | assert(result_inst->value.type->id == TypeTableEntryIdInt); |
| | 2316 | auto entry = occupied_tag_values.put_unique(result_inst->value.data.x_bigint, tag_value); |
| | 2317 | if (entry == nullptr) { |
| | 2318 | bigint_init_bigint(&union_field->enum_field->value, &result_inst->value.data.x_bigint); |
| | 2319 | } else { |
| | 2320 | Buf *val_buf = buf_alloc(); |
| | 2321 | bigint_append_buf(val_buf, &result_inst->value.data.x_bigint, 10); |
| | 2322 | |
| | 2323 | ErrorMsg *msg = add_node_error(g, tag_value, |
| | 2324 | buf_sprintf("enum tag value %s already taken", buf_ptr(val_buf))); |
| | 2325 | add_error_note(g, msg, entry->value, |
| | 2326 | buf_sprintf("other occurrence here")); |
| | 2327 | union_type->data.unionation.is_invalid = true; |
| | 2328 | continue; |
| | 2329 | } |
| | 2330 | } |
| | 2331 | } else if (enum_type_node != nullptr) { |
| | 2332 | union_field->enum_field = find_enum_type_field(tag_type, field_name); |
| | 2333 | if (union_field->enum_field == nullptr) { |
| | 2334 | ErrorMsg *msg = add_node_error(g, field_node, |
| | 2335 | buf_sprintf("enum field not found: '%s'", buf_ptr(field_name))); |
| | 2336 | add_error_note(g, msg, tag_type->data.enumeration.decl_node, |
| | 2337 | buf_sprintf("enum declared here")); |
| | 2338 | union_type->data.unionation.is_invalid = true; |
| | 2339 | continue; |
| | 2340 | } |
| | 2341 | covered_enum_fields[union_field->enum_field->decl_index] = true; |
| | 2342 | } else { |
| | 2343 | union_field->enum_field = allocate<TypeEnumField>(1); |
| | 2344 | union_field->enum_field->name = field_name; |
| | 2345 | union_field->enum_field->decl_index = i; |
| | 2346 | bigint_init_unsigned(&union_field->enum_field->value, i); |
| 2371 | } | 2347 | } |
| | 2348 | assert(union_field->enum_field != nullptr); |
| 2372 | | 2349 | |
| 2373 | if (!type_has_bits(field_type)) | 2350 | if (!type_has_bits(field_type)) |
| 2374 | continue; | 2351 | continue; |
| ... | @@ -2379,9 +2356,15 @@ static void resolve_union_zero_bits(CodeGen *g, TypeTableEntry *union_type) { | ... | @@ -2379,9 +2356,15 @@ static void resolve_union_zero_bits(CodeGen *g, TypeTableEntry *union_type) { |
| 2379 | uint32_t field_align_bytes = get_abi_alignment(g, field_type); | 2356 | uint32_t field_align_bytes = get_abi_alignment(g, field_type); |
| 2380 | if (field_align_bytes > biggest_align_bytes) { | 2357 | if (field_align_bytes > biggest_align_bytes) { |
| 2381 | biggest_align_bytes = field_align_bytes; | 2358 | biggest_align_bytes = field_align_bytes; |
| | 2359 | if (biggest_align_bytes > union_type->data.unionation.abi_alignment) { |
| | 2360 | union_type->data.unionation.abi_alignment = biggest_align_bytes; |
| | 2361 | } |
| 2382 | } | 2362 | } |
| 2383 | } | 2363 | } |
| 2384 | | 2364 | |
| | 2365 | if (union_type->data.unionation.is_invalid) |
| | 2366 | return; |
| | 2367 | |
| 2385 | bool src_have_tag = decl_node->data.container_decl.auto_enum || | 2368 | bool src_have_tag = decl_node->data.container_decl.auto_enum || |
| 2386 | decl_node->data.container_decl.init_arg_expr != nullptr; | 2369 | decl_node->data.container_decl.init_arg_expr != nullptr; |
| 2387 | | 2370 | |
| ... | @@ -2405,15 +2388,66 @@ static void resolve_union_zero_bits(CodeGen *g, TypeTableEntry *union_type) { | ... | @@ -2405,15 +2388,66 @@ static void resolve_union_zero_bits(CodeGen *g, TypeTableEntry *union_type) { |
| 2405 | return; | 2388 | return; |
| 2406 | } | 2389 | } |
| 2407 | | 2390 | |
| | 2391 | if (create_enum_type) { |
| | 2392 | // Now iterate again and populate the unspecified tag values |
| | 2393 | uint32_t next_maybe_unoccupied_index = 0; |
| | 2394 | |
| | 2395 | for (uint32_t field_i = 0; field_i < field_count; field_i += 1) { |
| | 2396 | AstNode *field_node = decl_node->data.container_decl.fields.at(field_i); |
| | 2397 | TypeUnionField *union_field = &union_type->data.unionation.fields[field_i]; |
| | 2398 | AstNode *tag_value = field_node->data.struct_field.value; |
| | 2399 | |
| | 2400 | if (tag_value == nullptr) { |
| | 2401 | if (occupied_tag_values.size() == 0) { |
| | 2402 | bigint_init_unsigned(&union_field->enum_field->value, next_maybe_unoccupied_index); |
| | 2403 | next_maybe_unoccupied_index += 1; |
| | 2404 | } else { |
| | 2405 | BigInt proposed_value; |
| | 2406 | for (;;) { |
| | 2407 | bigint_init_unsigned(&proposed_value, next_maybe_unoccupied_index); |
| | 2408 | next_maybe_unoccupied_index += 1; |
| | 2409 | auto entry = occupied_tag_values.put_unique(proposed_value, field_node); |
| | 2410 | if (entry != nullptr) { |
| | 2411 | continue; |
| | 2412 | } |
| | 2413 | break; |
| | 2414 | } |
| | 2415 | bigint_init_bigint(&union_field->enum_field->value, &proposed_value); |
| | 2416 | } |
| | 2417 | } |
| | 2418 | } |
| | 2419 | } else if (enum_type_node != nullptr) { |
| | 2420 | for (uint32_t i = 0; i < tag_type->data.enumeration.src_field_count; i += 1) { |
| | 2421 | TypeEnumField *enum_field = &tag_type->data.enumeration.fields[i]; |
| | 2422 | if (!covered_enum_fields[i]) { |
| | 2423 | AstNode *enum_decl_node = tag_type->data.enumeration.decl_node; |
| | 2424 | AstNode *field_node = enum_decl_node->data.container_decl.fields.at(i); |
| | 2425 | ErrorMsg *msg = add_node_error(g, decl_node, |
| | 2426 | buf_sprintf("enum field missing: '%s'", buf_ptr(enum_field->name))); |
| | 2427 | add_error_note(g, msg, field_node, |
| | 2428 | buf_sprintf("declared here")); |
| | 2429 | union_type->data.unionation.is_invalid = true; |
| | 2430 | } |
| | 2431 | } |
| | 2432 | } |
| | 2433 | |
| | 2434 | if (create_enum_type) { |
| | 2435 | ImportTableEntry *import = get_scope_import(scope); |
| | 2436 | uint64_t tag_debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, tag_type->type_ref); |
| | 2437 | uint64_t tag_debug_align_in_bits = 8*LLVMABIAlignmentOfType(g->target_data_ref, tag_type->type_ref); |
| | 2438 | // TODO get a more accurate debug scope |
| | 2439 | ZigLLVMDIType *tag_di_type = ZigLLVMCreateDebugEnumerationType(g->dbuilder, |
| | 2440 | ZigLLVMFileToScope(import->di_file), buf_ptr(&tag_type->name), |
| | 2441 | import->di_file, (unsigned)(decl_node->line + 1), |
| | 2442 | tag_debug_size_in_bits, tag_debug_align_in_bits, di_enumerators, field_count, |
| | 2443 | tag_type->di_type, ""); |
| | 2444 | tag_type->di_type = tag_di_type; |
| | 2445 | } |
| | 2446 | |
| 2408 | union_type->data.unionation.zero_bits_loop_flag = false; | 2447 | union_type->data.unionation.zero_bits_loop_flag = false; |
| 2409 | union_type->data.unionation.gen_field_count = gen_field_index; | 2448 | union_type->data.unionation.gen_field_count = gen_field_index; |
| 2410 | union_type->zero_bits = (gen_field_index == 0 && (field_count < 2 || !src_have_tag)); | 2449 | union_type->zero_bits = (gen_field_index == 0 && (field_count < 2 || !src_have_tag)); |
| 2411 | union_type->data.unionation.zero_bits_known = true; | 2450 | union_type->data.unionation.zero_bits_known = true; |
| 2412 | | | |
| 2413 | // also compute abi_alignment | | |
| 2414 | if (!union_type->zero_bits) { | | |
| 2415 | union_type->data.unionation.abi_alignment = biggest_align_bytes; | | |
| 2416 | } | | |
| 2417 | } | 2451 | } |
| 2418 | | 2452 | |
| 2419 | static void get_fully_qualified_decl_name_internal(Buf *buf, Scope *scope, uint8_t sep) { | 2453 | static void get_fully_qualified_decl_name_internal(Buf *buf, Scope *scope, uint8_t sep) { |