authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-12-03 20:43:56-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-12-03 20:43:56-05:00
log0ad1239522c70418990dc7b9da4e128da7cdd1d5
tree3a434788633db0a3d6e30f779fc1239a7513205a
parent137c8f5e8a6023db24f90555e968b592a4b843e4

rework enums and unions and their relationship to each other

* @enumTagName renamed to @tagName and it works on enums and union-enums * Remove the EnumTag type. Now there is only enum and union, and the tag type of a union is always an enum. * unions support specifying the tag enum type, and they support inferring an enum tag type. * Enums no longer support field types but they do support setting the tag values. Likewise union-enums when inferring an enum tag type support setting the tag values. * It is now an error for enums and unions to have 0 fields. * switch statements support union-enums closes #618

24 files changed, 800 insertions(+), 950 deletions(-)

doc/langref.html.in+12-9
......@@ -136,7 +136,7 @@
136136 <li><a href="#builtin-divFloor">@divFloor</a></li>
137137 <li><a href="#builtin-divTrunc">@divTrunc</a></li>
138138 <li><a href="#builtin-embedFile">@embedFile</a></li>
139 <li><a href="#builtin-enumTagName">@enumTagName</a></li>
139 <li><a href="#builtin-tagName">@tagName</a></li>
140140 <li><a href="#builtin-EnumTagType">@EnumTagType</a></li>
141141 <li><a href="#builtin-errorName">@errorName</a></li>
142142 <li><a href="#builtin-fence">@fence</a></li>
......@@ -2165,7 +2165,7 @@ test "enum variant switch" {
21652165 };
21662166}
21672167
2168// The @enumTagName and @memberCount builtin functions can be used to
2168// The @memberName and @memberCount builtin functions can be used to
21692169// the string representation and number of members respectively.
21702170const BuiltinType = enum {
21712171 A: f32,
......@@ -2174,8 +2174,8 @@ const BuiltinType = enum {
21742174};
21752175
21762176test "enum builtins" {
2177 assert(mem.eql(u8, @enumTagName(BuiltinType.A { 0 }), "A"));
2178 assert(mem.eql(u8, @enumTagName(BuiltinType.C), "C"));
2177 assert(mem.eql(u8, @memberName(BuiltinType.A { 0 }), "A"));
2178 assert(mem.eql(u8, @memberName(BuiltinType.C), "C"));
21792179 assert(@memberCount(BuiltinType) == 3);
21802180}</code></pre>
21812181 <pre><code class="sh">$ zig test enum.zig
......@@ -2189,8 +2189,9 @@ Test 4/4 enum builtins...OK</code></pre>
21892189 </p>
21902190 <p>See also:</p>
21912191 <ul>
2192 <li><a href="#builtin-enumTagName">@enumTagName</a></li>
2192 <li><a href="#builtin-memberName">@memberName</a></li>
21932193 <li><a href="#builtin-memberCount">@memberCount</a></li>
2194 <li><a href="#builtin-tagName">@tagName</a></li>
21942195 </ul>
21952196 <h2 id="union">union</h2>
21962197 <p>TODO union documentation</p>
......@@ -4252,10 +4253,10 @@ test.zig:6:2: error: found compile log statement
42524253 <ul>
42534254 <li><a href="#builtin-import">@import</a></li>
42544255 </ul>
4255 <h3 id="builtin-enumTagName">@enumTagName</h3>
4256 <pre><code class="zig">@enumTagName(value: var) -&gt; []const u8</code></pre>
4256 <h3 id="builtin-tagName">@tagName</h3>
4257 <pre><code class="zig">@tagName(value: var) -&gt; []const u8</code></pre>
42574258 <p>
4258 Converts an enum tag name to a slice of bytes.
4259 Converts an enum value or union value to a slice of bytes representing the name.
42594260 </p>
42604261 <h3 id="builtin-EnumTagType">@EnumTagType</h3>
42614262 <pre><code class="zig">@EnumTagType(T: type) -&gt; type</code></pre>
......@@ -5843,7 +5844,9 @@ GroupedExpression = "(" Expression ")"
58435844
58445845KeywordLiteral = "true" | "false" | "null" | "continue" | "undefined" | "error" | "this" | "unreachable"
58455846
5846ContainerDecl = option("extern" | "packed") ("struct" | "union" | ("enum" option(GroupedExpression))) "{" many(ContainerMember) "}"</code></pre>
5847ContainerDecl = option("extern" | "packed")
5848 ("struct" option(GroupedExpression) | "union" option("enum" option(GroupedExpression) | GroupedExpression) | ("enum" option(GroupedExpression)))
5849 "{" many(ContainerMember) "}"</code></pre>
58475850 <h2 id="zen">Zen</h2>
58485851 <ul>
58495852 <li>Communicate intent precisely.</li>
src/all_types.hpp+9-50
......@@ -97,11 +97,6 @@ struct ConstParent {
9797 } data;
9898};
9999
100struct ConstEnumValue {
101 BigInt tag;
102 ConstExprValue *payload;
103};
104
105100struct ConstStructValue {
106101 ConstExprValue *fields;
107102 ConstParent parent;
......@@ -249,7 +244,7 @@ struct ConstExprValue {
249244 ConstExprValue *x_maybe;
250245 ConstErrValue x_err_union;
251246 ErrorTableEntry *x_pure_err;
252 ConstEnumValue x_enum;
247 BigInt x_enum_tag;
253248 ConstStructValue x_struct;
254249 ConstUnionValue x_union;
255250 ConstArrayValue x_array;
......@@ -345,15 +340,14 @@ struct TldCompTime {
345340
346341struct TypeEnumField {
347342 Buf *name;
348 TypeTableEntry *type_entry;
349343 BigInt value;
350 uint32_t gen_index;
344 uint32_t decl_index;
351345};
352346
353347struct TypeUnionField {
354348 Buf *name;
349 TypeEnumField *enum_field;
355350 TypeTableEntry *type_entry;
356 BigInt value;
357351 uint32_t gen_index;
358352};
359353
......@@ -773,7 +767,8 @@ struct AstNodeContainerDecl {
773767 ZigList<AstNode *> fields;
774768 ZigList<AstNode *> decls;
775769 ContainerLayout layout;
776 AstNode *init_arg_expr; // enum(T) or struct(endianness)
770 AstNode *init_arg_expr; // enum(T), struct(endianness), or union(T), or union(enum(T))
771 bool auto_enum; // union(enum)
777772};
778773
779774struct AstNodeStructField {
......@@ -1010,13 +1005,9 @@ struct TypeTableEntryEnum {
10101005 AstNode *decl_node;
10111006 ContainerLayout layout;
10121007 uint32_t src_field_count;
1013 // number of fields in the union. 0 if enum with no payload
1014 uint32_t gen_field_count;
10151008 TypeEnumField *fields;
10161009 bool is_invalid; // true if any fields are invalid
1017 TypeTableEntry *tag_type;
10181010 TypeTableEntry *tag_int_type;
1019 LLVMTypeRef union_type_ref;
10201011
10211012 ScopeDecls *decls_scope;
10221013
......@@ -1028,18 +1019,7 @@ struct TypeTableEntryEnum {
10281019
10291020 bool zero_bits_loop_flag;
10301021 bool zero_bits_known;
1031 uint32_t abi_alignment; // also figured out with zero_bits pass
1032
1033 size_t gen_union_index;
1034 size_t gen_tag_index;
1035
1036 uint32_t union_size_bytes;
1037 TypeTableEntry *most_aligned_union_member;
1038};
10391022
1040struct TypeTableEntryEnumTag {
1041 TypeTableEntry *enum_type;
1042 TypeTableEntry *int_type;
10431023 bool generate_name_table;
10441024 LLVMValueRef name_table;
10451025};
......@@ -1054,7 +1034,7 @@ struct TypeTableEntryUnion {
10541034 uint32_t gen_field_count;
10551035 TypeUnionField *fields;
10561036 bool is_invalid; // true if any fields are invalid
1057 TypeTableEntry *tag_type;
1037 TypeTableEntry *tag_type; // always an enum or null
10581038 LLVMTypeRef union_type_ref;
10591039
10601040 ScopeDecls *decls_scope;
......@@ -1119,7 +1099,6 @@ enum TypeTableEntryId {
11191099 TypeTableEntryIdErrorUnion,
11201100 TypeTableEntryIdPureError,
11211101 TypeTableEntryIdEnum,
1122 TypeTableEntryIdEnumTag,
11231102 TypeTableEntryIdUnion,
11241103 TypeTableEntryIdFn,
11251104 TypeTableEntryIdNamespace,
......@@ -1148,7 +1127,6 @@ struct TypeTableEntry {
11481127 TypeTableEntryMaybe maybe;
11491128 TypeTableEntryError error;
11501129 TypeTableEntryEnum enumeration;
1151 TypeTableEntryEnumTag enum_tag;
11521130 TypeTableEntryUnion unionation;
11531131 TypeTableEntryFn fn;
11541132 TypeTableEntryBoundFn bound_fn;
......@@ -1287,7 +1265,7 @@ enum BuiltinFnId {
12871265 BuiltinFnIdBitCast,
12881266 BuiltinFnIdIntToPtr,
12891267 BuiltinFnIdPtrToInt,
1290 BuiltinFnIdEnumTagName,
1268 BuiltinFnIdTagName,
12911269 BuiltinFnIdEnumTagType,
12921270 BuiltinFnIdFieldParentPtr,
12931271 BuiltinFnIdOffsetOf,
......@@ -1832,7 +1810,6 @@ enum IrInstructionId {
18321810 IrInstructionIdStorePtr,
18331811 IrInstructionIdFieldPtr,
18341812 IrInstructionIdStructFieldPtr,
1835 IrInstructionIdEnumFieldPtr,
18361813 IrInstructionIdUnionFieldPtr,
18371814 IrInstructionIdElemPtr,
18381815 IrInstructionIdVarPtr,
......@@ -1857,7 +1834,7 @@ enum IrInstructionId {
18571834 IrInstructionIdTestNonNull,
18581835 IrInstructionIdUnwrapMaybe,
18591836 IrInstructionIdMaybeWrap,
1860 IrInstructionIdEnumTag,
1837 IrInstructionIdUnionTag,
18611838 IrInstructionIdClz,
18621839 IrInstructionIdCtz,
18631840 IrInstructionIdImport,
......@@ -1896,7 +1873,6 @@ enum IrInstructionId {
18961873 IrInstructionIdErrWrapPayload,
18971874 IrInstructionIdFnProto,
18981875 IrInstructionIdTestComptime,
1899 IrInstructionIdInitEnum,
19001876 IrInstructionIdPtrCast,
19011877 IrInstructionIdBitCast,
19021878 IrInstructionIdWidenOrShorten,
......@@ -2092,14 +2068,6 @@ struct IrInstructionStructFieldPtr {
20922068 bool is_const;
20932069};
20942070
2095struct IrInstructionEnumFieldPtr {
2096 IrInstruction base;
2097
2098 IrInstruction *enum_ptr;
2099 TypeEnumField *field;
2100 bool is_const;
2101};
2102
21032071struct IrInstructionUnionFieldPtr {
21042072 IrInstruction base;
21052073
......@@ -2303,7 +2271,7 @@ struct IrInstructionClz {
23032271 IrInstruction *value;
23042272};
23052273
2306struct IrInstructionEnumTag {
2274struct IrInstructionUnionTag {
23072275 IrInstruction base;
23082276
23092277 IrInstruction *value;
......@@ -2573,15 +2541,6 @@ struct IrInstructionTestComptime {
25732541 IrInstruction *value;
25742542};
25752543
2576struct IrInstructionInitEnum {
2577 IrInstruction base;
2578
2579 TypeTableEntry *enum_type;
2580 TypeEnumField *field;
2581 IrInstruction *init_value;
2582 LLVMValueRef tmp_ptr;
2583};
2584
25852544struct IrInstructionPtrCast {
25862545 IrInstruction base;
25872546
src/analyze.cpp+301-306
......@@ -223,7 +223,6 @@ bool type_is_complete(TypeTableEntry *type_entry) {
223223 case TypeTableEntryIdNamespace:
224224 case TypeTableEntryIdBlock:
225225 case TypeTableEntryIdBoundFn:
226 case TypeTableEntryIdEnumTag:
227226 case TypeTableEntryIdArgTuple:
228227 return true;
229228 }
......@@ -260,7 +259,6 @@ bool type_has_zero_bits_known(TypeTableEntry *type_entry) {
260259 case TypeTableEntryIdNamespace:
261260 case TypeTableEntryIdBlock:
262261 case TypeTableEntryIdBoundFn:
263 case TypeTableEntryIdEnumTag:
264262 case TypeTableEntryIdArgTuple:
265263 case TypeTableEntryIdOpaque:
266264 return true;
......@@ -1175,7 +1173,6 @@ static TypeTableEntry *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *c
11751173 case TypeTableEntryIdEnum:
11761174 case TypeTableEntryIdUnion:
11771175 case TypeTableEntryIdFn:
1178 case TypeTableEntryIdEnumTag:
11791176 ensure_complete_type(g, type_entry);
11801177 if (fn_type_id.cc == CallingConventionUnspecified && !type_is_copyable(g, type_entry)) {
11811178 add_node_error(g, param_node->data.param_decl.type,
......@@ -1239,7 +1236,6 @@ static TypeTableEntry *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *c
12391236 case TypeTableEntryIdEnum:
12401237 case TypeTableEntryIdUnion:
12411238 case TypeTableEntryIdFn:
1242 case TypeTableEntryIdEnumTag:
12431239 break;
12441240 }
12451241
......@@ -1263,22 +1259,6 @@ bool type_is_invalid(TypeTableEntry *type_entry) {
12631259}
12641260
12651261
1266TypeTableEntry *create_enum_tag_type(CodeGen *g, TypeTableEntry *enum_type, TypeTableEntry *int_type) {
1267 TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdEnumTag);
1268
1269 buf_resize(&entry->name, 0);
1270 buf_appendf(&entry->name, "@EnumTagType(%s)", buf_ptr(&enum_type->name));
1271
1272 entry->is_copyable = true;
1273 entry->data.enum_tag.enum_type = enum_type;
1274 entry->data.enum_tag.int_type = int_type;
1275 entry->type_ref = int_type->type_ref;
1276 entry->di_type = int_type->di_type;
1277 entry->zero_bits = int_type->zero_bits;
1278
1279 return entry;
1280}
1281
12821262static void resolve_enum_type(CodeGen *g, TypeTableEntry *enum_type) {
12831263 assert(enum_type->id == TypeTableEntryIdEnum);
12841264
......@@ -1308,14 +1288,6 @@ static void resolve_enum_type(CodeGen *g, TypeTableEntry *enum_type) {
13081288 assert(enum_type->data.enumeration.fields);
13091289 ZigLLVMDIEnumerator **di_enumerators = allocate<ZigLLVMDIEnumerator*>(field_count);
13101290
1311 uint32_t gen_field_count = enum_type->data.enumeration.gen_field_count;
1312 ZigLLVMDIType **union_inner_di_types = allocate<ZigLLVMDIType*>(gen_field_count);
1313
1314 TypeTableEntry *most_aligned_union_member = nullptr;
1315 uint64_t size_of_most_aligned_member_in_bits = 0;
1316 uint64_t biggest_align_in_bits = 0;
1317 uint64_t biggest_size_in_bits = 0;
1318
13191291 Scope *scope = &enum_type->data.enumeration.decls_scope->base;
13201292 ImportTableEntry *import = get_scope_import(scope);
13211293
......@@ -1323,49 +1295,17 @@ static void resolve_enum_type(CodeGen *g, TypeTableEntry *enum_type) {
13231295 enum_type->data.enumeration.embedded_in_current = true;
13241296
13251297 for (uint32_t i = 0; i < field_count; i += 1) {
1326 AstNode *field_node = decl_node->data.container_decl.fields.at(i);
1327 TypeEnumField *type_enum_field = &enum_type->data.enumeration.fields[i];
1328 TypeTableEntry *field_type = type_enum_field->type_entry;
1329
1330 di_enumerators[i] = ZigLLVMCreateDebugEnumerator(g->dbuilder, buf_ptr(type_enum_field->name), i);
1331
1332 ensure_complete_type(g, field_type);
1333 if (type_is_invalid(field_type)) {
1334 enum_type->data.enumeration.is_invalid = true;
1335 continue;
1336 }
1337
1338 if (!type_has_bits(field_type))
1339 continue;
1340
1341 uint64_t store_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, field_type->type_ref);
1342 uint64_t abi_align_in_bits = 8*LLVMABIAlignmentOfType(g->target_data_ref, field_type->type_ref);
1298 TypeEnumField *enum_field = &enum_type->data.enumeration.fields[i];
13431299
1344 assert(store_size_in_bits > 0);
1345 assert(abi_align_in_bits > 0);
1346
1347 union_inner_di_types[type_enum_field->gen_index] = ZigLLVMCreateDebugMemberType(g->dbuilder,
1348 ZigLLVMTypeToScope(enum_type->di_type), buf_ptr(type_enum_field->name),
1349 import->di_file, (unsigned)(field_node->line + 1),
1350 store_size_in_bits,
1351 abi_align_in_bits,
1352 0,
1353 0, field_type->di_type);
1354
1355 biggest_size_in_bits = max(biggest_size_in_bits, store_size_in_bits);
1356
1357 if (!most_aligned_union_member || abi_align_in_bits > biggest_align_in_bits) {
1358 most_aligned_union_member = field_type;
1359 biggest_align_in_bits = abi_align_in_bits;
1360 size_of_most_aligned_member_in_bits = store_size_in_bits;
1361 }
1300 // TODO send patch to LLVM to support APInt in createEnumerator instead of int64_t
1301 // http://lists.llvm.org/pipermail/llvm-dev/2017-December/119456.html
1302 di_enumerators[i] = ZigLLVMCreateDebugEnumerator(g->dbuilder, buf_ptr(enum_field->name),
1303 bigint_as_signed(&enum_field->value));
13621304 }
13631305
13641306 // unset temporary flag
13651307 enum_type->data.enumeration.embedded_in_current = false;
13661308 enum_type->data.enumeration.complete = true;
1367 enum_type->data.enumeration.union_size_bytes = biggest_size_in_bits / 8;
1368 enum_type->data.enumeration.most_aligned_union_member = most_aligned_union_member;
13691309
13701310 if (enum_type->data.enumeration.is_invalid)
13711311 return;
......@@ -1391,117 +1331,20 @@ static void resolve_enum_type(CodeGen *g, TypeTableEntry *enum_type) {
13911331 }
13921332
13931333 TypeTableEntry *tag_int_type = enum_type->data.enumeration.tag_int_type;
1394 TypeTableEntry *tag_type_entry = create_enum_tag_type(g, enum_type, tag_int_type);
1395 enum_type->data.enumeration.tag_type = tag_type_entry;
1396
1397 uint64_t align_of_tag_in_bits = 8*LLVMABIAlignmentOfType(g->target_data_ref, tag_int_type->type_ref);
1398
1399 if (most_aligned_union_member) {
1400 // create llvm type for union
1401 uint64_t padding_in_bits = biggest_size_in_bits - size_of_most_aligned_member_in_bits;
1402 LLVMTypeRef union_type_ref;
1403 if (padding_in_bits > 0) {
1404 TypeTableEntry *u8_type = get_int_type(g, false, 8);
1405 TypeTableEntry *padding_array = get_array_type(g, u8_type, padding_in_bits / 8);
1406 LLVMTypeRef union_element_types[] = {
1407 most_aligned_union_member->type_ref,
1408 padding_array->type_ref,
1409 };
1410 union_type_ref = LLVMStructType(union_element_types, 2, false);
1411 } else {
1412 union_type_ref = most_aligned_union_member->type_ref;
1413 }
1414 enum_type->data.enumeration.union_type_ref = union_type_ref;
1415
1416 assert(8*LLVMABIAlignmentOfType(g->target_data_ref, union_type_ref) >= biggest_align_in_bits);
1417 assert(8*LLVMStoreSizeOfType(g->target_data_ref, union_type_ref) >= biggest_size_in_bits);
1418
1419 if (align_of_tag_in_bits >= biggest_align_in_bits) {
1420 enum_type->data.enumeration.gen_tag_index = 0;
1421 enum_type->data.enumeration.gen_union_index = 1;
1422 } else {
1423 enum_type->data.enumeration.gen_union_index = 0;
1424 enum_type->data.enumeration.gen_tag_index = 1;
1425 }
1426
1427 // create llvm type for root struct
1428 LLVMTypeRef root_struct_element_types[2];
1429 root_struct_element_types[enum_type->data.enumeration.gen_tag_index] = tag_type_entry->type_ref;
1430 root_struct_element_types[enum_type->data.enumeration.gen_union_index] = union_type_ref;
1431 LLVMStructSetBody(enum_type->type_ref, root_struct_element_types, 2, false);
1432
1433 // create debug type for tag
1434 uint64_t tag_debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, tag_type_entry->type_ref);
1435 uint64_t tag_debug_align_in_bits = 8*LLVMABIAlignmentOfType(g->target_data_ref, tag_type_entry->type_ref);
1436 ZigLLVMDIType *tag_di_type = ZigLLVMCreateDebugEnumerationType(g->dbuilder,
1437 ZigLLVMTypeToScope(enum_type->di_type), "AnonEnum",
1438 import->di_file, (unsigned)(decl_node->line + 1),
1439 tag_debug_size_in_bits, tag_debug_align_in_bits, di_enumerators, field_count,
1440 tag_type_entry->di_type, "");
1441
1442 // create debug type for union
1443 ZigLLVMDIType *union_di_type = ZigLLVMCreateDebugUnionType(g->dbuilder,
1444 ZigLLVMTypeToScope(enum_type->di_type), "AnonUnion",
1445 import->di_file, (unsigned)(decl_node->line + 1),
1446 biggest_size_in_bits, biggest_align_in_bits, 0, union_inner_di_types,
1447 gen_field_count, 0, "");
1448
1449 // create debug types for members of root struct
1450 uint64_t tag_offset_in_bits = 8*LLVMOffsetOfElement(g->target_data_ref, enum_type->type_ref,
1451 enum_type->data.enumeration.gen_tag_index);
1452 ZigLLVMDIType *tag_member_di_type = ZigLLVMCreateDebugMemberType(g->dbuilder,
1453 ZigLLVMTypeToScope(enum_type->di_type), "tag_field",
1454 import->di_file, (unsigned)(decl_node->line + 1),
1455 tag_debug_size_in_bits,
1456 tag_debug_align_in_bits,
1457 tag_offset_in_bits,
1458 0, tag_di_type);
1459
1460 uint64_t union_offset_in_bits = 8*LLVMOffsetOfElement(g->target_data_ref, enum_type->type_ref,
1461 enum_type->data.enumeration.gen_union_index);
1462 ZigLLVMDIType *union_member_di_type = ZigLLVMCreateDebugMemberType(g->dbuilder,
1463 ZigLLVMTypeToScope(enum_type->di_type), "union_field",
1464 import->di_file, (unsigned)(decl_node->line + 1),
1465 biggest_size_in_bits,
1466 biggest_align_in_bits,
1467 union_offset_in_bits,
1468 0, union_di_type);
1469
1470 // create debug type for root struct
1471 ZigLLVMDIType *di_root_members[2];
1472 di_root_members[enum_type->data.enumeration.gen_tag_index] = tag_member_di_type;
1473 di_root_members[enum_type->data.enumeration.gen_union_index] = union_member_di_type;
1474
1475 uint64_t debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, enum_type->type_ref);
1476 uint64_t debug_align_in_bits = 8*LLVMABISizeOfType(g->target_data_ref, enum_type->type_ref);
1477 ZigLLVMDIType *replacement_di_type = ZigLLVMCreateDebugStructType(g->dbuilder,
1478 ZigLLVMFileToScope(import->di_file),
1479 buf_ptr(&enum_type->name),
1480 import->di_file, (unsigned)(decl_node->line + 1),
1481 debug_size_in_bits,
1482 debug_align_in_bits,
1483 0, nullptr, di_root_members, 2, 0, nullptr, "");
1484
1485 ZigLLVMReplaceTemporary(g->dbuilder, enum_type->di_type, replacement_di_type);
1486 enum_type->di_type = replacement_di_type;
1487 } else {
1488 // create llvm type for root struct
1489 enum_type->type_ref = tag_type_entry->type_ref;
14901334
1491 // create debug type for tag
1492 uint64_t tag_debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, tag_type_entry->type_ref);
1493 uint64_t tag_debug_align_in_bits = 8*LLVMABIAlignmentOfType(g->target_data_ref, tag_type_entry->type_ref);
1494 ZigLLVMDIType *tag_di_type = ZigLLVMCreateDebugEnumerationType(g->dbuilder,
1495 ZigLLVMFileToScope(import->di_file), buf_ptr(&enum_type->name),
1496 import->di_file, (unsigned)(decl_node->line + 1),
1497 tag_debug_size_in_bits,
1498 tag_debug_align_in_bits,
1499 di_enumerators, field_count,
1500 tag_type_entry->di_type, "");
1335 // create debug type for tag
1336 uint64_t tag_debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, tag_int_type->type_ref);
1337 uint64_t tag_debug_align_in_bits = 8*LLVMABIAlignmentOfType(g->target_data_ref, tag_int_type->type_ref);
1338 ZigLLVMDIType *tag_di_type = ZigLLVMCreateDebugEnumerationType(g->dbuilder,
1339 ZigLLVMFileToScope(import->di_file), buf_ptr(&enum_type->name),
1340 import->di_file, (unsigned)(decl_node->line + 1),
1341 tag_debug_size_in_bits,
1342 tag_debug_align_in_bits,
1343 di_enumerators, field_count,
1344 tag_int_type->di_type, "");
15011345
1502 ZigLLVMReplaceTemporary(g->dbuilder, enum_type->di_type, tag_di_type);
1503 enum_type->di_type = tag_di_type;
1504 }
1346 ZigLLVMReplaceTemporary(g->dbuilder, enum_type->di_type, tag_di_type);
1347 enum_type->di_type = tag_di_type;
15051348}
15061349
15071350static bool type_allowed_in_packed_struct(TypeTableEntry *type_entry) {
......@@ -1517,7 +1360,6 @@ static bool type_allowed_in_packed_struct(TypeTableEntry *type_entry) {
15171360 case TypeTableEntryIdNullLit:
15181361 case TypeTableEntryIdErrorUnion:
15191362 case TypeTableEntryIdPureError:
1520 case TypeTableEntryIdEnumTag:
15211363 case TypeTableEntryIdNamespace:
15221364 case TypeTableEntryIdBlock:
15231365 case TypeTableEntryIdBoundFn:
......@@ -1541,8 +1383,7 @@ static bool type_allowed_in_packed_struct(TypeTableEntry *type_entry) {
15411383 return child_type->id == TypeTableEntryIdPointer || child_type->id == TypeTableEntryIdFn;
15421384 }
15431385 case TypeTableEntryIdEnum:
1544 return type_entry->data.enumeration.gen_field_count == 0 &&
1545 type_entry->data.enumeration.decl_node->data.container_decl.init_arg_expr != nullptr;
1386 return type_entry->data.enumeration.decl_node->data.container_decl.init_arg_expr != nullptr;
15461387 }
15471388 zig_unreachable();
15481389}
......@@ -1850,6 +1691,7 @@ static void resolve_union_type(CodeGen *g, TypeTableEntry *union_type) {
18501691 if (union_type->data.unionation.embedded_in_current) {
18511692 if (!union_type->data.unionation.reported_infinite_err) {
18521693 union_type->data.unionation.reported_infinite_err = true;
1694 union_type->data.unionation.is_invalid = true;
18531695 add_node_error(g, decl_node, buf_sprintf("union '%s' contains itself", buf_ptr(&union_type->name)));
18541696 }
18551697 return;
......@@ -1871,8 +1713,7 @@ static void resolve_union_type(CodeGen *g, TypeTableEntry *union_type) {
18711713 uint64_t biggest_align_in_bits = 0;
18721714 uint64_t biggest_size_in_bits = 0;
18731715
1874 bool auto_layout = (union_type->data.unionation.layout == ContainerLayoutAuto);
1875 ZigLLVMDIEnumerator **di_enumerators = allocate<ZigLLVMDIEnumerator*>(field_count);
1716 ZigLLVMDIEnumerator **di_enumerators;
18761717
18771718 Scope *scope = &union_type->data.unionation.decls_scope->base;
18781719 ImportTableEntry *import = get_scope_import(scope);
......@@ -1880,10 +1721,77 @@ static void resolve_union_type(CodeGen *g, TypeTableEntry *union_type) {
18801721 // set temporary flag
18811722 union_type->data.unionation.embedded_in_current = true;
18821723
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
18831790 for (uint32_t i = 0; i < field_count; i += 1) {
18841791 AstNode *field_node = decl_node->data.container_decl.fields.at(i);
1885 TypeUnionField *type_union_field = &union_type->data.unionation.fields[i];
1886 TypeTableEntry *field_type = type_union_field->type_entry;
1792 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;
18871795
18881796 ensure_complete_type(g, field_type);
18891797 if (type_is_invalid(field_type)) {
......@@ -1891,19 +1799,68 @@ static void resolve_union_type(CodeGen *g, TypeTableEntry *union_type) {
18911799 continue;
18921800 }
18931801
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
18941853 if (!type_has_bits(field_type))
18951854 continue;
18961855
1897 di_enumerators[i] = ZigLLVMCreateDebugEnumerator(g->dbuilder, buf_ptr(type_union_field->name), i);
1898
18991856 uint64_t store_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, field_type->type_ref);
19001857 uint64_t abi_align_in_bits = 8*LLVMABIAlignmentOfType(g->target_data_ref, field_type->type_ref);
19011858
19021859 assert(store_size_in_bits > 0);
19031860 assert(abi_align_in_bits > 0);
19041861
1905 union_inner_di_types[type_union_field->gen_index] = ZigLLVMCreateDebugMemberType(g->dbuilder,
1906 ZigLLVMTypeToScope(union_type->di_type), buf_ptr(type_union_field->name),
1862 union_inner_di_types[union_field->gen_index] = ZigLLVMCreateDebugMemberType(g->dbuilder,
1863 ZigLLVMTypeToScope(union_type->di_type), buf_ptr(union_field->enum_field->name),
19071864 import->di_file, (unsigned)(field_node->line + 1),
19081865 store_size_in_bits,
19091866 abi_align_in_bits,
......@@ -1919,6 +1876,49 @@ static void resolve_union_type(CodeGen *g, TypeTableEntry *union_type) {
19191876 }
19201877 }
19211878
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
19221922 // unset temporary flag
19231923 union_type->data.unionation.embedded_in_current = false;
19241924 union_type->data.unionation.complete = true;
......@@ -1950,11 +1950,9 @@ static void resolve_union_type(CodeGen *g, TypeTableEntry *union_type) {
19501950
19511951 assert(most_aligned_union_member != nullptr);
19521952
1953 bool want_safety = auto_layout && (field_count >= 2);
19541953 uint64_t padding_in_bits = biggest_size_in_bits - size_of_most_aligned_member_in_bits;
19551954
1956
1957 if (!want_safety) {
1955 if (tag_type == nullptr) {
19581956 if (padding_in_bits > 0) {
19591957 TypeTableEntry *u8_type = get_int_type(g, false, 8);
19601958 TypeTableEntry *padding_array = get_array_type(g, u8_type, padding_in_bits / 8);
......@@ -1994,6 +1992,8 @@ static void resolve_union_type(CodeGen *g, TypeTableEntry *union_type) {
19941992 padding_array->type_ref,
19951993 };
19961994 union_type_ref = LLVMStructType(union_element_types, 2, false);
1995 } else if (most_aligned_union_member == nullptr) {
1996 zig_panic("TODO zero bit payload");
19971997 } else {
19981998 union_type_ref = most_aligned_union_member->type_ref;
19991999 }
......@@ -2003,9 +2003,7 @@ static void resolve_union_type(CodeGen *g, TypeTableEntry *union_type) {
20032003 assert(8*LLVMStoreSizeOfType(g->target_data_ref, union_type_ref) >= biggest_size_in_bits);
20042004
20052005 // create llvm type for root struct
2006 TypeTableEntry *tag_int_type = get_smallest_unsigned_int_type(g, field_count - 1);
2007 TypeTableEntry *tag_type_entry = tag_int_type;
2008 union_type->data.unionation.tag_type = tag_type_entry;
2006 TypeTableEntry *tag_int_type = tag_type->data.enumeration.tag_int_type;
20092007 uint64_t align_of_tag_in_bits = 8*LLVMABIAlignmentOfType(g->target_data_ref, tag_int_type->type_ref);
20102008
20112009 if (align_of_tag_in_bits >= biggest_align_in_bits) {
......@@ -2017,21 +2015,24 @@ static void resolve_union_type(CodeGen *g, TypeTableEntry *union_type) {
20172015 }
20182016
20192017 LLVMTypeRef root_struct_element_types[2];
2020 root_struct_element_types[union_type->data.unionation.gen_tag_index] = tag_type_entry->type_ref;
2018 root_struct_element_types[union_type->data.unionation.gen_tag_index] = tag_type->type_ref;
20212019 root_struct_element_types[union_type->data.unionation.gen_union_index] = union_type_ref;
20222020 LLVMStructSetBody(union_type->type_ref, root_struct_element_types, 2, false);
20232021
20242022
20252023 // create debug type for root struct
20262024
2027 // create debug type for tag
2028 uint64_t tag_debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, tag_type_entry->type_ref);
2029 uint64_t tag_debug_align_in_bits = 8*LLVMABIAlignmentOfType(g->target_data_ref, tag_type_entry->type_ref);
2030 ZigLLVMDIType *tag_di_type = ZigLLVMCreateDebugEnumerationType(g->dbuilder,
2031 ZigLLVMTypeToScope(union_type->di_type), "AnonEnum",
2032 import->di_file, (unsigned)(decl_node->line + 1),
2033 tag_debug_size_in_bits, tag_debug_align_in_bits, di_enumerators, field_count,
2034 tag_type_entry->di_type, "");
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 }
20352036
20362037 // create debug type for union
20372038 ZigLLVMDIType *union_di_type = ZigLLVMCreateDebugUnionType(g->dbuilder,
......@@ -2046,19 +2047,19 @@ static void resolve_union_type(CodeGen *g, TypeTableEntry *union_type) {
20462047 union_type->data.unionation.gen_tag_index);
20472048
20482049 ZigLLVMDIType *union_member_di_type = ZigLLVMCreateDebugMemberType(g->dbuilder,
2049 ZigLLVMTypeToScope(union_type->di_type), "union_field",
2050 ZigLLVMTypeToScope(union_type->di_type), "payload",
20502051 import->di_file, (unsigned)(decl_node->line + 1),
20512052 biggest_size_in_bits,
20522053 biggest_align_in_bits,
20532054 union_offset_in_bits,
20542055 0, union_di_type);
20552056 ZigLLVMDIType *tag_member_di_type = ZigLLVMCreateDebugMemberType(g->dbuilder,
2056 ZigLLVMTypeToScope(union_type->di_type), "tag_field",
2057 ZigLLVMTypeToScope(union_type->di_type), "tag",
20572058 import->di_file, (unsigned)(decl_node->line + 1),
20582059 tag_debug_size_in_bits,
20592060 tag_debug_align_in_bits,
20602061 tag_offset_in_bits,
2061 0, tag_di_type);
2062 0, tag_type->di_type);
20622063
20632064 ZigLLVMDIType *di_root_members[2];
20642065 di_root_members[union_type->data.unionation.gen_tag_index] = tag_member_di_type;
......@@ -2104,7 +2105,6 @@ static void resolve_enum_zero_bits(CodeGen *g, TypeTableEntry *enum_type) {
21042105 enum_type->data.enumeration.fields = nullptr;
21052106 enum_type->data.enumeration.is_invalid = true;
21062107 enum_type->data.enumeration.zero_bits_loop_flag = false;
2107 enum_type->data.enumeration.gen_field_count = 0;
21082108 enum_type->data.enumeration.zero_bits_known = true;
21092109 return;
21102110 }
......@@ -2112,8 +2112,6 @@ static void resolve_enum_zero_bits(CodeGen *g, TypeTableEntry *enum_type) {
21122112 enum_type->data.enumeration.src_field_count = field_count;
21132113 enum_type->data.enumeration.fields = allocate<TypeEnumField>(field_count);
21142114
2115 uint32_t biggest_align_bytes = 0;
2116
21172115 Scope *scope = &enum_type->data.enumeration.decls_scope->base;
21182116
21192117 HashMap<BigInt, AstNode *, bigint_hash, bigint_eql> occupied_tag_values = {};
......@@ -2143,14 +2141,20 @@ static void resolve_enum_zero_bits(CodeGen *g, TypeTableEntry *enum_type) {
21432141 }
21442142 }
21452143 enum_type->data.enumeration.tag_int_type = tag_int_type;
2144 enum_type->type_ref = tag_int_type->type_ref;
21462145
2147 uint32_t gen_field_index = 0;
21482146 for (uint32_t field_i = 0; field_i < field_count; field_i += 1) {
21492147 AstNode *field_node = decl_node->data.container_decl.fields.at(field_i);
21502148 TypeEnumField *type_enum_field = &enum_type->data.enumeration.fields[field_i];
21512149 type_enum_field->name = field_node->data.struct_field.name;
2152 TypeTableEntry *field_type = analyze_type_expr(g, scope, field_node->data.struct_field.type);
2153 type_enum_field->type_entry = field_type;
2150 type_enum_field->decl_index = field_i;
2151
2152 if (field_node->data.struct_field.type != nullptr) {
2153 ErrorMsg *msg = add_node_error(g, field_node->data.struct_field.type,
2154 buf_sprintf("structs and unions, not enums, support field types"));
2155 add_error_note(g, msg, decl_node,
2156 buf_sprintf("consider 'union(enum)' here"));
2157 }
21542158
21552159 AstNode *tag_value = field_node->data.struct_field.value;
21562160
......@@ -2179,23 +2183,6 @@ static void resolve_enum_zero_bits(CodeGen *g, TypeTableEntry *enum_type) {
21792183 continue;
21802184 }
21812185 }
2182
2183 type_ensure_zero_bits_known(g, field_type);
2184 if (type_is_invalid(field_type)) {
2185 enum_type->data.enumeration.is_invalid = true;
2186 continue;
2187 }
2188
2189 if (!type_has_bits(field_type))
2190 continue;
2191
2192 type_enum_field->gen_index = gen_field_index;
2193 gen_field_index += 1;
2194
2195 uint32_t field_align_bytes = get_abi_alignment(g, field_type);
2196 if (field_align_bytes > biggest_align_bytes) {
2197 biggest_align_bytes = field_align_bytes;
2198 }
21992186 }
22002187
22012188 // Now iterate again and populate the unspecified tag values
......@@ -2227,15 +2214,8 @@ static void resolve_enum_zero_bits(CodeGen *g, TypeTableEntry *enum_type) {
22272214 }
22282215
22292216 enum_type->data.enumeration.zero_bits_loop_flag = false;
2230 enum_type->data.enumeration.gen_field_count = gen_field_index;
2231 enum_type->zero_bits = (gen_field_index == 0 && field_count < 2);
2217 enum_type->zero_bits = (field_count < 2);
22322218 enum_type->data.enumeration.zero_bits_known = true;
2233
2234 // also compute abi_alignment
2235 if (!enum_type->zero_bits) {
2236 uint32_t align_of_tag_in_bytes = LLVMABIAlignmentOfType(g->target_data_ref, tag_int_type->type_ref);
2237 enum_type->data.enumeration.abi_alignment = max(align_of_tag_in_bytes, biggest_align_bytes);
2238 }
22392219}
22402220
22412221static void resolve_struct_zero_bits(CodeGen *g, TypeTableEntry *struct_type) {
......@@ -2279,6 +2259,13 @@ static void resolve_struct_zero_bits(CodeGen *g, TypeTableEntry *struct_type) {
22792259 AstNode *field_node = decl_node->data.container_decl.fields.at(i);
22802260 TypeStructField *type_struct_field = &struct_type->data.structure.fields[i];
22812261 type_struct_field->name = field_node->data.struct_field.name;
2262
2263 if (field_node->data.struct_field.type == nullptr) {
2264 add_node_error(g, field_node, buf_sprintf("struct field missing type"));
2265 struct_type->data.structure.is_invalid = true;
2266 continue;
2267 }
2268
22822269 TypeTableEntry *field_type = analyze_type_expr(g, scope, field_node->data.struct_field.type);
22832270 type_struct_field->type_entry = field_type;
22842271 type_struct_field->src_index = i;
......@@ -2338,6 +2325,16 @@ static void resolve_union_zero_bits(CodeGen *g, TypeTableEntry *union_type) {
23382325
23392326 assert(!union_type->data.unionation.fields);
23402327 uint32_t field_count = (uint32_t)decl_node->data.container_decl.fields.length;
2328 if (field_count == 0) {
2329 add_node_error(g, decl_node, buf_sprintf("unions must have 1 or more fields"));
2330
2331 union_type->data.unionation.src_field_count = field_count;
2332 union_type->data.unionation.fields = nullptr;
2333 union_type->data.unionation.is_invalid = true;
2334 union_type->data.unionation.zero_bits_loop_flag = false;
2335 union_type->data.unionation.zero_bits_known = true;
2336 return;
2337 }
23412338 union_type->data.unionation.src_field_count = field_count;
23422339 union_type->data.unionation.fields = allocate<TypeUnionField>(field_count);
23432340
......@@ -2348,17 +2345,23 @@ static void resolve_union_zero_bits(CodeGen *g, TypeTableEntry *union_type) {
23482345 uint32_t gen_field_index = 0;
23492346 for (uint32_t i = 0; i < field_count; i += 1) {
23502347 AstNode *field_node = decl_node->data.container_decl.fields.at(i);
2351 TypeUnionField *type_union_field = &union_type->data.unionation.fields[i];
2352 type_union_field->name = field_node->data.struct_field.name;
2353 TypeTableEntry *field_type = analyze_type_expr(g, scope, field_node->data.struct_field.type);
2354 type_union_field->type_entry = field_type;
2348 TypeUnionField *union_field = &union_type->data.unionation.fields[i];
2349 union_field->name = field_node->data.struct_field.name;
23552350
2356 // TODO look for enum arg to union
2357 bigint_init_unsigned(&type_union_field->value, i);
2351 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;
2355 }
23582356
2359 if (field_node->data.struct_field.value != nullptr) {
2360 add_node_error(g, field_node->data.struct_field.value,
2361 buf_sprintf("enums, not unions, support field assignment"));
2357 TypeTableEntry *field_type = analyze_type_expr(g, scope, field_node->data.struct_field.type);
2358 union_field->type_entry = field_type;
2359
2360 if (field_node->data.struct_field.value != nullptr && !decl_node->data.container_decl.auto_enum) {
2361 ErrorMsg *msg = add_node_error(g, field_node->data.struct_field.value,
2362 buf_sprintf("non-enum union field assignment"));
2363 add_error_note(g, msg, decl_node,
2364 buf_sprintf("consider 'union(enum)' here"));
23622365 }
23632366
23642367 type_ensure_zero_bits_known(g, field_type);
......@@ -2370,7 +2373,7 @@ static void resolve_union_zero_bits(CodeGen *g, TypeTableEntry *union_type) {
23702373 if (!type_has_bits(field_type))
23712374 continue;
23722375
2373 type_union_field->gen_index = gen_field_index;
2376 union_field->gen_index = gen_field_index;
23742377 gen_field_index += 1;
23752378
23762379 uint32_t field_align_bytes = get_abi_alignment(g, field_type);
......@@ -2379,11 +2382,32 @@ static void resolve_union_zero_bits(CodeGen *g, TypeTableEntry *union_type) {
23792382 }
23802383 }
23812384
2382 bool auto_layout = (union_type->data.unionation.layout == ContainerLayoutAuto);
2385 bool src_have_tag = decl_node->data.container_decl.auto_enum ||
2386 decl_node->data.container_decl.init_arg_expr != nullptr;
2387
2388 if (src_have_tag && union_type->data.unionation.layout != ContainerLayoutAuto) {
2389 const char *qual_str;
2390 switch (union_type->data.unionation.layout) {
2391 case ContainerLayoutAuto:
2392 zig_unreachable();
2393 case ContainerLayoutPacked:
2394 qual_str = "packed";
2395 break;
2396 case ContainerLayoutExtern:
2397 qual_str = "extern";
2398 break;
2399 }
2400 AstNode *source_node = (decl_node->data.container_decl.init_arg_expr != nullptr) ?
2401 decl_node->data.container_decl.init_arg_expr : decl_node;
2402 add_node_error(g, source_node,
2403 buf_sprintf("%s union does not support enum tag type", qual_str));
2404 union_type->data.unionation.is_invalid = true;
2405 return;
2406 }
23832407
23842408 union_type->data.unionation.zero_bits_loop_flag = false;
23852409 union_type->data.unionation.gen_field_count = gen_field_index;
2386 union_type->zero_bits = (gen_field_index == 0 && (field_count < 2 || !auto_layout));
2410 union_type->zero_bits = (gen_field_index == 0 && (field_count < 2 || !src_have_tag));
23872411 union_type->data.unionation.zero_bits_known = true;
23882412
23892413 // also compute abi_alignment
......@@ -2848,7 +2872,6 @@ TypeTableEntry *validate_var_type(CodeGen *g, AstNode *source_node, TypeTableEnt
28482872 case TypeTableEntryIdUnion:
28492873 case TypeTableEntryIdFn:
28502874 case TypeTableEntryIdBoundFn:
2851 case TypeTableEntryIdEnumTag:
28522875 return type_entry;
28532876 }
28542877 zig_unreachable();
......@@ -3265,19 +3288,20 @@ TypeUnionField *find_union_type_field(TypeTableEntry *type_entry, Buf *name) {
32653288 assert(type_entry->data.unionation.complete);
32663289 for (uint32_t i = 0; i < type_entry->data.unionation.src_field_count; i += 1) {
32673290 TypeUnionField *field = &type_entry->data.unionation.fields[i];
3268 if (buf_eql_buf(field->name, name)) {
3291 if (buf_eql_buf(field->enum_field->name, name)) {
32693292 return field;
32703293 }
32713294 }
32723295 return nullptr;
32733296}
32743297
3275static TypeUnionField *find_union_field_by_tag(TypeTableEntry *type_entry, const BigInt *tag) {
3298TypeUnionField *find_union_field_by_tag(TypeTableEntry *type_entry, const BigInt *tag) {
32763299 assert(type_entry->id == TypeTableEntryIdUnion);
32773300 assert(type_entry->data.unionation.complete);
3301 assert(type_entry->data.unionation.gen_tag_index != SIZE_MAX);
32783302 for (uint32_t i = 0; i < type_entry->data.unionation.src_field_count; i += 1) {
32793303 TypeUnionField *field = &type_entry->data.unionation.fields[i];
3280 if (bigint_cmp(&field->value, tag) == CmpEQ) {
3304 if (bigint_cmp(&field->enum_field->value, tag) == CmpEQ) {
32813305 return field;
32823306 }
32833307 }
......@@ -3323,7 +3347,6 @@ static bool is_container(TypeTableEntry *type_entry) {
33233347 case TypeTableEntryIdNamespace:
33243348 case TypeTableEntryIdBlock:
33253349 case TypeTableEntryIdBoundFn:
3326 case TypeTableEntryIdEnumTag:
33273350 case TypeTableEntryIdArgTuple:
33283351 case TypeTableEntryIdOpaque:
33293352 return false;
......@@ -3374,7 +3397,6 @@ void resolve_container_type(CodeGen *g, TypeTableEntry *type_entry) {
33743397 case TypeTableEntryIdBoundFn:
33753398 case TypeTableEntryIdInvalid:
33763399 case TypeTableEntryIdVar:
3377 case TypeTableEntryIdEnumTag:
33783400 case TypeTableEntryIdArgTuple:
33793401 case TypeTableEntryIdOpaque:
33803402 zig_unreachable();
......@@ -3828,7 +3850,7 @@ bool handle_is_ptr(TypeTableEntry *type_entry) {
38283850 case TypeTableEntryIdPointer:
38293851 case TypeTableEntryIdPureError:
38303852 case TypeTableEntryIdFn:
3831 case TypeTableEntryIdEnumTag:
3853 case TypeTableEntryIdEnum:
38323854 return false;
38333855 case TypeTableEntryIdArray:
38343856 case TypeTableEntryIdStruct:
......@@ -3836,9 +3858,6 @@ bool handle_is_ptr(TypeTableEntry *type_entry) {
38363858 return type_has_bits(type_entry);
38373859 case TypeTableEntryIdErrorUnion:
38383860 return type_has_bits(type_entry->data.error.child_type);
3839 case TypeTableEntryIdEnum:
3840 assert(type_entry->data.enumeration.complete);
3841 return type_entry->data.enumeration.gen_field_count != 0;
38423861 case TypeTableEntryIdMaybe:
38433862 return type_has_bits(type_entry->data.maybe.child_type) &&
38443863 type_entry->data.maybe.child_type->id != TypeTableEntryIdPointer &&
......@@ -3980,7 +3999,6 @@ static uint32_t hash_const_val(ConstExprValue *const_val) {
39803999 return (uint32_t)4149439618;
39814000 case TypeTableEntryIdInt:
39824001 case TypeTableEntryIdNumLitInt:
3983 case TypeTableEntryIdEnumTag:
39844002 {
39854003 uint32_t result = 1331471175;
39864004 for (size_t i = 0; i < const_val->data.x_bigint.digit_count; i += 1) {
......@@ -3989,6 +4007,15 @@ static uint32_t hash_const_val(ConstExprValue *const_val) {
39894007 }
39904008 return result;
39914009 }
4010 case TypeTableEntryIdEnum:
4011 {
4012 uint32_t result = 31643936;
4013 for (size_t i = 0; i < const_val->data.x_enum_tag.digit_count; i += 1) {
4014 uint64_t digit = bigint_ptr(&const_val->data.x_enum_tag)[i];
4015 result ^= ((uint32_t)(digit >> 32)) ^ (uint32_t)(result);
4016 }
4017 return result;
4018 }
39924019 case TypeTableEntryIdFloat:
39934020 switch (const_val->type->data.floating.bit_count) {
39944021 case 32:
......@@ -4089,9 +4116,6 @@ static uint32_t hash_const_val(ConstExprValue *const_val) {
40894116 case TypeTableEntryIdPureError:
40904117 // TODO better hashing algorithm
40914118 return 2630160122;
4092 case TypeTableEntryIdEnum:
4093 // TODO better hashing algorithm
4094 return 31643936;
40954119 case TypeTableEntryIdFn:
40964120 return 4133894920 ^ hash_ptr(const_val->data.x_fn.fn_entry);
40974121 case TypeTableEntryIdNamespace:
......@@ -4224,7 +4248,6 @@ bool type_requires_comptime(TypeTableEntry *type_entry) {
42244248 case TypeTableEntryIdInt:
42254249 case TypeTableEntryIdFloat:
42264250 case TypeTableEntryIdPointer:
4227 case TypeTableEntryIdEnumTag:
42284251 case TypeTableEntryIdVoid:
42294252 case TypeTableEntryIdUnreachable:
42304253 return false;
......@@ -4295,6 +4318,7 @@ ConstExprValue *create_const_bigint(TypeTableEntry *type, const BigInt *bigint)
42954318 return const_val;
42964319}
42974320
4321
42984322void init_const_unsigned_negative(ConstExprValue *const_val, TypeTableEntry *type, uint64_t x, bool negative) {
42994323 const_val->special = ConstValSpecialStatic;
43004324 const_val->type = type;
......@@ -4358,18 +4382,19 @@ ConstExprValue *create_const_float(TypeTableEntry *type, double value) {
43584382 return const_val;
43594383}
43604384
4361void init_const_enum_tag(ConstExprValue *const_val, TypeTableEntry *type, const BigInt *tag) {
4385void init_const_enum(ConstExprValue *const_val, TypeTableEntry *type, const BigInt *tag) {
43624386 const_val->special = ConstValSpecialStatic;
43634387 const_val->type = type;
4364 bigint_init_bigint(&const_val->data.x_enum.tag, tag);
4388 bigint_init_bigint(&const_val->data.x_enum_tag, tag);
43654389}
43664390
4367ConstExprValue *create_const_enum_tag(TypeTableEntry *type, const BigInt *tag) {
4391ConstExprValue *create_const_enum(TypeTableEntry *type, const BigInt *tag) {
43684392 ConstExprValue *const_val = create_const_vals(1);
4369 init_const_enum_tag(const_val, type, tag);
4393 init_const_enum(const_val, type, tag);
43704394 return const_val;
43714395}
43724396
4397
43734398void init_const_bool(CodeGen *g, ConstExprValue *const_val, bool value) {
43744399 const_val->special = ConstValSpecialStatic;
43754400 const_val->type = g->builtin_types.entry_bool;
......@@ -4567,20 +4592,8 @@ bool const_values_equal(ConstExprValue *a, ConstExprValue *b) {
45674592 switch (a->type->id) {
45684593 case TypeTableEntryIdOpaque:
45694594 zig_unreachable();
4570 case TypeTableEntryIdEnum: {
4571 ConstEnumValue *enum1 = &a->data.x_enum;
4572 ConstEnumValue *enum2 = &b->data.x_enum;
4573 if (bigint_cmp(&enum1->tag, &enum2->tag) == CmpEQ) {
4574 TypeEnumField *field = find_enum_field_by_tag(a->type, &enum1->tag);
4575 assert(field != nullptr);
4576 if (type_has_bits(field->type_entry)) {
4577 zig_panic("TODO const expr analyze enum field value for equality");
4578 } else {
4579 return true;
4580 }
4581 }
4582 return false;
4583 }
4595 case TypeTableEntryIdEnum:
4596 return bigint_cmp(&a->data.x_enum_tag, &b->data.x_enum_tag) == CmpEQ;
45844597 case TypeTableEntryIdUnion: {
45854598 ConstUnionValue *union1 = &a->data.x_union;
45864599 ConstUnionValue *union2 = &b->data.x_union;
......@@ -4622,7 +4635,6 @@ bool const_values_equal(ConstExprValue *a, ConstExprValue *b) {
46224635 return bigfloat_cmp(&a->data.x_bigfloat, &b->data.x_bigfloat) == CmpEQ;
46234636 case TypeTableEntryIdInt:
46244637 case TypeTableEntryIdNumLitInt:
4625 case TypeTableEntryIdEnumTag:
46264638 return bigint_cmp(&a->data.x_bigint, &b->data.x_bigint) == CmpEQ;
46274639 case TypeTableEntryIdPointer:
46284640 if (a->data.x_ptr.special != b->data.x_ptr.special)
......@@ -4949,7 +4961,8 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) {
49494961 }
49504962 case TypeTableEntryIdEnum:
49514963 {
4952 buf_appendf(buf, "(enum %s constant)", buf_ptr(&type_entry->name));
4964 TypeEnumField *field = find_enum_field_by_tag(type_entry, &const_val->data.x_enum_tag);
4965 buf_appendf(buf, "%s.%s", buf_ptr(&type_entry->name), buf_ptr(field->name));
49534966 return;
49544967 }
49554968 case TypeTableEntryIdErrorUnion:
......@@ -4967,14 +4980,6 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) {
49674980 buf_appendf(buf, "(pure error constant)");
49684981 return;
49694982 }
4970 case TypeTableEntryIdEnumTag:
4971 {
4972 TypeTableEntry *enum_type = type_entry->data.enum_tag.enum_type;
4973 size_t field_index = bigint_as_unsigned(&const_val->data.x_bigint);
4974 TypeEnumField *field = &enum_type->data.enumeration.fields[field_index];
4975 buf_appendf(buf, "%s.%s", buf_ptr(&enum_type->name), buf_ptr(field->name));
4976 return;
4977 }
49784983 case TypeTableEntryIdArgTuple:
49794984 {
49804985 buf_appendf(buf, "(args value)");
......@@ -5036,7 +5041,6 @@ uint32_t type_id_hash(TypeId x) {
50365041 case TypeTableEntryIdErrorUnion:
50375042 case TypeTableEntryIdPureError:
50385043 case TypeTableEntryIdEnum:
5039 case TypeTableEntryIdEnumTag:
50405044 case TypeTableEntryIdUnion:
50415045 case TypeTableEntryIdFn:
50425046 case TypeTableEntryIdNamespace:
......@@ -5081,7 +5085,6 @@ bool type_id_eql(TypeId a, TypeId b) {
50815085 case TypeTableEntryIdErrorUnion:
50825086 case TypeTableEntryIdPureError:
50835087 case TypeTableEntryIdEnum:
5084 case TypeTableEntryIdEnumTag:
50855088 case TypeTableEntryIdUnion:
50865089 case TypeTableEntryIdFn:
50875090 case TypeTableEntryIdNamespace:
......@@ -5196,7 +5199,6 @@ static const TypeTableEntryId all_type_ids[] = {
51965199 TypeTableEntryIdErrorUnion,
51975200 TypeTableEntryIdPureError,
51985201 TypeTableEntryIdEnum,
5199 TypeTableEntryIdEnumTag,
52005202 TypeTableEntryIdUnion,
52015203 TypeTableEntryIdFn,
52025204 TypeTableEntryIdNamespace,
......@@ -5254,22 +5256,20 @@ size_t type_id_index(TypeTableEntryId id) {
52545256 return 15;
52555257 case TypeTableEntryIdEnum:
52565258 return 16;
5257 case TypeTableEntryIdEnumTag:
5258 return 17;
52595259 case TypeTableEntryIdUnion:
5260 return 18;
5260 return 17;
52615261 case TypeTableEntryIdFn:
5262 return 19;
5262 return 18;
52635263 case TypeTableEntryIdNamespace:
5264 return 20;
5264 return 19;
52655265 case TypeTableEntryIdBlock:
5266 return 21;
5266 return 20;
52675267 case TypeTableEntryIdBoundFn:
5268 return 22;
5268 return 21;
52695269 case TypeTableEntryIdArgTuple:
5270 return 23;
5270 return 22;
52715271 case TypeTableEntryIdOpaque:
5272 return 24;
5272 return 23;
52735273 }
52745274 zig_unreachable();
52755275}
......@@ -5313,8 +5313,6 @@ const char *type_id_name(TypeTableEntryId id) {
53135313 return "Error";
53145314 case TypeTableEntryIdEnum:
53155315 return "Enum";
5316 case TypeTableEntryIdEnumTag:
5317 return "EnumTag";
53185316 case TypeTableEntryIdUnion:
53195317 return "Union";
53205318 case TypeTableEntryIdFn:
......@@ -5381,9 +5379,6 @@ uint32_t get_abi_alignment(CodeGen *g, TypeTableEntry *type_entry) {
53815379 if (type_entry->id == TypeTableEntryIdStruct) {
53825380 assert(type_entry->data.structure.abi_alignment != 0);
53835381 return type_entry->data.structure.abi_alignment;
5384 } else if (type_entry->id == TypeTableEntryIdEnum) {
5385 assert(type_entry->data.enumeration.abi_alignment != 0);
5386 return type_entry->data.enumeration.abi_alignment;
53875382 } else if (type_entry->id == TypeTableEntryIdUnion) {
53885383 assert(type_entry->data.unionation.abi_alignment != 0);
53895384 return type_entry->data.unionation.abi_alignment;
src/analyze.hpp+3-3
......@@ -65,6 +65,7 @@ ScopeDecls *get_container_scope(TypeTableEntry *type_entry);
6565TypeEnumField *find_enum_type_field(TypeTableEntry *enum_type, Buf *name);
6666TypeUnionField *find_union_type_field(TypeTableEntry *type_entry, Buf *name);
6767TypeEnumField *find_enum_field_by_tag(TypeTableEntry *enum_type, const BigInt *tag);
68TypeUnionField *find_union_field_by_tag(TypeTableEntry *type_entry, const BigInt *tag);
6869
6970bool is_container_ref(TypeTableEntry *type_entry);
7071void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node);
......@@ -126,8 +127,8 @@ ConstExprValue *create_const_usize(CodeGen *g, uint64_t x);
126127void init_const_float(ConstExprValue *const_val, TypeTableEntry *type, double value);
127128ConstExprValue *create_const_float(TypeTableEntry *type, double value);
128129
129void init_const_enum_tag(ConstExprValue *const_val, TypeTableEntry *type, const BigInt *tag);
130ConstExprValue *create_const_enum_tag(TypeTableEntry *type, const BigInt *tag);
130void init_const_enum(ConstExprValue *const_val, TypeTableEntry *type, const BigInt *tag);
131ConstExprValue *create_const_enum(TypeTableEntry *type, const BigInt *tag);
131132
132133void init_const_bool(CodeGen *g, ConstExprValue *const_val, bool value);
133134ConstExprValue *create_const_bool(CodeGen *g, bool value);
......@@ -163,7 +164,6 @@ ConstExprValue *create_const_vals(size_t count);
163164
164165TypeTableEntry *make_int_type(CodeGen *g, bool is_signed, uint32_t size_in_bits);
165166ConstParent *get_const_val_parent(CodeGen *g, ConstExprValue *value);
166TypeTableEntry *create_enum_tag_type(CodeGen *g, TypeTableEntry *enum_type, TypeTableEntry *int_type);
167167void expand_undef_array(CodeGen *g, ConstExprValue *const_val);
168168void update_compile_var(CodeGen *g, Buf *name, ConstExprValue *value);
169169
src/ast_render.cpp+7
......@@ -661,11 +661,18 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {
661661 const char *layout_str = layout_string(node->data.container_decl.layout);
662662 const char *container_str = container_string(node->data.container_decl.kind);
663663 fprintf(ar->f, "%s%s", layout_str, container_str);
664 if (node->data.container_decl.auto_enum) {
665 fprintf(ar->f, "(enum");
666 }
664667 if (node->data.container_decl.init_arg_expr != nullptr) {
665668 fprintf(ar->f, "(");
666669 render_node_grouped(ar, node->data.container_decl.init_arg_expr);
667670 fprintf(ar->f, ")");
668671 }
672 if (node->data.container_decl.auto_enum) {
673 fprintf(ar->f, ")");
674 }
675
669676 fprintf(ar->f, " {\n");
670677 ar->indent += ar->indent_size;
671678 for (size_t field_i = 0; field_i < node->data.container_decl.fields.length; field_i += 1) {
src/codegen.cpp+68-171
......@@ -1631,12 +1631,8 @@ static LLVMValueRef ir_render_bin_op(CodeGen *g, IrExecutable *executable,
16311631 LLVMIntPredicate pred = cmp_op_to_int_predicate(op_id, type_entry->data.integral.is_signed);
16321632 return LLVMBuildICmp(g->builder, pred, op1_value, op2_value, "");
16331633 } else if (type_entry->id == TypeTableEntryIdEnum) {
1634 if (type_entry->data.enumeration.gen_field_count == 0) {
1635 LLVMIntPredicate pred = cmp_op_to_int_predicate(op_id, false);
1636 return LLVMBuildICmp(g->builder, pred, op1_value, op2_value, "");
1637 } else {
1638 zig_unreachable();
1639 }
1634 LLVMIntPredicate pred = cmp_op_to_int_predicate(op_id, false);
1635 return LLVMBuildICmp(g->builder, pred, op1_value, op2_value, "");
16401636 } else if (type_entry->id == TypeTableEntryIdPureError ||
16411637 type_entry->id == TypeTableEntryIdPointer ||
16421638 type_entry->id == TypeTableEntryIdBool)
......@@ -1920,9 +1916,7 @@ static LLVMValueRef ir_render_widen_or_shorten(CodeGen *g, IrExecutable *executa
19201916 // enum_tag to the underlying int type
19211917 TypeTableEntry *int_type;
19221918 if (actual_type->id == TypeTableEntryIdEnum) {
1923 TypeTableEntry *tag_type = actual_type->data.enumeration.tag_type;
1924 assert(tag_type->id == TypeTableEntryIdEnumTag);
1925 int_type = tag_type->data.enum_tag.int_type;
1919 int_type = actual_type->data.enumeration.tag_int_type;
19261920 } else {
19271921 int_type = actual_type;
19281922 }
......@@ -1946,19 +1940,11 @@ static LLVMValueRef ir_render_ptr_to_int(CodeGen *g, IrExecutable *executable, I
19461940static LLVMValueRef ir_render_int_to_enum(CodeGen *g, IrExecutable *executable, IrInstructionIntToEnum *instruction) {
19471941 TypeTableEntry *wanted_type = instruction->base.value.type;
19481942 assert(wanted_type->id == TypeTableEntryIdEnum);
1949 TypeTableEntry *tag_type = wanted_type->data.enumeration.tag_type;
1950 TypeTableEntry *wanted_int_type;
1951 if (tag_type->id == TypeTableEntryIdEnumTag) {
1952 wanted_int_type = tag_type->data.enum_tag.int_type;
1953 } else if (tag_type->id == TypeTableEntryIdInt) {
1954 wanted_int_type = tag_type;
1955 } else {
1956 zig_unreachable();
1957 }
1943 TypeTableEntry *tag_int_type = wanted_type->data.enumeration.tag_int_type;
19581944
19591945 LLVMValueRef target_val = ir_llvm_value(g, instruction->target);
19601946 return gen_widen_or_shorten(g, ir_want_debug_safety(g, &instruction->base),
1961 instruction->target->value.type, wanted_int_type, target_val);
1947 instruction->target->value.type, tag_int_type, target_val);
19621948}
19631949
19641950static LLVMValueRef ir_render_int_to_err(CodeGen *g, IrExecutable *executable, IrInstructionIntToErr *instruction) {
......@@ -2378,27 +2364,6 @@ static LLVMValueRef ir_render_struct_field_ptr(CodeGen *g, IrExecutable *executa
23782364 return LLVMBuildStructGEP(g->builder, struct_ptr, (unsigned)field->gen_index, "");
23792365}
23802366
2381static LLVMValueRef ir_render_enum_field_ptr(CodeGen *g, IrExecutable *executable,
2382 IrInstructionEnumFieldPtr *instruction)
2383{
2384 TypeTableEntry *enum_ptr_type = instruction->enum_ptr->value.type;
2385 assert(enum_ptr_type->id == TypeTableEntryIdPointer);
2386 TypeTableEntry *enum_type = enum_ptr_type->data.pointer.child_type;
2387 assert(enum_type->id == TypeTableEntryIdEnum);
2388
2389 TypeEnumField *field = instruction->field;
2390
2391 if (!type_has_bits(field->type_entry))
2392 return nullptr;
2393
2394 LLVMValueRef enum_ptr = ir_llvm_value(g, instruction->enum_ptr);
2395 LLVMTypeRef field_type_ref = LLVMPointerType(field->type_entry->type_ref, 0);
2396 LLVMValueRef union_field_ptr = LLVMBuildStructGEP(g->builder, enum_ptr, enum_type->data.enumeration.gen_union_index, "");
2397 LLVMValueRef bitcasted_union_field_ptr = LLVMBuildBitCast(g->builder, union_field_ptr, field_type_ref, "");
2398
2399 return bitcasted_union_field_ptr;
2400}
2401
24022367static LLVMValueRef ir_render_union_field_ptr(CodeGen *g, IrExecutable *executable,
24032368 IrInstructionUnionFieldPtr *instruction)
24042369{
......@@ -2427,7 +2392,7 @@ static LLVMValueRef ir_render_union_field_ptr(CodeGen *g, IrExecutable *executab
24272392
24282393
24292394 LLVMValueRef expected_tag_value = bigint_to_llvm_const(union_type->data.unionation.tag_type->type_ref,
2430 &field->value);
2395 &field->enum_field->value);
24312396 LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn_val, "UnionCheckOk");
24322397 LLVMBasicBlockRef bad_block = LLVMAppendBasicBlock(g->cur_fn_val, "UnionCheckFail");
24332398 LLVMValueRef ok_val = LLVMBuildICmp(g->builder, LLVMIntEQ, tag_value, expected_tag_value, "");
......@@ -2754,19 +2719,19 @@ static LLVMValueRef ir_render_err_name(CodeGen *g, IrExecutable *executable, IrI
27542719static LLVMValueRef ir_render_enum_tag_name(CodeGen *g, IrExecutable *executable,
27552720 IrInstructionEnumTagName *instruction)
27562721{
2757 TypeTableEntry *enum_tag_type = instruction->target->value.type;
2758 assert(enum_tag_type->data.enum_tag.generate_name_table);
2722 TypeTableEntry *enum_type = instruction->target->value.type;
2723 assert(enum_type->id == TypeTableEntryIdEnum);
2724 assert(enum_type->data.enumeration.generate_name_table);
27592725
2726 TypeTableEntry *tag_int_type = enum_type->data.enumeration.tag_int_type;
27602727 LLVMValueRef enum_tag_value = ir_llvm_value(g, instruction->target);
27612728 if (ir_want_debug_safety(g, &instruction->base)) {
2762 TypeTableEntry *enum_type = enum_tag_type->data.enum_tag.enum_type;
27632729 size_t field_count = enum_type->data.enumeration.src_field_count;
27642730
2765 // if the field_count can't fit in the bits of the enum_tag_type, then it can't possibly
2731 // if the field_count can't fit in the bits of the enum_type, then it can't possibly
27662732 // be the wrong value
27672733 BigInt field_bi;
27682734 bigint_init_unsigned(&field_bi, field_count);
2769 TypeTableEntry *tag_int_type = enum_tag_type->data.enum_tag.int_type;
27702735 if (bigint_fits_in_bits(&field_bi, tag_int_type->data.integral.bit_count, false)) {
27712736 LLVMValueRef end_val = LLVMConstInt(LLVMTypeOf(enum_tag_value), field_count, false);
27722737 add_bounds_check(g, enum_tag_value, LLVMIntEQ, nullptr, LLVMIntULT, end_val);
......@@ -2775,10 +2740,10 @@ static LLVMValueRef ir_render_enum_tag_name(CodeGen *g, IrExecutable *executable
27752740
27762741 LLVMValueRef indices[] = {
27772742 LLVMConstNull(g->builtin_types.entry_usize->type_ref),
2778 gen_widen_or_shorten(g, false, enum_tag_type->data.enum_tag.int_type,
2743 gen_widen_or_shorten(g, false, tag_int_type,
27792744 g->builtin_types.entry_usize, enum_tag_value),
27802745 };
2781 return LLVMBuildInBoundsGEP(g->builder, enum_tag_type->data.enum_tag.name_table, indices, 2, "");
2746 return LLVMBuildInBoundsGEP(g->builder, enum_type->data.enumeration.name_table, indices, 2, "");
27822747}
27832748
27842749static LLVMValueRef ir_render_field_parent_ptr(CodeGen *g, IrExecutable *executable,
......@@ -3352,48 +3317,24 @@ static LLVMValueRef ir_render_err_wrap_payload(CodeGen *g, IrExecutable *executa
33523317 return instruction->tmp_ptr;
33533318}
33543319
3355static LLVMValueRef ir_render_enum_tag(CodeGen *g, IrExecutable *executable, IrInstructionEnumTag *instruction) {
3356 TypeTableEntry *enum_type = instruction->value->value.type;
3357 TypeTableEntry *tag_type = enum_type->data.enumeration.tag_type;
3320static LLVMValueRef ir_render_union_tag(CodeGen *g, IrExecutable *executable, IrInstructionUnionTag *instruction) {
3321 TypeTableEntry *union_type = instruction->value->value.type;
3322 assert(union_type->data.unionation.gen_tag_index != SIZE_MAX);
3323
3324 TypeTableEntry *tag_type = union_type->data.unionation.tag_type;
33583325 if (!type_has_bits(tag_type))
33593326 return nullptr;
33603327
3361 LLVMValueRef enum_val = ir_llvm_value(g, instruction->value);
3362 if (enum_type->data.enumeration.gen_field_count == 0)
3363 return enum_val;
3328 LLVMValueRef union_val = ir_llvm_value(g, instruction->value);
3329 if (union_type->data.unionation.gen_field_count == 0)
3330 return union_val;
33643331
3365 LLVMValueRef tag_field_ptr = LLVMBuildStructGEP(g->builder, enum_val, enum_type->data.enumeration.gen_tag_index, "");
3332 LLVMValueRef tag_field_ptr = LLVMBuildStructGEP(g->builder, union_val,
3333 union_type->data.unionation.gen_tag_index, "");
33663334 TypeTableEntry *ptr_type = get_pointer_to_type(g, tag_type, false);
33673335 return get_handle_value(g, tag_field_ptr, tag_type, ptr_type);
33683336}
33693337
3370static LLVMValueRef ir_render_init_enum(CodeGen *g, IrExecutable *executable, IrInstructionInitEnum *instruction) {
3371 TypeTableEntry *enum_type = instruction->enum_type;
3372 LLVMTypeRef tag_type_ref = enum_type->data.enumeration.tag_type->type_ref;
3373
3374 LLVMValueRef tag_value = bigint_to_llvm_const(tag_type_ref, &instruction->field->value);
3375
3376 if (enum_type->data.enumeration.gen_field_count == 0)
3377 return tag_value;
3378
3379 LLVMValueRef tmp_struct_ptr = instruction->tmp_ptr;
3380
3381 LLVMValueRef tag_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, enum_type->data.enumeration.gen_tag_index, "");
3382 gen_store_untyped(g, tag_value, tag_field_ptr, 0, false);
3383
3384 TypeTableEntry *union_val_type = instruction->field->type_entry;
3385 if (type_has_bits(union_val_type)) {
3386 LLVMValueRef new_union_val = ir_llvm_value(g, instruction->init_value);
3387 LLVMValueRef union_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, enum_type->data.enumeration.gen_union_index, "");
3388 LLVMValueRef bitcasted_union_field_ptr = LLVMBuildBitCast(g->builder, union_field_ptr,
3389 LLVMPointerType(union_val_type->type_ref, 0), "");
3390
3391 gen_assign_raw(g, bitcasted_union_field_ptr, get_pointer_to_type(g, union_val_type, false), new_union_val);
3392 }
3393
3394 return tmp_struct_ptr;
3395}
3396
33973338static LLVMValueRef ir_render_struct_init(CodeGen *g, IrExecutable *executable, IrInstructionStructInit *instruction) {
33983339 for (size_t i = 0; i < instruction->field_count; i += 1) {
33993340 IrInstructionStructInitField *field = &instruction->fields[i];
......@@ -3436,7 +3377,7 @@ static LLVMValueRef ir_render_union_init(CodeGen *g, IrExecutable *executable, I
34363377 union_type->data.unionation.gen_tag_index, "");
34373378
34383379 LLVMValueRef tag_value = bigint_to_llvm_const(union_type->data.unionation.tag_type->type_ref,
3439 &type_union_field->value);
3380 &type_union_field->enum_field->value);
34403381 gen_store_untyped(g, tag_value, tag_field_ptr, 0, false);
34413382
34423383 uncasted_union_ptr = LLVMBuildStructGEP(g->builder, instruction->tmp_ptr,
......@@ -3573,8 +3514,6 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
35733514 return ir_render_call(g, executable, (IrInstructionCall *)instruction);
35743515 case IrInstructionIdStructFieldPtr:
35753516 return ir_render_struct_field_ptr(g, executable, (IrInstructionStructFieldPtr *)instruction);
3576 case IrInstructionIdEnumFieldPtr:
3577 return ir_render_enum_field_ptr(g, executable, (IrInstructionEnumFieldPtr *)instruction);
35783517 case IrInstructionIdUnionFieldPtr:
35793518 return ir_render_union_field_ptr(g, executable, (IrInstructionUnionFieldPtr *)instruction);
35803519 case IrInstructionIdAsm:
......@@ -3629,10 +3568,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
36293568 return ir_render_err_wrap_code(g, executable, (IrInstructionErrWrapCode *)instruction);
36303569 case IrInstructionIdErrWrapPayload:
36313570 return ir_render_err_wrap_payload(g, executable, (IrInstructionErrWrapPayload *)instruction);
3632 case IrInstructionIdEnumTag:
3633 return ir_render_enum_tag(g, executable, (IrInstructionEnumTag *)instruction);
3634 case IrInstructionIdInitEnum:
3635 return ir_render_init_enum(g, executable, (IrInstructionInitEnum *)instruction);
3571 case IrInstructionIdUnionTag:
3572 return ir_render_union_tag(g, executable, (IrInstructionUnionTag *)instruction);
36363573 case IrInstructionIdStructInit:
36373574 return ir_render_struct_init(g, executable, (IrInstructionStructInit *)instruction);
36383575 case IrInstructionIdUnionInit:
......@@ -3768,7 +3705,6 @@ static LLVMValueRef pack_const_int(CodeGen *g, LLVMTypeRef big_int_type_ref, Con
37683705 case TypeTableEntryIdNullLit:
37693706 case TypeTableEntryIdErrorUnion:
37703707 case TypeTableEntryIdPureError:
3771 case TypeTableEntryIdEnumTag:
37723708 case TypeTableEntryIdNamespace:
37733709 case TypeTableEntryIdBlock:
37743710 case TypeTableEntryIdBoundFn:
......@@ -3780,7 +3716,6 @@ static LLVMValueRef pack_const_int(CodeGen *g, LLVMTypeRef big_int_type_ref, Con
37803716 return LLVMConstInt(big_int_type_ref, const_val->data.x_bool ? 1 : 0, false);
37813717 case TypeTableEntryIdEnum:
37823718 {
3783 assert(type_entry->data.enumeration.gen_field_count == 0);
37843719 assert(type_entry->data.enumeration.decl_node->data.container_decl.init_arg_expr != nullptr);
37853720 LLVMValueRef int_val = gen_const_val(g, const_val);
37863721 return LLVMConstZExt(int_val, big_int_type_ref);
......@@ -3852,7 +3787,6 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val) {
38523787
38533788 switch (type_entry->id) {
38543789 case TypeTableEntryIdInt:
3855 case TypeTableEntryIdEnumTag:
38563790 return bigint_to_llvm_const(type_entry->type_ref, &const_val->data.x_bigint);
38573791 case TypeTableEntryIdPureError:
38583792 assert(const_val->data.x_pure_err);
......@@ -4015,34 +3949,48 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val) {
40153949 ConstExprValue *payload_value = const_val->data.x_union.payload;
40163950 assert(payload_value != nullptr);
40173951
4018 if (!type_has_bits(payload_value->type)) {
4019 return LLVMGetUndef(union_type_ref);
3952 if (type_entry->data.unionation.gen_field_count == 0) {
3953 if (type_entry->data.unionation.gen_tag_index == SIZE_MAX) {
3954 return nullptr;
3955 } else {
3956 return bigint_to_llvm_const(type_entry->data.unionation.tag_type->type_ref,
3957 &const_val->data.x_union.tag);
3958 }
40203959 }
40213960
4022 uint64_t field_type_bytes = LLVMStoreSizeOfType(g->target_data_ref, payload_value->type->type_ref);
4023 uint64_t pad_bytes = type_entry->data.unionation.union_size_bytes - field_type_bytes;
4024 LLVMValueRef correctly_typed_value = gen_const_val(g, payload_value);
4025 bool make_unnamed_struct = is_llvm_value_unnamed_type(payload_value->type, correctly_typed_value) ||
4026 payload_value->type != type_entry->data.unionation.most_aligned_union_member;
4027
40283961 LLVMValueRef union_value_ref;
4029 {
4030 if (pad_bytes == 0) {
4031 union_value_ref = correctly_typed_value;
4032 } else {
4033 LLVMValueRef fields[2];
4034 fields[0] = correctly_typed_value;
4035 fields[1] = LLVMGetUndef(LLVMArrayType(LLVMInt8Type(), (unsigned)pad_bytes));
4036 if (make_unnamed_struct || type_entry->data.unionation.gen_tag_index != SIZE_MAX) {
4037 union_value_ref = LLVMConstStruct(fields, 2, false);
3962 bool make_unnamed_struct;
3963 if (!type_has_bits(payload_value->type)) {
3964 if (type_entry->data.unionation.gen_tag_index == SIZE_MAX)
3965 return LLVMGetUndef(type_entry->type_ref);
3966
3967 union_value_ref = LLVMGetUndef(type_entry->data.unionation.most_aligned_union_member->type_ref);
3968 make_unnamed_struct = false;
3969 } else {
3970 uint64_t field_type_bytes = LLVMStoreSizeOfType(g->target_data_ref, payload_value->type->type_ref);
3971 uint64_t pad_bytes = type_entry->data.unionation.union_size_bytes - field_type_bytes;
3972 LLVMValueRef correctly_typed_value = gen_const_val(g, payload_value);
3973 make_unnamed_struct = is_llvm_value_unnamed_type(payload_value->type, correctly_typed_value) ||
3974 payload_value->type != type_entry->data.unionation.most_aligned_union_member;
3975
3976 {
3977 if (pad_bytes == 0) {
3978 union_value_ref = correctly_typed_value;
40383979 } else {
4039 union_value_ref = LLVMConstNamedStruct(union_type_ref, fields, 2);
3980 LLVMValueRef fields[2];
3981 fields[0] = correctly_typed_value;
3982 fields[1] = LLVMGetUndef(LLVMArrayType(LLVMInt8Type(), (unsigned)pad_bytes));
3983 if (make_unnamed_struct || type_entry->data.unionation.gen_tag_index != SIZE_MAX) {
3984 union_value_ref = LLVMConstStruct(fields, 2, false);
3985 } else {
3986 union_value_ref = LLVMConstNamedStruct(union_type_ref, fields, 2);
3987 }
40403988 }
40413989 }
4042 }
40433990
4044 if (type_entry->data.unionation.gen_tag_index == SIZE_MAX) {
4045 return union_value_ref;
3991 if (type_entry->data.unionation.gen_tag_index == SIZE_MAX) {
3992 return union_value_ref;
3993 }
40463994 }
40473995
40483996 LLVMValueRef tag_value = bigint_to_llvm_const(type_entry->data.unionation.tag_type->type_ref,
......@@ -4059,55 +4007,9 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val) {
40594007 }
40604008
40614009 }
4062 case TypeTableEntryIdEnum:
4063 {
4064 LLVMTypeRef tag_type_ref = type_entry->data.enumeration.tag_type->type_ref;
4065 LLVMValueRef tag_value = bigint_to_llvm_const(tag_type_ref, &const_val->data.x_enum.tag);
4066 if (type_entry->data.enumeration.gen_field_count == 0) {
4067 return tag_value;
4068 } else {
4069 LLVMTypeRef union_type_ref = type_entry->data.enumeration.union_type_ref;
4070 TypeEnumField *enum_field = find_enum_field_by_tag(type_entry, &const_val->data.x_enum.tag);
4071 assert(bigint_cmp(&enum_field->value, &const_val->data.x_enum.tag) == CmpEQ);
4072 LLVMValueRef union_value;
4073
4074 bool make_unnamed_struct;
40754010
4076 if (type_has_bits(enum_field->type_entry)) {
4077 uint64_t field_type_bytes = LLVMStoreSizeOfType(g->target_data_ref,
4078 enum_field->type_entry->type_ref);
4079 uint64_t pad_bytes = type_entry->data.enumeration.union_size_bytes - field_type_bytes;
4080
4081 ConstExprValue *payload_value = const_val->data.x_enum.payload;
4082 LLVMValueRef correctly_typed_value = gen_const_val(g, payload_value);
4083
4084 make_unnamed_struct = is_llvm_value_unnamed_type(payload_value->type, correctly_typed_value) ||
4085 payload_value->type != type_entry->data.enumeration.most_aligned_union_member;
4086
4087 if (pad_bytes == 0) {
4088 union_value = correctly_typed_value;
4089 } else {
4090 LLVMValueRef fields[] = {
4091 correctly_typed_value,
4092 LLVMGetUndef(LLVMArrayType(LLVMInt8Type(), (unsigned)pad_bytes)),
4093 };
4094 union_value = LLVMConstStruct(fields, 2, false);
4095 }
4096 } else {
4097 make_unnamed_struct = false;
4098 union_value = LLVMGetUndef(union_type_ref);
4099 }
4100 LLVMValueRef fields[2];
4101 fields[type_entry->data.enumeration.gen_tag_index] = tag_value;
4102 fields[type_entry->data.enumeration.gen_union_index] = union_value;
4103
4104 if (make_unnamed_struct) {
4105 return LLVMConstStruct(fields, 2, false);
4106 } else {
4107 return LLVMConstNamedStruct(type_entry->type_ref, fields, 2);
4108 }
4109 }
4110 }
4011 case TypeTableEntryIdEnum:
4012 return bigint_to_llvm_const(type_entry->type_ref, &const_val->data.x_enum_tag);
41114013 case TypeTableEntryIdFn:
41124014 return fn_llvm_value(g, const_val->data.x_fn.fn_entry);
41134015 case TypeTableEntryIdPointer:
......@@ -4318,9 +4220,8 @@ static void generate_enum_name_tables(CodeGen *g) {
43184220
43194221
43204222 for (size_t enum_i = 0; enum_i < g->name_table_enums.length; enum_i += 1) {
4321 TypeTableEntry *enum_tag_type = g->name_table_enums.at(enum_i);
4322 assert(enum_tag_type->id == TypeTableEntryIdEnumTag);
4323 TypeTableEntry *enum_type = enum_tag_type->data.enum_tag.enum_type;
4223 TypeTableEntry *enum_type = g->name_table_enums.at(enum_i);
4224 assert(enum_type->id == TypeTableEntryIdEnum);
43244225
43254226 size_t field_count = enum_type->data.enumeration.src_field_count;
43264227 LLVMValueRef *values = allocate<LLVMValueRef>(field_count);
......@@ -4351,7 +4252,7 @@ static void generate_enum_name_tables(CodeGen *g) {
43514252 LLVMSetGlobalConstant(name_table, true);
43524253 LLVMSetUnnamedAddr(name_table, true);
43534254 LLVMSetAlignment(name_table, LLVMABIAlignmentOfType(g->target_data_ref, LLVMTypeOf(name_table_init)));
4354 enum_tag_type->data.enum_tag.name_table = name_table;
4255 enum_type->data.enumeration.name_table = name_table;
43554256 }
43564257}
43574258
......@@ -4555,9 +4456,6 @@ static void do_code_gen(CodeGen *g) {
45554456 } else if (instruction->id == IrInstructionIdErrWrapCode) {
45564457 IrInstructionErrWrapCode *err_wrap_code_instruction = (IrInstructionErrWrapCode *)instruction;
45574458 slot = &err_wrap_code_instruction->tmp_ptr;
4558 } else if (instruction->id == IrInstructionIdInitEnum) {
4559 IrInstructionInitEnum *init_enum_instruction = (IrInstructionInitEnum *)instruction;
4560 slot = &init_enum_instruction->tmp_ptr;
45614459 } else {
45624460 zig_unreachable();
45634461 }
......@@ -5054,7 +4952,7 @@ static void define_builtin_fns(CodeGen *g) {
50544952 create_builtin_fn(g, BuiltinFnIdTruncate, "truncate", 2);
50554953 create_builtin_fn(g, BuiltinFnIdCompileErr, "compileError", 1);
50564954 create_builtin_fn(g, BuiltinFnIdCompileLog, "compileLog", SIZE_MAX);
5057 create_builtin_fn(g, BuiltinFnIdIntType, "IntType", 2);
4955 create_builtin_fn(g, BuiltinFnIdIntType, "IntType", 2); // TODO rename to Int
50584956 create_builtin_fn(g, BuiltinFnIdSetDebugSafety, "setDebugSafety", 2);
50594957 create_builtin_fn(g, BuiltinFnIdSetFloatMode, "setFloatMode", 2);
50604958 create_builtin_fn(g, BuiltinFnIdSetGlobalSection, "setGlobalSection", 2);
......@@ -5064,7 +4962,7 @@ static void define_builtin_fns(CodeGen *g) {
50644962 create_builtin_fn(g, BuiltinFnIdBitCast, "bitCast", 2);
50654963 create_builtin_fn(g, BuiltinFnIdIntToPtr, "intToPtr", 2);
50664964 create_builtin_fn(g, BuiltinFnIdPtrToInt, "ptrToInt", 1);
5067 create_builtin_fn(g, BuiltinFnIdEnumTagName, "enumTagName", 1); // TODO rename to memberName
4965 create_builtin_fn(g, BuiltinFnIdTagName, "tagName", 1);
50684966 create_builtin_fn(g, BuiltinFnIdEnumTagType, "EnumTagType", 1);
50694967 create_builtin_fn(g, BuiltinFnIdFieldParentPtr, "fieldParentPtr", 3);
50704968 create_builtin_fn(g, BuiltinFnIdOffsetOf, "offsetOf", 2);
......@@ -5681,7 +5579,6 @@ static void get_c_type(CodeGen *g, TypeTableEntry *type_entry, Buf *out_buf) {
56815579 case TypeTableEntryIdEnum:
56825580 case TypeTableEntryIdUnion:
56835581 case TypeTableEntryIdFn:
5684 case TypeTableEntryIdEnumTag:
56855582 zig_panic("TODO implement get_c_type for more types");
56865583 case TypeTableEntryIdInvalid:
56875584 case TypeTableEntryIdMetaType:
src/ir.cpp+206-282
......@@ -223,10 +223,6 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionStructFieldPtr *
223223 return IrInstructionIdStructFieldPtr;
224224}
225225
226static constexpr IrInstructionId ir_instruction_id(IrInstructionEnumFieldPtr *) {
227 return IrInstructionIdEnumFieldPtr;
228}
229
230226static constexpr IrInstructionId ir_instruction_id(IrInstructionUnionFieldPtr *) {
231227 return IrInstructionIdUnionFieldPtr;
232228}
......@@ -319,8 +315,8 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionCtz *) {
319315 return IrInstructionIdCtz;
320316}
321317
322static constexpr IrInstructionId ir_instruction_id(IrInstructionEnumTag *) {
323 return IrInstructionIdEnumTag;
318static constexpr IrInstructionId ir_instruction_id(IrInstructionUnionTag *) {
319 return IrInstructionIdUnionTag;
324320}
325321
326322static constexpr IrInstructionId ir_instruction_id(IrInstructionImport *) {
......@@ -479,10 +475,6 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionTestComptime *)
479475 return IrInstructionIdTestComptime;
480476}
481477
482static constexpr IrInstructionId ir_instruction_id(IrInstructionInitEnum *) {
483 return IrInstructionIdInitEnum;
484}
485
486478static constexpr IrInstructionId ir_instruction_id(IrInstructionPtrCast *) {
487479 return IrInstructionIdPtrCast;
488480}
......@@ -913,27 +905,6 @@ static IrInstruction *ir_build_struct_field_ptr_from(IrBuilder *irb, IrInstructi
913905 return new_instruction;
914906}
915907
916static IrInstruction *ir_build_enum_field_ptr(IrBuilder *irb, Scope *scope, AstNode *source_node,
917 IrInstruction *enum_ptr, TypeEnumField *field)
918{
919 IrInstructionEnumFieldPtr *instruction = ir_build_instruction<IrInstructionEnumFieldPtr>(irb, scope, source_node);
920 instruction->enum_ptr = enum_ptr;
921 instruction->field = field;
922
923 ir_ref_instruction(enum_ptr, irb->current_basic_block);
924
925 return &instruction->base;
926}
927
928static IrInstruction *ir_build_enum_field_ptr_from(IrBuilder *irb, IrInstruction *old_instruction,
929 IrInstruction *enum_ptr, TypeEnumField *type_enum_field)
930{
931 IrInstruction *new_instruction = ir_build_enum_field_ptr(irb, old_instruction->scope,
932 old_instruction->source_node, enum_ptr, type_enum_field);
933 ir_link_new_instruction(new_instruction, old_instruction);
934 return new_instruction;
935}
936
937908static IrInstruction *ir_build_union_field_ptr(IrBuilder *irb, Scope *scope, AstNode *source_node,
938909 IrInstruction *union_ptr, TypeUnionField *field)
939910{
......@@ -1528,8 +1499,8 @@ static IrInstruction *ir_build_switch_var(IrBuilder *irb, Scope *scope, AstNode
15281499 return &instruction->base;
15291500}
15301501
1531static IrInstruction *ir_build_enum_tag(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *value) {
1532 IrInstructionEnumTag *instruction = ir_build_instruction<IrInstructionEnumTag>(irb, scope, source_node);
1502static IrInstruction *ir_build_union_tag(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *value) {
1503 IrInstructionUnionTag *instruction = ir_build_instruction<IrInstructionUnionTag>(irb, scope, source_node);
15331504 instruction->value = value;
15341505
15351506 ir_ref_instruction(value, irb->current_basic_block);
......@@ -1537,13 +1508,6 @@ static IrInstruction *ir_build_enum_tag(IrBuilder *irb, Scope *scope, AstNode *s
15371508 return &instruction->base;
15381509}
15391510
1540static IrInstruction *ir_build_enum_tag_from(IrBuilder *irb, IrInstruction *old_instruction, IrInstruction *value) {
1541 IrInstruction *new_instruction = ir_build_enum_tag(irb, old_instruction->scope,
1542 old_instruction->source_node, value);
1543 ir_link_new_instruction(new_instruction, old_instruction);
1544 return new_instruction;
1545}
1546
15471511static IrInstruction *ir_build_import(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *name) {
15481512 IrInstructionImport *instruction = ir_build_instruction<IrInstructionImport>(irb, scope, source_node);
15491513 instruction->name = name;
......@@ -2033,28 +1997,6 @@ static IrInstruction *ir_build_test_comptime(IrBuilder *irb, Scope *scope, AstNo
20331997 return &instruction->base;
20341998}
20351999
2036static IrInstruction *ir_build_init_enum(IrBuilder *irb, Scope *scope, AstNode *source_node,
2037 TypeTableEntry *enum_type, TypeEnumField *field, IrInstruction *init_value)
2038{
2039 IrInstructionInitEnum *instruction = ir_build_instruction<IrInstructionInitEnum>(irb, scope, source_node);
2040 instruction->enum_type = enum_type;
2041 instruction->field = field;
2042 instruction->init_value = init_value;
2043
2044 ir_ref_instruction(init_value, irb->current_basic_block);
2045
2046 return &instruction->base;
2047}
2048
2049static IrInstruction *ir_build_init_enum_from(IrBuilder *irb, IrInstruction *old_instruction,
2050 TypeTableEntry *enum_type, TypeEnumField *field, IrInstruction *init_value)
2051{
2052 IrInstruction *new_instruction = ir_build_init_enum(irb, old_instruction->scope, old_instruction->source_node,
2053 enum_type, field, init_value);
2054 ir_link_new_instruction(new_instruction, old_instruction);
2055 return new_instruction;
2056}
2057
20582000static IrInstruction *ir_build_ptr_cast(IrBuilder *irb, Scope *scope, AstNode *source_node,
20592001 IrInstruction *dest_type, IrInstruction *ptr)
20602002{
......@@ -2481,13 +2423,6 @@ static IrInstruction *ir_instruction_structfieldptr_get_dep(IrInstructionStructF
24812423 }
24822424}
24832425
2484static IrInstruction *ir_instruction_enumfieldptr_get_dep(IrInstructionEnumFieldPtr *instruction, size_t index) {
2485 switch (index) {
2486 case 0: return instruction->enum_ptr;
2487 default: return nullptr;
2488 }
2489}
2490
24912426static IrInstruction *ir_instruction_unionfieldptr_get_dep(IrInstructionUnionFieldPtr *instruction, size_t index) {
24922427 switch (index) {
24932428 case 0: return instruction->union_ptr;
......@@ -2657,7 +2592,7 @@ static IrInstruction *ir_instruction_maybewrap_get_dep(IrInstructionMaybeWrap *i
26572592 }
26582593}
26592594
2660static IrInstruction *ir_instruction_enumtag_get_dep(IrInstructionEnumTag *instruction, size_t index) {
2595static IrInstruction *ir_instruction_uniontag_get_dep(IrInstructionUnionTag *instruction, size_t index) {
26612596 switch (index) {
26622597 case 0: return instruction->value;
26632598 default: return nullptr;
......@@ -2943,13 +2878,6 @@ static IrInstruction *ir_instruction_testcomptime_get_dep(IrInstructionTestCompt
29432878 }
29442879}
29452880
2946static IrInstruction *ir_instruction_initenum_get_dep(IrInstructionInitEnum *instruction, size_t index) {
2947 switch (index) {
2948 case 0: return instruction->init_value;
2949 default: return nullptr;
2950 }
2951}
2952
29532881static IrInstruction *ir_instruction_ptrcast_get_dep(IrInstructionPtrCast *instruction,
29542882 size_t index)
29552883{
......@@ -3184,8 +3112,6 @@ static IrInstruction *ir_instruction_get_dep(IrInstruction *instruction, size_t
31843112 return ir_instruction_fieldptr_get_dep((IrInstructionFieldPtr *) instruction, index);
31853113 case IrInstructionIdStructFieldPtr:
31863114 return ir_instruction_structfieldptr_get_dep((IrInstructionStructFieldPtr *) instruction, index);
3187 case IrInstructionIdEnumFieldPtr:
3188 return ir_instruction_enumfieldptr_get_dep((IrInstructionEnumFieldPtr *) instruction, index);
31893115 case IrInstructionIdUnionFieldPtr:
31903116 return ir_instruction_unionfieldptr_get_dep((IrInstructionUnionFieldPtr *) instruction, index);
31913117 case IrInstructionIdElemPtr:
......@@ -3234,8 +3160,8 @@ static IrInstruction *ir_instruction_get_dep(IrInstruction *instruction, size_t
32343160 return ir_instruction_unwrapmaybe_get_dep((IrInstructionUnwrapMaybe *) instruction, index);
32353161 case IrInstructionIdMaybeWrap:
32363162 return ir_instruction_maybewrap_get_dep((IrInstructionMaybeWrap *) instruction, index);
3237 case IrInstructionIdEnumTag:
3238 return ir_instruction_enumtag_get_dep((IrInstructionEnumTag *) instruction, index);
3163 case IrInstructionIdUnionTag:
3164 return ir_instruction_uniontag_get_dep((IrInstructionUnionTag *) instruction, index);
32393165 case IrInstructionIdClz:
32403166 return ir_instruction_clz_get_dep((IrInstructionClz *) instruction, index);
32413167 case IrInstructionIdCtz:
......@@ -3312,8 +3238,6 @@ static IrInstruction *ir_instruction_get_dep(IrInstruction *instruction, size_t
33123238 return ir_instruction_fnproto_get_dep((IrInstructionFnProto *) instruction, index);
33133239 case IrInstructionIdTestComptime:
33143240 return ir_instruction_testcomptime_get_dep((IrInstructionTestComptime *) instruction, index);
3315 case IrInstructionIdInitEnum:
3316 return ir_instruction_initenum_get_dep((IrInstructionInitEnum *) instruction, index);
33173241 case IrInstructionIdPtrCast:
33183242 return ir_instruction_ptrcast_get_dep((IrInstructionPtrCast *) instruction, index);
33193243 case IrInstructionIdBitCast:
......@@ -4695,14 +4619,14 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
46954619
46964620 return ir_build_ptr_to_int(irb, scope, node, arg0_value);
46974621 }
4698 case BuiltinFnIdEnumTagName:
4622 case BuiltinFnIdTagName:
46994623 {
47004624 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
47014625 IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope);
47024626 if (arg0_value == irb->codegen->invalid_instruction)
47034627 return arg0_value;
47044628
4705 IrInstruction *actual_tag = ir_build_enum_tag(irb, scope, node, arg0_value);
4629 IrInstruction *actual_tag = ir_build_union_tag(irb, scope, node, arg0_value);
47064630 return ir_build_enum_tag_name(irb, scope, node, actual_tag);
47074631 }
47084632 case BuiltinFnIdEnumTagType:
......@@ -8381,13 +8305,28 @@ static IrInstruction *ir_analyze_enum_to_int(IrAnalyze *ira, IrInstruction *sour
83818305{
83828306 assert(wanted_type->id == TypeTableEntryIdInt);
83838307
8308 TypeTableEntry *actual_type = target->value.type;
8309 ensure_complete_type(ira->codegen, actual_type);
8310 if (type_is_invalid(actual_type))
8311 return ira->codegen->invalid_instruction;
8312
8313 if (wanted_type != actual_type->data.enumeration.tag_int_type) {
8314 ir_add_error(ira, source_instr,
8315 buf_sprintf("enum to integer cast to '%s' instead of its tag type, '%s'",
8316 buf_ptr(&wanted_type->name),
8317 buf_ptr(&actual_type->data.enumeration.tag_int_type->name)));
8318 return ira->codegen->invalid_instruction;
8319 }
8320
8321 assert(actual_type->id == TypeTableEntryIdEnum);
8322
83848323 if (instr_is_comptime(target)) {
83858324 ConstExprValue *val = ir_resolve_const(ira, target, UndefBad);
83868325 if (!val)
83878326 return ira->codegen->invalid_instruction;
83888327 IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,
83898328 source_instr->source_node, wanted_type);
8390 init_const_bigint(&result->value, wanted_type, &val->data.x_enum.tag);
8329 init_const_bigint(&result->value, wanted_type, &val->data.x_enum_tag);
83918330 return result;
83928331 }
83938332
......@@ -8397,6 +8336,31 @@ static IrInstruction *ir_analyze_enum_to_int(IrAnalyze *ira, IrInstruction *sour
83978336 return result;
83988337}
83998338
8339static IrInstruction *ir_analyze_union_to_tag(IrAnalyze *ira, IrInstruction *source_instr,
8340 IrInstruction *target, TypeTableEntry *wanted_type)
8341{
8342 assert(target->value.type->id == TypeTableEntryIdUnion);
8343 assert(wanted_type->id == TypeTableEntryIdEnum);
8344 assert(wanted_type == target->value.type->data.unionation.tag_type);
8345
8346 if (instr_is_comptime(target)) {
8347 ConstExprValue *val = ir_resolve_const(ira, target, UndefBad);
8348 if (!val)
8349 return ira->codegen->invalid_instruction;
8350 IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,
8351 source_instr->source_node, wanted_type);
8352 result->value.special = ConstValSpecialStatic;
8353 result->value.type = wanted_type;
8354 bigint_init_bigint(&result->value.data.x_enum_tag, &val->data.x_union.tag);
8355 return result;
8356 }
8357
8358 IrInstruction *result = ir_build_union_tag(&ira->new_irb, source_instr->scope,
8359 source_instr->source_node, target);
8360 result->value.type = wanted_type;
8361 return result;
8362}
8363
84008364static IrInstruction *ir_analyze_undefined_to_anything(IrAnalyze *ira, IrInstruction *source_instr,
84018365 IrInstruction *target, TypeTableEntry *wanted_type)
84028366{
......@@ -8452,6 +8416,22 @@ static IrInstruction *ir_analyze_int_to_enum(IrAnalyze *ira, IrInstruction *sour
84528416{
84538417 assert(wanted_type->id == TypeTableEntryIdEnum);
84548418
8419 TypeTableEntry *actual_type = target->value.type;
8420
8421 ensure_complete_type(ira->codegen, wanted_type);
8422 if (type_is_invalid(wanted_type))
8423 return ira->codegen->invalid_instruction;
8424
8425 if (actual_type != wanted_type->data.enumeration.tag_int_type) {
8426 ir_add_error(ira, source_instr,
8427 buf_sprintf("integer to enum cast from '%s' instead of its tag type, '%s'",
8428 buf_ptr(&actual_type->name),
8429 buf_ptr(&wanted_type->data.enumeration.tag_int_type->name)));
8430 return ira->codegen->invalid_instruction;
8431 }
8432
8433 assert(actual_type->id == TypeTableEntryIdInt);
8434
84558435 if (instr_is_comptime(target)) {
84568436 ConstExprValue *val = ir_resolve_const(ira, target, UndefBad);
84578437 if (!val)
......@@ -8469,7 +8449,7 @@ static IrInstruction *ir_analyze_int_to_enum(IrAnalyze *ira, IrInstruction *sour
84698449
84708450 IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,
84718451 source_instr->source_node, wanted_type);
8472 bigint_init_bigint(&result->value.data.x_enum.tag, &val->data.x_bigint);
8452 bigint_init_bigint(&result->value.data.x_enum_tag, &val->data.x_bigint);
84738453 return result;
84748454 }
84758455
......@@ -8907,39 +8887,24 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
89078887 }
89088888
89098889 // explicit cast from integer to enum type with no payload
8910 if (actual_type->id == TypeTableEntryIdInt &&
8911 wanted_type->id == TypeTableEntryIdEnum &&
8912 wanted_type->data.enumeration.gen_field_count == 0)
8913 {
8914 ensure_complete_type(ira->codegen, wanted_type);
8915 if (type_is_invalid(wanted_type))
8916 return ira->codegen->invalid_instruction;
8917 if (actual_type == wanted_type->data.enumeration.tag_type->data.enum_tag.int_type) {
8918 return ir_analyze_int_to_enum(ira, source_instr, value, wanted_type);
8919 }
8920 ir_add_error(ira, source_instr,
8921 buf_sprintf("integer to enum cast from '%s' instead of its tag type, '%s'",
8922 buf_ptr(&actual_type->name),
8923 buf_ptr(&wanted_type->data.enumeration.tag_type->data.enum_tag.int_type->name)));
8924 return ira->codegen->invalid_instruction;
8890 if (actual_type->id == TypeTableEntryIdInt && wanted_type->id == TypeTableEntryIdEnum) {
8891 return ir_analyze_int_to_enum(ira, source_instr, value, wanted_type);
89258892 }
89268893
89278894 // explicit cast from enum type with no payload to integer
8928 if (wanted_type->id == TypeTableEntryIdInt &&
8929 actual_type->id == TypeTableEntryIdEnum &&
8930 actual_type->data.enumeration.gen_field_count == 0)
8931 {
8932 ensure_complete_type(ira->codegen, actual_type);
8895 if (wanted_type->id == TypeTableEntryIdInt && actual_type->id == TypeTableEntryIdEnum) {
8896 return ir_analyze_enum_to_int(ira, source_instr, value, wanted_type);
8897 }
8898
8899 // explicit cast from union to the enum type of the union
8900 if (actual_type->id == TypeTableEntryIdUnion && wanted_type->id == TypeTableEntryIdEnum) {
8901 type_ensure_zero_bits_known(ira->codegen, actual_type);
89338902 if (type_is_invalid(actual_type))
89348903 return ira->codegen->invalid_instruction;
8935 if (wanted_type == actual_type->data.enumeration.tag_type->data.enum_tag.int_type) {
8936 return ir_analyze_enum_to_int(ira, source_instr, value, wanted_type);
8904
8905 if (actual_type->data.unionation.tag_type == wanted_type) {
8906 return ir_analyze_union_to_tag(ira, source_instr, value, wanted_type);
89378907 }
8938 ir_add_error(ira, source_instr,
8939 buf_sprintf("enum to integer cast to '%s' instead of its tag type, '%s'",
8940 buf_ptr(&wanted_type->name),
8941 buf_ptr(&actual_type->data.enumeration.tag_type->data.enum_tag.int_type->name)));
8942 return ira->codegen->invalid_instruction;
89438908 }
89448909
89458910 // explicit cast from undefined to anything
......@@ -9148,7 +9113,7 @@ static bool ir_resolve_atomic_order(IrAnalyze *ira, IrInstruction *value, Atomic
91489113 if (!const_val)
91499114 return false;
91509115
9151 *out = (AtomicOrder)bigint_as_unsigned(&const_val->data.x_enum.tag);
9116 *out = (AtomicOrder)bigint_as_unsigned(&const_val->data.x_enum_tag);
91529117 return true;
91539118}
91549119
......@@ -9168,7 +9133,7 @@ static bool ir_resolve_global_linkage(IrAnalyze *ira, IrInstruction *value, Glob
91689133 if (!const_val)
91699134 return false;
91709135
9171 *out = (GlobalLinkageId)bigint_as_unsigned(&const_val->data.x_enum.tag);
9136 *out = (GlobalLinkageId)bigint_as_unsigned(&const_val->data.x_enum_tag);
91729137 return true;
91739138}
91749139
......@@ -9188,7 +9153,7 @@ static bool ir_resolve_float_mode(IrAnalyze *ira, IrInstruction *value, FloatMod
91889153 if (!const_val)
91899154 return false;
91909155
9191 *out = (FloatMode)bigint_as_unsigned(&const_val->data.x_enum.tag);
9156 *out = (FloatMode)bigint_as_unsigned(&const_val->data.x_enum_tag);
91929157 return true;
91939158}
91949159
......@@ -9400,7 +9365,7 @@ static TypeTableEntry *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp
94009365 break;
94019366
94029367 case TypeTableEntryIdEnum:
9403 if (!is_equality_cmp || resolved_type->data.enumeration.gen_field_count != 0) {
9368 if (!is_equality_cmp) {
94049369 ir_add_error_node(ira, source_node,
94059370 buf_sprintf("operator not allowed for type '%s'", buf_ptr(&resolved_type->name)));
94069371 return ira->codegen->builtin_types.entry_invalid;
......@@ -9419,9 +9384,6 @@ static TypeTableEntry *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp
94199384 buf_sprintf("operator not allowed for type '%s'", buf_ptr(&resolved_type->name)));
94209385 return ira->codegen->builtin_types.entry_invalid;
94219386
9422 case TypeTableEntryIdEnumTag:
9423 zig_panic("TODO implement comparison for enum tag type");
9424
94259387 case TypeTableEntryIdVar:
94269388 zig_unreachable();
94279389 }
......@@ -10170,7 +10132,6 @@ static VarClassRequired get_var_class_required(TypeTableEntry *type_entry) {
1017010132 case TypeTableEntryIdVoid:
1017110133 case TypeTableEntryIdPureError:
1017210134 case TypeTableEntryIdFn:
10173 case TypeTableEntryIdEnumTag:
1017410135 return VarClassRequiredAny;
1017510136 case TypeTableEntryIdNumLitFloat:
1017610137 case TypeTableEntryIdNumLitInt:
......@@ -10913,7 +10874,6 @@ static TypeTableEntry *ir_analyze_unary_prefix_op_err(IrAnalyze *ira, IrInstruct
1091310874 case TypeTableEntryIdUnion:
1091410875 case TypeTableEntryIdFn:
1091510876 case TypeTableEntryIdBoundFn:
10916 case TypeTableEntryIdEnumTag:
1091710877 {
1091810878 ConstExprValue *out_val = ir_build_const_from(ira, &un_op_instruction->base);
1091910879 TypeTableEntry *result_type = get_error_type(ira->codegen, meta_type);
......@@ -11001,7 +10961,6 @@ static TypeTableEntry *ir_analyze_maybe(IrAnalyze *ira, IrInstructionUnOp *un_op
1100110961 case TypeTableEntryIdNamespace:
1100210962 case TypeTableEntryIdBlock:
1100310963 case TypeTableEntryIdBoundFn:
11004 case TypeTableEntryIdEnumTag:
1100510964 case TypeTableEntryIdArgTuple:
1100610965 {
1100710966 ConstExprValue *out_val = ir_build_const_from(ira, &un_op_instruction->base);
......@@ -11662,15 +11621,8 @@ static TypeTableEntry *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field
1166211621 field_ptr_instruction, container_ptr, container_type);
1166311622 }
1166411623 } else if (bare_type->id == TypeTableEntryIdEnum) {
11665 TypeEnumField *field = find_enum_type_field(bare_type, field_name);
11666 if (field) {
11667 ir_build_enum_field_ptr_from(&ira->new_irb, &field_ptr_instruction->base, container_ptr, field);
11668 return get_pointer_to_type_extra(ira->codegen, field->type_entry, is_const, is_volatile,
11669 get_abi_alignment(ira->codegen, field->type_entry), 0, 0);
11670 } else {
11671 return ir_analyze_container_member_access_inner(ira, bare_type, field_name,
11672 field_ptr_instruction, container_ptr, container_type);
11673 }
11624 return ir_analyze_container_member_access_inner(ira, bare_type, field_name,
11625 field_ptr_instruction, container_ptr, container_type);
1167411626 } else if (bare_type->id == TypeTableEntryIdUnion) {
1167511627 TypeUnionField *field = find_union_type_field(bare_type, field_name);
1167611628 if (field) {
......@@ -11841,20 +11793,27 @@ static TypeTableEntry *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstru
1184111793
1184211794 TypeEnumField *field = find_enum_type_field(child_type, field_name);
1184311795 if (field) {
11844 if (field->type_entry->id == TypeTableEntryIdVoid) {
11845 bool ptr_is_const = true;
11846 bool ptr_is_volatile = false;
11847 return ir_analyze_const_ptr(ira, &field_ptr_instruction->base,
11848 create_const_enum_tag(child_type, &field->value), child_type,
11849 ConstPtrMutComptimeConst, ptr_is_const, ptr_is_volatile);
11850 } else {
11851 bool ptr_is_const = true;
11852 bool ptr_is_volatile = false;
11853 return ir_analyze_const_ptr(ira, &field_ptr_instruction->base,
11854 create_const_bigint(child_type->data.enumeration.tag_type, &field->value),
11855 child_type->data.enumeration.tag_type,
11796 bool ptr_is_const = true;
11797 bool ptr_is_volatile = false;
11798 return ir_analyze_const_ptr(ira, &field_ptr_instruction->base,
11799 create_const_enum(child_type, &field->value), child_type,
11800 ConstPtrMutComptimeConst, ptr_is_const, ptr_is_volatile);
11801 }
11802 } else if (child_type->id == TypeTableEntryIdUnion &&
11803 (child_type->data.unionation.decl_node->data.container_decl.init_arg_expr != nullptr ||
11804 child_type->data.unionation.decl_node->data.container_decl.auto_enum))
11805 {
11806 ensure_complete_type(ira->codegen, child_type);
11807 if (type_is_invalid(child_type))
11808 return ira->codegen->builtin_types.entry_invalid;
11809 TypeUnionField *field = find_union_type_field(child_type, field_name);
11810 if (field) {
11811 TypeTableEntry *enum_type = child_type->data.unionation.tag_type;
11812 bool ptr_is_const = true;
11813 bool ptr_is_volatile = false;
11814 return ir_analyze_const_ptr(ira, &field_ptr_instruction->base,
11815 create_const_enum(enum_type, &field->enum_field->value), enum_type,
1185611816 ConstPtrMutComptimeConst, ptr_is_const, ptr_is_volatile);
11857 }
1185811817 }
1185911818 }
1186011819 ScopeDecls *container_scope = get_container_scope(child_type);
......@@ -12163,7 +12122,6 @@ static TypeTableEntry *ir_analyze_instruction_typeof(IrAnalyze *ira, IrInstructi
1216312122 case TypeTableEntryIdEnum:
1216412123 case TypeTableEntryIdUnion:
1216512124 case TypeTableEntryIdFn:
12166 case TypeTableEntryIdEnumTag:
1216712125 case TypeTableEntryIdArgTuple:
1216812126 case TypeTableEntryIdOpaque:
1216912127 {
......@@ -12511,7 +12469,6 @@ static TypeTableEntry *ir_analyze_instruction_slice_type(IrAnalyze *ira,
1251112469 case TypeTableEntryIdFn:
1251212470 case TypeTableEntryIdNamespace:
1251312471 case TypeTableEntryIdBoundFn:
12514 case TypeTableEntryIdEnumTag:
1251512472 {
1251612473 type_ensure_zero_bits_known(ira->codegen, child_type);
1251712474 TypeTableEntry *slice_ptr_type = get_pointer_to_type_extra(ira->codegen, child_type,
......@@ -12620,7 +12577,6 @@ static TypeTableEntry *ir_analyze_instruction_array_type(IrAnalyze *ira,
1262012577 case TypeTableEntryIdFn:
1262112578 case TypeTableEntryIdNamespace:
1262212579 case TypeTableEntryIdBoundFn:
12623 case TypeTableEntryIdEnumTag:
1262412580 {
1262512581 TypeTableEntry *result_type = get_array_type(ira->codegen, child_type, size);
1262612582 ConstExprValue *out_val = ir_build_const_from(ira, &array_type_instruction->base);
......@@ -12671,7 +12627,6 @@ static TypeTableEntry *ir_analyze_instruction_size_of(IrAnalyze *ira,
1267112627 case TypeTableEntryIdPureError:
1267212628 case TypeTableEntryIdEnum:
1267312629 case TypeTableEntryIdUnion:
12674 case TypeTableEntryIdEnumTag:
1267512630 case TypeTableEntryIdFn:
1267612631 {
1267712632 uint64_t size_in_bytes = type_size(ira->codegen, type_entry);
......@@ -12824,17 +12779,22 @@ static TypeTableEntry *ir_analyze_instruction_clz(IrAnalyze *ira, IrInstructionC
1282412779 }
1282512780}
1282612781
12827static IrInstruction *ir_analyze_enum_tag(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value) {
12782static IrInstruction *ir_analyze_union_tag(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value) {
1282812783 if (type_is_invalid(value->value.type))
1282912784 return ira->codegen->invalid_instruction;
1283012785
12831 if (value->value.type->id != TypeTableEntryIdEnum) {
12786 if (value->value.type->id == TypeTableEntryIdEnum) {
12787 return value;
12788 }
12789
12790 if (value->value.type->id != TypeTableEntryIdUnion) {
1283212791 ir_add_error(ira, source_instr,
12833 buf_sprintf("expected enum type, found '%s'", buf_ptr(&value->value.type->name)));
12792 buf_sprintf("expected enum or union type, found '%s'", buf_ptr(&value->value.type->name)));
1283412793 return ira->codegen->invalid_instruction;
1283512794 }
1283612795
12837 TypeTableEntry *tag_type = value->value.type->data.enumeration.tag_type;
12796 TypeTableEntry *tag_type = value->value.type->data.unionation.tag_type;
12797 assert(tag_type->id == TypeTableEntryIdEnum);
1283812798
1283912799 if (instr_is_comptime(value)) {
1284012800 ConstExprValue *val = ir_resolve_const(ira, value, UndefBad);
......@@ -12845,11 +12805,11 @@ static IrInstruction *ir_analyze_enum_tag(IrAnalyze *ira, IrInstruction *source_
1284512805 source_instr->scope, source_instr->source_node);
1284612806 const_instruction->base.value.type = tag_type;
1284712807 const_instruction->base.value.special = ConstValSpecialStatic;
12848 bigint_init_bigint(&const_instruction->base.value.data.x_bigint, &val->data.x_enum.tag);
12808 bigint_init_bigint(&const_instruction->base.value.data.x_enum_tag, &val->data.x_union.tag);
1284912809 return &const_instruction->base;
1285012810 }
1285112811
12852 IrInstruction *result = ir_build_enum_tag(&ira->new_irb, source_instr->scope, source_instr->source_node, value);
12812 IrInstruction *result = ir_build_union_tag(&ira->new_irb, source_instr->scope, source_instr->source_node, value);
1285312813 result->value.type = tag_type;
1285412814 return result;
1285512815}
......@@ -12880,7 +12840,7 @@ static TypeTableEntry *ir_analyze_instruction_switch_br(IrAnalyze *ira,
1288012840 return ir_unreach_error(ira);
1288112841
1288212842 if (case_value->value.type->id == TypeTableEntryIdEnum) {
12883 case_value = ir_analyze_enum_tag(ira, &switch_br_instruction->base, case_value);
12843 case_value = ir_analyze_union_tag(ira, &switch_br_instruction->base, case_value);
1288412844 if (type_is_invalid(case_value->value.type))
1288512845 return ir_unreach_error(ira);
1288612846 }
......@@ -12927,7 +12887,7 @@ static TypeTableEntry *ir_analyze_instruction_switch_br(IrAnalyze *ira,
1292712887 continue;
1292812888
1292912889 if (new_value->value.type->id == TypeTableEntryIdEnum) {
12930 new_value = ir_analyze_enum_tag(ira, &switch_br_instruction->base, new_value);
12890 new_value = ir_analyze_union_tag(ira, &switch_br_instruction->base, new_value);
1293112891 if (type_is_invalid(new_value->value.type))
1293212892 continue;
1293312893 }
......@@ -13009,34 +12969,54 @@ static TypeTableEntry *ir_analyze_instruction_switch_target(IrAnalyze *ira,
1300912969
1301012970 ir_build_load_ptr_from(&ira->new_irb, &switch_target_instruction->base, target_value_ptr);
1301112971 return target_type;
13012 case TypeTableEntryIdEnum:
13013 {
13014 TypeTableEntry *tag_type = target_type->data.enumeration.tag_type;
13015 assert(tag_type != nullptr);
13016 if (pointee_val) {
13017 ConstExprValue *out_val = ir_build_const_from(ira, &switch_target_instruction->base);
13018 bigint_init_bigint(&out_val->data.x_bigint, &pointee_val->data.x_enum.tag);
13019 return tag_type;
13020 }
13021
13022 IrInstruction *enum_value = ir_build_load_ptr(&ira->new_irb, switch_target_instruction->base.scope,
13023 switch_target_instruction->base.source_node, target_value_ptr);
13024 enum_value->value.type = target_type;
13025 ir_build_enum_tag_from(&ira->new_irb, &switch_target_instruction->base, enum_value);
12972 case TypeTableEntryIdUnion: {
12973 if (target_type->data.unionation.gen_tag_index == SIZE_MAX) {
12974 ErrorMsg *msg = ir_add_error(ira, target_value_ptr,
12975 buf_sprintf("switch on union which has no attached enum"));
12976 add_error_note(ira->codegen, msg, target_type->data.unionation.decl_node,
12977 buf_sprintf("union declared here"));
12978 return ira->codegen->builtin_types.entry_invalid;
12979 }
12980 TypeTableEntry *tag_type = target_type->data.unionation.tag_type;
12981 assert(tag_type != nullptr);
12982 if (pointee_val) {
12983 ConstExprValue *out_val = ir_build_const_from(ira, &switch_target_instruction->base);
12984 bigint_init_bigint(&out_val->data.x_enum_tag, &pointee_val->data.x_union.tag);
1302612985 return tag_type;
1302712986 }
12987
12988 IrInstruction *union_value = ir_build_load_ptr(&ira->new_irb, switch_target_instruction->base.scope,
12989 switch_target_instruction->base.source_node, target_value_ptr);
12990 union_value->value.type = target_type;
12991
12992 IrInstruction *union_tag_inst = ir_build_union_tag(&ira->new_irb, switch_target_instruction->base.scope,
12993 switch_target_instruction->base.source_node, union_value);
12994 union_tag_inst->value.type = tag_type;
12995 ir_link_new_instruction(union_tag_inst, &switch_target_instruction->base);
12996 return tag_type;
12997 }
12998 case TypeTableEntryIdEnum: {
12999 if (pointee_val) {
13000 ConstExprValue *out_val = ir_build_const_from(ira, &switch_target_instruction->base);
13001 bigint_init_bigint(&out_val->data.x_enum_tag, &pointee_val->data.x_enum_tag);
13002 return target_type;
13003 }
13004
13005 IrInstruction *enum_value = ir_build_load_ptr(&ira->new_irb, switch_target_instruction->base.scope,
13006 switch_target_instruction->base.source_node, target_value_ptr);
13007 enum_value->value.type = target_type;
13008 ir_link_new_instruction(enum_value, &switch_target_instruction->base);
13009 return target_type;
13010 }
1302813011 case TypeTableEntryIdErrorUnion:
13029 // see https://github.com/andrewrk/zig/issues/83
13012 // see https://github.com/andrewrk/zig/issues/632
1303013013 zig_panic("TODO switch on error union");
13031 case TypeTableEntryIdEnumTag:
13032 zig_panic("TODO switch on enum tag type");
1303313014 case TypeTableEntryIdUnreachable:
1303413015 case TypeTableEntryIdArray:
1303513016 case TypeTableEntryIdStruct:
1303613017 case TypeTableEntryIdUndefLit:
1303713018 case TypeTableEntryIdNullLit:
1303813019 case TypeTableEntryIdMaybe:
13039 case TypeTableEntryIdUnion:
1304013020 case TypeTableEntryIdBlock:
1304113021 case TypeTableEntryIdBoundFn:
1304213022 case TypeTableEntryIdArgTuple:
......@@ -13059,19 +13039,13 @@ static TypeTableEntry *ir_analyze_instruction_switch_var(IrAnalyze *ira, IrInstr
1305913039
1306013040 assert(target_value_ptr->value.type->id == TypeTableEntryIdPointer);
1306113041 TypeTableEntry *target_type = target_value_ptr->value.type->data.pointer.child_type;
13062 if (target_type->id == TypeTableEntryIdEnum) {
13042 if (target_type->id == TypeTableEntryIdUnion) {
1306313043 ConstExprValue *prong_val = ir_resolve_const(ira, prong_value, UndefBad);
1306413044 if (!prong_val)
1306513045 return ira->codegen->builtin_types.entry_invalid;
1306613046
13067 TypeEnumField *field;
13068 if (prong_value->value.type->id == TypeTableEntryIdEnumTag) {
13069 field = find_enum_field_by_tag(target_type, &prong_val->data.x_bigint);
13070 } else if (prong_value->value.type->id == TypeTableEntryIdEnum) {
13071 field = find_enum_field_by_tag(target_type, &prong_val->data.x_enum.tag);
13072 } else {
13073 zig_unreachable();
13074 }
13047 assert(prong_value->value.type->id == TypeTableEntryIdEnum);
13048 TypeUnionField *field = find_union_field_by_tag(target_type, &prong_val->data.x_enum_tag);
1307513049
1307613050 if (instr_is_comptime(target_value_ptr)) {
1307713051 ConstExprValue *target_val_ptr = ir_resolve_const(ira, target_value_ptr, UndefBad);
......@@ -13082,11 +13056,11 @@ static TypeTableEntry *ir_analyze_instruction_switch_var(IrAnalyze *ira, IrInstr
1308213056 ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
1308313057 out_val->data.x_ptr.special = ConstPtrSpecialRef;
1308413058 out_val->data.x_ptr.mut = target_val_ptr->data.x_ptr.mut;
13085 out_val->data.x_ptr.data.ref.pointee = pointee_val->data.x_enum.payload;
13059 out_val->data.x_ptr.data.ref.pointee = pointee_val->data.x_union.payload;
1308613060 return get_pointer_to_type(ira->codegen, field->type_entry, target_val_ptr->type->data.pointer.is_const);
1308713061 }
1308813062
13089 ir_build_enum_field_ptr_from(&ira->new_irb, &instruction->base, target_value_ptr, field);
13063 ir_build_union_field_ptr_from(&ira->new_irb, &instruction->base, target_value_ptr, field);
1309013064 return get_pointer_to_type(ira->codegen, field->type_entry,
1309113065 target_value_ptr->value.type->data.pointer.is_const);
1309213066 } else {
......@@ -13096,10 +13070,10 @@ static TypeTableEntry *ir_analyze_instruction_switch_var(IrAnalyze *ira, IrInstr
1309613070 }
1309713071}
1309813072
13099static TypeTableEntry *ir_analyze_instruction_enum_tag(IrAnalyze *ira, IrInstructionEnumTag *enum_tag_instruction) {
13100 IrInstruction *value = enum_tag_instruction->value->other;
13101 IrInstruction *new_instruction = ir_analyze_enum_tag(ira, &enum_tag_instruction->base, value);
13102 ir_link_new_instruction(new_instruction, &enum_tag_instruction->base);
13073static TypeTableEntry *ir_analyze_instruction_union_tag(IrAnalyze *ira, IrInstructionUnionTag *instruction) {
13074 IrInstruction *value = instruction->value->other;
13075 IrInstruction *new_instruction = ir_analyze_union_tag(ira, &instruction->base, value);
13076 ir_link_new_instruction(new_instruction, &instruction->base);
1310313077 return new_instruction->value.type;
1310413078}
1310513079
......@@ -13255,7 +13229,7 @@ static TypeTableEntry *ir_analyze_container_init_fields_union(IrAnalyze *ira, Ir
1325513229
1325613230 ConstExprValue *out_val = ir_build_const_from(ira, instruction);
1325713231 out_val->data.x_union.payload = field_val;
13258 out_val->data.x_union.tag = type_field->value;
13232 out_val->data.x_union.tag = type_field->enum_field->value;
1325913233
1326013234 ConstParent *parent = get_const_val_parent(ira->codegen, field_val);
1326113235 if (parent != nullptr) {
......@@ -13502,46 +13476,9 @@ static TypeTableEntry *ir_analyze_instruction_container_init_list(IrAnalyze *ira
1350213476 buf_ptr(&container_type->name)));
1350313477 return ira->codegen->builtin_types.entry_invalid;
1350413478 }
13505 } else if (container_type_value->value.type->id == TypeTableEntryIdEnumTag) {
13506 if (elem_count != 1) {
13507 ir_add_error(ira, &instruction->base, buf_sprintf("enum initialization requires exactly one element"));
13508 return ira->codegen->builtin_types.entry_invalid;
13509 }
13510 ConstExprValue *tag_value = ir_resolve_const(ira, container_type_value, UndefBad);
13511 if (!tag_value)
13512 return ira->codegen->builtin_types.entry_invalid;
13513
13514 TypeTableEntry *enum_type = container_type_value->value.type->data.enum_tag.enum_type;
13515
13516 TypeEnumField *field = find_enum_field_by_tag(enum_type, &tag_value->data.x_bigint);
13517 assert(field != nullptr);
13518 TypeTableEntry *this_field_type = field->type_entry;
13519
13520 IrInstruction *init_value = instruction->items[0]->other;
13521 if (type_is_invalid(init_value->value.type))
13522 return ira->codegen->builtin_types.entry_invalid;
13523
13524 IrInstruction *casted_init_value = ir_implicit_cast(ira, init_value, this_field_type);
13525 if (casted_init_value == ira->codegen->invalid_instruction)
13526 return ira->codegen->builtin_types.entry_invalid;
13527
13528 if (instr_is_comptime(casted_init_value)) {
13529 ConstExprValue *init_val = ir_resolve_const(ira, casted_init_value, UndefOk);
13530 if (!init_val)
13531 return ira->codegen->builtin_types.entry_invalid;
13532 ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
13533 bigint_init_bigint(&out_val->data.x_enum.tag, &tag_value->data.x_bigint);
13534 out_val->data.x_enum.payload = init_val;
13535 return enum_type;
13536 }
13537
13538 IrInstruction *new_instruction = ir_build_init_enum_from(&ira->new_irb, &instruction->base,
13539 enum_type, field, casted_init_value);
13540 ir_add_alloca(ira, new_instruction, enum_type);
13541 return enum_type;
1354213479 } else {
1354313480 ir_add_error(ira, container_type_value,
13544 buf_sprintf("expected type, found '%s'", buf_ptr(&container_type_value->value.type->name)));
13481 buf_sprintf("expected type, found '%s' value", buf_ptr(&container_type_value->value.type->name)));
1354513482 return ira->codegen->builtin_types.entry_invalid;
1354613483 }
1354713484}
......@@ -13584,8 +13521,8 @@ static TypeTableEntry *ir_analyze_min_max(IrAnalyze *ira, IrInstruction *source_
1358413521 eval_min_max_value(ira->codegen, target_type, out_val, is_max);
1358513522 return target_type;
1358613523 }
13587 case TypeTableEntryIdEnumTag:
13588 zig_panic("TODO min/max value for enum tag type");
13524 case TypeTableEntryIdEnum:
13525 zig_panic("TODO min/max value for enum type");
1358913526 case TypeTableEntryIdVar:
1359013527 case TypeTableEntryIdMetaType:
1359113528 case TypeTableEntryIdUnreachable:
......@@ -13599,7 +13536,6 @@ static TypeTableEntry *ir_analyze_min_max(IrAnalyze *ira, IrInstruction *source_
1359913536 case TypeTableEntryIdMaybe:
1360013537 case TypeTableEntryIdErrorUnion:
1360113538 case TypeTableEntryIdPureError:
13602 case TypeTableEntryIdEnum:
1360313539 case TypeTableEntryIdUnion:
1360413540 case TypeTableEntryIdFn:
1360513541 case TypeTableEntryIdNamespace:
......@@ -13707,20 +13643,18 @@ static TypeTableEntry *ir_analyze_instruction_enum_tag_name(IrAnalyze *ira, IrIn
1370713643 if (type_is_invalid(target->value.type))
1370813644 return ira->codegen->builtin_types.entry_invalid;
1370913645
13710 assert(target->value.type->id == TypeTableEntryIdEnumTag);
13646 assert(target->value.type->id == TypeTableEntryIdEnum);
1371113647
1371213648 if (instr_is_comptime(target)) {
13713 TypeTableEntry *enum_type = target->value.type->data.enum_tag.enum_type;
13714 uint64_t tag_value = bigint_as_unsigned(&target->value.data.x_bigint);
13715 TypeEnumField *field = &enum_type->data.enumeration.fields[tag_value];
13649 TypeEnumField *field = find_enum_field_by_tag(target->value.type, &target->value.data.x_bigint);
1371613650 ConstExprValue *array_val = create_const_str_lit(ira->codegen, field->name);
1371713651 ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
1371813652 init_const_slice(ira->codegen, out_val, array_val, 0, buf_len(field->name), true);
1371913653 return out_val->type;
1372013654 }
1372113655
13722 if (!target->value.type->data.enum_tag.generate_name_table) {
13723 target->value.type->data.enum_tag.generate_name_table = true;
13656 if (!target->value.type->data.enumeration.generate_name_table) {
13657 target->value.type->data.enumeration.generate_name_table = true;
1372413658 ira->codegen->name_table_enums.append(target->value.type);
1372513659 }
1372613660
......@@ -13869,7 +13803,7 @@ static TypeTableEntry *ir_analyze_instruction_type_id(IrAnalyze *ira,
1386913803 TypeTableEntry *result_type = var_value->data.x_type;
1387013804
1387113805 ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
13872 bigint_init_unsigned(&out_val->data.x_enum.tag, type_id_index(type_entry->id));
13806 bigint_init_unsigned(&out_val->data.x_enum_tag, type_id_index(type_entry->id));
1387313807 return result_type;
1387413808}
1387513809
......@@ -14698,14 +14632,14 @@ static TypeTableEntry *ir_analyze_instruction_member_type(IrAnalyze *ira, IrInst
1469814632 ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
1469914633 out_val->data.x_type = field->type_entry;
1470014634 return ira->codegen->builtin_types.entry_type;
14701 } else if (container_type->id == TypeTableEntryIdEnum) {
14702 if (member_index >= container_type->data.enumeration.src_field_count) {
14635 } else if (container_type->id == TypeTableEntryIdUnion) {
14636 if (member_index >= container_type->data.unionation.src_field_count) {
1470314637 ir_add_error(ira, index_value,
1470414638 buf_sprintf("member index %" ZIG_PRI_u64 " out of bounds; '%s' has %" PRIu32 " members",
14705 member_index, buf_ptr(&container_type->name), container_type->data.enumeration.src_field_count));
14639 member_index, buf_ptr(&container_type->name), container_type->data.unionation.src_field_count));
1470614640 return ira->codegen->builtin_types.entry_invalid;
1470714641 }
14708 TypeEnumField *field = &container_type->data.enumeration.fields[member_index];
14642 TypeUnionField *field = &container_type->data.unionation.fields[member_index];
1470914643
1471014644 ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
1471114645 out_val->data.x_type = field->type_entry;
......@@ -14749,6 +14683,18 @@ static TypeTableEntry *ir_analyze_instruction_member_name(IrAnalyze *ira, IrInst
1474914683 }
1475014684 TypeEnumField *field = &container_type->data.enumeration.fields[member_index];
1475114685
14686 ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
14687 init_const_str_lit(ira->codegen, out_val, field->name);
14688 return out_val->type;
14689 } else if (container_type->id == TypeTableEntryIdUnion) {
14690 if (member_index >= container_type->data.unionation.src_field_count) {
14691 ir_add_error(ira, index_value,
14692 buf_sprintf("member index %" ZIG_PRI_u64 " out of bounds; '%s' has %" PRIu32 " members",
14693 member_index, buf_ptr(&container_type->name), container_type->data.unionation.src_field_count));
14694 return ira->codegen->builtin_types.entry_invalid;
14695 }
14696 TypeUnionField *field = &container_type->data.unionation.fields[member_index];
14697
1475214698 ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
1475314699 init_const_str_lit(ira->codegen, out_val, field->name);
1475414700 return out_val->type;
......@@ -14819,7 +14765,6 @@ static TypeTableEntry *ir_analyze_instruction_align_of(IrAnalyze *ira, IrInstruc
1481914765 case TypeTableEntryIdErrorUnion:
1482014766 case TypeTableEntryIdPureError:
1482114767 case TypeTableEntryIdEnum:
14822 case TypeTableEntryIdEnumTag:
1482314768 case TypeTableEntryIdUnion:
1482414769 case TypeTableEntryIdFn:
1482514770 {
......@@ -15125,10 +15070,9 @@ static TypeTableEntry *ir_analyze_instruction_check_switch_prongs(IrAnalyze *ira
1512515070 if (type_is_invalid(switch_type))
1512615071 return ira->codegen->builtin_types.entry_invalid;
1512715072
15128 if (switch_type->id == TypeTableEntryIdEnumTag) {
15129 TypeTableEntry *enum_type = switch_type->data.enum_tag.enum_type;
15073 if (switch_type->id == TypeTableEntryIdEnum) {
1513015074 HashMap<BigInt, AstNode *, bigint_hash, bigint_eql> field_prev_uses = {};
15131 field_prev_uses.init(enum_type->data.enumeration.src_field_count);
15075 field_prev_uses.init(switch_type->data.enumeration.src_field_count);
1513215076
1513315077 for (size_t range_i = 0; range_i < instruction->range_count; range_i += 1) {
1513415078 IrInstructionCheckSwitchProngsRange *range = &instruction->ranges[range_i];
......@@ -15141,22 +15085,13 @@ static TypeTableEntry *ir_analyze_instruction_check_switch_prongs(IrAnalyze *ira
1514115085 if (type_is_invalid(end_value->value.type))
1514215086 return ira->codegen->builtin_types.entry_invalid;
1514315087
15088 assert(start_value->value.type->id == TypeTableEntryIdEnum);
1514415089 BigInt start_index;
15090 bigint_init_bigint(&start_index, &start_value->value.data.x_enum_tag);
15091
15092 assert(end_value->value.type->id == TypeTableEntryIdEnum);
1514515093 BigInt end_index;
15146 if (start_value->value.type->id == TypeTableEntryIdEnumTag) {
15147 bigint_init_bigint(&start_index, &start_value->value.data.x_bigint);
15148 } else if (start_value->value.type->id == TypeTableEntryIdEnum) {
15149 bigint_init_bigint(&start_index, &start_value->value.data.x_enum.tag);
15150 } else {
15151 zig_unreachable();
15152 }
15153 if (end_value->value.type->id == TypeTableEntryIdEnumTag) {
15154 bigint_init_bigint(&end_index, &end_value->value.data.x_bigint);
15155 } else if (end_value->value.type->id == TypeTableEntryIdEnum) {
15156 bigint_init_bigint(&end_index, &end_value->value.data.x_enum.tag);
15157 } else {
15158 zig_unreachable();
15159 }
15094 bigint_init_bigint(&end_index, &end_value->value.data.x_enum_tag);
1516015095
1516115096 BigInt field_index;
1516215097 bigint_init_bigint(&field_index, &start_index);
......@@ -15168,10 +15103,10 @@ static TypeTableEntry *ir_analyze_instruction_check_switch_prongs(IrAnalyze *ira
1516815103 auto entry = field_prev_uses.put_unique(field_index, start_value->source_node);
1516915104 if (entry) {
1517015105 AstNode *prev_node = entry->value;
15171 TypeEnumField *enum_field = find_enum_field_by_tag(enum_type, &field_index);
15106 TypeEnumField *enum_field = find_enum_field_by_tag(switch_type, &field_index);
1517215107 assert(enum_field != nullptr);
1517315108 ErrorMsg *msg = ir_add_error(ira, start_value,
15174 buf_sprintf("duplicate switch value: '%s.%s'", buf_ptr(&enum_type->name),
15109 buf_sprintf("duplicate switch value: '%s.%s'", buf_ptr(&switch_type->name),
1517515110 buf_ptr(enum_field->name)));
1517615111 add_error_note(ira->codegen, msg, prev_node, buf_sprintf("other value is here"));
1517715112 }
......@@ -15179,13 +15114,13 @@ static TypeTableEntry *ir_analyze_instruction_check_switch_prongs(IrAnalyze *ira
1517915114 }
1518015115 }
1518115116 if (!instruction->have_else_prong) {
15182 for (uint32_t i = 0; i < enum_type->data.enumeration.src_field_count; i += 1) {
15183 TypeEnumField *enum_field = &enum_type->data.enumeration.fields[i];
15117 for (uint32_t i = 0; i < switch_type->data.enumeration.src_field_count; i += 1) {
15118 TypeEnumField *enum_field = &switch_type->data.enumeration.fields[i];
1518415119
1518515120 auto entry = field_prev_uses.maybe_get(enum_field->value);
1518615121 if (!entry) {
1518715122 ir_add_error(ira, &instruction->base,
15188 buf_sprintf("enumeration value '%s.%s' not handled in switch", buf_ptr(&enum_type->name),
15123 buf_sprintf("enumeration value '%s.%s' not handled in switch", buf_ptr(&switch_type->name),
1518915124 buf_ptr(enum_field->name)));
1519015125 }
1519115126 }
......@@ -15481,8 +15416,6 @@ static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue
1548115416 zig_panic("TODO buf_write_value_bytes pure error type");
1548215417 case TypeTableEntryIdEnum:
1548315418 zig_panic("TODO buf_write_value_bytes enum type");
15484 case TypeTableEntryIdEnumTag:
15485 zig_panic("TODO buf_write_value_bytes enum tag type");
1548615419 case TypeTableEntryIdFn:
1548715420 zig_panic("TODO buf_write_value_bytes fn type");
1548815421 case TypeTableEntryIdUnion:
......@@ -15541,8 +15474,6 @@ static void buf_read_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue
1554115474 zig_panic("TODO buf_read_value_bytes pure error type");
1554215475 case TypeTableEntryIdEnum:
1554315476 zig_panic("TODO buf_read_value_bytes enum type");
15544 case TypeTableEntryIdEnumTag:
15545 zig_panic("TODO buf_read_value_bytes enum tag type");
1554615477 case TypeTableEntryIdFn:
1554715478 zig_panic("TODO buf_read_value_bytes fn type");
1554815479 case TypeTableEntryIdUnion:
......@@ -15920,11 +15851,8 @@ static TypeTableEntry *ir_analyze_instruction_enum_tag_type(IrAnalyze *ira, IrIn
1592015851 if (type_is_invalid(enum_type))
1592115852 return ira->codegen->builtin_types.entry_invalid;
1592215853
15923 TypeTableEntry *non_int_tag_type = enum_type->data.enumeration.tag_type;
15924 assert(non_int_tag_type->id == TypeTableEntryIdEnumTag);
15925
1592615854 ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
15927 out_val->data.x_type = non_int_tag_type->data.enum_tag.int_type;
15855 out_val->data.x_type = enum_type->data.enumeration.tag_int_type;
1592815856 return ira->codegen->builtin_types.entry_type;
1592915857}
1593015858
......@@ -15938,9 +15866,7 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi
1593815866 case IrInstructionIdStructInit:
1593915867 case IrInstructionIdUnionInit:
1594015868 case IrInstructionIdStructFieldPtr:
15941 case IrInstructionIdEnumFieldPtr:
1594215869 case IrInstructionIdUnionFieldPtr:
15943 case IrInstructionIdInitEnum:
1594415870 case IrInstructionIdMaybeWrap:
1594515871 case IrInstructionIdErrWrapCode:
1594615872 case IrInstructionIdErrWrapPayload:
......@@ -16012,8 +15938,8 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi
1601215938 return ir_analyze_instruction_switch_target(ira, (IrInstructionSwitchTarget *)instruction);
1601315939 case IrInstructionIdSwitchVar:
1601415940 return ir_analyze_instruction_switch_var(ira, (IrInstructionSwitchVar *)instruction);
16015 case IrInstructionIdEnumTag:
16016 return ir_analyze_instruction_enum_tag(ira, (IrInstructionEnumTag *)instruction);
15941 case IrInstructionIdUnionTag:
15942 return ir_analyze_instruction_union_tag(ira, (IrInstructionUnionTag *)instruction);
1601715943 case IrInstructionIdImport:
1601815944 return ir_analyze_instruction_import(ira, (IrInstructionImport *)instruction);
1601915945 case IrInstructionIdArrayLen:
......@@ -16260,7 +16186,6 @@ bool ir_has_side_effects(IrInstruction *instruction) {
1626016186 case IrInstructionIdPtrTypeChild:
1626116187 case IrInstructionIdArrayLen:
1626216188 case IrInstructionIdStructFieldPtr:
16263 case IrInstructionIdEnumFieldPtr:
1626416189 case IrInstructionIdUnionFieldPtr:
1626516190 case IrInstructionIdArrayType:
1626616191 case IrInstructionIdSliceType:
......@@ -16271,7 +16196,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {
1627116196 case IrInstructionIdCtz:
1627216197 case IrInstructionIdSwitchVar:
1627316198 case IrInstructionIdSwitchTarget:
16274 case IrInstructionIdEnumTag:
16199 case IrInstructionIdUnionTag:
1627516200 case IrInstructionIdRef:
1627616201 case IrInstructionIdMinValue:
1627716202 case IrInstructionIdMaxValue:
......@@ -16293,7 +16218,6 @@ bool ir_has_side_effects(IrInstruction *instruction) {
1629316218 case IrInstructionIdErrWrapPayload:
1629416219 case IrInstructionIdFnProto:
1629516220 case IrInstructionIdTestComptime:
16296 case IrInstructionIdInitEnum:
1629716221 case IrInstructionIdPtrCast:
1629816222 case IrInstructionIdBitCast:
1629916223 case IrInstructionIdWidenOrShorten:
src/ir_print.cpp+6-25
......@@ -291,7 +291,7 @@ static void ir_print_struct_init(IrPrint *irp, IrInstructionStructInit *instruct
291291}
292292
293293static void ir_print_union_init(IrPrint *irp, IrInstructionUnionInit *instruction) {
294 Buf *field_name = instruction->field->name;
294 Buf *field_name = instruction->field->enum_field->name;
295295
296296 fprintf(irp->f, "%s {", buf_ptr(&instruction->union_type->name));
297297 fprintf(irp->f, ".%s = ", buf_ptr(field_name));
......@@ -361,17 +361,10 @@ static void ir_print_struct_field_ptr(IrPrint *irp, IrInstructionStructFieldPtr
361361 fprintf(irp->f, ")");
362362}
363363
364static void ir_print_enum_field_ptr(IrPrint *irp, IrInstructionEnumFieldPtr *instruction) {
365 fprintf(irp->f, "@EnumFieldPtr(&");
366 ir_print_other_instruction(irp, instruction->enum_ptr);
367 fprintf(irp->f, ".%s", buf_ptr(instruction->field->name));
368 fprintf(irp->f, ")");
369}
370
371364static void ir_print_union_field_ptr(IrPrint *irp, IrInstructionUnionFieldPtr *instruction) {
372365 fprintf(irp->f, "@UnionFieldPtr(&");
373366 ir_print_other_instruction(irp, instruction->union_ptr);
374 fprintf(irp->f, ".%s", buf_ptr(instruction->field->name));
367 fprintf(irp->f, ".%s", buf_ptr(instruction->field->enum_field->name));
375368 fprintf(irp->f, ")");
376369}
377370
......@@ -509,8 +502,8 @@ static void ir_print_switch_target(IrPrint *irp, IrInstructionSwitchTarget *inst
509502 ir_print_other_instruction(irp, instruction->target_value_ptr);
510503}
511504
512static void ir_print_enum_tag(IrPrint *irp, IrInstructionEnumTag *instruction) {
513 fprintf(irp->f, "enumtag ");
505static void ir_print_union_tag(IrPrint *irp, IrInstructionUnionTag *instruction) {
506 fprintf(irp->f, "uniontag ");
514507 ir_print_other_instruction(irp, instruction->value);
515508}
516509
......@@ -799,12 +792,6 @@ static void ir_print_test_comptime(IrPrint *irp, IrInstructionTestComptime *inst
799792 fprintf(irp->f, ")");
800793}
801794
802static void ir_print_init_enum(IrPrint *irp, IrInstructionInitEnum *instruction) {
803 fprintf(irp->f, "%s.%s {", buf_ptr(&instruction->enum_type->name), buf_ptr(instruction->field->name));
804 ir_print_other_instruction(irp, instruction->init_value);
805 fprintf(irp->f, "}");
806}
807
808795static void ir_print_ptr_cast(IrPrint *irp, IrInstructionPtrCast *instruction) {
809796 fprintf(irp->f, "@ptrCast(");
810797 if (instruction->dest_type) {
......@@ -1078,9 +1065,6 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
10781065 case IrInstructionIdStructFieldPtr:
10791066 ir_print_struct_field_ptr(irp, (IrInstructionStructFieldPtr *)instruction);
10801067 break;
1081 case IrInstructionIdEnumFieldPtr:
1082 ir_print_enum_field_ptr(irp, (IrInstructionEnumFieldPtr *)instruction);
1083 break;
10841068 case IrInstructionIdUnionFieldPtr:
10851069 ir_print_union_field_ptr(irp, (IrInstructionUnionFieldPtr *)instruction);
10861070 break;
......@@ -1123,8 +1107,8 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
11231107 case IrInstructionIdSwitchTarget:
11241108 ir_print_switch_target(irp, (IrInstructionSwitchTarget *)instruction);
11251109 break;
1126 case IrInstructionIdEnumTag:
1127 ir_print_enum_tag(irp, (IrInstructionEnumTag *)instruction);
1110 case IrInstructionIdUnionTag:
1111 ir_print_union_tag(irp, (IrInstructionUnionTag *)instruction);
11281112 break;
11291113 case IrInstructionIdImport:
11301114 ir_print_import(irp, (IrInstructionImport *)instruction);
......@@ -1237,9 +1221,6 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
12371221 case IrInstructionIdTestComptime:
12381222 ir_print_test_comptime(irp, (IrInstructionTestComptime *)instruction);
12391223 break;
1240 case IrInstructionIdInitEnum:
1241 ir_print_init_enum(irp, (IrInstructionInitEnum *)instruction);
1242 break;
12431224 case IrInstructionIdPtrCast:
12441225 ir_print_ptr_cast(irp, (IrInstructionPtrCast *)instruction);
12451226 break;
src/parser.cpp+25-4
......@@ -2377,7 +2377,9 @@ static AstNode *ast_parse_use(ParseContext *pc, size_t *token_index, VisibMod vi
23772377}
23782378
23792379/*
2380ContainerDecl = option("extern" | "packed") ("struct" | "union" | ("enum" option(GroupedExpression))) "{" many(ContainerMember) "}"
2380ContainerDecl = option("extern" | "packed")
2381 ("struct" option(GroupedExpression) | "union" option("enum" option(GroupedExpression) | GroupedExpression) | ("enum" option(GroupedExpression)))
2382 "{" many(ContainerMember) "}"
23812383ContainerMember = (ContainerField | FnDef | GlobalVarDecl)
23822384ContainerField = Symbol option(":" PrefixOpExpression option("=" PrefixOpExpression ","
23832385*/
......@@ -2414,7 +2416,28 @@ static AstNode *ast_parse_container_decl(ParseContext *pc, size_t *token_index,
24142416 AstNode *node = ast_create_node(pc, NodeTypeContainerDecl, first_token);
24152417 node->data.container_decl.layout = layout;
24162418 node->data.container_decl.kind = kind;
2417 node->data.container_decl.init_arg_expr = ast_parse_grouped_expr(pc, token_index, false);
2419
2420 if (kind == ContainerKindUnion) {
2421 Token *lparen_token = &pc->tokens->at(*token_index);
2422 if (lparen_token->id == TokenIdLParen) {
2423 Token *enum_token = &pc->tokens->at(*token_index + 1);
2424 if (enum_token->id == TokenIdKeywordEnum) {
2425 Token *paren_token = &pc->tokens->at(*token_index + 2);
2426 if (paren_token->id == TokenIdLParen) {
2427 node->data.container_decl.auto_enum = true;
2428 *token_index += 2;
2429 node->data.container_decl.init_arg_expr = ast_parse_grouped_expr(pc, token_index, true);
2430 ast_eat_token(pc, token_index, TokenIdRParen);
2431 } else if (paren_token->id == TokenIdRParen) {
2432 node->data.container_decl.auto_enum = true;
2433 *token_index += 3;
2434 }
2435 }
2436 }
2437 }
2438 if (!node->data.container_decl.auto_enum) {
2439 node->data.container_decl.init_arg_expr = ast_parse_grouped_expr(pc, token_index, false);
2440 }
24182441
24192442 ast_eat_token(pc, token_index, TokenIdLBrace);
24202443
......@@ -2461,8 +2484,6 @@ static AstNode *ast_parse_container_decl(ParseContext *pc, size_t *token_index,
24612484 if (colon_token->id == TokenIdColon) {
24622485 *token_index += 1;
24632486 field_node->data.struct_field.type = ast_parse_prefix_op_expr(pc, token_index, true);
2464 } else {
2465 field_node->data.struct_field.type = ast_create_void_type_node(pc, colon_token);
24662487 }
24672488 Token *eq_token = &pc->tokens->at(*token_index);
24682489 if (eq_token->id == TokenIdEq) {
std/build.zig+21-21
......@@ -69,8 +69,8 @@ pub const Builder = struct {
6969 used: bool,
7070 };
7171
72 const UserValue = enum {
73 Flag,
72 const UserValue = union(enum) {
73 Flag: void,
7474 Scalar: []const u8,
7575 List: ArrayList([]const u8),
7676 };
......@@ -450,7 +450,7 @@ pub const Builder = struct {
450450 pub fn addUserInputOption(self: &Builder, name: []const u8, value: []const u8) -> bool {
451451 if (%%self.user_input_options.put(name, UserInputOption {
452452 .name = name,
453 .value = UserValue.Scalar { value },
453 .value = UserValue { .Scalar = value },
454454 .used = false,
455455 })) |*prev_value| {
456456 // option already exists
......@@ -462,7 +462,7 @@ pub const Builder = struct {
462462 %%list.append(value);
463463 _ = %%self.user_input_options.put(name, UserInputOption {
464464 .name = name,
465 .value = UserValue.List { list },
465 .value = UserValue { .List = list },
466466 .used = false,
467467 });
468468 },
......@@ -471,7 +471,7 @@ pub const Builder = struct {
471471 %%list.append(value);
472472 _ = %%self.user_input_options.put(name, UserInputOption {
473473 .name = name,
474 .value = UserValue.List { *list },
474 .value = UserValue { .List = *list },
475475 .used = false,
476476 });
477477 },
......@@ -487,7 +487,7 @@ pub const Builder = struct {
487487 pub fn addUserInputFlag(self: &Builder, name: []const u8) -> bool {
488488 if (%%self.user_input_options.put(name, UserInputOption {
489489 .name = name,
490 .value = UserValue.Flag,
490 .value = UserValue {.Flag = {} },
491491 .used = false,
492492 })) |*prev_value| {
493493 switch (prev_value.value) {
......@@ -685,8 +685,8 @@ const CrossTarget = struct {
685685 environ: builtin.Environ,
686686};
687687
688const Target = enum {
689 Native,
688const Target = union(enum) {
689 Native: void,
690690 Cross: CrossTarget,
691691
692692 pub fn oFileExt(self: &const Target) -> []const u8 {
......@@ -844,7 +844,7 @@ pub const LibExeObjStep = struct {
844844 .kind = kind,
845845 .root_src = root_src,
846846 .name = name,
847 .target = Target.Native,
847 .target = Target { .Native = {} },
848848 .linker_script = null,
849849 .link_libs = BufSet.init(builder.allocator),
850850 .frameworks = BufSet.init(builder.allocator),
......@@ -879,7 +879,7 @@ pub const LibExeObjStep = struct {
879879 .kind = kind,
880880 .version = *version,
881881 .static = static,
882 .target = Target.Native,
882 .target = Target { .Native = {} },
883883 .cflags = ArrayList([]const u8).init(builder.allocator),
884884 .source_files = ArrayList([]const u8).init(builder.allocator),
885885 .object_files = ArrayList([]const u8).init(builder.allocator),
......@@ -948,8 +948,8 @@ pub const LibExeObjStep = struct {
948948 pub fn setTarget(self: &LibExeObjStep, target_arch: builtin.Arch, target_os: builtin.Os,
949949 target_environ: builtin.Environ)
950950 {
951 self.target = Target.Cross {
952 CrossTarget {
951 self.target = Target {
952 .Cross = CrossTarget {
953953 .arch = target_arch,
954954 .os = target_os,
955955 .environ = target_environ,
......@@ -1186,13 +1186,13 @@ pub const LibExeObjStep = struct {
11861186 Target.Native => {},
11871187 Target.Cross => |cross_target| {
11881188 %%zig_args.append("--target-arch");
1189 %%zig_args.append(@enumTagName(cross_target.arch));
1189 %%zig_args.append(@tagName(cross_target.arch));
11901190
11911191 %%zig_args.append("--target-os");
1192 %%zig_args.append(@enumTagName(cross_target.os));
1192 %%zig_args.append(@tagName(cross_target.os));
11931193
11941194 %%zig_args.append("--target-environ");
1195 %%zig_args.append(@enumTagName(cross_target.environ));
1195 %%zig_args.append(@tagName(cross_target.environ));
11961196 },
11971197 }
11981198
......@@ -1553,7 +1553,7 @@ pub const TestStep = struct {
15531553 .name_prefix = "",
15541554 .filter = null,
15551555 .link_libs = BufSet.init(builder.allocator),
1556 .target = Target.Native,
1556 .target = Target { .Native = {} },
15571557 .exec_cmd_args = null,
15581558 }
15591559 }
......@@ -1581,8 +1581,8 @@ pub const TestStep = struct {
15811581 pub fn setTarget(self: &TestStep, target_arch: builtin.Arch, target_os: builtin.Os,
15821582 target_environ: builtin.Environ)
15831583 {
1584 self.target = Target.Cross {
1585 CrossTarget {
1584 self.target = Target {
1585 .Cross = CrossTarget {
15861586 .arch = target_arch,
15871587 .os = target_os,
15881588 .environ = target_environ,
......@@ -1620,13 +1620,13 @@ pub const TestStep = struct {
16201620 Target.Native => {},
16211621 Target.Cross => |cross_target| {
16221622 %%zig_args.append("--target-arch");
1623 %%zig_args.append(@enumTagName(cross_target.arch));
1623 %%zig_args.append(@tagName(cross_target.arch));
16241624
16251625 %%zig_args.append("--target-os");
1626 %%zig_args.append(@enumTagName(cross_target.os));
1626 %%zig_args.append(@tagName(cross_target.os));
16271627
16281628 %%zig_args.append("--target-environ");
1629 %%zig_args.append(@enumTagName(cross_target.environ));
1629 %%zig_args.append(@tagName(cross_target.environ));
16301630 },
16311631 }
16321632
std/debug.zig+13-15
......@@ -280,7 +280,7 @@ const AbbrevAttr = struct {
280280 form_id: u64,
281281};
282282
283const FormValue = enum {
283const FormValue = union(enum) {
284284 Address: u64,
285285 Block: []u8,
286286 Const: Constant,
......@@ -475,7 +475,7 @@ fn readAllocBytes(allocator: &mem.Allocator, in_stream: &io.InStream, size: usiz
475475
476476fn parseFormValueBlockLen(allocator: &mem.Allocator, in_stream: &io.InStream, size: usize) -> %FormValue {
477477 const buf = %return readAllocBytes(allocator, in_stream, size);
478 return FormValue.Block { buf };
478 return FormValue { .Block = buf };
479479}
480480
481481fn parseFormValueBlock(allocator: &mem.Allocator, in_stream: &io.InStream, size: usize) -> %FormValue {
......@@ -484,7 +484,7 @@ fn parseFormValueBlock(allocator: &mem.Allocator, in_stream: &io.InStream, size:
484484}
485485
486486fn parseFormValueConstant(allocator: &mem.Allocator, in_stream: &io.InStream, signed: bool, size: usize) -> %FormValue {
487 FormValue.Const { Constant {
487 FormValue { .Const = Constant {
488488 .signed = signed,
489489 .payload = %return readAllocBytes(allocator, in_stream, size),
490490 }}
......@@ -510,7 +510,7 @@ fn parseFormValueTargetAddrSize(in_stream: &io.InStream) -> %u64 {
510510
511511fn parseFormValueRefLen(allocator: &mem.Allocator, in_stream: &io.InStream, size: usize) -> %FormValue {
512512 const buf = %return readAllocBytes(allocator, in_stream, size);
513 return FormValue.Ref { buf };
513 return FormValue { .Ref = buf };
514514}
515515
516516fn parseFormValueRef(allocator: &mem.Allocator, in_stream: &io.InStream, comptime T: type) -> %FormValue {
......@@ -520,7 +520,7 @@ fn parseFormValueRef(allocator: &mem.Allocator, in_stream: &io.InStream, comptim
520520
521521fn parseFormValue(allocator: &mem.Allocator, in_stream: &io.InStream, form_id: u64, is_64: bool) -> %FormValue {
522522 return switch (form_id) {
523 DW.FORM_addr => FormValue.Address { %return parseFormValueTargetAddrSize(in_stream) },
523 DW.FORM_addr => FormValue { .Address = %return parseFormValueTargetAddrSize(in_stream) },
524524 DW.FORM_block1 => parseFormValueBlock(allocator, in_stream, 1),
525525 DW.FORM_block2 => parseFormValueBlock(allocator, in_stream, 2),
526526 DW.FORM_block4 => parseFormValueBlock(allocator, in_stream, 4),
......@@ -540,13 +540,11 @@ fn parseFormValue(allocator: &mem.Allocator, in_stream: &io.InStream, form_id: u
540540 DW.FORM_exprloc => {
541541 const size = %return readULeb128(in_stream);
542542 const buf = %return readAllocBytes(allocator, in_stream, size);
543 return FormValue.ExprLoc { buf };
544 },
545 DW.FORM_flag => FormValue.Flag { (%return in_stream.readByte()) != 0 },
546 DW.FORM_flag_present => FormValue.Flag { true },
547 DW.FORM_sec_offset => FormValue.SecOffset {
548 %return parseFormValueDwarfOffsetSize(in_stream, is_64)
543 return FormValue { .ExprLoc = buf };
549544 },
545 DW.FORM_flag => FormValue { .Flag = (%return in_stream.readByte()) != 0 },
546 DW.FORM_flag_present => FormValue { .Flag = true },
547 DW.FORM_sec_offset => FormValue { .SecOffset = %return parseFormValueDwarfOffsetSize(in_stream, is_64) },
550548
551549 DW.FORM_ref1 => parseFormValueRef(allocator, in_stream, u8),
552550 DW.FORM_ref2 => parseFormValueRef(allocator, in_stream, u16),
......@@ -557,11 +555,11 @@ fn parseFormValue(allocator: &mem.Allocator, in_stream: &io.InStream, form_id: u
557555 parseFormValueRefLen(allocator, in_stream, ref_len)
558556 },
559557
560 DW.FORM_ref_addr => FormValue.RefAddr { %return parseFormValueDwarfOffsetSize(in_stream, is_64) },
561 DW.FORM_ref_sig8 => FormValue.RefSig8 { %return in_stream.readIntLe(u64) },
558 DW.FORM_ref_addr => FormValue { .RefAddr = %return parseFormValueDwarfOffsetSize(in_stream, is_64) },
559 DW.FORM_ref_sig8 => FormValue { .RefSig8 = %return in_stream.readIntLe(u64) },
562560
563 DW.FORM_string => FormValue.String { %return readStringRaw(allocator, in_stream) },
564 DW.FORM_strp => FormValue.StrPtr { %return parseFormValueDwarfOffsetSize(in_stream, is_64) },
561 DW.FORM_string => FormValue { .String = %return readStringRaw(allocator, in_stream) },
562 DW.FORM_strp => FormValue { .StrPtr = %return parseFormValueDwarfOffsetSize(in_stream, is_64) },
565563 DW.FORM_indirect => {
566564 const child_form_id = %return readULeb128(in_stream);
567565 parseFormValue(allocator, in_stream, child_form_id, is_64)
std/os/child_process.zig+5-5
......@@ -58,7 +58,7 @@ pub const ChildProcess = struct {
5858 err_pipe: if (is_windows) void else [2]i32,
5959 llnode: if (is_windows) void else LinkedList(&ChildProcess).Node,
6060
61 pub const Term = enum {
61 pub const Term = union(enum) {
6262 Exited: i32,
6363 Signal: i32,
6464 Stopped: i32,
......@@ -281,13 +281,13 @@ pub const ChildProcess = struct {
281281
282282 fn statusToTerm(status: i32) -> Term {
283283 return if (posix.WIFEXITED(status)) {
284 Term.Exited { posix.WEXITSTATUS(status) }
284 Term { .Exited = posix.WEXITSTATUS(status) }
285285 } else if (posix.WIFSIGNALED(status)) {
286 Term.Signal { posix.WTERMSIG(status) }
286 Term { .Signal = posix.WTERMSIG(status) }
287287 } else if (posix.WIFSTOPPED(status)) {
288 Term.Stopped { posix.WSTOPSIG(status) }
288 Term { .Stopped = posix.WSTOPSIG(status) }
289289 } else {
290 Term.Unknown { status }
290 Term { .Unknown = status }
291291 };
292292 }
293293
std/os/path.zig+1-1
......@@ -1016,7 +1016,7 @@ pub fn real(allocator: &Allocator, pathname: []const u8) -> %[]u8 {
10161016
10171017 return os.readLink(allocator, proc_path);
10181018 },
1019 else => @compileError("TODO implement os.path.real for " ++ @enumTagName(builtin.os)),
1019 else => @compileError("TODO implement os.path.real for " ++ @tagName(builtin.os)),
10201020 }
10211021}
10221022
test/cases/bugs/394.zig+2-2
......@@ -1,9 +1,9 @@
1const E = enum { A: [9]u8, B: u64, };
1const E = union(enum) { A: [9]u8, B: u64, };
22const S = struct { x: u8, y: E, };
33
44const assert = @import("std").debug.assert;
55
66test "bug 394 fixed" {
7 const x = S { .x = 3, .y = E.B {1} };
7 const x = S { .x = 3, .y = E {.B = 1 } };
88 assert(x.x == 3);
99}
test/cases/enum.zig+12-12
......@@ -2,8 +2,8 @@ const assert = @import("std").debug.assert;
22const mem = @import("std").mem;
33
44test "enum type" {
5 const foo1 = Foo.One {13};
6 const foo2 = Foo.Two { Point { .x = 1234, .y = 5678, }};
5 const foo1 = Foo{ .One = 13};
6 const foo2 = Foo{. Two = Point { .x = 1234, .y = 5678, }};
77 const bar = Bar.B;
88
99 assert(bar == Bar.B);
......@@ -24,12 +24,12 @@ const Point = struct {
2424 x: u64,
2525 y: u64,
2626};
27const Foo = enum {
27const Foo = union(enum) {
2828 One: i32,
2929 Two: Point,
3030 Three: void,
3131};
32const FooNoVoid = enum {
32const FooNoVoid = union(enum) {
3333 One: i32,
3434 Two: Point,
3535};
......@@ -41,13 +41,13 @@ const Bar = enum {
4141};
4242
4343fn returnAnInt(x: i32) -> Foo {
44 Foo.One { x }
44 Foo { .One = x }
4545}
4646
4747
4848test "constant enum with payload" {
49 var empty = AnEnumWithPayload.Empty;
50 var full = AnEnumWithPayload.Full {13};
49 var empty = AnEnumWithPayload {.Empty = {}};
50 var full = AnEnumWithPayload {.Full = 13};
5151 shouldBeEmpty(empty);
5252 shouldBeNotEmpty(full);
5353}
......@@ -66,8 +66,8 @@ fn shouldBeNotEmpty(x: &const AnEnumWithPayload) {
6666 }
6767}
6868
69const AnEnumWithPayload = enum {
70 Empty,
69const AnEnumWithPayload = union(enum) {
70 Empty: void,
7171 Full: i32,
7272};
7373
......@@ -109,13 +109,13 @@ const IntToEnumNumber = enum {
109109};
110110
111111
112test "@enumTagName" {
112test "@tagName" {
113113 assert(mem.eql(u8, testEnumTagNameBare(BareNumber.Three), "Three"));
114114 comptime assert(mem.eql(u8, testEnumTagNameBare(BareNumber.Three), "Three"));
115115}
116116
117117fn testEnumTagNameBare(n: BareNumber) -> []const u8 {
118 return @enumTagName(n);
118 return @tagName(n);
119119}
120120
121121const BareNumber = enum {
......@@ -132,7 +132,7 @@ test "enum alignment" {
132132 }
133133}
134134
135const AlignTestEnum = enum {
135const AlignTestEnum = union(enum) {
136136 A: [9]u8,
137137 B: u64,
138138};
test/cases/enum_with_members.zig+3-3
......@@ -2,7 +2,7 @@ const assert = @import("std").debug.assert;
22const mem = @import("std").mem;
33const fmt = @import("std").fmt;
44
5const ET = enum {
5const ET = union(enum) {
66 SINT: i32,
77 UINT: u32,
88
......@@ -15,8 +15,8 @@ const ET = enum {
1515};
1616
1717test "enum with members" {
18 const a = ET.SINT { -42 };
19 const b = ET.UINT { 42 };
18 const a = ET { .SINT = -42 };
19 const b = ET { .UINT = 42 };
2020 var buf: [20]u8 = undefined;
2121
2222 assert(%%a.print(buf[0..]) == 3);
test/cases/misc.zig+9-7
......@@ -324,8 +324,8 @@ test "constant enum initialization with differing sizes" {
324324 test3_1(test3_foo);
325325 test3_2(test3_bar);
326326}
327const Test3Foo = enum {
328 One,
327const Test3Foo = union(enum) {
328 One: void,
329329 Two: f32,
330330 Three: Test3Point,
331331};
......@@ -333,8 +333,8 @@ const Test3Point = struct {
333333 x: i32,
334334 y: i32,
335335};
336const test3_foo = Test3Foo.Three{Test3Point {.x = 3, .y = 4}};
337const test3_bar = Test3Foo.Two{13};
336const test3_foo = Test3Foo { .Three = Test3Point {.x = 3, .y = 4}};
337const test3_bar = Test3Foo { .Two = 13};
338338fn test3_1(f: &const Test3Foo) {
339339 switch (*f) {
340340 Test3Foo.Three => |pt| {
......@@ -449,7 +449,8 @@ fn testArray2DConstDoublePtr(ptr: &const f32) {
449449const Tid = builtin.TypeId;
450450const AStruct = struct { x: i32, };
451451const AnEnum = enum { One, Two, };
452const AnEnumWithPayload = enum { One: i32, Two, };
452const AUnionEnum = union(enum) { One: i32, Two: void, };
453const AUnion = union { One: void, Two: void };
453454
454455test "@typeId" {
455456 comptime {
......@@ -474,8 +475,9 @@ test "@typeId" {
474475 assert(@typeId(%i32) == Tid.ErrorUnion);
475476 assert(@typeId(error) == Tid.Error);
476477 assert(@typeId(AnEnum) == Tid.Enum);
477 assert(@typeId(@typeOf(AnEnumWithPayload.One)) == Tid.EnumTag);
478 // TODO union
478 assert(@typeId(@typeOf(AUnionEnum.One)) == Tid.Enum);
479 assert(@typeId(AUnionEnum) == Tid.Union);
480 assert(@typeId(AUnion) == Tid.Union);
479481 assert(@typeId(fn()) == Tid.Fn);
480482 assert(@typeId(@typeOf(builtin)) == Tid.Namespace);
481483 assert(@typeId(@typeOf({this})) == Tid.Block);
test/cases/reflection.zig+2-2
......@@ -62,8 +62,8 @@ const Foo = struct {
6262 three: void,
6363};
6464
65const Bar = enum {
66 One,
65const Bar = union(enum) {
66 One: void,
6767 Two: i32,
6868 Three: bool,
6969 Four: f64,
test/cases/switch.zig+8-8
......@@ -83,14 +83,14 @@ const SwitchStatmentFoo = enum {
8383
8484
8585test "switch prong with variable" {
86 switchProngWithVarFn(SwitchProngWithVarEnum.One {13});
87 switchProngWithVarFn(SwitchProngWithVarEnum.Two {13.0});
88 switchProngWithVarFn(SwitchProngWithVarEnum.Meh);
86 switchProngWithVarFn(SwitchProngWithVarEnum { .One = 13});
87 switchProngWithVarFn(SwitchProngWithVarEnum { .Two = 13.0});
88 switchProngWithVarFn(SwitchProngWithVarEnum { .Meh = {}});
8989}
90const SwitchProngWithVarEnum = enum {
90const SwitchProngWithVarEnum = union(enum) {
9191 One: i32,
9292 Two: f32,
93 Meh,
93 Meh: void,
9494};
9595fn switchProngWithVarFn(a: &const SwitchProngWithVarEnum) {
9696 switch(*a) {
......@@ -112,7 +112,7 @@ test "switch on enum using pointer capture" {
112112}
113113
114114fn testSwitchEnumPtrCapture() {
115 var value = SwitchProngWithVarEnum.One { 1234 };
115 var value = SwitchProngWithVarEnum { .One = 1234 };
116116 switch (value) {
117117 SwitchProngWithVarEnum.One => |*x| *x += 1,
118118 else => unreachable,
......@@ -136,13 +136,13 @@ fn returnsFive() -> i32 {
136136}
137137
138138
139const Number = enum {
139const Number = union(enum) {
140140 One: u64,
141141 Two: u8,
142142 Three: f32,
143143};
144144
145const number = Number.Three { 1.23 };
145const number = Number { .Three = 1.23 };
146146
147147fn returnsFalse() -> bool {
148148 switch (number) {
test/cases/switch_prong_err_enum.zig+2-2
......@@ -9,14 +9,14 @@ fn readOnce() -> %u64 {
99
1010error InvalidDebugInfo;
1111
12const FormValue = enum {
12const FormValue = union(enum) {
1313 Address: u64,
1414 Other: bool,
1515};
1616
1717fn doThing(form_id: u64) -> %FormValue {
1818 return switch (form_id) {
19 17 => FormValue.Address { %return readOnce() },
19 17 => FormValue { .Address = %return readOnce() },
2020 else => error.InvalidDebugInfo,
2121 }
2222}
test/cases/switch_prong_implicit_cast.zig+4-4
......@@ -1,7 +1,7 @@
11const assert = @import("std").debug.assert;
22
3const FormValue = enum {
4 One,
3const FormValue = union(enum) {
4 One: void,
55 Two: bool,
66};
77
......@@ -9,8 +9,8 @@ error Whatever;
99
1010fn foo(id: u64) -> %FormValue {
1111 switch (id) {
12 2 => FormValue.Two { true },
13 1 => FormValue.One,
12 2 => FormValue { .Two = true },
13 1 => FormValue { .One = {} },
1414 else => return error.Whatever,
1515 }
1616}
test/cases/union.zig+32-3
......@@ -1,6 +1,6 @@
11const assert = @import("std").debug.assert;
22
3const Value = enum {
3const Value = union(enum) {
44 Int: u64,
55 Array: [9]u8,
66};
......@@ -10,8 +10,8 @@ const Agg = struct {
1010 val2: Value,
1111};
1212
13const v1 = Value.Int { 1234 };
14const v2 = Value.Array { []u8{3} ** 9 };
13const v1 = Value { .Int = 1234 };
14const v2 = Value { .Array = []u8{3} ** 9 };
1515
1616const err = (%Agg)(Agg {
1717 .val1 = v1,
......@@ -75,3 +75,32 @@ test "basic extern unions" {
7575 assert(foo.float == 12.34);
7676}
7777
78
79const Letter = enum {
80 A,
81 B,
82 C,
83};
84const Payload = union(Letter) {
85 A: i32,
86 B: f64,
87 C: bool,
88};
89
90test "union with specified enum tag" {
91 doTest();
92 comptime doTest();
93}
94
95fn doTest() {
96 assert(bar(Payload {.A = 1234}) == -10);
97}
98
99fn bar(value: &const Payload) -> i32 {
100 assert(Letter(*value) == Letter.A);
101 return switch (*value) {
102 Payload.A => |x| return x - 1244,
103 Payload.B => |x| if (x == 12.34) i32(20) else 21,
104 Payload.C => |x| if (x) i32(30) else 31,
105 };
106}
test/compile_errors.zig+44-10
......@@ -930,8 +930,8 @@ pub fn addCases(cases: &tests.CompileErrorContext) {
930930 \\fn bad_eql_1(a: []u8, b: []u8) -> bool {
931931 \\ a == b
932932 \\}
933 \\const EnumWithData = enum {
934 \\ One,
933 \\const EnumWithData = union(enum) {
934 \\ One: void,
935935 \\ Two: i32,
936936 \\};
937937 \\fn bad_eql_2(a: &const EnumWithData, b: &const EnumWithData) -> bool {
......@@ -1145,19 +1145,19 @@ pub fn addCases(cases: &tests.CompileErrorContext) {
11451145 \\const JasonHM = u8;
11461146 \\const JasonList = &JsonNode;
11471147 \\
1148 \\const JsonOA = enum {
1148 \\const JsonOA = union(enum) {
11491149 \\ JSONArray: JsonList,
11501150 \\ JSONObject: JasonHM,
11511151 \\};
11521152 \\
1153 \\const JsonType = enum {
1153 \\const JsonType = union(enum) {
11541154 \\ JSONNull: void,
11551155 \\ JSONInteger: isize,
11561156 \\ JSONDouble: f64,
11571157 \\ JSONBool: bool,
11581158 \\ JSONString: []u8,
1159 \\ JSONArray,
1160 \\ JSONObject,
1159 \\ JSONArray: void,
1160 \\ JSONObject: void,
11611161 \\};
11621162 \\
11631163 \\pub const JsonNode = struct {
......@@ -2138,7 +2138,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) {
21382138 \\
21392139 \\const MdText = ArrayList(u8);
21402140 \\
2141 \\const MdNode = enum {
2141 \\const MdNode = union(enum) {
21422142 \\ Header: struct {
21432143 \\ text: MdText,
21442144 \\ weight: HeaderValue,
......@@ -2297,6 +2297,14 @@ pub fn addCases(cases: &tests.CompileErrorContext) {
22972297 ,
22982298 ".tmp_source.zig:2:21: error: type 'i32' does not support @memberType");
22992299
2300 cases.add("@memberType on enum",
2301 \\comptime {
2302 \\ _ = @memberType(Foo, 0);
2303 \\}
2304 \\const Foo = enum {A,};
2305 ,
2306 ".tmp_source.zig:2:21: error: type 'Foo' does not support @memberType");
2307
23002308 cases.add("@memberType struct out of bounds",
23012309 \\comptime {
23022310 \\ _ = @memberType(Foo, 0);
......@@ -2305,11 +2313,11 @@ pub fn addCases(cases: &tests.CompileErrorContext) {
23052313 ,
23062314 ".tmp_source.zig:2:26: error: member index 0 out of bounds; 'Foo' has 0 members");
23072315
2308 cases.add("@memberType enum out of bounds",
2316 cases.add("@memberType union out of bounds",
23092317 \\comptime {
23102318 \\ _ = @memberType(Foo, 1);
23112319 \\}
2312 \\const Foo = enum {A,};
2320 \\const Foo = union {A: void,};
23132321 ,
23142322 ".tmp_source.zig:2:26: error: member index 1 out of bounds; 'Foo' has 1 members");
23152323
......@@ -2336,6 +2344,14 @@ pub fn addCases(cases: &tests.CompileErrorContext) {
23362344 ,
23372345 ".tmp_source.zig:2:26: error: member index 1 out of bounds; 'Foo' has 1 members");
23382346
2347 cases.add("@memberName union out of bounds",
2348 \\comptime {
2349 \\ _ = @memberName(Foo, 1);
2350 \\}
2351 \\const Foo = union {A:i32,};
2352 ,
2353 ".tmp_source.zig:2:26: error: member index 1 out of bounds; 'Foo' has 1 members");
2354
23392355 cases.add("calling var args extern function, passing array instead of pointer",
23402356 \\export fn entry() {
23412357 \\ foo("hello");
......@@ -2466,7 +2482,8 @@ pub fn addCases(cases: &tests.CompileErrorContext) {
24662482 \\ var x: MultipleChoice = undefined;
24672483 \\}
24682484 ,
2469 ".tmp_source.zig:2:14: error: enums, not unions, support field assignment");
2485 ".tmp_source.zig:2:14: error: non-enum union field assignment",
2486 ".tmp_source.zig:1:24: note: consider 'union(enum)' here");
24702487
24712488 cases.add("enum with 0 fields",
24722489 \\const Foo = enum {};
......@@ -2490,4 +2507,21 @@ pub fn addCases(cases: &tests.CompileErrorContext) {
24902507 ,
24912508 ".tmp_source.zig:6:9: error: enum tag value 60 already taken",
24922509 ".tmp_source.zig:4:9: note: other occurrence here");
2510
2511 cases.add("union with specified enum omits field",
2512 \\const Letter = enum {
2513 \\ A,
2514 \\ B,
2515 \\ C,
2516 \\};
2517 \\const Payload = union(Letter) {
2518 \\ A: i32,
2519 \\ B: f64,
2520 \\};
2521 \\export fn entry() -> usize {
2522 \\ return @sizeOf(Payload);
2523 \\}
2524 ,
2525 ".tmp_source.zig:6:17: error: enum field missing: 'C'",
2526 ".tmp_source.zig:4:5: note: declared here");
24932527}
test/tests.zig+5-5
......@@ -150,8 +150,8 @@ pub fn addPkgTests(b: &build.Builder, test_filter: ?[]const u8, root_src: []cons
150150 continue;
151151 }
152152 const these_tests = b.addTest(root_src);
153 these_tests.setNamePrefix(b.fmt("{}-{}-{}-{}-{} ", name, @enumTagName(test_target.os),
154 @enumTagName(test_target.arch), @enumTagName(mode), if (link_libc) "c" else "bare"));
153 these_tests.setNamePrefix(b.fmt("{}-{}-{}-{}-{} ", name, @tagName(test_target.os),
154 @tagName(test_target.arch), @tagName(mode), if (link_libc) "c" else "bare"));
155155 these_tests.setFilter(test_filter);
156156 these_tests.setBuildMode(mode);
157157 if (!is_native) {
......@@ -428,7 +428,7 @@ pub const CompareOutputContext = struct {
428428 Special.None => {
429429 for ([]Mode{Mode.Debug, Mode.ReleaseSafe, Mode.ReleaseFast}) |mode| {
430430 const annotated_case_name = %%fmt.allocPrint(self.b.allocator, "{} {} ({})",
431 "compare-output", case.name, @enumTagName(mode));
431 "compare-output", case.name, @tagName(mode));
432432 if (self.test_filter) |filter| {
433433 if (mem.indexOf(u8, annotated_case_name, filter) == null)
434434 continue;
......@@ -682,7 +682,7 @@ pub const CompileErrorContext = struct {
682682
683683 for ([]Mode{Mode.Debug, Mode.ReleaseSafe, Mode.ReleaseFast}) |mode| {
684684 const annotated_case_name = %%fmt.allocPrint(self.b.allocator, "compile-error {} ({})",
685 case.name, @enumTagName(mode));
685 case.name, @tagName(mode));
686686 if (self.test_filter) |filter| {
687687 if (mem.indexOf(u8, annotated_case_name, filter) == null)
688688 continue;
......@@ -750,7 +750,7 @@ pub const BuildExamplesContext = struct {
750750
751751 for ([]Mode{Mode.Debug, Mode.ReleaseSafe, Mode.ReleaseFast}) |mode| {
752752 const annotated_case_name = %%fmt.allocPrint(self.b.allocator, "build {} ({})",
753 root_src, @enumTagName(mode));
753 root_src, @tagName(mode));
754754 if (self.test_filter) |filter| {
755755 if (mem.indexOf(u8, annotated_case_name, filter) == null)
756756 continue;