authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-11-14 23:53:53-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-11-15 13:04:18-05:00
logf276fd0f3728bf1a43b185e3e2d33d593309cb2f
tree39d52f6a39df87005065ddba1531e40f968cee86
parent7a74dbadd79d2b26a449027dd83753ae4d2a8032

basic union support

See #144

10 files changed, 559 insertions(+), 26 deletions(-)

src/all_types.hpp+41-2
......@@ -73,6 +73,7 @@ enum ConstParentId {
7373 ConstParentIdNone,
7474 ConstParentIdStruct,
7575 ConstParentIdArray,
76 ConstParentIdUnion,
7677};
7778
7879struct ConstParent {
......@@ -87,6 +88,9 @@ struct ConstParent {
8788 ConstExprValue *struct_val;
8889 size_t field_index;
8990 } p_struct;
91 struct {
92 ConstExprValue *union_val;
93 } p_union;
9094 } data;
9195};
9296
......@@ -100,6 +104,11 @@ struct ConstStructValue {
100104 ConstParent parent;
101105};
102106
107struct ConstUnionValue {
108 ConstExprValue *value;
109 ConstParent parent;
110};
111
103112enum ConstArraySpecial {
104113 ConstArraySpecialNone,
105114 ConstArraySpecialUndef,
......@@ -238,6 +247,7 @@ struct ConstExprValue {
238247 ErrorTableEntry *x_pure_err;
239248 ConstEnumValue x_enum;
240249 ConstStructValue x_struct;
250 ConstUnionValue x_union;
241251 ConstArrayValue x_array;
242252 ConstPtrValue x_ptr;
243253 ImportTableEntry *x_import;
......@@ -336,6 +346,12 @@ struct TypeEnumField {
336346 uint32_t gen_index;
337347};
338348
349struct TypeUnionField {
350 Buf *name;
351 TypeTableEntry *type_entry;
352 uint32_t gen_index;
353};
354
339355enum NodeType {
340356 NodeTypeRoot,
341357 NodeTypeFnProto,
......@@ -1026,9 +1042,9 @@ struct TypeTableEntryUnion {
10261042 ContainerLayout layout;
10271043 uint32_t src_field_count;
10281044 uint32_t gen_field_count;
1029 TypeStructField *fields;
1030 uint64_t size_bytes;
1045 TypeUnionField *fields;
10311046 bool is_invalid; // true if any fields are invalid
1047
10321048 ScopeDecls *decls_scope;
10331049
10341050 // set this flag temporarily to detect infinite loops
......@@ -1039,6 +1055,10 @@ struct TypeTableEntryUnion {
10391055
10401056 bool zero_bits_loop_flag;
10411057 bool zero_bits_known;
1058 uint32_t abi_alignment; // also figured out with zero_bits pass
1059
1060 uint32_t size_bytes;
1061 TypeTableEntry *most_aligned_union_member;
10421062};
10431063
10441064struct FnGenParamInfo {
......@@ -1796,6 +1816,7 @@ enum IrInstructionId {
17961816 IrInstructionIdFieldPtr,
17971817 IrInstructionIdStructFieldPtr,
17981818 IrInstructionIdEnumFieldPtr,
1819 IrInstructionIdUnionFieldPtr,
17991820 IrInstructionIdElemPtr,
18001821 IrInstructionIdVarPtr,
18011822 IrInstructionIdCall,
......@@ -1805,6 +1826,7 @@ enum IrInstructionId {
18051826 IrInstructionIdContainerInitList,
18061827 IrInstructionIdContainerInitFields,
18071828 IrInstructionIdStructInit,
1829 IrInstructionIdUnionInit,
18081830 IrInstructionIdUnreachable,
18091831 IrInstructionIdTypeOf,
18101832 IrInstructionIdToPtrType,
......@@ -2060,6 +2082,14 @@ struct IrInstructionEnumFieldPtr {
20602082 bool is_const;
20612083};
20622084
2085struct IrInstructionUnionFieldPtr {
2086 IrInstruction base;
2087
2088 IrInstruction *union_ptr;
2089 TypeUnionField *field;
2090 bool is_const;
2091};
2092
20632093struct IrInstructionElemPtr {
20642094 IrInstruction base;
20652095
......@@ -2150,6 +2180,15 @@ struct IrInstructionStructInit {
21502180 LLVMValueRef tmp_ptr;
21512181};
21522182
2183struct IrInstructionUnionInit {
2184 IrInstruction base;
2185
2186 TypeTableEntry *union_type;
2187 TypeUnionField *field;
2188 IrInstruction *init_value;
2189 LLVMValueRef tmp_ptr;
2190};
2191
21532192struct IrInstructionUnreachable {
21542193 IrInstruction base;
21552194};
src/analyze.cpp+217-6
......@@ -992,18 +992,22 @@ TypeTableEntry *get_partial_container_type(CodeGen *g, Scope *scope, ContainerKi
992992 TypeTableEntryId type_id = container_to_type(kind);
993993 TypeTableEntry *entry = new_container_type_entry(type_id, decl_node, scope);
994994
995 unsigned dwarf_kind;
995996 switch (kind) {
996997 case ContainerKindStruct:
997998 entry->data.structure.decl_node = decl_node;
998999 entry->data.structure.layout = layout;
1000 dwarf_kind = ZigLLVMTag_DW_structure_type();
9991001 break;
10001002 case ContainerKindEnum:
10011003 entry->data.enumeration.decl_node = decl_node;
10021004 entry->data.enumeration.layout = layout;
1005 dwarf_kind = ZigLLVMTag_DW_structure_type();
10031006 break;
10041007 case ContainerKindUnion:
10051008 entry->data.unionation.decl_node = decl_node;
10061009 entry->data.unionation.layout = layout;
1010 dwarf_kind = ZigLLVMTag_DW_union_type();
10071011 break;
10081012 }
10091013
......@@ -1012,7 +1016,7 @@ TypeTableEntry *get_partial_container_type(CodeGen *g, Scope *scope, ContainerKi
10121016 ImportTableEntry *import = get_scope_import(scope);
10131017 entry->type_ref = LLVMStructCreateNamed(LLVMGetGlobalContext(), name);
10141018 entry->di_type = ZigLLVMCreateReplaceableCompositeType(g->dbuilder,
1015 ZigLLVMTag_DW_structure_type(), name,
1019 dwarf_kind, name,
10161020 ZigLLVMFileToScope(import->di_file), import->di_file, (unsigned)(line + 1));
10171021
10181022 buf_init_from_str(&entry->name, name);
......@@ -1285,7 +1289,7 @@ static void resolve_enum_type(CodeGen *g, TypeTableEntry *enum_type) {
12851289 return;
12861290
12871291 resolve_enum_zero_bits(g, enum_type);
1288 if (enum_type->data.enumeration.is_invalid)
1292 if (type_is_invalid(enum_type))
12891293 return;
12901294
12911295 AstNode *decl_node = enum_type->data.enumeration.decl_node;
......@@ -1834,7 +1838,140 @@ static void resolve_struct_type(CodeGen *g, TypeTableEntry *struct_type) {
18341838}
18351839
18361840static void resolve_union_type(CodeGen *g, TypeTableEntry *union_type) {
1837 zig_panic("TODO");
1841 assert(union_type->id == TypeTableEntryIdUnion);
1842
1843 if (union_type->data.unionation.complete)
1844 return;
1845
1846 resolve_union_zero_bits(g, union_type);
1847 if (type_is_invalid(union_type))
1848 return;
1849
1850 AstNode *decl_node = union_type->data.unionation.decl_node;
1851
1852 if (union_type->data.unionation.embedded_in_current) {
1853 if (!union_type->data.unionation.reported_infinite_err) {
1854 union_type->data.unionation.reported_infinite_err = true;
1855 add_node_error(g, decl_node, buf_sprintf("union '%s' contains itself", buf_ptr(&union_type->name)));
1856 }
1857 return;
1858 }
1859
1860 assert(!union_type->data.unionation.zero_bits_loop_flag);
1861 assert(decl_node->type == NodeTypeContainerDecl);
1862 assert(union_type->di_type);
1863
1864 uint32_t field_count = union_type->data.unionation.src_field_count;
1865
1866 assert(union_type->data.unionation.fields);
1867
1868 uint32_t gen_field_count = union_type->data.unionation.gen_field_count;
1869 ZigLLVMDIType **union_inner_di_types = allocate<ZigLLVMDIType*>(gen_field_count);
1870
1871 TypeTableEntry *most_aligned_union_member = nullptr;
1872 uint64_t size_of_most_aligned_member_in_bits = 0;
1873 uint64_t biggest_align_in_bits = 0;
1874 uint64_t biggest_size_in_bits = 0;
1875
1876 Scope *scope = &union_type->data.unionation.decls_scope->base;
1877 ImportTableEntry *import = get_scope_import(scope);
1878
1879 // set temporary flag
1880 union_type->data.unionation.embedded_in_current = true;
1881
1882 for (uint32_t i = 0; i < field_count; i += 1) {
1883 AstNode *field_node = decl_node->data.container_decl.fields.at(i);
1884 TypeUnionField *type_union_field = &union_type->data.unionation.fields[i];
1885 TypeTableEntry *field_type = type_union_field->type_entry;
1886
1887 ensure_complete_type(g, field_type);
1888 if (type_is_invalid(field_type)) {
1889 union_type->data.unionation.is_invalid = true;
1890 continue;
1891 }
1892
1893 if (!type_has_bits(field_type))
1894 continue;
1895
1896 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);
1898
1899 assert(store_size_in_bits > 0);
1900 assert(abi_align_in_bits > 0);
1901
1902 union_inner_di_types[type_union_field->gen_index] = ZigLLVMCreateDebugMemberType(g->dbuilder,
1903 ZigLLVMTypeToScope(union_type->di_type), buf_ptr(type_union_field->name),
1904 import->di_file, (unsigned)(field_node->line + 1),
1905 store_size_in_bits,
1906 abi_align_in_bits,
1907 0,
1908 0, field_type->di_type);
1909
1910 biggest_size_in_bits = max(biggest_size_in_bits, store_size_in_bits);
1911
1912 if (!most_aligned_union_member || abi_align_in_bits > biggest_align_in_bits) {
1913 most_aligned_union_member = field_type;
1914 biggest_align_in_bits = abi_align_in_bits;
1915 size_of_most_aligned_member_in_bits = store_size_in_bits;
1916 }
1917 }
1918
1919 // unset temporary flag
1920 union_type->data.unionation.embedded_in_current = false;
1921 union_type->data.unionation.complete = true;
1922 union_type->data.unionation.size_bytes = biggest_size_in_bits / 8;
1923 union_type->data.unionation.most_aligned_union_member = most_aligned_union_member;
1924
1925 if (union_type->data.unionation.is_invalid)
1926 return;
1927
1928 if (union_type->zero_bits) {
1929 union_type->type_ref = LLVMVoidType();
1930
1931 uint64_t debug_size_in_bits = 0;
1932 uint64_t debug_align_in_bits = 0;
1933 ZigLLVMDIType **di_root_members = nullptr;
1934 size_t debug_member_count = 0;
1935 ZigLLVMDIType *replacement_di_type = ZigLLVMCreateDebugUnionType(g->dbuilder,
1936 ZigLLVMFileToScope(import->di_file),
1937 buf_ptr(&union_type->name),
1938 import->di_file, (unsigned)(decl_node->line + 1),
1939 debug_size_in_bits,
1940 debug_align_in_bits,
1941 0, di_root_members, (int)debug_member_count, 0, "");
1942
1943 ZigLLVMReplaceTemporary(g->dbuilder, union_type->di_type, replacement_di_type);
1944 union_type->di_type = replacement_di_type;
1945 return;
1946 }
1947
1948 assert(most_aligned_union_member != nullptr);
1949
1950 // create llvm type for union
1951 uint64_t padding_in_bits = biggest_size_in_bits - size_of_most_aligned_member_in_bits;
1952 if (padding_in_bits > 0) {
1953 TypeTableEntry *u8_type = get_int_type(g, false, 8);
1954 TypeTableEntry *padding_array = get_array_type(g, u8_type, padding_in_bits / 8);
1955 LLVMTypeRef union_element_types[] = {
1956 most_aligned_union_member->type_ref,
1957 padding_array->type_ref,
1958 };
1959 LLVMStructSetBody(union_type->type_ref, union_element_types, 2, false);
1960 } else {
1961 LLVMStructSetBody(union_type->type_ref, &most_aligned_union_member->type_ref, 1, false);
1962 }
1963
1964 assert(8*LLVMABIAlignmentOfType(g->target_data_ref, union_type->type_ref) >= biggest_align_in_bits);
1965 assert(8*LLVMStoreSizeOfType(g->target_data_ref, union_type->type_ref) >= biggest_size_in_bits);
1966
1967 // create debug type for union
1968 ZigLLVMDIType *replacement_di_type = ZigLLVMCreateDebugUnionType(g->dbuilder,
1969 ZigLLVMFileToScope(import->di_file), buf_ptr(&union_type->name),
1970 import->di_file, (unsigned)(decl_node->line + 1),
1971 biggest_size_in_bits, biggest_align_in_bits, 0, union_inner_di_types,
1972 gen_field_count, 0, "");
1973 ZigLLVMReplaceTemporary(g->dbuilder, union_type->di_type, replacement_di_type);
1974 union_type->di_type = replacement_di_type;
18381975}
18391976
18401977static void resolve_enum_zero_bits(CodeGen *g, TypeTableEntry *enum_type) {
......@@ -1873,7 +2010,7 @@ static void resolve_enum_zero_bits(CodeGen *g, TypeTableEntry *enum_type) {
18732010 type_enum_field->value = i;
18742011
18752012 type_ensure_zero_bits_known(g, field_type);
1876 if (field_type->id == TypeTableEntryIdInvalid) {
2013 if (type_is_invalid(field_type)) {
18772014 enum_type->data.enumeration.is_invalid = true;
18782015 continue;
18792016 }
......@@ -1980,7 +2117,66 @@ static void resolve_struct_zero_bits(CodeGen *g, TypeTableEntry *struct_type) {
19802117}
19812118
19822119static void resolve_union_zero_bits(CodeGen *g, TypeTableEntry *union_type) {
1983 zig_panic("TODO resolve_union_zero_bits");
2120 assert(union_type->id == TypeTableEntryIdUnion);
2121
2122 if (union_type->data.unionation.zero_bits_known)
2123 return;
2124
2125 if (union_type->data.unionation.zero_bits_loop_flag) {
2126 union_type->data.unionation.zero_bits_known = true;
2127 return;
2128 }
2129
2130 union_type->data.unionation.zero_bits_loop_flag = true;
2131
2132 AstNode *decl_node = union_type->data.unionation.decl_node;
2133 assert(decl_node->type == NodeTypeContainerDecl);
2134 assert(union_type->di_type);
2135
2136 assert(!union_type->data.unionation.fields);
2137 uint32_t field_count = (uint32_t)decl_node->data.container_decl.fields.length;
2138 union_type->data.unionation.src_field_count = field_count;
2139 union_type->data.unionation.fields = allocate<TypeUnionField>(field_count);
2140
2141 uint32_t biggest_align_bytes = 0;
2142
2143 Scope *scope = &union_type->data.unionation.decls_scope->base;
2144
2145 uint32_t gen_field_index = 0;
2146 for (uint32_t i = 0; i < field_count; i += 1) {
2147 AstNode *field_node = decl_node->data.container_decl.fields.at(i);
2148 TypeUnionField *type_union_field = &union_type->data.unionation.fields[i];
2149 type_union_field->name = field_node->data.struct_field.name;
2150 TypeTableEntry *field_type = analyze_type_expr(g, scope, field_node->data.struct_field.type);
2151 type_union_field->type_entry = field_type;
2152
2153 type_ensure_zero_bits_known(g, field_type);
2154 if (type_is_invalid(field_type)) {
2155 union_type->data.unionation.is_invalid = true;
2156 continue;
2157 }
2158
2159 if (!type_has_bits(field_type))
2160 continue;
2161
2162 type_union_field->gen_index = gen_field_index;
2163 gen_field_index += 1;
2164
2165 uint32_t field_align_bytes = get_abi_alignment(g, field_type);
2166 if (field_align_bytes > biggest_align_bytes) {
2167 biggest_align_bytes = field_align_bytes;
2168 }
2169 }
2170
2171 union_type->data.unionation.zero_bits_loop_flag = false;
2172 union_type->data.unionation.gen_field_count = gen_field_index;
2173 union_type->zero_bits = (gen_field_index == 0);
2174 union_type->data.unionation.zero_bits_known = true;
2175
2176 // also compute abi_alignment
2177 if (!union_type->zero_bits) {
2178 union_type->data.unionation.abi_alignment = biggest_align_bytes;
2179 }
19842180}
19852181
19862182static void get_fully_qualified_decl_name_internal(Buf *buf, Scope *scope, uint8_t sep) {
......@@ -2851,6 +3047,18 @@ TypeStructField *find_struct_type_field(TypeTableEntry *type_entry, Buf *name) {
28513047 return nullptr;
28523048}
28533049
3050TypeUnionField *find_union_type_field(TypeTableEntry *type_entry, Buf *name) {
3051 assert(type_entry->id == TypeTableEntryIdUnion);
3052 assert(type_entry->data.unionation.complete);
3053 for (uint32_t i = 0; i < type_entry->data.unionation.src_field_count; i += 1) {
3054 TypeUnionField *field = &type_entry->data.unionation.fields[i];
3055 if (buf_eql_buf(field->name, name)) {
3056 return field;
3057 }
3058 }
3059 return nullptr;
3060}
3061
28543062static bool is_container(TypeTableEntry *type_entry) {
28553063 switch (type_entry->id) {
28563064 case TypeTableEntryIdInvalid:
......@@ -4703,6 +4911,8 @@ ConstParent *get_const_val_parent(CodeGen *g, ConstExprValue *value) {
47034911 return &value->data.x_array.s_none.parent;
47044912 } else if (type_entry->id == TypeTableEntryIdStruct) {
47054913 return &value->data.x_struct.parent;
4914 } else if (type_entry->id == TypeTableEntryIdUnion) {
4915 return &value->data.x_union.parent;
47064916 }
47074917 return nullptr;
47084918}
......@@ -4914,7 +5124,8 @@ uint32_t get_abi_alignment(CodeGen *g, TypeTableEntry *type_entry) {
49145124 assert(type_entry->data.enumeration.abi_alignment != 0);
49155125 return type_entry->data.enumeration.abi_alignment;
49165126 } else if (type_entry->id == TypeTableEntryIdUnion) {
4917 zig_panic("TODO");
5127 assert(type_entry->data.unionation.abi_alignment != 0);
5128 return type_entry->data.unionation.abi_alignment;
49185129 } else if (type_entry->id == TypeTableEntryIdOpaque) {
49195130 return 1;
49205131 } else {
src/analyze.hpp+1
......@@ -63,6 +63,7 @@ void resolve_container_type(CodeGen *g, TypeTableEntry *type_entry);
6363TypeStructField *find_struct_type_field(TypeTableEntry *type_entry, Buf *name);
6464ScopeDecls *get_container_scope(TypeTableEntry *type_entry);
6565TypeEnumField *find_enum_type_field(TypeTableEntry *enum_type, Buf *name);
66TypeUnionField *find_union_type_field(TypeTableEntry *type_entry, Buf *name);
6667bool is_container_ref(TypeTableEntry *type_entry);
6768void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node);
6869void scan_import(CodeGen *g, ImportTableEntry *import);
src/codegen.cpp+97-4
......@@ -2393,6 +2393,27 @@ static LLVMValueRef ir_render_enum_field_ptr(CodeGen *g, IrExecutable *executabl
23932393 return bitcasted_union_field_ptr;
23942394}
23952395
2396static LLVMValueRef ir_render_union_field_ptr(CodeGen *g, IrExecutable *executable,
2397 IrInstructionUnionFieldPtr *instruction)
2398{
2399 TypeTableEntry *union_ptr_type = instruction->union_ptr->value.type;
2400 assert(union_ptr_type->id == TypeTableEntryIdPointer);
2401 TypeTableEntry *union_type = union_ptr_type->data.pointer.child_type;
2402 assert(union_type->id == TypeTableEntryIdUnion);
2403
2404 TypeUnionField *field = instruction->field;
2405
2406 if (!type_has_bits(field->type_entry))
2407 return nullptr;
2408
2409 LLVMValueRef union_ptr = ir_llvm_value(g, instruction->union_ptr);
2410 LLVMTypeRef field_type_ref = LLVMPointerType(field->type_entry->type_ref, 0);
2411 LLVMValueRef union_field_ptr = LLVMBuildStructGEP(g->builder, union_ptr, 0, "");
2412 LLVMValueRef bitcasted_union_field_ptr = LLVMBuildBitCast(g->builder, union_field_ptr, field_type_ref, "");
2413
2414 return bitcasted_union_field_ptr;
2415}
2416
23962417static size_t find_asm_index(CodeGen *g, AstNode *node, AsmToken *tok) {
23972418 const char *ptr = buf_ptr(node->data.asm_expr.asm_template) + tok->start + 2;
23982419 size_t len = tok->end - tok->start - 2;
......@@ -3365,6 +3386,25 @@ static LLVMValueRef ir_render_struct_init(CodeGen *g, IrExecutable *executable,
33653386 return instruction->tmp_ptr;
33663387}
33673388
3389static LLVMValueRef ir_render_union_init(CodeGen *g, IrExecutable *executable, IrInstructionUnionInit *instruction) {
3390 TypeUnionField *type_union_field = instruction->field;
3391
3392 assert(type_has_bits(type_union_field->type_entry));
3393
3394 LLVMValueRef field_ptr = LLVMBuildStructGEP(g->builder, instruction->tmp_ptr, (unsigned)0, "");
3395 LLVMValueRef value = ir_llvm_value(g, instruction->init_value);
3396
3397 uint32_t field_align_bytes = get_abi_alignment(g, type_union_field->type_entry);
3398
3399 TypeTableEntry *ptr_type = get_pointer_to_type_extra(g, type_union_field->type_entry,
3400 false, false, field_align_bytes,
3401 0, 0);
3402
3403 gen_assign_raw(g, field_ptr, ptr_type, value);
3404
3405 return instruction->tmp_ptr;
3406}
3407
33683408static LLVMValueRef ir_render_container_init_list(CodeGen *g, IrExecutable *executable,
33693409 IrInstructionContainerInitList *instruction)
33703410{
......@@ -3486,6 +3526,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
34863526 return ir_render_struct_field_ptr(g, executable, (IrInstructionStructFieldPtr *)instruction);
34873527 case IrInstructionIdEnumFieldPtr:
34883528 return ir_render_enum_field_ptr(g, executable, (IrInstructionEnumFieldPtr *)instruction);
3529 case IrInstructionIdUnionFieldPtr:
3530 return ir_render_union_field_ptr(g, executable, (IrInstructionUnionFieldPtr *)instruction);
34893531 case IrInstructionIdAsm:
34903532 return ir_render_asm(g, executable, (IrInstructionAsm *)instruction);
34913533 case IrInstructionIdTestNonNull:
......@@ -3544,6 +3586,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
35443586 return ir_render_init_enum(g, executable, (IrInstructionInitEnum *)instruction);
35453587 case IrInstructionIdStructInit:
35463588 return ir_render_struct_init(g, executable, (IrInstructionStructInit *)instruction);
3589 case IrInstructionIdUnionInit:
3590 return ir_render_union_init(g, executable, (IrInstructionUnionInit *)instruction);
35473591 case IrInstructionIdPtrCast:
35483592 return ir_render_ptr_cast(g, executable, (IrInstructionPtrCast *)instruction);
35493593 case IrInstructionIdBitCast:
......@@ -3595,6 +3639,7 @@ static void ir_render(CodeGen *g, FnTableEntry *fn_entry) {
35953639
35963640static LLVMValueRef gen_const_ptr_struct_recursive(CodeGen *g, ConstExprValue *struct_const_val, size_t field_index);
35973641static LLVMValueRef gen_const_ptr_array_recursive(CodeGen *g, ConstExprValue *array_const_val, size_t index);
3642static LLVMValueRef gen_const_ptr_union_recursive(CodeGen *g, ConstExprValue *array_const_val);
35983643
35993644static LLVMValueRef gen_parent_ptr(CodeGen *g, ConstExprValue *val, ConstParent *parent) {
36003645 switch (parent->id) {
......@@ -3608,6 +3653,8 @@ static LLVMValueRef gen_parent_ptr(CodeGen *g, ConstExprValue *val, ConstParent
36083653 case ConstParentIdArray:
36093654 return gen_const_ptr_array_recursive(g, parent->data.p_array.array_val,
36103655 parent->data.p_array.elem_index);
3656 case ConstParentIdUnion:
3657 return gen_const_ptr_union_recursive(g, parent->data.p_union.union_val);
36113658 }
36123659 zig_unreachable();
36133660}
......@@ -3637,6 +3684,18 @@ static LLVMValueRef gen_const_ptr_struct_recursive(CodeGen *g, ConstExprValue *s
36373684 return LLVMConstInBoundsGEP(base_ptr, indices, 2);
36383685}
36393686
3687static LLVMValueRef gen_const_ptr_union_recursive(CodeGen *g, ConstExprValue *union_const_val) {
3688 ConstParent *parent = &union_const_val->data.x_union.parent;
3689 LLVMValueRef base_ptr = gen_parent_ptr(g, union_const_val, parent);
3690
3691 TypeTableEntry *u32 = g->builtin_types.entry_u32;
3692 LLVMValueRef indices[] = {
3693 LLVMConstNull(u32->type_ref),
3694 LLVMConstInt(u32->type_ref, 0, false),
3695 };
3696 return LLVMConstInBoundsGEP(base_ptr, indices, 2);
3697}
3698
36403699static LLVMValueRef pack_const_int(CodeGen *g, LLVMTypeRef big_int_type_ref, ConstExprValue *const_val) {
36413700 switch (const_val->special) {
36423701 case ConstValSpecialRuntime:
......@@ -3872,10 +3931,6 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val) {
38723931 return LLVMConstNamedStruct(type_entry->type_ref, fields, type_entry->data.structure.gen_field_count);
38733932 }
38743933 }
3875 case TypeTableEntryIdUnion:
3876 {
3877 zig_panic("TODO");
3878 }
38793934 case TypeTableEntryIdArray:
38803935 {
38813936 uint64_t len = type_entry->data.array.len;
......@@ -3898,6 +3953,41 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val) {
38983953 return LLVMConstArray(element_type_ref, values, (unsigned)len);
38993954 }
39003955 }
3956 case TypeTableEntryIdUnion:
3957 {
3958 LLVMTypeRef union_type_ref = type_entry->type_ref;
3959 ConstExprValue *payload_value = const_val->data.x_union.value;
3960 assert(payload_value != nullptr);
3961
3962 if (!type_has_bits(payload_value->type)) {
3963 return LLVMGetUndef(union_type_ref);
3964 }
3965
3966 uint64_t field_type_bytes = LLVMStoreSizeOfType(g->target_data_ref, payload_value->type->type_ref);
3967 uint64_t pad_bytes = type_entry->data.unionation.size_bytes - field_type_bytes;
3968
3969 LLVMValueRef correctly_typed_value = gen_const_val(g, payload_value);
3970
3971 bool make_unnamed_struct = is_llvm_value_unnamed_type(payload_value->type, correctly_typed_value) ||
3972 payload_value->type != type_entry->data.unionation.most_aligned_union_member;
3973
3974 unsigned field_count;
3975 LLVMValueRef fields[2];
3976 fields[0] = correctly_typed_value;
3977 if (pad_bytes == 0) {
3978 field_count = 1;
3979 } else {
3980 fields[0] = correctly_typed_value;
3981 fields[1] = LLVMGetUndef(LLVMArrayType(LLVMInt8Type(), (unsigned)pad_bytes));
3982 field_count = 2;
3983 }
3984
3985 if (make_unnamed_struct) {
3986 return LLVMConstStruct(fields, field_count, false);
3987 } else {
3988 return LLVMConstNamedStruct(type_entry->type_ref, fields, field_count);
3989 }
3990 }
39013991 case TypeTableEntryIdEnum:
39023992 {
39033993 LLVMTypeRef tag_type_ref = type_entry->data.enumeration.tag_type->type_ref;
......@@ -4376,6 +4466,9 @@ static void do_code_gen(CodeGen *g) {
43764466 } else if (instruction->id == IrInstructionIdStructInit) {
43774467 IrInstructionStructInit *struct_init_instruction = (IrInstructionStructInit *)instruction;
43784468 slot = &struct_init_instruction->tmp_ptr;
4469 } else if (instruction->id == IrInstructionIdUnionInit) {
4470 IrInstructionUnionInit *union_init_instruction = (IrInstructionUnionInit *)instruction;
4471 slot = &union_init_instruction->tmp_ptr;
43794472 } else if (instruction->id == IrInstructionIdCall) {
43804473 IrInstructionCall *call_instruction = (IrInstructionCall *)instruction;
43814474 slot = &call_instruction->tmp_ptr;
src/ir.cpp+160-11
......@@ -227,6 +227,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionEnumFieldPtr *)
227227 return IrInstructionIdEnumFieldPtr;
228228}
229229
230static constexpr IrInstructionId ir_instruction_id(IrInstructionUnionFieldPtr *) {
231 return IrInstructionIdUnionFieldPtr;
232}
233
230234static constexpr IrInstructionId ir_instruction_id(IrInstructionElemPtr *) {
231235 return IrInstructionIdElemPtr;
232236}
......@@ -351,6 +355,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionStructInit *) {
351355 return IrInstructionIdStructInit;
352356}
353357
358static constexpr IrInstructionId ir_instruction_id(IrInstructionUnionInit *) {
359 return IrInstructionIdUnionInit;
360}
361
354362static constexpr IrInstructionId ir_instruction_id(IrInstructionMinValue *) {
355363 return IrInstructionIdMinValue;
356364}
......@@ -922,6 +930,27 @@ static IrInstruction *ir_build_enum_field_ptr_from(IrBuilder *irb, IrInstruction
922930 return new_instruction;
923931}
924932
933static IrInstruction *ir_build_union_field_ptr(IrBuilder *irb, Scope *scope, AstNode *source_node,
934 IrInstruction *union_ptr, TypeUnionField *field)
935{
936 IrInstructionUnionFieldPtr *instruction = ir_build_instruction<IrInstructionUnionFieldPtr>(irb, scope, source_node);
937 instruction->union_ptr = union_ptr;
938 instruction->field = field;
939
940 ir_ref_instruction(union_ptr, irb->current_basic_block);
941
942 return &instruction->base;
943}
944
945static IrInstruction *ir_build_union_field_ptr_from(IrBuilder *irb, IrInstruction *old_instruction,
946 IrInstruction *union_ptr, TypeUnionField *type_union_field)
947{
948 IrInstruction *new_instruction = ir_build_union_field_ptr(irb, old_instruction->scope,
949 old_instruction->source_node, union_ptr, type_union_field);
950 ir_link_new_instruction(new_instruction, old_instruction);
951 return new_instruction;
952}
953
925954static IrInstruction *ir_build_call(IrBuilder *irb, Scope *scope, AstNode *source_node,
926955 FnTableEntry *fn_entry, IrInstruction *fn_ref, size_t arg_count, IrInstruction **args,
927956 bool is_comptime, bool is_inline)
......@@ -1112,6 +1141,28 @@ static IrInstruction *ir_build_struct_init_from(IrBuilder *irb, IrInstruction *o
11121141 return new_instruction;
11131142}
11141143
1144static IrInstruction *ir_build_union_init(IrBuilder *irb, Scope *scope, AstNode *source_node,
1145 TypeTableEntry *union_type, TypeUnionField *field, IrInstruction *init_value)
1146{
1147 IrInstructionUnionInit *union_init_instruction = ir_build_instruction<IrInstructionUnionInit>(irb, scope, source_node);
1148 union_init_instruction->union_type = union_type;
1149 union_init_instruction->field = field;
1150 union_init_instruction->init_value = init_value;
1151
1152 ir_ref_instruction(init_value, irb->current_basic_block);
1153
1154 return &union_init_instruction->base;
1155}
1156
1157static IrInstruction *ir_build_union_init_from(IrBuilder *irb, IrInstruction *old_instruction,
1158 TypeTableEntry *union_type, TypeUnionField *field, IrInstruction *init_value)
1159{
1160 IrInstruction *new_instruction = ir_build_union_init(irb, old_instruction->scope,
1161 old_instruction->source_node, union_type, field, init_value);
1162 ir_link_new_instruction(new_instruction, old_instruction);
1163 return new_instruction;
1164}
1165
11151166static IrInstruction *ir_build_unreachable(IrBuilder *irb, Scope *scope, AstNode *source_node) {
11161167 IrInstructionUnreachable *unreachable_instruction =
11171168 ir_build_instruction<IrInstructionUnreachable>(irb, scope, source_node);
......@@ -2422,6 +2473,13 @@ static IrInstruction *ir_instruction_enumfieldptr_get_dep(IrInstructionEnumField
24222473 }
24232474}
24242475
2476static IrInstruction *ir_instruction_unionfieldptr_get_dep(IrInstructionUnionFieldPtr *instruction, size_t index) {
2477 switch (index) {
2478 case 0: return instruction->union_ptr;
2479 default: return nullptr;
2480 }
2481}
2482
24252483static IrInstruction *ir_instruction_elemptr_get_dep(IrInstructionElemPtr *instruction, size_t index) {
24262484 switch (index) {
24272485 case 0: return instruction->array_ptr;
......@@ -2485,6 +2543,13 @@ static IrInstruction *ir_instruction_structinit_get_dep(IrInstructionStructInit
24852543 return nullptr;
24862544}
24872545
2546static IrInstruction *ir_instruction_unioninit_get_dep(IrInstructionUnionInit *instruction, size_t index) {
2547 switch (index) {
2548 case 0: return instruction->init_value;
2549 default: return nullptr;
2550 }
2551}
2552
24882553static IrInstruction *ir_instruction_unreachable_get_dep(IrInstructionUnreachable *instruction, size_t index) {
24892554 return nullptr;
24902555}
......@@ -3099,6 +3164,8 @@ static IrInstruction *ir_instruction_get_dep(IrInstruction *instruction, size_t
30993164 return ir_instruction_structfieldptr_get_dep((IrInstructionStructFieldPtr *) instruction, index);
31003165 case IrInstructionIdEnumFieldPtr:
31013166 return ir_instruction_enumfieldptr_get_dep((IrInstructionEnumFieldPtr *) instruction, index);
3167 case IrInstructionIdUnionFieldPtr:
3168 return ir_instruction_unionfieldptr_get_dep((IrInstructionUnionFieldPtr *) instruction, index);
31023169 case IrInstructionIdElemPtr:
31033170 return ir_instruction_elemptr_get_dep((IrInstructionElemPtr *) instruction, index);
31043171 case IrInstructionIdVarPtr:
......@@ -3117,6 +3184,8 @@ static IrInstruction *ir_instruction_get_dep(IrInstruction *instruction, size_t
31173184 return ir_instruction_containerinitfields_get_dep((IrInstructionContainerInitFields *) instruction, index);
31183185 case IrInstructionIdStructInit:
31193186 return ir_instruction_structinit_get_dep((IrInstructionStructInit *) instruction, index);
3187 case IrInstructionIdUnionInit:
3188 return ir_instruction_unioninit_get_dep((IrInstructionUnionInit *) instruction, index);
31203189 case IrInstructionIdUnreachable:
31213190 return ir_instruction_unreachable_get_dep((IrInstructionUnreachable *) instruction, index);
31223191 case IrInstructionIdTypeOf:
......@@ -11417,8 +11486,20 @@ static TypeTableEntry *ir_analyze_container_member_access_inner(IrAnalyze *ira,
1141711486 return ir_analyze_ref(ira, &field_ptr_instruction->base, bound_fn_value, true, false);
1141811487 }
1141911488 }
11489 const char *prefix_name;
11490 if (is_slice(bare_struct_type)) {
11491 prefix_name = "";
11492 } else if (bare_struct_type->id == TypeTableEntryIdStruct) {
11493 prefix_name = "struct ";
11494 } else if (bare_struct_type->id == TypeTableEntryIdEnum) {
11495 prefix_name = "enum ";
11496 } else if (bare_struct_type->id == TypeTableEntryIdUnion) {
11497 prefix_name = "union ";
11498 } else {
11499 prefix_name = "";
11500 }
1142011501 ir_add_error_node(ira, field_ptr_instruction->base.source_node,
11421 buf_sprintf("no member named '%s' in '%s'", buf_ptr(field_name), buf_ptr(&bare_struct_type->name)));
11502 buf_sprintf("no member named '%s' in %s'%s'", buf_ptr(field_name), prefix_name, buf_ptr(&bare_struct_type->name)));
1142211503 return ira->codegen->builtin_types.entry_invalid;
1142311504}
1142411505
......@@ -11428,14 +11509,13 @@ static TypeTableEntry *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field
1142811509{
1142911510 TypeTableEntry *bare_type = container_ref_type(container_type);
1143011511 ensure_complete_type(ira->codegen, bare_type);
11512 if (type_is_invalid(bare_type))
11513 return ira->codegen->builtin_types.entry_invalid;
1143111514
1143211515 assert(container_ptr->value.type->id == TypeTableEntryIdPointer);
1143311516 bool is_const = container_ptr->value.type->data.pointer.is_const;
1143411517 bool is_volatile = container_ptr->value.type->data.pointer.is_volatile;
1143511518 if (bare_type->id == TypeTableEntryIdStruct) {
11436 if (bare_type->data.structure.is_invalid)
11437 return ira->codegen->builtin_types.entry_invalid;
11438
1143911519 TypeStructField *field = find_struct_type_field(bare_type, field_name);
1144011520 if (field) {
1144111521 bool is_packed = (bare_type->data.structure.layout == ContainerLayoutPacked);
......@@ -11476,9 +11556,6 @@ static TypeTableEntry *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field
1147611556 field_ptr_instruction, container_ptr, container_type);
1147711557 }
1147811558 } else if (bare_type->id == TypeTableEntryIdEnum) {
11479 if (bare_type->data.enumeration.is_invalid)
11480 return ira->codegen->builtin_types.entry_invalid;
11481
1148211559 TypeEnumField *field = find_enum_type_field(bare_type, field_name);
1148311560 if (field) {
1148411561 ir_build_enum_field_ptr_from(&ira->new_irb, &field_ptr_instruction->base, container_ptr, field);
......@@ -11489,7 +11566,15 @@ static TypeTableEntry *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field
1148911566 field_ptr_instruction, container_ptr, container_type);
1149011567 }
1149111568 } else if (bare_type->id == TypeTableEntryIdUnion) {
11492 zig_panic("TODO");
11569 TypeUnionField *field = find_union_type_field(bare_type, field_name);
11570 if (field) {
11571 ir_build_union_field_ptr_from(&ira->new_irb, &field_ptr_instruction->base, container_ptr, field);
11572 return get_pointer_to_type_extra(ira->codegen, field->type_entry, is_const, is_volatile,
11573 get_abi_alignment(ira->codegen, field->type_entry), 0, 0);
11574 } else {
11575 return ir_analyze_container_member_access_inner(ira, bare_type, field_name,
11576 field_ptr_instruction, container_ptr, container_type);
11577 }
1149311578 } else {
1149411579 zig_unreachable();
1149511580 }
......@@ -13033,9 +13118,70 @@ static TypeTableEntry *ir_analyze_instruction_ref(IrAnalyze *ira, IrInstructionR
1303313118 return ir_analyze_ref(ira, &ref_instruction->base, value, ref_instruction->is_const, ref_instruction->is_volatile);
1303413119}
1303513120
13121static TypeTableEntry *ir_analyze_container_init_fields_union(IrAnalyze *ira, IrInstruction *instruction,
13122 TypeTableEntry *container_type, size_t instr_field_count, IrInstructionContainerInitFieldsField *fields)
13123{
13124 assert(container_type->id == TypeTableEntryIdUnion);
13125
13126 ensure_complete_type(ira->codegen, container_type);
13127
13128 if (instr_field_count != 1) {
13129 ir_add_error(ira, instruction,
13130 buf_sprintf("union initialization expects exactly one field"));
13131 return ira->codegen->builtin_types.entry_invalid;
13132 }
13133
13134 IrInstructionContainerInitFieldsField *field = &fields[0];
13135 IrInstruction *field_value = field->value->other;
13136 if (type_is_invalid(field_value->value.type))
13137 return ira->codegen->builtin_types.entry_invalid;
13138
13139 TypeUnionField *type_field = find_union_type_field(container_type, field->name);
13140 if (!type_field) {
13141 ir_add_error_node(ira, field->source_node,
13142 buf_sprintf("no member named '%s' in union '%s'",
13143 buf_ptr(field->name), buf_ptr(&container_type->name)));
13144 return ira->codegen->builtin_types.entry_invalid;
13145 }
13146
13147 if (type_is_invalid(type_field->type_entry))
13148 return ira->codegen->builtin_types.entry_invalid;
13149
13150 IrInstruction *casted_field_value = ir_implicit_cast(ira, field_value, type_field->type_entry);
13151 if (casted_field_value == ira->codegen->invalid_instruction)
13152 return ira->codegen->builtin_types.entry_invalid;
13153
13154 bool is_comptime = ir_should_inline(ira->new_irb.exec, instruction->scope);
13155 if (is_comptime || casted_field_value->value.special != ConstValSpecialRuntime) {
13156 ConstExprValue *field_val = ir_resolve_const(ira, casted_field_value, UndefOk);
13157 if (!field_val)
13158 return ira->codegen->builtin_types.entry_invalid;
13159
13160 ConstExprValue *out_val = ir_build_const_from(ira, instruction);
13161 out_val->data.x_union.value = field_val;
13162
13163 ConstParent *parent = get_const_val_parent(ira->codegen, field_val);
13164 if (parent != nullptr) {
13165 parent->id = ConstParentIdUnion;
13166 parent->data.p_union.union_val = out_val;
13167 }
13168
13169 return container_type;
13170 }
13171
13172 IrInstruction *new_instruction = ir_build_union_init_from(&ira->new_irb, instruction,
13173 container_type, type_field, casted_field_value);
13174
13175 ir_add_alloca(ira, new_instruction, container_type);
13176 return container_type;
13177}
13178
1303613179static TypeTableEntry *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruction *instruction,
1303713180 TypeTableEntry *container_type, size_t instr_field_count, IrInstructionContainerInitFieldsField *fields)
1303813181{
13182 if (container_type->id == TypeTableEntryIdUnion) {
13183 return ir_analyze_container_init_fields_union(ira, instruction, container_type, instr_field_count, fields);
13184 }
1303913185 if (container_type->id != TypeTableEntryIdStruct || is_slice(container_type)) {
1304013186 ir_add_error(ira, instruction,
1304113187 buf_sprintf("type '%s' does not support struct initialization syntax",
......@@ -13043,8 +13189,7 @@ static TypeTableEntry *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstru
1304313189 return ira->codegen->builtin_types.entry_invalid;
1304413190 }
1304513191
13046 if (!type_is_complete(container_type))
13047 resolve_container_type(ira->codegen, container_type);
13192 ensure_complete_type(ira->codegen, container_type);
1304813193
1304913194 size_t actual_field_count = container_type->data.structure.src_field_count;
1305013195
......@@ -13070,7 +13215,7 @@ static TypeTableEntry *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstru
1307013215 TypeStructField *type_field = find_struct_type_field(container_type, field->name);
1307113216 if (!type_field) {
1307213217 ir_add_error_node(ira, field->source_node,
13073 buf_sprintf("no member named '%s' in '%s'",
13218 buf_sprintf("no member named '%s' in struct '%s'",
1307413219 buf_ptr(field->name), buf_ptr(&container_type->name)));
1307513220 return ira->codegen->builtin_types.entry_invalid;
1307613221 }
......@@ -15657,8 +15802,10 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi
1565715802 case IrInstructionIdIntToErr:
1565815803 case IrInstructionIdErrToInt:
1565915804 case IrInstructionIdStructInit:
15805 case IrInstructionIdUnionInit:
1566015806 case IrInstructionIdStructFieldPtr:
1566115807 case IrInstructionIdEnumFieldPtr:
15808 case IrInstructionIdUnionFieldPtr:
1566215809 case IrInstructionIdInitEnum:
1566315810 case IrInstructionIdMaybeWrap:
1566415811 case IrInstructionIdErrWrapCode:
......@@ -15968,6 +16115,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {
1596816115 case IrInstructionIdContainerInitList:
1596916116 case IrInstructionIdContainerInitFields:
1597016117 case IrInstructionIdStructInit:
16118 case IrInstructionIdUnionInit:
1597116119 case IrInstructionIdFieldPtr:
1597216120 case IrInstructionIdElemPtr:
1597316121 case IrInstructionIdVarPtr:
......@@ -15977,6 +16125,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {
1597716125 case IrInstructionIdArrayLen:
1597816126 case IrInstructionIdStructFieldPtr:
1597916127 case IrInstructionIdEnumFieldPtr:
16128 case IrInstructionIdUnionFieldPtr:
1598016129 case IrInstructionIdArrayType:
1598116130 case IrInstructionIdSliceType:
1598216131 case IrInstructionIdSizeOf:
src/ir_print.cpp+22
......@@ -290,6 +290,15 @@ static void ir_print_struct_init(IrPrint *irp, IrInstructionStructInit *instruct
290290 fprintf(irp->f, "} // struct init");
291291}
292292
293static void ir_print_union_init(IrPrint *irp, IrInstructionUnionInit *instruction) {
294 Buf *field_name = instruction->field->name;
295
296 fprintf(irp->f, "%s {", buf_ptr(&instruction->union_type->name));
297 fprintf(irp->f, ".%s = ", buf_ptr(field_name));
298 ir_print_other_instruction(irp, instruction->init_value);
299 fprintf(irp->f, "} // union init");
300}
301
293302static void ir_print_unreachable(IrPrint *irp, IrInstructionUnreachable *instruction) {
294303 fprintf(irp->f, "unreachable");
295304}
......@@ -359,6 +368,13 @@ static void ir_print_enum_field_ptr(IrPrint *irp, IrInstructionEnumFieldPtr *ins
359368 fprintf(irp->f, ")");
360369}
361370
371static void ir_print_union_field_ptr(IrPrint *irp, IrInstructionUnionFieldPtr *instruction) {
372 fprintf(irp->f, "@UnionFieldPtr(&");
373 ir_print_other_instruction(irp, instruction->union_ptr);
374 fprintf(irp->f, ".%s", buf_ptr(instruction->field->name));
375 fprintf(irp->f, ")");
376}
377
362378static void ir_print_set_debug_safety(IrPrint *irp, IrInstructionSetDebugSafety *instruction) {
363379 fprintf(irp->f, "@setDebugSafety(");
364380 ir_print_other_instruction(irp, instruction->scope_value);
......@@ -1023,6 +1039,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
10231039 case IrInstructionIdStructInit:
10241040 ir_print_struct_init(irp, (IrInstructionStructInit *)instruction);
10251041 break;
1042 case IrInstructionIdUnionInit:
1043 ir_print_union_init(irp, (IrInstructionUnionInit *)instruction);
1044 break;
10261045 case IrInstructionIdUnreachable:
10271046 ir_print_unreachable(irp, (IrInstructionUnreachable *)instruction);
10281047 break;
......@@ -1056,6 +1075,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
10561075 case IrInstructionIdEnumFieldPtr:
10571076 ir_print_enum_field_ptr(irp, (IrInstructionEnumFieldPtr *)instruction);
10581077 break;
1078 case IrInstructionIdUnionFieldPtr:
1079 ir_print_union_field_ptr(irp, (IrInstructionUnionFieldPtr *)instruction);
1080 break;
10591081 case IrInstructionIdSetDebugSafety:
10601082 ir_print_set_debug_safety(irp, (IrInstructionSetDebugSafety *)instruction);
10611083 break;
src/zig_llvm.cpp+4
......@@ -403,6 +403,10 @@ unsigned ZigLLVMTag_DW_structure_type(void) {
403403 return dwarf::DW_TAG_structure_type;
404404}
405405
406unsigned ZigLLVMTag_DW_union_type(void) {
407 return dwarf::DW_TAG_union_type;
408}
409
406410ZigLLVMDIBuilder *ZigLLVMCreateDIBuilder(LLVMModuleRef module, bool allow_unresolved) {
407411 DIBuilder *di_builder = new DIBuilder(*unwrap(module), allow_unresolved);
408412 return reinterpret_cast<ZigLLVMDIBuilder *>(di_builder);
src/zig_llvm.hpp+1
......@@ -117,6 +117,7 @@ unsigned ZigLLVMEncoding_DW_ATE_signed_char(void);
117117unsigned ZigLLVMLang_DW_LANG_C99(void);
118118unsigned ZigLLVMTag_DW_variable(void);
119119unsigned ZigLLVMTag_DW_structure_type(void);
120unsigned ZigLLVMTag_DW_union_type(void);
120121
121122ZigLLVMDIBuilder *ZigLLVMCreateDIBuilder(LLVMModuleRef module, bool allow_unresolved);
122123void ZigLLVMAddModuleDebugInfoFlag(LLVMModuleRef module);
test/cases/union.zig+13
......@@ -31,3 +31,16 @@ test "unions embedded in aggregate types" {
3131 else => unreachable,
3232 }
3333}
34
35
36const Foo = union {
37 float: f64,
38 int: i32,
39};
40
41test "basic unions" {
42 var foo = Foo { .int = 1 };
43 assert(foo.int == 1);
44 foo.float = 12.34;
45 assert(foo.float == 12.34);
46}
test/compile_errors.zig+3-3
......@@ -389,8 +389,8 @@ pub fn addCases(cases: &tests.CompileErrorContext) {
389389 \\ const y = a.bar;
390390 \\}
391391 ,
392 ".tmp_source.zig:4:6: error: no member named 'foo' in 'A'",
393 ".tmp_source.zig:5:16: error: no member named 'bar' in 'A'");
392 ".tmp_source.zig:4:6: error: no member named 'foo' in struct 'A'",
393 ".tmp_source.zig:5:16: error: no member named 'bar' in struct 'A'");
394394
395395 cases.add("redefinition of struct",
396396 \\const A = struct { x : i32, };
......@@ -454,7 +454,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) {
454454 \\ .foo = 42,
455455 \\ };
456456 \\}
457 , ".tmp_source.zig:10:9: error: no member named 'foo' in 'A'");
457 , ".tmp_source.zig:10:9: error: no member named 'foo' in struct 'A'");
458458
459459 cases.add("invalid break expression",
460460 \\export fn f() {