| ... | ... | @@ -1713,84 +1713,16 @@ static void resolve_union_type(CodeGen *g, TypeTableEntry *union_type) { |
| 1713 | 1713 | uint64_t biggest_align_in_bits = 0; |
| 1714 | 1714 | uint64_t biggest_size_in_bits = 0; |
| 1715 | 1715 | |
| 1716 | | ZigLLVMDIEnumerator **di_enumerators; |
| 1717 | | |
| 1718 | 1716 | Scope *scope = &union_type->data.unionation.decls_scope->base; |
| 1719 | 1717 | ImportTableEntry *import = get_scope_import(scope); |
| 1720 | 1718 | |
| 1721 | 1719 | // set temporary flag |
| 1722 | 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 | 1723 | for (uint32_t i = 0; i < field_count; i += 1) { |
| 1791 | 1724 | AstNode *field_node = decl_node->data.container_decl.fields.at(i); |
| 1792 | 1725 | TypeUnionField *union_field = &union_type->data.unionation.fields[i]; |
| 1793 | | Buf *field_name = field_node->data.struct_field.name; |
| 1794 | 1726 | TypeTableEntry *field_type = union_field->type_entry; |
| 1795 | 1727 | |
| 1796 | 1728 | ensure_complete_type(g, field_type); |
| ... | ... | @@ -1799,57 +1731,6 @@ static void resolve_union_type(CodeGen *g, TypeTableEntry *union_type) { |
| 1799 | 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 | 1734 | if (!type_has_bits(field_type)) |
| 1854 | 1735 | continue; |
| 1855 | 1736 | |
| ... | ... | @@ -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 | 1761 | // unset temporary flag |
| 1923 | 1762 | union_type->data.unionation.embedded_in_current = false; |
| ... | ... | @@ -1948,11 +1787,12 @@ static void resolve_union_type(CodeGen *g, TypeTableEntry *union_type) { |
| 1948 | 1787 | return; |
| 1949 | 1788 | } |
| 1950 | 1789 | |
| 1951 | | assert(most_aligned_union_member != nullptr); |
| 1952 | | |
| 1953 | 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 | 1793 | if (tag_type == nullptr) { |
| 1794 | assert(most_aligned_union_member != nullptr); |
| 1795 | |
| 1956 | 1796 | if (padding_in_bits > 0) { |
| 1957 | 1797 | TypeTableEntry *u8_type = get_int_type(g, false, 8); |
| 1958 | 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 | 1833 | }; |
| 1994 | 1834 | union_type_ref = LLVMStructType(union_element_types, 2, false); |
| 1995 | 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 | 1843 | } else { |
| 1998 | 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 | 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 | 1869 | // create debug type for union |
| 2038 | 1870 | ZigLLVMDIType *union_di_type = ZigLLVMCreateDebugUnionType(g->dbuilder, |
| 2039 | 1871 | ZigLLVMTypeToScope(union_type->di_type), "AnonUnion", |
| ... | ... | @@ -2053,6 +1885,10 @@ static void resolve_union_type(CodeGen *g, TypeTableEntry *union_type) { |
| 2053 | 1885 | biggest_align_in_bits, |
| 2054 | 1886 | union_offset_in_bits, |
| 2055 | 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 | 1892 | ZigLLVMDIType *tag_member_di_type = ZigLLVMCreateDebugMemberType(g->dbuilder, |
| 2057 | 1893 | ZigLLVMTypeToScope(union_type->di_type), "tag", |
| 2058 | 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 | 2148 | if (union_type->data.unionation.zero_bits_known) |
| 2313 | 2149 | return; |
| 2314 | 2150 | |
| 2151 | if (type_is_invalid(union_type)) |
| 2152 | return; |
| 2153 | |
| 2315 | 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 | 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 | 2168 | return; |
| 2318 | 2169 | } |
| 2319 | 2170 | |
| ... | ... | @@ -2342,19 +2193,99 @@ static void resolve_union_zero_bits(CodeGen *g, TypeTableEntry *union_type) { |
| 2342 | 2193 | |
| 2343 | 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 | 2265 | uint32_t gen_field_index = 0; |
| 2346 | 2266 | for (uint32_t i = 0; i < field_count; i += 1) { |
| 2347 | 2267 | AstNode *field_node = decl_node->data.container_decl.fields.at(i); |
| 2268 | Buf *field_name = field_node->data.struct_field.name; |
| 2348 | 2269 | TypeUnionField *union_field = &union_type->data.unionation.fields[i]; |
| 2349 | 2270 | union_field->name = field_node->data.struct_field.name; |
| 2350 | 2271 | |
| 2272 | TypeTableEntry *field_type; |
| 2351 | 2273 | if (field_node->data.struct_field.type == nullptr) { |
| 2352 | | add_node_error(g, field_node, buf_sprintf("union field missing type")); |
| 2353 | | union_type->data.unionation.is_invalid = true; |
| 2354 | | continue; |
| 2274 | if (decl_node->data.container_decl.auto_enum || decl_node->data.container_decl.init_arg_expr != nullptr) { |
| 2275 | field_type = g->builtin_types.entry_void; |
| 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 | 2289 | union_field->type_entry = field_type; |
| 2359 | 2290 | |
| 2360 | 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 | 2295 | buf_sprintf("consider 'union(enum)' here")); |
| 2365 | 2296 | } |
| 2366 | 2297 | |
| 2367 | | type_ensure_zero_bits_known(g, field_type); |
| 2368 | | if (type_is_invalid(field_type)) { |
| 2369 | | union_type->data.unionation.is_invalid = true; |
| 2370 | | continue; |
| 2298 | if (create_enum_type) { |
| 2299 | di_enumerators[i] = ZigLLVMCreateDebugEnumerator(g->dbuilder, buf_ptr(field_name), i); |
| 2300 | union_field->enum_field = &tag_type->data.enumeration.fields[i]; |
| 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 | 2350 | if (!type_has_bits(field_type)) |
| 2374 | 2351 | continue; |
| ... | ... | @@ -2379,9 +2356,15 @@ static void resolve_union_zero_bits(CodeGen *g, TypeTableEntry *union_type) { |
| 2379 | 2356 | uint32_t field_align_bytes = get_abi_alignment(g, field_type); |
| 2380 | 2357 | if (field_align_bytes > biggest_align_bytes) { |
| 2381 | 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 | 2368 | bool src_have_tag = decl_node->data.container_decl.auto_enum || |
| 2386 | 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 | 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 | 2447 | union_type->data.unionation.zero_bits_loop_flag = false; |
| 2409 | 2448 | union_type->data.unionation.gen_field_count = gen_field_index; |
| 2410 | 2449 | union_type->zero_bits = (gen_field_index == 0 && (field_count < 2 || !src_have_tag)); |
| 2411 | 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 | 2453 | static void get_fully_qualified_decl_name_internal(Buf *buf, Scope *scope, uint8_t sep) { |