| ... | @@ -992,26 +992,23 @@ TypeTableEntry *get_partial_container_type(CodeGen *g, Scope *scope, ContainerKi | ... | @@ -992,26 +992,23 @@ TypeTableEntry *get_partial_container_type(CodeGen *g, Scope *scope, ContainerKi |
| 992 | TypeTableEntryId type_id = container_to_type(kind); | 992 | TypeTableEntryId type_id = container_to_type(kind); |
| 993 | TypeTableEntry *entry = new_container_type_entry(type_id, decl_node, scope); | 993 | TypeTableEntry *entry = new_container_type_entry(type_id, decl_node, scope); |
| 994 | | 994 | |
| 995 | unsigned dwarf_kind; | | |
| 996 | switch (kind) { | 995 | switch (kind) { |
| 997 | case ContainerKindStruct: | 996 | case ContainerKindStruct: |
| 998 | entry->data.structure.decl_node = decl_node; | 997 | entry->data.structure.decl_node = decl_node; |
| 999 | entry->data.structure.layout = layout; | 998 | entry->data.structure.layout = layout; |
| 1000 | dwarf_kind = ZigLLVMTag_DW_structure_type(); | | |
| 1001 | break; | 999 | break; |
| 1002 | case ContainerKindEnum: | 1000 | case ContainerKindEnum: |
| 1003 | entry->data.enumeration.decl_node = decl_node; | 1001 | entry->data.enumeration.decl_node = decl_node; |
| 1004 | entry->data.enumeration.layout = layout; | 1002 | entry->data.enumeration.layout = layout; |
| 1005 | dwarf_kind = ZigLLVMTag_DW_structure_type(); | | |
| 1006 | break; | 1003 | break; |
| 1007 | case ContainerKindUnion: | 1004 | case ContainerKindUnion: |
| 1008 | entry->data.unionation.decl_node = decl_node; | 1005 | entry->data.unionation.decl_node = decl_node; |
| 1009 | entry->data.unionation.layout = layout; | 1006 | entry->data.unionation.layout = layout; |
| 1010 | dwarf_kind = ZigLLVMTag_DW_union_type(); | | |
| 1011 | break; | 1007 | break; |
| 1012 | } | 1008 | } |
| 1013 | | 1009 | |
| 1014 | size_t line = decl_node ? decl_node->line : 0; | 1010 | size_t line = decl_node ? decl_node->line : 0; |
| | 1011 | unsigned dwarf_kind = ZigLLVMTag_DW_structure_type(); |
| 1015 | | 1012 | |
| 1016 | ImportTableEntry *import = get_scope_import(scope); | 1013 | ImportTableEntry *import = get_scope_import(scope); |
| 1017 | entry->type_ref = LLVMStructCreateNamed(LLVMGetGlobalContext(), name); | 1014 | entry->type_ref = LLVMStructCreateNamed(LLVMGetGlobalContext(), name); |
| ... | @@ -1873,6 +1870,11 @@ static void resolve_union_type(CodeGen *g, TypeTableEntry *union_type) { | ... | @@ -1873,6 +1870,11 @@ static void resolve_union_type(CodeGen *g, TypeTableEntry *union_type) { |
| 1873 | uint64_t biggest_align_in_bits = 0; | 1870 | uint64_t biggest_align_in_bits = 0; |
| 1874 | uint64_t biggest_size_in_bits = 0; | 1871 | uint64_t biggest_size_in_bits = 0; |
| 1875 | | 1872 | |
| | 1873 | bool auto_layout = (union_type->data.unionation.layout == ContainerLayoutAuto); |
| | 1874 | ZigLLVMDIEnumerator **di_enumerators = allocate<ZigLLVMDIEnumerator*>(field_count); |
| | 1875 | auto distinct_types = &union_type->data.unionation.distinct_types; |
| | 1876 | distinct_types->init(4); |
| | 1877 | |
| 1876 | Scope *scope = &union_type->data.unionation.decls_scope->base; | 1878 | Scope *scope = &union_type->data.unionation.decls_scope->base; |
| 1877 | ImportTableEntry *import = get_scope_import(scope); | 1879 | ImportTableEntry *import = get_scope_import(scope); |
| 1878 | | 1880 | |
| ... | @@ -1893,6 +1895,11 @@ static void resolve_union_type(CodeGen *g, TypeTableEntry *union_type) { | ... | @@ -1893,6 +1895,11 @@ static void resolve_union_type(CodeGen *g, TypeTableEntry *union_type) { |
| 1893 | if (!type_has_bits(field_type)) | 1895 | if (!type_has_bits(field_type)) |
| 1894 | continue; | 1896 | continue; |
| 1895 | | 1897 | |
| | 1898 | size_t distinct_type_index = distinct_types->size(); |
| | 1899 | if (distinct_types->put_unique(field_type, distinct_type_index) == nullptr) { |
| | 1900 | di_enumerators[i] = ZigLLVMCreateDebugEnumerator(g->dbuilder, buf_ptr(&field_type->name), distinct_type_index); |
| | 1901 | } |
| | 1902 | |
| 1896 | uint64_t store_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, field_type->type_ref); | 1903 | uint64_t store_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, field_type->type_ref); |
| 1897 | uint64_t abi_align_in_bits = 8*LLVMABIAlignmentOfType(g->target_data_ref, field_type->type_ref); | 1904 | uint64_t abi_align_in_bits = 8*LLVMABIAlignmentOfType(g->target_data_ref, field_type->type_ref); |
| 1898 | | 1905 | |
| ... | @@ -1919,7 +1926,7 @@ static void resolve_union_type(CodeGen *g, TypeTableEntry *union_type) { | ... | @@ -1919,7 +1926,7 @@ static void resolve_union_type(CodeGen *g, TypeTableEntry *union_type) { |
| 1919 | // unset temporary flag | 1926 | // unset temporary flag |
| 1920 | union_type->data.unionation.embedded_in_current = false; | 1927 | union_type->data.unionation.embedded_in_current = false; |
| 1921 | union_type->data.unionation.complete = true; | 1928 | union_type->data.unionation.complete = true; |
| 1922 | union_type->data.unionation.size_bytes = biggest_size_in_bits / 8; | 1929 | union_type->data.unionation.union_size_bytes = biggest_size_in_bits / 8; |
| 1923 | union_type->data.unionation.most_aligned_union_member = most_aligned_union_member; | 1930 | union_type->data.unionation.most_aligned_union_member = most_aligned_union_member; |
| 1924 | | 1931 | |
| 1925 | if (union_type->data.unionation.is_invalid) | 1932 | if (union_type->data.unionation.is_invalid) |
| ... | @@ -1947,8 +1954,42 @@ static void resolve_union_type(CodeGen *g, TypeTableEntry *union_type) { | ... | @@ -1947,8 +1954,42 @@ static void resolve_union_type(CodeGen *g, TypeTableEntry *union_type) { |
| 1947 | | 1954 | |
| 1948 | assert(most_aligned_union_member != nullptr); | 1955 | assert(most_aligned_union_member != nullptr); |
| 1949 | | 1956 | |
| 1950 | // create llvm type for union | 1957 | bool want_safety = (distinct_types->size() > 1) && auto_layout; |
| 1951 | uint64_t padding_in_bits = biggest_size_in_bits - size_of_most_aligned_member_in_bits; | 1958 | uint64_t padding_in_bits = biggest_size_in_bits - size_of_most_aligned_member_in_bits; |
| | 1959 | |
| | 1960 | |
| | 1961 | if (!want_safety) { |
| | 1962 | if (padding_in_bits > 0) { |
| | 1963 | TypeTableEntry *u8_type = get_int_type(g, false, 8); |
| | 1964 | TypeTableEntry *padding_array = get_array_type(g, u8_type, padding_in_bits / 8); |
| | 1965 | LLVMTypeRef union_element_types[] = { |
| | 1966 | most_aligned_union_member->type_ref, |
| | 1967 | padding_array->type_ref, |
| | 1968 | }; |
| | 1969 | LLVMStructSetBody(union_type->type_ref, union_element_types, 2, false); |
| | 1970 | } else { |
| | 1971 | LLVMStructSetBody(union_type->type_ref, &most_aligned_union_member->type_ref, 1, false); |
| | 1972 | } |
| | 1973 | union_type->data.unionation.union_type_ref = union_type->type_ref; |
| | 1974 | union_type->data.unionation.gen_tag_index = SIZE_MAX; |
| | 1975 | union_type->data.unionation.gen_union_index = SIZE_MAX; |
| | 1976 | |
| | 1977 | assert(8*LLVMABIAlignmentOfType(g->target_data_ref, union_type->type_ref) >= biggest_align_in_bits); |
| | 1978 | assert(8*LLVMStoreSizeOfType(g->target_data_ref, union_type->type_ref) >= biggest_size_in_bits); |
| | 1979 | |
| | 1980 | // create debug type for union |
| | 1981 | ZigLLVMDIType *replacement_di_type = ZigLLVMCreateDebugUnionType(g->dbuilder, |
| | 1982 | ZigLLVMFileToScope(import->di_file), buf_ptr(&union_type->name), |
| | 1983 | import->di_file, (unsigned)(decl_node->line + 1), |
| | 1984 | biggest_size_in_bits, biggest_align_in_bits, 0, union_inner_di_types, |
| | 1985 | gen_field_count, 0, ""); |
| | 1986 | |
| | 1987 | ZigLLVMReplaceTemporary(g->dbuilder, union_type->di_type, replacement_di_type); |
| | 1988 | union_type->di_type = replacement_di_type; |
| | 1989 | return; |
| | 1990 | } |
| | 1991 | |
| | 1992 | LLVMTypeRef union_type_ref; |
| 1952 | if (padding_in_bits > 0) { | 1993 | if (padding_in_bits > 0) { |
| 1953 | TypeTableEntry *u8_type = get_int_type(g, false, 8); | 1994 | TypeTableEntry *u8_type = get_int_type(g, false, 8); |
| 1954 | TypeTableEntry *padding_array = get_array_type(g, u8_type, padding_in_bits / 8); | 1995 | TypeTableEntry *padding_array = get_array_type(g, u8_type, padding_in_bits / 8); |
| ... | @@ -1956,20 +1997,87 @@ static void resolve_union_type(CodeGen *g, TypeTableEntry *union_type) { | ... | @@ -1956,20 +1997,87 @@ static void resolve_union_type(CodeGen *g, TypeTableEntry *union_type) { |
| 1956 | most_aligned_union_member->type_ref, | 1997 | most_aligned_union_member->type_ref, |
| 1957 | padding_array->type_ref, | 1998 | padding_array->type_ref, |
| 1958 | }; | 1999 | }; |
| 1959 | LLVMStructSetBody(union_type->type_ref, union_element_types, 2, false); | 2000 | union_type_ref = LLVMStructType(union_element_types, 2, false); |
| | 2001 | } else { |
| | 2002 | union_type_ref = most_aligned_union_member->type_ref; |
| | 2003 | } |
| | 2004 | union_type->data.unionation.union_type_ref = union_type_ref; |
| | 2005 | |
| | 2006 | assert(8*LLVMABIAlignmentOfType(g->target_data_ref, union_type_ref) >= biggest_align_in_bits); |
| | 2007 | assert(8*LLVMStoreSizeOfType(g->target_data_ref, union_type_ref) >= biggest_size_in_bits); |
| | 2008 | |
| | 2009 | // create llvm type for root struct |
| | 2010 | TypeTableEntry *tag_int_type = get_smallest_unsigned_int_type(g, distinct_types->size() - 1); |
| | 2011 | TypeTableEntry *tag_type_entry = tag_int_type; |
| | 2012 | union_type->data.unionation.tag_type = tag_type_entry; |
| | 2013 | uint64_t align_of_tag_in_bits = 8*LLVMABIAlignmentOfType(g->target_data_ref, tag_int_type->type_ref); |
| | 2014 | |
| | 2015 | if (align_of_tag_in_bits >= biggest_align_in_bits) { |
| | 2016 | union_type->data.unionation.gen_tag_index = 0; |
| | 2017 | union_type->data.unionation.gen_union_index = 1; |
| 1960 | } else { | 2018 | } else { |
| 1961 | LLVMStructSetBody(union_type->type_ref, &most_aligned_union_member->type_ref, 1, false); | 2019 | union_type->data.unionation.gen_union_index = 0; |
| | 2020 | union_type->data.unionation.gen_tag_index = 1; |
| 1962 | } | 2021 | } |
| 1963 | | 2022 | |
| 1964 | assert(8*LLVMABIAlignmentOfType(g->target_data_ref, union_type->type_ref) >= biggest_align_in_bits); | 2023 | LLVMTypeRef root_struct_element_types[2]; |
| 1965 | assert(8*LLVMStoreSizeOfType(g->target_data_ref, union_type->type_ref) >= biggest_size_in_bits); | 2024 | root_struct_element_types[union_type->data.unionation.gen_tag_index] = tag_type_entry->type_ref; |
| | 2025 | root_struct_element_types[union_type->data.unionation.gen_union_index] = union_type_ref; |
| | 2026 | LLVMStructSetBody(union_type->type_ref, root_struct_element_types, 2, false); |
| | 2027 | |
| | 2028 | |
| | 2029 | // create debug type for root struct |
| | 2030 | |
| | 2031 | // create debug type for tag |
| | 2032 | uint64_t tag_debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, tag_type_entry->type_ref); |
| | 2033 | uint64_t tag_debug_align_in_bits = 8*LLVMABIAlignmentOfType(g->target_data_ref, tag_type_entry->type_ref); |
| | 2034 | ZigLLVMDIType *tag_di_type = ZigLLVMCreateDebugEnumerationType(g->dbuilder, |
| | 2035 | ZigLLVMTypeToScope(union_type->di_type), "AnonEnum", |
| | 2036 | import->di_file, (unsigned)(decl_node->line + 1), |
| | 2037 | tag_debug_size_in_bits, tag_debug_align_in_bits, di_enumerators, distinct_types->size(), |
| | 2038 | tag_type_entry->di_type, ""); |
| 1966 | | 2039 | |
| 1967 | // create debug type for union | 2040 | // create debug type for union |
| 1968 | ZigLLVMDIType *replacement_di_type = ZigLLVMCreateDebugUnionType(g->dbuilder, | 2041 | ZigLLVMDIType *union_di_type = ZigLLVMCreateDebugUnionType(g->dbuilder, |
| 1969 | ZigLLVMFileToScope(import->di_file), buf_ptr(&union_type->name), | 2042 | ZigLLVMTypeToScope(union_type->di_type), "AnonUnion", |
| 1970 | import->di_file, (unsigned)(decl_node->line + 1), | 2043 | import->di_file, (unsigned)(decl_node->line + 1), |
| 1971 | biggest_size_in_bits, biggest_align_in_bits, 0, union_inner_di_types, | 2044 | biggest_size_in_bits, biggest_align_in_bits, 0, union_inner_di_types, |
| 1972 | gen_field_count, 0, ""); | 2045 | gen_field_count, 0, ""); |
| | 2046 | |
| | 2047 | uint64_t union_offset_in_bits = 8*LLVMOffsetOfElement(g->target_data_ref, union_type->type_ref, |
| | 2048 | union_type->data.unionation.gen_union_index); |
| | 2049 | uint64_t tag_offset_in_bits = 8*LLVMOffsetOfElement(g->target_data_ref, union_type->type_ref, |
| | 2050 | union_type->data.unionation.gen_tag_index); |
| | 2051 | |
| | 2052 | ZigLLVMDIType *union_member_di_type = ZigLLVMCreateDebugMemberType(g->dbuilder, |
| | 2053 | ZigLLVMTypeToScope(union_type->di_type), "union_field", |
| | 2054 | import->di_file, (unsigned)(decl_node->line + 1), |
| | 2055 | biggest_size_in_bits, |
| | 2056 | biggest_align_in_bits, |
| | 2057 | union_offset_in_bits, |
| | 2058 | 0, union_di_type); |
| | 2059 | ZigLLVMDIType *tag_member_di_type = ZigLLVMCreateDebugMemberType(g->dbuilder, |
| | 2060 | ZigLLVMTypeToScope(union_type->di_type), "tag_field", |
| | 2061 | import->di_file, (unsigned)(decl_node->line + 1), |
| | 2062 | tag_debug_size_in_bits, |
| | 2063 | tag_debug_align_in_bits, |
| | 2064 | tag_offset_in_bits, |
| | 2065 | 0, tag_di_type); |
| | 2066 | |
| | 2067 | ZigLLVMDIType *di_root_members[2]; |
| | 2068 | di_root_members[union_type->data.unionation.gen_tag_index] = tag_member_di_type; |
| | 2069 | di_root_members[union_type->data.unionation.gen_union_index] = union_member_di_type; |
| | 2070 | |
| | 2071 | uint64_t debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, union_type->type_ref); |
| | 2072 | uint64_t debug_align_in_bits = 8*LLVMABISizeOfType(g->target_data_ref, union_type->type_ref); |
| | 2073 | ZigLLVMDIType *replacement_di_type = ZigLLVMCreateDebugStructType(g->dbuilder, |
| | 2074 | ZigLLVMFileToScope(import->di_file), |
| | 2075 | buf_ptr(&union_type->name), |
| | 2076 | import->di_file, (unsigned)(decl_node->line + 1), |
| | 2077 | debug_size_in_bits, |
| | 2078 | debug_align_in_bits, |
| | 2079 | 0, nullptr, di_root_members, 2, 0, nullptr, ""); |
| | 2080 | |
| 1973 | ZigLLVMReplaceTemporary(g->dbuilder, union_type->di_type, replacement_di_type); | 2081 | ZigLLVMReplaceTemporary(g->dbuilder, union_type->di_type, replacement_di_type); |
| 1974 | union_type->di_type = replacement_di_type; | 2082 | union_type->di_type = replacement_di_type; |
| 1975 | } | 2083 | } |
| ... | @@ -5140,3 +5248,11 @@ TypeTableEntry *get_align_amt_type(CodeGen *g) { | ... | @@ -5140,3 +5248,11 @@ TypeTableEntry *get_align_amt_type(CodeGen *g) { |
| 5140 | } | 5248 | } |
| 5141 | return g->align_amt_type; | 5249 | return g->align_amt_type; |
| 5142 | } | 5250 | } |
| | 5251 | |
| | 5252 | uint32_t type_ptr_hash(const TypeTableEntry *ptr) { |
| | 5253 | return hash_ptr((void*)ptr); |
| | 5254 | } |
| | 5255 | |
| | 5256 | bool type_ptr_eql(const TypeTableEntry *a, const TypeTableEntry *b) { |
| | 5257 | return a == b; |
| | 5258 | } |