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 @@...@@ -136,7 +136,7 @@
136 <li><a href="#builtin-divFloor">@divFloor</a></li>136 <li><a href="#builtin-divFloor">@divFloor</a></li>
137 <li><a href="#builtin-divTrunc">@divTrunc</a></li>137 <li><a href="#builtin-divTrunc">@divTrunc</a></li>
138 <li><a href="#builtin-embedFile">@embedFile</a></li>138 <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>
140 <li><a href="#builtin-EnumTagType">@EnumTagType</a></li>140 <li><a href="#builtin-EnumTagType">@EnumTagType</a></li>
141 <li><a href="#builtin-errorName">@errorName</a></li>141 <li><a href="#builtin-errorName">@errorName</a></li>
142 <li><a href="#builtin-fence">@fence</a></li>142 <li><a href="#builtin-fence">@fence</a></li>
...@@ -2165,7 +2165,7 @@ test "enum variant switch" {...@@ -2165,7 +2165,7 @@ test "enum variant switch" {
2165 };2165 };
2166}2166}
21672167
2168// The @enumTagName and @memberCount builtin functions can be used to2168// The @memberName and @memberCount builtin functions can be used to
2169// the string representation and number of members respectively.2169// the string representation and number of members respectively.
2170const BuiltinType = enum {2170const BuiltinType = enum {
2171 A: f32,2171 A: f32,
...@@ -2174,8 +2174,8 @@ const BuiltinType = enum {...@@ -2174,8 +2174,8 @@ const BuiltinType = enum {
2174};2174};
21752175
2176test "enum builtins" {2176test "enum builtins" {
2177 assert(mem.eql(u8, @enumTagName(BuiltinType.A { 0 }), "A"));2177 assert(mem.eql(u8, @memberName(BuiltinType.A { 0 }), "A"));
2178 assert(mem.eql(u8, @enumTagName(BuiltinType.C), "C"));2178 assert(mem.eql(u8, @memberName(BuiltinType.C), "C"));
2179 assert(@memberCount(BuiltinType) == 3);2179 assert(@memberCount(BuiltinType) == 3);
2180}</code></pre>2180}</code></pre>
2181 <pre><code class="sh">$ zig test enum.zig2181 <pre><code class="sh">$ zig test enum.zig
...@@ -2189,8 +2189,9 @@ Test 4/4 enum builtins...OK</code></pre>...@@ -2189,8 +2189,9 @@ Test 4/4 enum builtins...OK</code></pre>
2189 </p>2189 </p>
2190 <p>See also:</p>2190 <p>See also:</p>
2191 <ul>2191 <ul>
2192 <li><a href="#builtin-enumTagName">@enumTagName</a></li>2192 <li><a href="#builtin-memberName">@memberName</a></li>
2193 <li><a href="#builtin-memberCount">@memberCount</a></li>2193 <li><a href="#builtin-memberCount">@memberCount</a></li>
2194 <li><a href="#builtin-tagName">@tagName</a></li>
2194 </ul>2195 </ul>
2195 <h2 id="union">union</h2>2196 <h2 id="union">union</h2>
2196 <p>TODO union documentation</p>2197 <p>TODO union documentation</p>
...@@ -4252,10 +4253,10 @@ test.zig:6:2: error: found compile log statement...@@ -4252,10 +4253,10 @@ test.zig:6:2: error: found compile log statement
4252 <ul>4253 <ul>
4253 <li><a href="#builtin-import">@import</a></li>4254 <li><a href="#builtin-import">@import</a></li>
4254 </ul>4255 </ul>
4255 <h3 id="builtin-enumTagName">@enumTagName</h3>4256 <h3 id="builtin-tagName">@tagName</h3>
4256 <pre><code class="zig">@enumTagName(value: var) -&gt; []const u8</code></pre>4257 <pre><code class="zig">@tagName(value: var) -&gt; []const u8</code></pre>
4257 <p>4258 <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.
4259 </p>4260 </p>
4260 <h3 id="builtin-EnumTagType">@EnumTagType</h3>4261 <h3 id="builtin-EnumTagType">@EnumTagType</h3>
4261 <pre><code class="zig">@EnumTagType(T: type) -&gt; type</code></pre>4262 <pre><code class="zig">@EnumTagType(T: type) -&gt; type</code></pre>
...@@ -5843,7 +5844,9 @@ GroupedExpression = "(" Expression ")"...@@ -5843,7 +5844,9 @@ GroupedExpression = "(" Expression ")"
58435844
5844KeywordLiteral = "true" | "false" | "null" | "continue" | "undefined" | "error" | "this" | "unreachable"5845KeywordLiteral = "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>
5847 <h2 id="zen">Zen</h2>5850 <h2 id="zen">Zen</h2>
5848 <ul>5851 <ul>
5849 <li>Communicate intent precisely.</li>5852 <li>Communicate intent precisely.</li>
src/all_types.hpp+9-50
...@@ -97,11 +97,6 @@ struct ConstParent {...@@ -97,11 +97,6 @@ struct ConstParent {
97 } data;97 } data;
98};98};
9999
100struct ConstEnumValue {
101 BigInt tag;
102 ConstExprValue *payload;
103};
104
105struct ConstStructValue {100struct ConstStructValue {
106 ConstExprValue *fields;101 ConstExprValue *fields;
107 ConstParent parent;102 ConstParent parent;
...@@ -249,7 +244,7 @@ struct ConstExprValue {...@@ -249,7 +244,7 @@ struct ConstExprValue {
249 ConstExprValue *x_maybe;244 ConstExprValue *x_maybe;
250 ConstErrValue x_err_union;245 ConstErrValue x_err_union;
251 ErrorTableEntry *x_pure_err;246 ErrorTableEntry *x_pure_err;
252 ConstEnumValue x_enum;247 BigInt x_enum_tag;
253 ConstStructValue x_struct;248 ConstStructValue x_struct;
254 ConstUnionValue x_union;249 ConstUnionValue x_union;
255 ConstArrayValue x_array;250 ConstArrayValue x_array;
...@@ -345,15 +340,14 @@ struct TldCompTime {...@@ -345,15 +340,14 @@ struct TldCompTime {
345340
346struct TypeEnumField {341struct TypeEnumField {
347 Buf *name;342 Buf *name;
348 TypeTableEntry *type_entry;
349 BigInt value;343 BigInt value;
350 uint32_t gen_index;344 uint32_t decl_index;
351};345};
352346
353struct TypeUnionField {347struct TypeUnionField {
354 Buf *name;348 Buf *name;
349 TypeEnumField *enum_field;
355 TypeTableEntry *type_entry;350 TypeTableEntry *type_entry;
356 BigInt value;
357 uint32_t gen_index;351 uint32_t gen_index;
358};352};
359353
...@@ -773,7 +767,8 @@ struct AstNodeContainerDecl {...@@ -773,7 +767,8 @@ struct AstNodeContainerDecl {
773 ZigList<AstNode *> fields;767 ZigList<AstNode *> fields;
774 ZigList<AstNode *> decls;768 ZigList<AstNode *> decls;
775 ContainerLayout layout;769 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)
777};772};
778773
779struct AstNodeStructField {774struct AstNodeStructField {
...@@ -1010,13 +1005,9 @@ struct TypeTableEntryEnum {...@@ -1010,13 +1005,9 @@ struct TypeTableEntryEnum {
1010 AstNode *decl_node;1005 AstNode *decl_node;
1011 ContainerLayout layout;1006 ContainerLayout layout;
1012 uint32_t src_field_count;1007 uint32_t src_field_count;
1013 // number of fields in the union. 0 if enum with no payload
1014 uint32_t gen_field_count;
1015 TypeEnumField *fields;1008 TypeEnumField *fields;
1016 bool is_invalid; // true if any fields are invalid1009 bool is_invalid; // true if any fields are invalid
1017 TypeTableEntry *tag_type;
1018 TypeTableEntry *tag_int_type;1010 TypeTableEntry *tag_int_type;
1019 LLVMTypeRef union_type_ref;
10201011
1021 ScopeDecls *decls_scope;1012 ScopeDecls *decls_scope;
10221013
...@@ -1028,18 +1019,7 @@ struct TypeTableEntryEnum {...@@ -1028,18 +1019,7 @@ struct TypeTableEntryEnum {
10281019
1029 bool zero_bits_loop_flag;1020 bool zero_bits_loop_flag;
1030 bool zero_bits_known;1021 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;
1043 bool generate_name_table;1023 bool generate_name_table;
1044 LLVMValueRef name_table;1024 LLVMValueRef name_table;
1045};1025};
...@@ -1054,7 +1034,7 @@ struct TypeTableEntryUnion {...@@ -1054,7 +1034,7 @@ struct TypeTableEntryUnion {
1054 uint32_t gen_field_count;1034 uint32_t gen_field_count;
1055 TypeUnionField *fields;1035 TypeUnionField *fields;
1056 bool is_invalid; // true if any fields are invalid1036 bool is_invalid; // true if any fields are invalid
1057 TypeTableEntry *tag_type;1037 TypeTableEntry *tag_type; // always an enum or null
1058 LLVMTypeRef union_type_ref;1038 LLVMTypeRef union_type_ref;
10591039
1060 ScopeDecls *decls_scope;1040 ScopeDecls *decls_scope;
...@@ -1119,7 +1099,6 @@ enum TypeTableEntryId {...@@ -1119,7 +1099,6 @@ enum TypeTableEntryId {
1119 TypeTableEntryIdErrorUnion,1099 TypeTableEntryIdErrorUnion,
1120 TypeTableEntryIdPureError,1100 TypeTableEntryIdPureError,
1121 TypeTableEntryIdEnum,1101 TypeTableEntryIdEnum,
1122 TypeTableEntryIdEnumTag,
1123 TypeTableEntryIdUnion,1102 TypeTableEntryIdUnion,
1124 TypeTableEntryIdFn,1103 TypeTableEntryIdFn,
1125 TypeTableEntryIdNamespace,1104 TypeTableEntryIdNamespace,
...@@ -1148,7 +1127,6 @@ struct TypeTableEntry {...@@ -1148,7 +1127,6 @@ struct TypeTableEntry {
1148 TypeTableEntryMaybe maybe;1127 TypeTableEntryMaybe maybe;
1149 TypeTableEntryError error;1128 TypeTableEntryError error;
1150 TypeTableEntryEnum enumeration;1129 TypeTableEntryEnum enumeration;
1151 TypeTableEntryEnumTag enum_tag;
1152 TypeTableEntryUnion unionation;1130 TypeTableEntryUnion unionation;
1153 TypeTableEntryFn fn;1131 TypeTableEntryFn fn;
1154 TypeTableEntryBoundFn bound_fn;1132 TypeTableEntryBoundFn bound_fn;
...@@ -1287,7 +1265,7 @@ enum BuiltinFnId {...@@ -1287,7 +1265,7 @@ enum BuiltinFnId {
1287 BuiltinFnIdBitCast,1265 BuiltinFnIdBitCast,
1288 BuiltinFnIdIntToPtr,1266 BuiltinFnIdIntToPtr,
1289 BuiltinFnIdPtrToInt,1267 BuiltinFnIdPtrToInt,
1290 BuiltinFnIdEnumTagName,1268 BuiltinFnIdTagName,
1291 BuiltinFnIdEnumTagType,1269 BuiltinFnIdEnumTagType,
1292 BuiltinFnIdFieldParentPtr,1270 BuiltinFnIdFieldParentPtr,
1293 BuiltinFnIdOffsetOf,1271 BuiltinFnIdOffsetOf,
...@@ -1832,7 +1810,6 @@ enum IrInstructionId {...@@ -1832,7 +1810,6 @@ enum IrInstructionId {
1832 IrInstructionIdStorePtr,1810 IrInstructionIdStorePtr,
1833 IrInstructionIdFieldPtr,1811 IrInstructionIdFieldPtr,
1834 IrInstructionIdStructFieldPtr,1812 IrInstructionIdStructFieldPtr,
1835 IrInstructionIdEnumFieldPtr,
1836 IrInstructionIdUnionFieldPtr,1813 IrInstructionIdUnionFieldPtr,
1837 IrInstructionIdElemPtr,1814 IrInstructionIdElemPtr,
1838 IrInstructionIdVarPtr,1815 IrInstructionIdVarPtr,
...@@ -1857,7 +1834,7 @@ enum IrInstructionId {...@@ -1857,7 +1834,7 @@ enum IrInstructionId {
1857 IrInstructionIdTestNonNull,1834 IrInstructionIdTestNonNull,
1858 IrInstructionIdUnwrapMaybe,1835 IrInstructionIdUnwrapMaybe,
1859 IrInstructionIdMaybeWrap,1836 IrInstructionIdMaybeWrap,
1860 IrInstructionIdEnumTag,1837 IrInstructionIdUnionTag,
1861 IrInstructionIdClz,1838 IrInstructionIdClz,
1862 IrInstructionIdCtz,1839 IrInstructionIdCtz,
1863 IrInstructionIdImport,1840 IrInstructionIdImport,
...@@ -1896,7 +1873,6 @@ enum IrInstructionId {...@@ -1896,7 +1873,6 @@ enum IrInstructionId {
1896 IrInstructionIdErrWrapPayload,1873 IrInstructionIdErrWrapPayload,
1897 IrInstructionIdFnProto,1874 IrInstructionIdFnProto,
1898 IrInstructionIdTestComptime,1875 IrInstructionIdTestComptime,
1899 IrInstructionIdInitEnum,
1900 IrInstructionIdPtrCast,1876 IrInstructionIdPtrCast,
1901 IrInstructionIdBitCast,1877 IrInstructionIdBitCast,
1902 IrInstructionIdWidenOrShorten,1878 IrInstructionIdWidenOrShorten,
...@@ -2092,14 +2068,6 @@ struct IrInstructionStructFieldPtr {...@@ -2092,14 +2068,6 @@ struct IrInstructionStructFieldPtr {
2092 bool is_const;2068 bool is_const;
2093};2069};
20942070
2095struct IrInstructionEnumFieldPtr {
2096 IrInstruction base;
2097
2098 IrInstruction *enum_ptr;
2099 TypeEnumField *field;
2100 bool is_const;
2101};
2102
2103struct IrInstructionUnionFieldPtr {2071struct IrInstructionUnionFieldPtr {
2104 IrInstruction base;2072 IrInstruction base;
21052073
...@@ -2303,7 +2271,7 @@ struct IrInstructionClz {...@@ -2303,7 +2271,7 @@ struct IrInstructionClz {
2303 IrInstruction *value;2271 IrInstruction *value;
2304};2272};
23052273
2306struct IrInstructionEnumTag {2274struct IrInstructionUnionTag {
2307 IrInstruction base;2275 IrInstruction base;
23082276
2309 IrInstruction *value;2277 IrInstruction *value;
...@@ -2573,15 +2541,6 @@ struct IrInstructionTestComptime {...@@ -2573,15 +2541,6 @@ struct IrInstructionTestComptime {
2573 IrInstruction *value;2541 IrInstruction *value;
2574};2542};
25752543
2576struct IrInstructionInitEnum {
2577 IrInstruction base;
2578
2579 TypeTableEntry *enum_type;
2580 TypeEnumField *field;
2581 IrInstruction *init_value;
2582 LLVMValueRef tmp_ptr;
2583};
2584
2585struct IrInstructionPtrCast {2544struct IrInstructionPtrCast {
2586 IrInstruction base;2545 IrInstruction base;
25872546
src/analyze.cpp+301-306
...@@ -223,7 +223,6 @@ bool type_is_complete(TypeTableEntry *type_entry) {...@@ -223,7 +223,6 @@ bool type_is_complete(TypeTableEntry *type_entry) {
223 case TypeTableEntryIdNamespace:223 case TypeTableEntryIdNamespace:
224 case TypeTableEntryIdBlock:224 case TypeTableEntryIdBlock:
225 case TypeTableEntryIdBoundFn:225 case TypeTableEntryIdBoundFn:
226 case TypeTableEntryIdEnumTag:
227 case TypeTableEntryIdArgTuple:226 case TypeTableEntryIdArgTuple:
228 return true;227 return true;
229 }228 }
...@@ -260,7 +259,6 @@ bool type_has_zero_bits_known(TypeTableEntry *type_entry) {...@@ -260,7 +259,6 @@ bool type_has_zero_bits_known(TypeTableEntry *type_entry) {
260 case TypeTableEntryIdNamespace:259 case TypeTableEntryIdNamespace:
261 case TypeTableEntryIdBlock:260 case TypeTableEntryIdBlock:
262 case TypeTableEntryIdBoundFn:261 case TypeTableEntryIdBoundFn:
263 case TypeTableEntryIdEnumTag:
264 case TypeTableEntryIdArgTuple:262 case TypeTableEntryIdArgTuple:
265 case TypeTableEntryIdOpaque:263 case TypeTableEntryIdOpaque:
266 return true;264 return true;
...@@ -1175,7 +1173,6 @@ static TypeTableEntry *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *c...@@ -1175,7 +1173,6 @@ static TypeTableEntry *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *c
1175 case TypeTableEntryIdEnum:1173 case TypeTableEntryIdEnum:
1176 case TypeTableEntryIdUnion:1174 case TypeTableEntryIdUnion:
1177 case TypeTableEntryIdFn:1175 case TypeTableEntryIdFn:
1178 case TypeTableEntryIdEnumTag:
1179 ensure_complete_type(g, type_entry);1176 ensure_complete_type(g, type_entry);
1180 if (fn_type_id.cc == CallingConventionUnspecified && !type_is_copyable(g, type_entry)) {1177 if (fn_type_id.cc == CallingConventionUnspecified && !type_is_copyable(g, type_entry)) {
1181 add_node_error(g, param_node->data.param_decl.type,1178 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...@@ -1239,7 +1236,6 @@ static TypeTableEntry *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *c
1239 case TypeTableEntryIdEnum:1236 case TypeTableEntryIdEnum:
1240 case TypeTableEntryIdUnion:1237 case TypeTableEntryIdUnion:
1241 case TypeTableEntryIdFn:1238 case TypeTableEntryIdFn:
1242 case TypeTableEntryIdEnumTag:
1243 break;1239 break;
1244 }1240 }
12451241
...@@ -1263,22 +1259,6 @@ bool type_is_invalid(TypeTableEntry *type_entry) {...@@ -1263,22 +1259,6 @@ bool type_is_invalid(TypeTableEntry *type_entry) {
1263}1259}
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
1282static void resolve_enum_type(CodeGen *g, TypeTableEntry *enum_type) {1262static void resolve_enum_type(CodeGen *g, TypeTableEntry *enum_type) {
1283 assert(enum_type->id == TypeTableEntryIdEnum);1263 assert(enum_type->id == TypeTableEntryIdEnum);
12841264
...@@ -1308,14 +1288,6 @@ static void resolve_enum_type(CodeGen *g, TypeTableEntry *enum_type) {...@@ -1308,14 +1288,6 @@ static void resolve_enum_type(CodeGen *g, TypeTableEntry *enum_type) {
1308 assert(enum_type->data.enumeration.fields);1288 assert(enum_type->data.enumeration.fields);
1309 ZigLLVMDIEnumerator **di_enumerators = allocate<ZigLLVMDIEnumerator*>(field_count);1289 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
1319 Scope *scope = &enum_type->data.enumeration.decls_scope->base;1291 Scope *scope = &enum_type->data.enumeration.decls_scope->base;
1320 ImportTableEntry *import = get_scope_import(scope);1292 ImportTableEntry *import = get_scope_import(scope);
13211293
...@@ -1323,49 +1295,17 @@ static void resolve_enum_type(CodeGen *g, TypeTableEntry *enum_type) {...@@ -1323,49 +1295,17 @@ static void resolve_enum_type(CodeGen *g, TypeTableEntry *enum_type) {
1323 enum_type->data.enumeration.embedded_in_current = true;1295 enum_type->data.enumeration.embedded_in_current = true;
13241296
1325 for (uint32_t i = 0; i < field_count; i += 1) {1297 for (uint32_t i = 0; i < field_count; i += 1) {
1326 AstNode *field_node = decl_node->data.container_decl.fields.at(i);1298 TypeEnumField *enum_field = &enum_type->data.enumeration.fields[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);
13431299
1344 assert(store_size_in_bits > 0);1300 // TODO send patch to LLVM to support APInt in createEnumerator instead of int64_t
1345 assert(abi_align_in_bits > 0);1301 // http://lists.llvm.org/pipermail/llvm-dev/2017-December/119456.html
13461302 di_enumerators[i] = ZigLLVMCreateDebugEnumerator(g->dbuilder, buf_ptr(enum_field->name),
1347 union_inner_di_types[type_enum_field->gen_index] = ZigLLVMCreateDebugMemberType(g->dbuilder,1303 bigint_as_signed(&enum_field->value));
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 }
1362 }1304 }
13631305
1364 // unset temporary flag1306 // unset temporary flag
1365 enum_type->data.enumeration.embedded_in_current = false;1307 enum_type->data.enumeration.embedded_in_current = false;
1366 enum_type->data.enumeration.complete = true;1308 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
1370 if (enum_type->data.enumeration.is_invalid)1310 if (enum_type->data.enumeration.is_invalid)
1371 return;1311 return;
...@@ -1391,117 +1331,20 @@ static void resolve_enum_type(CodeGen *g, TypeTableEntry *enum_type) {...@@ -1391,117 +1331,20 @@ static void resolve_enum_type(CodeGen *g, TypeTableEntry *enum_type) {
1391 }1331 }
13921332
1393 TypeTableEntry *tag_int_type = enum_type->data.enumeration.tag_int_type;1333 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 tag1335 // create debug type for tag
1492 uint64_t tag_debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, tag_type_entry->type_ref);1336 uint64_t tag_debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, tag_int_type->type_ref);
1493 uint64_t tag_debug_align_in_bits = 8*LLVMABIAlignmentOfType(g->target_data_ref, tag_type_entry->type_ref);1337 uint64_t tag_debug_align_in_bits = 8*LLVMABIAlignmentOfType(g->target_data_ref, tag_int_type->type_ref);
1494 ZigLLVMDIType *tag_di_type = ZigLLVMCreateDebugEnumerationType(g->dbuilder,1338 ZigLLVMDIType *tag_di_type = ZigLLVMCreateDebugEnumerationType(g->dbuilder,
1495 ZigLLVMFileToScope(import->di_file), buf_ptr(&enum_type->name),1339 ZigLLVMFileToScope(import->di_file), buf_ptr(&enum_type->name),
1496 import->di_file, (unsigned)(decl_node->line + 1),1340 import->di_file, (unsigned)(decl_node->line + 1),
1497 tag_debug_size_in_bits,1341 tag_debug_size_in_bits,
1498 tag_debug_align_in_bits,1342 tag_debug_align_in_bits,
1499 di_enumerators, field_count,1343 di_enumerators, field_count,
1500 tag_type_entry->di_type, "");1344 tag_int_type->di_type, "");
15011345
1502 ZigLLVMReplaceTemporary(g->dbuilder, enum_type->di_type, tag_di_type);1346 ZigLLVMReplaceTemporary(g->dbuilder, enum_type->di_type, tag_di_type);
1503 enum_type->di_type = tag_di_type;1347 enum_type->di_type = tag_di_type;
1504 }
1505}1348}
15061349
1507static bool type_allowed_in_packed_struct(TypeTableEntry *type_entry) {1350static bool type_allowed_in_packed_struct(TypeTableEntry *type_entry) {
...@@ -1517,7 +1360,6 @@ static bool type_allowed_in_packed_struct(TypeTableEntry *type_entry) {...@@ -1517,7 +1360,6 @@ static bool type_allowed_in_packed_struct(TypeTableEntry *type_entry) {
1517 case TypeTableEntryIdNullLit:1360 case TypeTableEntryIdNullLit:
1518 case TypeTableEntryIdErrorUnion:1361 case TypeTableEntryIdErrorUnion:
1519 case TypeTableEntryIdPureError:1362 case TypeTableEntryIdPureError:
1520 case TypeTableEntryIdEnumTag:
1521 case TypeTableEntryIdNamespace:1363 case TypeTableEntryIdNamespace:
1522 case TypeTableEntryIdBlock:1364 case TypeTableEntryIdBlock:
1523 case TypeTableEntryIdBoundFn:1365 case TypeTableEntryIdBoundFn:
...@@ -1541,8 +1383,7 @@ static bool type_allowed_in_packed_struct(TypeTableEntry *type_entry) {...@@ -1541,8 +1383,7 @@ static bool type_allowed_in_packed_struct(TypeTableEntry *type_entry) {
1541 return child_type->id == TypeTableEntryIdPointer || child_type->id == TypeTableEntryIdFn;1383 return child_type->id == TypeTableEntryIdPointer || child_type->id == TypeTableEntryIdFn;
1542 }1384 }
1543 case TypeTableEntryIdEnum:1385 case TypeTableEntryIdEnum:
1544 return type_entry->data.enumeration.gen_field_count == 0 &&1386 return type_entry->data.enumeration.decl_node->data.container_decl.init_arg_expr != nullptr;
1545 type_entry->data.enumeration.decl_node->data.container_decl.init_arg_expr != nullptr;
1546 }1387 }
1547 zig_unreachable();1388 zig_unreachable();
1548}1389}
...@@ -1850,6 +1691,7 @@ static void resolve_union_type(CodeGen *g, TypeTableEntry *union_type) {...@@ -1850,6 +1691,7 @@ static void resolve_union_type(CodeGen *g, TypeTableEntry *union_type) {
1850 if (union_type->data.unionation.embedded_in_current) {1691 if (union_type->data.unionation.embedded_in_current) {
1851 if (!union_type->data.unionation.reported_infinite_err) {1692 if (!union_type->data.unionation.reported_infinite_err) {
1852 union_type->data.unionation.reported_infinite_err = true;1693 union_type->data.unionation.reported_infinite_err = true;
1694 union_type->data.unionation.is_invalid = true;
1853 add_node_error(g, decl_node, buf_sprintf("union '%s' contains itself", buf_ptr(&union_type->name)));1695 add_node_error(g, decl_node, buf_sprintf("union '%s' contains itself", buf_ptr(&union_type->name)));
1854 }1696 }
1855 return;1697 return;
...@@ -1871,8 +1713,7 @@ static void resolve_union_type(CodeGen *g, TypeTableEntry *union_type) {...@@ -1871,8 +1713,7 @@ static void resolve_union_type(CodeGen *g, TypeTableEntry *union_type) {
1871 uint64_t biggest_align_in_bits = 0;1713 uint64_t biggest_align_in_bits = 0;
1872 uint64_t biggest_size_in_bits = 0;1714 uint64_t biggest_size_in_bits = 0;
18731715
1874 bool auto_layout = (union_type->data.unionation.layout == ContainerLayoutAuto);1716 ZigLLVMDIEnumerator **di_enumerators;
1875 ZigLLVMDIEnumerator **di_enumerators = allocate<ZigLLVMDIEnumerator*>(field_count);
18761717
1877 Scope *scope = &union_type->data.unionation.decls_scope->base;1718 Scope *scope = &union_type->data.unionation.decls_scope->base;
1878 ImportTableEntry *import = get_scope_import(scope);1719 ImportTableEntry *import = get_scope_import(scope);
...@@ -1880,10 +1721,77 @@ static void resolve_union_type(CodeGen *g, TypeTableEntry *union_type) {...@@ -1880,10 +1721,77 @@ static void resolve_union_type(CodeGen *g, TypeTableEntry *union_type) {
1880 // set temporary flag1721 // set temporary flag
1881 union_type->data.unionation.embedded_in_current = true;1722 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
1883 for (uint32_t i = 0; i < field_count; i += 1) {1790 for (uint32_t i = 0; i < field_count; i += 1) {
1884 AstNode *field_node = decl_node->data.container_decl.fields.at(i);1791 AstNode *field_node = decl_node->data.container_decl.fields.at(i);
1885 TypeUnionField *type_union_field = &union_type->data.unionation.fields[i];1792 TypeUnionField *union_field = &union_type->data.unionation.fields[i];
1886 TypeTableEntry *field_type = type_union_field->type_entry;1793 Buf *field_name = field_node->data.struct_field.name;
1794 TypeTableEntry *field_type = union_field->type_entry;
18871795
1888 ensure_complete_type(g, field_type);1796 ensure_complete_type(g, field_type);
1889 if (type_is_invalid(field_type)) {1797 if (type_is_invalid(field_type)) {
...@@ -1891,19 +1799,68 @@ static void resolve_union_type(CodeGen *g, TypeTableEntry *union_type) {...@@ -1891,19 +1799,68 @@ static void resolve_union_type(CodeGen *g, TypeTableEntry *union_type) {
1891 continue;1799 continue;
1892 }1800 }
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
1894 if (!type_has_bits(field_type))1853 if (!type_has_bits(field_type))
1895 continue;1854 continue;
18961855
1897 di_enumerators[i] = ZigLLVMCreateDebugEnumerator(g->dbuilder, buf_ptr(type_union_field->name), i);
1898
1899 uint64_t store_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, field_type->type_ref);1856 uint64_t store_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, field_type->type_ref);
1900 uint64_t abi_align_in_bits = 8*LLVMABIAlignmentOfType(g->target_data_ref, field_type->type_ref);1857 uint64_t abi_align_in_bits = 8*LLVMABIAlignmentOfType(g->target_data_ref, field_type->type_ref);
19011858
1902 assert(store_size_in_bits > 0);1859 assert(store_size_in_bits > 0);
1903 assert(abi_align_in_bits > 0);1860 assert(abi_align_in_bits > 0);
19041861
1905 union_inner_di_types[type_union_field->gen_index] = ZigLLVMCreateDebugMemberType(g->dbuilder,1862 union_inner_di_types[union_field->gen_index] = ZigLLVMCreateDebugMemberType(g->dbuilder,
1906 ZigLLVMTypeToScope(union_type->di_type), buf_ptr(type_union_field->name),1863 ZigLLVMTypeToScope(union_type->di_type), buf_ptr(union_field->enum_field->name),
1907 import->di_file, (unsigned)(field_node->line + 1),1864 import->di_file, (unsigned)(field_node->line + 1),
1908 store_size_in_bits,1865 store_size_in_bits,
1909 abi_align_in_bits,1866 abi_align_in_bits,
...@@ -1919,6 +1876,49 @@ static void resolve_union_type(CodeGen *g, TypeTableEntry *union_type) {...@@ -1919,6 +1876,49 @@ static void resolve_union_type(CodeGen *g, TypeTableEntry *union_type) {
1919 }1876 }
1920 }1877 }
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
1922 // unset temporary flag1922 // unset temporary flag
1923 union_type->data.unionation.embedded_in_current = false;1923 union_type->data.unionation.embedded_in_current = false;
1924 union_type->data.unionation.complete = true;1924 union_type->data.unionation.complete = true;
...@@ -1950,11 +1950,9 @@ static void resolve_union_type(CodeGen *g, TypeTableEntry *union_type) {...@@ -1950,11 +1950,9 @@ static void resolve_union_type(CodeGen *g, TypeTableEntry *union_type) {
19501950
1951 assert(most_aligned_union_member != nullptr);1951 assert(most_aligned_union_member != nullptr);
19521952
1953 bool want_safety = auto_layout && (field_count >= 2);
1954 uint64_t padding_in_bits = biggest_size_in_bits - size_of_most_aligned_member_in_bits;1953 uint64_t padding_in_bits = biggest_size_in_bits - size_of_most_aligned_member_in_bits;
19551954
19561955 if (tag_type == nullptr) {
1957 if (!want_safety) {
1958 if (padding_in_bits > 0) {1956 if (padding_in_bits > 0) {
1959 TypeTableEntry *u8_type = get_int_type(g, false, 8);1957 TypeTableEntry *u8_type = get_int_type(g, false, 8);
1960 TypeTableEntry *padding_array = get_array_type(g, u8_type, padding_in_bits / 8);1958 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) {...@@ -1994,6 +1992,8 @@ static void resolve_union_type(CodeGen *g, TypeTableEntry *union_type) {
1994 padding_array->type_ref,1992 padding_array->type_ref,
1995 };1993 };
1996 union_type_ref = LLVMStructType(union_element_types, 2, false);1994 union_type_ref = LLVMStructType(union_element_types, 2, false);
1995 } else if (most_aligned_union_member == nullptr) {
1996 zig_panic("TODO zero bit payload");
1997 } else {1997 } else {
1998 union_type_ref = most_aligned_union_member->type_ref;1998 union_type_ref = most_aligned_union_member->type_ref;
1999 }1999 }
...@@ -2003,9 +2003,7 @@ static void resolve_union_type(CodeGen *g, TypeTableEntry *union_type) {...@@ -2003,9 +2003,7 @@ static void resolve_union_type(CodeGen *g, TypeTableEntry *union_type) {
2003 assert(8*LLVMStoreSizeOfType(g->target_data_ref, union_type_ref) >= biggest_size_in_bits);2003 assert(8*LLVMStoreSizeOfType(g->target_data_ref, union_type_ref) >= biggest_size_in_bits);
20042004
2005 // create llvm type for root struct2005 // create llvm type for root struct
2006 TypeTableEntry *tag_int_type = get_smallest_unsigned_int_type(g, field_count - 1);2006 TypeTableEntry *tag_int_type = tag_type->data.enumeration.tag_int_type;
2007 TypeTableEntry *tag_type_entry = tag_int_type;
2008 union_type->data.unionation.tag_type = tag_type_entry;
2009 uint64_t align_of_tag_in_bits = 8*LLVMABIAlignmentOfType(g->target_data_ref, tag_int_type->type_ref);2007 uint64_t align_of_tag_in_bits = 8*LLVMABIAlignmentOfType(g->target_data_ref, tag_int_type->type_ref);
20102008
2011 if (align_of_tag_in_bits >= biggest_align_in_bits) {2009 if (align_of_tag_in_bits >= biggest_align_in_bits) {
...@@ -2017,21 +2015,24 @@ static void resolve_union_type(CodeGen *g, TypeTableEntry *union_type) {...@@ -2017,21 +2015,24 @@ static void resolve_union_type(CodeGen *g, TypeTableEntry *union_type) {
2017 }2015 }
20182016
2019 LLVMTypeRef root_struct_element_types[2];2017 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;
2021 root_struct_element_types[union_type->data.unionation.gen_union_index] = union_type_ref;2019 root_struct_element_types[union_type->data.unionation.gen_union_index] = union_type_ref;
2022 LLVMStructSetBody(union_type->type_ref, root_struct_element_types, 2, false);2020 LLVMStructSetBody(union_type->type_ref, root_struct_element_types, 2, false);
20232021
20242022
2025 // create debug type for root struct2023 // create debug type for root struct
20262024
2027 // create debug type for tag2025 uint64_t tag_debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, tag_type->type_ref);
2028 uint64_t tag_debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, tag_type_entry->type_ref);2026 uint64_t tag_debug_align_in_bits = 8*LLVMABIAlignmentOfType(g->target_data_ref, tag_type->type_ref);
2029 uint64_t tag_debug_align_in_bits = 8*LLVMABIAlignmentOfType(g->target_data_ref, tag_type_entry->type_ref);2027 if (create_enum_type) {
2030 ZigLLVMDIType *tag_di_type = ZigLLVMCreateDebugEnumerationType(g->dbuilder,2028 // create debug type for tag
2031 ZigLLVMTypeToScope(union_type->di_type), "AnonEnum",2029 ZigLLVMDIType *tag_di_type = ZigLLVMCreateDebugEnumerationType(g->dbuilder,
2032 import->di_file, (unsigned)(decl_node->line + 1),2030 ZigLLVMTypeToScope(union_type->di_type), "AnonEnum",
2033 tag_debug_size_in_bits, tag_debug_align_in_bits, di_enumerators, field_count,2031 import->di_file, (unsigned)(decl_node->line + 1),
2034 tag_type_entry->di_type, "");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
2036 // create debug type for union2037 // create debug type for union
2037 ZigLLVMDIType *union_di_type = ZigLLVMCreateDebugUnionType(g->dbuilder,2038 ZigLLVMDIType *union_di_type = ZigLLVMCreateDebugUnionType(g->dbuilder,
...@@ -2046,19 +2047,19 @@ static void resolve_union_type(CodeGen *g, TypeTableEntry *union_type) {...@@ -2046,19 +2047,19 @@ static void resolve_union_type(CodeGen *g, TypeTableEntry *union_type) {
2046 union_type->data.unionation.gen_tag_index);2047 union_type->data.unionation.gen_tag_index);
20472048
2048 ZigLLVMDIType *union_member_di_type = ZigLLVMCreateDebugMemberType(g->dbuilder,2049 ZigLLVMDIType *union_member_di_type = ZigLLVMCreateDebugMemberType(g->dbuilder,
2049 ZigLLVMTypeToScope(union_type->di_type), "union_field",2050 ZigLLVMTypeToScope(union_type->di_type), "payload",
2050 import->di_file, (unsigned)(decl_node->line + 1),2051 import->di_file, (unsigned)(decl_node->line + 1),
2051 biggest_size_in_bits,2052 biggest_size_in_bits,
2052 biggest_align_in_bits,2053 biggest_align_in_bits,
2053 union_offset_in_bits,2054 union_offset_in_bits,
2054 0, union_di_type);2055 0, union_di_type);
2055 ZigLLVMDIType *tag_member_di_type = ZigLLVMCreateDebugMemberType(g->dbuilder,2056 ZigLLVMDIType *tag_member_di_type = ZigLLVMCreateDebugMemberType(g->dbuilder,
2056 ZigLLVMTypeToScope(union_type->di_type), "tag_field",2057 ZigLLVMTypeToScope(union_type->di_type), "tag",
2057 import->di_file, (unsigned)(decl_node->line + 1),2058 import->di_file, (unsigned)(decl_node->line + 1),
2058 tag_debug_size_in_bits,2059 tag_debug_size_in_bits,
2059 tag_debug_align_in_bits,2060 tag_debug_align_in_bits,
2060 tag_offset_in_bits,2061 tag_offset_in_bits,
2061 0, tag_di_type);2062 0, tag_type->di_type);
20622063
2063 ZigLLVMDIType *di_root_members[2];2064 ZigLLVMDIType *di_root_members[2];
2064 di_root_members[union_type->data.unionation.gen_tag_index] = tag_member_di_type;2065 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) {...@@ -2104,7 +2105,6 @@ static void resolve_enum_zero_bits(CodeGen *g, TypeTableEntry *enum_type) {
2104 enum_type->data.enumeration.fields = nullptr;2105 enum_type->data.enumeration.fields = nullptr;
2105 enum_type->data.enumeration.is_invalid = true;2106 enum_type->data.enumeration.is_invalid = true;
2106 enum_type->data.enumeration.zero_bits_loop_flag = false;2107 enum_type->data.enumeration.zero_bits_loop_flag = false;
2107 enum_type->data.enumeration.gen_field_count = 0;
2108 enum_type->data.enumeration.zero_bits_known = true;2108 enum_type->data.enumeration.zero_bits_known = true;
2109 return;2109 return;
2110 }2110 }
...@@ -2112,8 +2112,6 @@ static void resolve_enum_zero_bits(CodeGen *g, TypeTableEntry *enum_type) {...@@ -2112,8 +2112,6 @@ static void resolve_enum_zero_bits(CodeGen *g, TypeTableEntry *enum_type) {
2112 enum_type->data.enumeration.src_field_count = field_count;2112 enum_type->data.enumeration.src_field_count = field_count;
2113 enum_type->data.enumeration.fields = allocate<TypeEnumField>(field_count);2113 enum_type->data.enumeration.fields = allocate<TypeEnumField>(field_count);
21142114
2115 uint32_t biggest_align_bytes = 0;
2116
2117 Scope *scope = &enum_type->data.enumeration.decls_scope->base;2115 Scope *scope = &enum_type->data.enumeration.decls_scope->base;
21182116
2119 HashMap<BigInt, AstNode *, bigint_hash, bigint_eql> occupied_tag_values = {};2117 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) {...@@ -2143,14 +2141,20 @@ static void resolve_enum_zero_bits(CodeGen *g, TypeTableEntry *enum_type) {
2143 }2141 }
2144 }2142 }
2145 enum_type->data.enumeration.tag_int_type = tag_int_type;2143 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;
2148 for (uint32_t field_i = 0; field_i < field_count; field_i += 1) {2146 for (uint32_t field_i = 0; field_i < field_count; field_i += 1) {
2149 AstNode *field_node = decl_node->data.container_decl.fields.at(field_i);2147 AstNode *field_node = decl_node->data.container_decl.fields.at(field_i);
2150 TypeEnumField *type_enum_field = &enum_type->data.enumeration.fields[field_i];2148 TypeEnumField *type_enum_field = &enum_type->data.enumeration.fields[field_i];
2151 type_enum_field->name = field_node->data.struct_field.name;2149 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);2150 type_enum_field->decl_index = field_i;
2153 type_enum_field->type_entry = field_type;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
2155 AstNode *tag_value = field_node->data.struct_field.value;2159 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) {...@@ -2179,23 +2183,6 @@ static void resolve_enum_zero_bits(CodeGen *g, TypeTableEntry *enum_type) {
2179 continue;2183 continue;
2180 }2184 }
2181 }2185 }
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 }
2199 }2186 }
22002187
2201 // Now iterate again and populate the unspecified tag values2188 // Now iterate again and populate the unspecified tag values
...@@ -2227,15 +2214,8 @@ static void resolve_enum_zero_bits(CodeGen *g, TypeTableEntry *enum_type) {...@@ -2227,15 +2214,8 @@ static void resolve_enum_zero_bits(CodeGen *g, TypeTableEntry *enum_type) {
2227 }2214 }
22282215
2229 enum_type->data.enumeration.zero_bits_loop_flag = false;2216 enum_type->data.enumeration.zero_bits_loop_flag = false;
2230 enum_type->data.enumeration.gen_field_count = gen_field_index;2217 enum_type->zero_bits = (field_count < 2);
2231 enum_type->zero_bits = (gen_field_index == 0 && field_count < 2);
2232 enum_type->data.enumeration.zero_bits_known = true;2218 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 }
2239}2219}
22402220
2241static void resolve_struct_zero_bits(CodeGen *g, TypeTableEntry *struct_type) {2221static 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) {...@@ -2279,6 +2259,13 @@ static void resolve_struct_zero_bits(CodeGen *g, TypeTableEntry *struct_type) {
2279 AstNode *field_node = decl_node->data.container_decl.fields.at(i);2259 AstNode *field_node = decl_node->data.container_decl.fields.at(i);
2280 TypeStructField *type_struct_field = &struct_type->data.structure.fields[i];2260 TypeStructField *type_struct_field = &struct_type->data.structure.fields[i];
2281 type_struct_field->name = field_node->data.struct_field.name;2261 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
2282 TypeTableEntry *field_type = analyze_type_expr(g, scope, field_node->data.struct_field.type);2269 TypeTableEntry *field_type = analyze_type_expr(g, scope, field_node->data.struct_field.type);
2283 type_struct_field->type_entry = field_type;2270 type_struct_field->type_entry = field_type;
2284 type_struct_field->src_index = i;2271 type_struct_field->src_index = i;
...@@ -2338,6 +2325,16 @@ static void resolve_union_zero_bits(CodeGen *g, TypeTableEntry *union_type) {...@@ -2338,6 +2325,16 @@ static void resolve_union_zero_bits(CodeGen *g, TypeTableEntry *union_type) {
23382325
2339 assert(!union_type->data.unionation.fields);2326 assert(!union_type->data.unionation.fields);
2340 uint32_t field_count = (uint32_t)decl_node->data.container_decl.fields.length;2327 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 }
2341 union_type->data.unionation.src_field_count = field_count;2338 union_type->data.unionation.src_field_count = field_count;
2342 union_type->data.unionation.fields = allocate<TypeUnionField>(field_count);2339 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) {...@@ -2348,17 +2345,23 @@ static void resolve_union_zero_bits(CodeGen *g, TypeTableEntry *union_type) {
2348 uint32_t gen_field_index = 0;2345 uint32_t gen_field_index = 0;
2349 for (uint32_t i = 0; i < field_count; i += 1) {2346 for (uint32_t i = 0; i < field_count; i += 1) {
2350 AstNode *field_node = decl_node->data.container_decl.fields.at(i);2347 AstNode *field_node = decl_node->data.container_decl.fields.at(i);
2351 TypeUnionField *type_union_field = &union_type->data.unionation.fields[i];2348 TypeUnionField *union_field = &union_type->data.unionation.fields[i];
2352 type_union_field->name = field_node->data.struct_field.name;2349 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;
23552350
2356 // TODO look for enum arg to union2351 if (field_node->data.struct_field.type == nullptr) {
2357 bigint_init_unsigned(&type_union_field->value, i);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) {2357 TypeTableEntry *field_type = analyze_type_expr(g, scope, field_node->data.struct_field.type);
2360 add_node_error(g, field_node->data.struct_field.value,2358 union_field->type_entry = field_type;
2361 buf_sprintf("enums, not unions, support field assignment"));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"));
2362 }2365 }
23632366
2364 type_ensure_zero_bits_known(g, field_type);2367 type_ensure_zero_bits_known(g, field_type);
...@@ -2370,7 +2373,7 @@ static void resolve_union_zero_bits(CodeGen *g, TypeTableEntry *union_type) {...@@ -2370,7 +2373,7 @@ static void resolve_union_zero_bits(CodeGen *g, TypeTableEntry *union_type) {
2370 if (!type_has_bits(field_type))2373 if (!type_has_bits(field_type))
2371 continue;2374 continue;
23722375
2373 type_union_field->gen_index = gen_field_index;2376 union_field->gen_index = gen_field_index;
2374 gen_field_index += 1;2377 gen_field_index += 1;
23752378
2376 uint32_t field_align_bytes = get_abi_alignment(g, field_type);2379 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) {...@@ -2379,11 +2382,32 @@ static void resolve_union_zero_bits(CodeGen *g, TypeTableEntry *union_type) {
2379 }2382 }
2380 }2383 }
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
2384 union_type->data.unionation.zero_bits_loop_flag = false;2408 union_type->data.unionation.zero_bits_loop_flag = false;
2385 union_type->data.unionation.gen_field_count = gen_field_index;2409 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));
2387 union_type->data.unionation.zero_bits_known = true;2411 union_type->data.unionation.zero_bits_known = true;
23882412
2389 // also compute abi_alignment2413 // also compute abi_alignment
...@@ -2848,7 +2872,6 @@ TypeTableEntry *validate_var_type(CodeGen *g, AstNode *source_node, TypeTableEnt...@@ -2848,7 +2872,6 @@ TypeTableEntry *validate_var_type(CodeGen *g, AstNode *source_node, TypeTableEnt
2848 case TypeTableEntryIdUnion:2872 case TypeTableEntryIdUnion:
2849 case TypeTableEntryIdFn:2873 case TypeTableEntryIdFn:
2850 case TypeTableEntryIdBoundFn:2874 case TypeTableEntryIdBoundFn:
2851 case TypeTableEntryIdEnumTag:
2852 return type_entry;2875 return type_entry;
2853 }2876 }
2854 zig_unreachable();2877 zig_unreachable();
...@@ -3265,19 +3288,20 @@ TypeUnionField *find_union_type_field(TypeTableEntry *type_entry, Buf *name) {...@@ -3265,19 +3288,20 @@ TypeUnionField *find_union_type_field(TypeTableEntry *type_entry, Buf *name) {
3265 assert(type_entry->data.unionation.complete);3288 assert(type_entry->data.unionation.complete);
3266 for (uint32_t i = 0; i < type_entry->data.unionation.src_field_count; i += 1) {3289 for (uint32_t i = 0; i < type_entry->data.unionation.src_field_count; i += 1) {
3267 TypeUnionField *field = &type_entry->data.unionation.fields[i];3290 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)) {
3269 return field;3292 return field;
3270 }3293 }
3271 }3294 }
3272 return nullptr;3295 return nullptr;
3273}3296}
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) {
3276 assert(type_entry->id == TypeTableEntryIdUnion);3299 assert(type_entry->id == TypeTableEntryIdUnion);
3277 assert(type_entry->data.unionation.complete);3300 assert(type_entry->data.unionation.complete);
3301 assert(type_entry->data.unionation.gen_tag_index != SIZE_MAX);
3278 for (uint32_t i = 0; i < type_entry->data.unionation.src_field_count; i += 1) {3302 for (uint32_t i = 0; i < type_entry->data.unionation.src_field_count; i += 1) {
3279 TypeUnionField *field = &type_entry->data.unionation.fields[i];3303 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) {
3281 return field;3305 return field;
3282 }3306 }
3283 }3307 }
...@@ -3323,7 +3347,6 @@ static bool is_container(TypeTableEntry *type_entry) {...@@ -3323,7 +3347,6 @@ static bool is_container(TypeTableEntry *type_entry) {
3323 case TypeTableEntryIdNamespace:3347 case TypeTableEntryIdNamespace:
3324 case TypeTableEntryIdBlock:3348 case TypeTableEntryIdBlock:
3325 case TypeTableEntryIdBoundFn:3349 case TypeTableEntryIdBoundFn:
3326 case TypeTableEntryIdEnumTag:
3327 case TypeTableEntryIdArgTuple:3350 case TypeTableEntryIdArgTuple:
3328 case TypeTableEntryIdOpaque:3351 case TypeTableEntryIdOpaque:
3329 return false;3352 return false;
...@@ -3374,7 +3397,6 @@ void resolve_container_type(CodeGen *g, TypeTableEntry *type_entry) {...@@ -3374,7 +3397,6 @@ void resolve_container_type(CodeGen *g, TypeTableEntry *type_entry) {
3374 case TypeTableEntryIdBoundFn:3397 case TypeTableEntryIdBoundFn:
3375 case TypeTableEntryIdInvalid:3398 case TypeTableEntryIdInvalid:
3376 case TypeTableEntryIdVar:3399 case TypeTableEntryIdVar:
3377 case TypeTableEntryIdEnumTag:
3378 case TypeTableEntryIdArgTuple:3400 case TypeTableEntryIdArgTuple:
3379 case TypeTableEntryIdOpaque:3401 case TypeTableEntryIdOpaque:
3380 zig_unreachable();3402 zig_unreachable();
...@@ -3828,7 +3850,7 @@ bool handle_is_ptr(TypeTableEntry *type_entry) {...@@ -3828,7 +3850,7 @@ bool handle_is_ptr(TypeTableEntry *type_entry) {
3828 case TypeTableEntryIdPointer:3850 case TypeTableEntryIdPointer:
3829 case TypeTableEntryIdPureError:3851 case TypeTableEntryIdPureError:
3830 case TypeTableEntryIdFn:3852 case TypeTableEntryIdFn:
3831 case TypeTableEntryIdEnumTag:3853 case TypeTableEntryIdEnum:
3832 return false;3854 return false;
3833 case TypeTableEntryIdArray:3855 case TypeTableEntryIdArray:
3834 case TypeTableEntryIdStruct:3856 case TypeTableEntryIdStruct:
...@@ -3836,9 +3858,6 @@ bool handle_is_ptr(TypeTableEntry *type_entry) {...@@ -3836,9 +3858,6 @@ bool handle_is_ptr(TypeTableEntry *type_entry) {
3836 return type_has_bits(type_entry);3858 return type_has_bits(type_entry);
3837 case TypeTableEntryIdErrorUnion:3859 case TypeTableEntryIdErrorUnion:
3838 return type_has_bits(type_entry->data.error.child_type);3860 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;
3842 case TypeTableEntryIdMaybe:3861 case TypeTableEntryIdMaybe:
3843 return type_has_bits(type_entry->data.maybe.child_type) &&3862 return type_has_bits(type_entry->data.maybe.child_type) &&
3844 type_entry->data.maybe.child_type->id != TypeTableEntryIdPointer &&3863 type_entry->data.maybe.child_type->id != TypeTableEntryIdPointer &&
...@@ -3980,7 +3999,6 @@ static uint32_t hash_const_val(ConstExprValue *const_val) {...@@ -3980,7 +3999,6 @@ static uint32_t hash_const_val(ConstExprValue *const_val) {
3980 return (uint32_t)4149439618;3999 return (uint32_t)4149439618;
3981 case TypeTableEntryIdInt:4000 case TypeTableEntryIdInt:
3982 case TypeTableEntryIdNumLitInt:4001 case TypeTableEntryIdNumLitInt:
3983 case TypeTableEntryIdEnumTag:
3984 {4002 {
3985 uint32_t result = 1331471175;4003 uint32_t result = 1331471175;
3986 for (size_t i = 0; i < const_val->data.x_bigint.digit_count; i += 1) {4004 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) {...@@ -3989,6 +4007,15 @@ static uint32_t hash_const_val(ConstExprValue *const_val) {
3989 }4007 }
3990 return result;4008 return result;
3991 }4009 }
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 }
3992 case TypeTableEntryIdFloat:4019 case TypeTableEntryIdFloat:
3993 switch (const_val->type->data.floating.bit_count) {4020 switch (const_val->type->data.floating.bit_count) {
3994 case 32:4021 case 32:
...@@ -4089,9 +4116,6 @@ static uint32_t hash_const_val(ConstExprValue *const_val) {...@@ -4089,9 +4116,6 @@ static uint32_t hash_const_val(ConstExprValue *const_val) {
4089 case TypeTableEntryIdPureError:4116 case TypeTableEntryIdPureError:
4090 // TODO better hashing algorithm4117 // TODO better hashing algorithm
4091 return 2630160122;4118 return 2630160122;
4092 case TypeTableEntryIdEnum:
4093 // TODO better hashing algorithm
4094 return 31643936;
4095 case TypeTableEntryIdFn:4119 case TypeTableEntryIdFn:
4096 return 4133894920 ^ hash_ptr(const_val->data.x_fn.fn_entry);4120 return 4133894920 ^ hash_ptr(const_val->data.x_fn.fn_entry);
4097 case TypeTableEntryIdNamespace:4121 case TypeTableEntryIdNamespace:
...@@ -4224,7 +4248,6 @@ bool type_requires_comptime(TypeTableEntry *type_entry) {...@@ -4224,7 +4248,6 @@ bool type_requires_comptime(TypeTableEntry *type_entry) {
4224 case TypeTableEntryIdInt:4248 case TypeTableEntryIdInt:
4225 case TypeTableEntryIdFloat:4249 case TypeTableEntryIdFloat:
4226 case TypeTableEntryIdPointer:4250 case TypeTableEntryIdPointer:
4227 case TypeTableEntryIdEnumTag:
4228 case TypeTableEntryIdVoid:4251 case TypeTableEntryIdVoid:
4229 case TypeTableEntryIdUnreachable:4252 case TypeTableEntryIdUnreachable:
4230 return false;4253 return false;
...@@ -4295,6 +4318,7 @@ ConstExprValue *create_const_bigint(TypeTableEntry *type, const BigInt *bigint)...@@ -4295,6 +4318,7 @@ ConstExprValue *create_const_bigint(TypeTableEntry *type, const BigInt *bigint)
4295 return const_val;4318 return const_val;
4296}4319}
42974320
4321
4298void init_const_unsigned_negative(ConstExprValue *const_val, TypeTableEntry *type, uint64_t x, bool negative) {4322void init_const_unsigned_negative(ConstExprValue *const_val, TypeTableEntry *type, uint64_t x, bool negative) {
4299 const_val->special = ConstValSpecialStatic;4323 const_val->special = ConstValSpecialStatic;
4300 const_val->type = type;4324 const_val->type = type;
...@@ -4358,18 +4382,19 @@ ConstExprValue *create_const_float(TypeTableEntry *type, double value) {...@@ -4358,18 +4382,19 @@ ConstExprValue *create_const_float(TypeTableEntry *type, double value) {
4358 return const_val;4382 return const_val;
4359}4383}
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) {
4362 const_val->special = ConstValSpecialStatic;4386 const_val->special = ConstValSpecialStatic;
4363 const_val->type = type;4387 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);
4365}4389}
43664390
4367ConstExprValue *create_const_enum_tag(TypeTableEntry *type, const BigInt *tag) {4391ConstExprValue *create_const_enum(TypeTableEntry *type, const BigInt *tag) {
4368 ConstExprValue *const_val = create_const_vals(1);4392 ConstExprValue *const_val = create_const_vals(1);
4369 init_const_enum_tag(const_val, type, tag);4393 init_const_enum(const_val, type, tag);
4370 return const_val;4394 return const_val;
4371}4395}
43724396
4397
4373void init_const_bool(CodeGen *g, ConstExprValue *const_val, bool value) {4398void init_const_bool(CodeGen *g, ConstExprValue *const_val, bool value) {
4374 const_val->special = ConstValSpecialStatic;4399 const_val->special = ConstValSpecialStatic;
4375 const_val->type = g->builtin_types.entry_bool;4400 const_val->type = g->builtin_types.entry_bool;
...@@ -4567,20 +4592,8 @@ bool const_values_equal(ConstExprValue *a, ConstExprValue *b) {...@@ -4567,20 +4592,8 @@ bool const_values_equal(ConstExprValue *a, ConstExprValue *b) {
4567 switch (a->type->id) {4592 switch (a->type->id) {
4568 case TypeTableEntryIdOpaque:4593 case TypeTableEntryIdOpaque:
4569 zig_unreachable();4594 zig_unreachable();
4570 case TypeTableEntryIdEnum: {4595 case TypeTableEntryIdEnum:
4571 ConstEnumValue *enum1 = &a->data.x_enum;4596 return bigint_cmp(&a->data.x_enum_tag, &b->data.x_enum_tag) == CmpEQ;
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 }
4584 case TypeTableEntryIdUnion: {4597 case TypeTableEntryIdUnion: {
4585 ConstUnionValue *union1 = &a->data.x_union;4598 ConstUnionValue *union1 = &a->data.x_union;
4586 ConstUnionValue *union2 = &b->data.x_union;4599 ConstUnionValue *union2 = &b->data.x_union;
...@@ -4622,7 +4635,6 @@ bool const_values_equal(ConstExprValue *a, ConstExprValue *b) {...@@ -4622,7 +4635,6 @@ bool const_values_equal(ConstExprValue *a, ConstExprValue *b) {
4622 return bigfloat_cmp(&a->data.x_bigfloat, &b->data.x_bigfloat) == CmpEQ;4635 return bigfloat_cmp(&a->data.x_bigfloat, &b->data.x_bigfloat) == CmpEQ;
4623 case TypeTableEntryIdInt:4636 case TypeTableEntryIdInt:
4624 case TypeTableEntryIdNumLitInt:4637 case TypeTableEntryIdNumLitInt:
4625 case TypeTableEntryIdEnumTag:
4626 return bigint_cmp(&a->data.x_bigint, &b->data.x_bigint) == CmpEQ;4638 return bigint_cmp(&a->data.x_bigint, &b->data.x_bigint) == CmpEQ;
4627 case TypeTableEntryIdPointer:4639 case TypeTableEntryIdPointer:
4628 if (a->data.x_ptr.special != b->data.x_ptr.special)4640 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) {...@@ -4949,7 +4961,8 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) {
4949 }4961 }
4950 case TypeTableEntryIdEnum:4962 case TypeTableEntryIdEnum:
4951 {4963 {
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));
4953 return;4966 return;
4954 }4967 }
4955 case TypeTableEntryIdErrorUnion:4968 case TypeTableEntryIdErrorUnion:
...@@ -4967,14 +4980,6 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) {...@@ -4967,14 +4980,6 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) {
4967 buf_appendf(buf, "(pure error constant)");4980 buf_appendf(buf, "(pure error constant)");
4968 return;4981 return;
4969 }4982 }
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 }
4978 case TypeTableEntryIdArgTuple:4983 case TypeTableEntryIdArgTuple:
4979 {4984 {
4980 buf_appendf(buf, "(args value)");4985 buf_appendf(buf, "(args value)");
...@@ -5036,7 +5041,6 @@ uint32_t type_id_hash(TypeId x) {...@@ -5036,7 +5041,6 @@ uint32_t type_id_hash(TypeId x) {
5036 case TypeTableEntryIdErrorUnion:5041 case TypeTableEntryIdErrorUnion:
5037 case TypeTableEntryIdPureError:5042 case TypeTableEntryIdPureError:
5038 case TypeTableEntryIdEnum:5043 case TypeTableEntryIdEnum:
5039 case TypeTableEntryIdEnumTag:
5040 case TypeTableEntryIdUnion:5044 case TypeTableEntryIdUnion:
5041 case TypeTableEntryIdFn:5045 case TypeTableEntryIdFn:
5042 case TypeTableEntryIdNamespace:5046 case TypeTableEntryIdNamespace:
...@@ -5081,7 +5085,6 @@ bool type_id_eql(TypeId a, TypeId b) {...@@ -5081,7 +5085,6 @@ bool type_id_eql(TypeId a, TypeId b) {
5081 case TypeTableEntryIdErrorUnion:5085 case TypeTableEntryIdErrorUnion:
5082 case TypeTableEntryIdPureError:5086 case TypeTableEntryIdPureError:
5083 case TypeTableEntryIdEnum:5087 case TypeTableEntryIdEnum:
5084 case TypeTableEntryIdEnumTag:
5085 case TypeTableEntryIdUnion:5088 case TypeTableEntryIdUnion:
5086 case TypeTableEntryIdFn:5089 case TypeTableEntryIdFn:
5087 case TypeTableEntryIdNamespace:5090 case TypeTableEntryIdNamespace:
...@@ -5196,7 +5199,6 @@ static const TypeTableEntryId all_type_ids[] = {...@@ -5196,7 +5199,6 @@ static const TypeTableEntryId all_type_ids[] = {
5196 TypeTableEntryIdErrorUnion,5199 TypeTableEntryIdErrorUnion,
5197 TypeTableEntryIdPureError,5200 TypeTableEntryIdPureError,
5198 TypeTableEntryIdEnum,5201 TypeTableEntryIdEnum,
5199 TypeTableEntryIdEnumTag,
5200 TypeTableEntryIdUnion,5202 TypeTableEntryIdUnion,
5201 TypeTableEntryIdFn,5203 TypeTableEntryIdFn,
5202 TypeTableEntryIdNamespace,5204 TypeTableEntryIdNamespace,
...@@ -5254,22 +5256,20 @@ size_t type_id_index(TypeTableEntryId id) {...@@ -5254,22 +5256,20 @@ size_t type_id_index(TypeTableEntryId id) {
5254 return 15;5256 return 15;
5255 case TypeTableEntryIdEnum:5257 case TypeTableEntryIdEnum:
5256 return 16;5258 return 16;
5257 case TypeTableEntryIdEnumTag:
5258 return 17;
5259 case TypeTableEntryIdUnion:5259 case TypeTableEntryIdUnion:
5260 return 18;5260 return 17;
5261 case TypeTableEntryIdFn:5261 case TypeTableEntryIdFn:
5262 return 19;5262 return 18;
5263 case TypeTableEntryIdNamespace:5263 case TypeTableEntryIdNamespace:
5264 return 20;5264 return 19;
5265 case TypeTableEntryIdBlock:5265 case TypeTableEntryIdBlock:
5266 return 21;5266 return 20;
5267 case TypeTableEntryIdBoundFn:5267 case TypeTableEntryIdBoundFn:
5268 return 22;5268 return 21;
5269 case TypeTableEntryIdArgTuple:5269 case TypeTableEntryIdArgTuple:
5270 return 23;5270 return 22;
5271 case TypeTableEntryIdOpaque:5271 case TypeTableEntryIdOpaque:
5272 return 24;5272 return 23;
5273 }5273 }
5274 zig_unreachable();5274 zig_unreachable();
5275}5275}
...@@ -5313,8 +5313,6 @@ const char *type_id_name(TypeTableEntryId id) {...@@ -5313,8 +5313,6 @@ const char *type_id_name(TypeTableEntryId id) {
5313 return "Error";5313 return "Error";
5314 case TypeTableEntryIdEnum:5314 case TypeTableEntryIdEnum:
5315 return "Enum";5315 return "Enum";
5316 case TypeTableEntryIdEnumTag:
5317 return "EnumTag";
5318 case TypeTableEntryIdUnion:5316 case TypeTableEntryIdUnion:
5319 return "Union";5317 return "Union";
5320 case TypeTableEntryIdFn:5318 case TypeTableEntryIdFn:
...@@ -5381,9 +5379,6 @@ uint32_t get_abi_alignment(CodeGen *g, TypeTableEntry *type_entry) {...@@ -5381,9 +5379,6 @@ uint32_t get_abi_alignment(CodeGen *g, TypeTableEntry *type_entry) {
5381 if (type_entry->id == TypeTableEntryIdStruct) {5379 if (type_entry->id == TypeTableEntryIdStruct) {
5382 assert(type_entry->data.structure.abi_alignment != 0);5380 assert(type_entry->data.structure.abi_alignment != 0);
5383 return type_entry->data.structure.abi_alignment;5381 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;
5387 } else if (type_entry->id == TypeTableEntryIdUnion) {5382 } else if (type_entry->id == TypeTableEntryIdUnion) {
5388 assert(type_entry->data.unionation.abi_alignment != 0);5383 assert(type_entry->data.unionation.abi_alignment != 0);
5389 return type_entry->data.unionation.abi_alignment;5384 return type_entry->data.unionation.abi_alignment;
src/analyze.hpp+3-3
...@@ -65,6 +65,7 @@ ScopeDecls *get_container_scope(TypeTableEntry *type_entry);...@@ -65,6 +65,7 @@ ScopeDecls *get_container_scope(TypeTableEntry *type_entry);
65TypeEnumField *find_enum_type_field(TypeTableEntry *enum_type, Buf *name);65TypeEnumField *find_enum_type_field(TypeTableEntry *enum_type, Buf *name);
66TypeUnionField *find_union_type_field(TypeTableEntry *type_entry, Buf *name);66TypeUnionField *find_union_type_field(TypeTableEntry *type_entry, Buf *name);
67TypeEnumField *find_enum_field_by_tag(TypeTableEntry *enum_type, const BigInt *tag);67TypeEnumField *find_enum_field_by_tag(TypeTableEntry *enum_type, const BigInt *tag);
68TypeUnionField *find_union_field_by_tag(TypeTableEntry *type_entry, const BigInt *tag);
6869
69bool is_container_ref(TypeTableEntry *type_entry);70bool is_container_ref(TypeTableEntry *type_entry);
70void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node);71void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node);
...@@ -126,8 +127,8 @@ ConstExprValue *create_const_usize(CodeGen *g, uint64_t x);...@@ -126,8 +127,8 @@ ConstExprValue *create_const_usize(CodeGen *g, uint64_t x);
126void init_const_float(ConstExprValue *const_val, TypeTableEntry *type, double value);127void init_const_float(ConstExprValue *const_val, TypeTableEntry *type, double value);
127ConstExprValue *create_const_float(TypeTableEntry *type, double value);128ConstExprValue *create_const_float(TypeTableEntry *type, double value);
128129
129void init_const_enum_tag(ConstExprValue *const_val, TypeTableEntry *type, const BigInt *tag);130void init_const_enum(ConstExprValue *const_val, TypeTableEntry *type, const BigInt *tag);
130ConstExprValue *create_const_enum_tag(TypeTableEntry *type, const BigInt *tag);131ConstExprValue *create_const_enum(TypeTableEntry *type, const BigInt *tag);
131132
132void init_const_bool(CodeGen *g, ConstExprValue *const_val, bool value);133void init_const_bool(CodeGen *g, ConstExprValue *const_val, bool value);
133ConstExprValue *create_const_bool(CodeGen *g, bool value);134ConstExprValue *create_const_bool(CodeGen *g, bool value);
...@@ -163,7 +164,6 @@ ConstExprValue *create_const_vals(size_t count);...@@ -163,7 +164,6 @@ ConstExprValue *create_const_vals(size_t count);
163164
164TypeTableEntry *make_int_type(CodeGen *g, bool is_signed, uint32_t size_in_bits);165TypeTableEntry *make_int_type(CodeGen *g, bool is_signed, uint32_t size_in_bits);
165ConstParent *get_const_val_parent(CodeGen *g, ConstExprValue *value);166ConstParent *get_const_val_parent(CodeGen *g, ConstExprValue *value);
166TypeTableEntry *create_enum_tag_type(CodeGen *g, TypeTableEntry *enum_type, TypeTableEntry *int_type);
167void expand_undef_array(CodeGen *g, ConstExprValue *const_val);167void expand_undef_array(CodeGen *g, ConstExprValue *const_val);
168void update_compile_var(CodeGen *g, Buf *name, ConstExprValue *value);168void 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) {...@@ -661,11 +661,18 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {
661 const char *layout_str = layout_string(node->data.container_decl.layout);661 const char *layout_str = layout_string(node->data.container_decl.layout);
662 const char *container_str = container_string(node->data.container_decl.kind);662 const char *container_str = container_string(node->data.container_decl.kind);
663 fprintf(ar->f, "%s%s", layout_str, container_str);663 fprintf(ar->f, "%s%s", layout_str, container_str);
664 if (node->data.container_decl.auto_enum) {
665 fprintf(ar->f, "(enum");
666 }
664 if (node->data.container_decl.init_arg_expr != nullptr) {667 if (node->data.container_decl.init_arg_expr != nullptr) {
665 fprintf(ar->f, "(");668 fprintf(ar->f, "(");
666 render_node_grouped(ar, node->data.container_decl.init_arg_expr);669 render_node_grouped(ar, node->data.container_decl.init_arg_expr);
667 fprintf(ar->f, ")");670 fprintf(ar->f, ")");
668 }671 }
672 if (node->data.container_decl.auto_enum) {
673 fprintf(ar->f, ")");
674 }
675
669 fprintf(ar->f, " {\n");676 fprintf(ar->f, " {\n");
670 ar->indent += ar->indent_size;677 ar->indent += ar->indent_size;
671 for (size_t field_i = 0; field_i < node->data.container_decl.fields.length; field_i += 1) {678 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,...@@ -1631,12 +1631,8 @@ static LLVMValueRef ir_render_bin_op(CodeGen *g, IrExecutable *executable,
1631 LLVMIntPredicate pred = cmp_op_to_int_predicate(op_id, type_entry->data.integral.is_signed);1631 LLVMIntPredicate pred = cmp_op_to_int_predicate(op_id, type_entry->data.integral.is_signed);
1632 return LLVMBuildICmp(g->builder, pred, op1_value, op2_value, "");1632 return LLVMBuildICmp(g->builder, pred, op1_value, op2_value, "");
1633 } else if (type_entry->id == TypeTableEntryIdEnum) {1633 } else if (type_entry->id == TypeTableEntryIdEnum) {
1634 if (type_entry->data.enumeration.gen_field_count == 0) {1634 LLVMIntPredicate pred = cmp_op_to_int_predicate(op_id, false);
1635 LLVMIntPredicate pred = cmp_op_to_int_predicate(op_id, false);1635 return LLVMBuildICmp(g->builder, pred, op1_value, op2_value, "");
1636 return LLVMBuildICmp(g->builder, pred, op1_value, op2_value, "");
1637 } else {
1638 zig_unreachable();
1639 }
1640 } else if (type_entry->id == TypeTableEntryIdPureError ||1636 } else if (type_entry->id == TypeTableEntryIdPureError ||
1641 type_entry->id == TypeTableEntryIdPointer ||1637 type_entry->id == TypeTableEntryIdPointer ||
1642 type_entry->id == TypeTableEntryIdBool)1638 type_entry->id == TypeTableEntryIdBool)
...@@ -1920,9 +1916,7 @@ static LLVMValueRef ir_render_widen_or_shorten(CodeGen *g, IrExecutable *executa...@@ -1920,9 +1916,7 @@ static LLVMValueRef ir_render_widen_or_shorten(CodeGen *g, IrExecutable *executa
1920 // enum_tag to the underlying int type1916 // enum_tag to the underlying int type
1921 TypeTableEntry *int_type;1917 TypeTableEntry *int_type;
1922 if (actual_type->id == TypeTableEntryIdEnum) {1918 if (actual_type->id == TypeTableEntryIdEnum) {
1923 TypeTableEntry *tag_type = actual_type->data.enumeration.tag_type;1919 int_type = actual_type->data.enumeration.tag_int_type;
1924 assert(tag_type->id == TypeTableEntryIdEnumTag);
1925 int_type = tag_type->data.enum_tag.int_type;
1926 } else {1920 } else {
1927 int_type = actual_type;1921 int_type = actual_type;
1928 }1922 }
...@@ -1946,19 +1940,11 @@ static LLVMValueRef ir_render_ptr_to_int(CodeGen *g, IrExecutable *executable, I...@@ -1946,19 +1940,11 @@ static LLVMValueRef ir_render_ptr_to_int(CodeGen *g, IrExecutable *executable, I
1946static LLVMValueRef ir_render_int_to_enum(CodeGen *g, IrExecutable *executable, IrInstructionIntToEnum *instruction) {1940static LLVMValueRef ir_render_int_to_enum(CodeGen *g, IrExecutable *executable, IrInstructionIntToEnum *instruction) {
1947 TypeTableEntry *wanted_type = instruction->base.value.type;1941 TypeTableEntry *wanted_type = instruction->base.value.type;
1948 assert(wanted_type->id == TypeTableEntryIdEnum);1942 assert(wanted_type->id == TypeTableEntryIdEnum);
1949 TypeTableEntry *tag_type = wanted_type->data.enumeration.tag_type;1943 TypeTableEntry *tag_int_type = wanted_type->data.enumeration.tag_int_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 }
19581944
1959 LLVMValueRef target_val = ir_llvm_value(g, instruction->target);1945 LLVMValueRef target_val = ir_llvm_value(g, instruction->target);
1960 return gen_widen_or_shorten(g, ir_want_debug_safety(g, &instruction->base),1946 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);
1962}1948}
19631949
1964static LLVMValueRef ir_render_int_to_err(CodeGen *g, IrExecutable *executable, IrInstructionIntToErr *instruction) {1950static 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...@@ -2378,27 +2364,6 @@ static LLVMValueRef ir_render_struct_field_ptr(CodeGen *g, IrExecutable *executa
2378 return LLVMBuildStructGEP(g->builder, struct_ptr, (unsigned)field->gen_index, "");2364 return LLVMBuildStructGEP(g->builder, struct_ptr, (unsigned)field->gen_index, "");
2379}2365}
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
2402static LLVMValueRef ir_render_union_field_ptr(CodeGen *g, IrExecutable *executable,2367static LLVMValueRef ir_render_union_field_ptr(CodeGen *g, IrExecutable *executable,
2403 IrInstructionUnionFieldPtr *instruction)2368 IrInstructionUnionFieldPtr *instruction)
2404{2369{
...@@ -2427,7 +2392,7 @@ static LLVMValueRef ir_render_union_field_ptr(CodeGen *g, IrExecutable *executab...@@ -2427,7 +2392,7 @@ static LLVMValueRef ir_render_union_field_ptr(CodeGen *g, IrExecutable *executab
24272392
24282393
2429 LLVMValueRef expected_tag_value = bigint_to_llvm_const(union_type->data.unionation.tag_type->type_ref,2394 LLVMValueRef expected_tag_value = bigint_to_llvm_const(union_type->data.unionation.tag_type->type_ref,
2430 &field->value);2395 &field->enum_field->value);
2431 LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn_val, "UnionCheckOk");2396 LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn_val, "UnionCheckOk");
2432 LLVMBasicBlockRef bad_block = LLVMAppendBasicBlock(g->cur_fn_val, "UnionCheckFail");2397 LLVMBasicBlockRef bad_block = LLVMAppendBasicBlock(g->cur_fn_val, "UnionCheckFail");
2433 LLVMValueRef ok_val = LLVMBuildICmp(g->builder, LLVMIntEQ, tag_value, expected_tag_value, "");2398 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...@@ -2754,19 +2719,19 @@ static LLVMValueRef ir_render_err_name(CodeGen *g, IrExecutable *executable, IrI
2754static LLVMValueRef ir_render_enum_tag_name(CodeGen *g, IrExecutable *executable,2719static LLVMValueRef ir_render_enum_tag_name(CodeGen *g, IrExecutable *executable,
2755 IrInstructionEnumTagName *instruction)2720 IrInstructionEnumTagName *instruction)
2756{2721{
2757 TypeTableEntry *enum_tag_type = instruction->target->value.type;2722 TypeTableEntry *enum_type = instruction->target->value.type;
2758 assert(enum_tag_type->data.enum_tag.generate_name_table);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;
2760 LLVMValueRef enum_tag_value = ir_llvm_value(g, instruction->target);2727 LLVMValueRef enum_tag_value = ir_llvm_value(g, instruction->target);
2761 if (ir_want_debug_safety(g, &instruction->base)) {2728 if (ir_want_debug_safety(g, &instruction->base)) {
2762 TypeTableEntry *enum_type = enum_tag_type->data.enum_tag.enum_type;
2763 size_t field_count = enum_type->data.enumeration.src_field_count;2729 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 possibly2731 // if the field_count can't fit in the bits of the enum_type, then it can't possibly
2766 // be the wrong value2732 // be the wrong value
2767 BigInt field_bi;2733 BigInt field_bi;
2768 bigint_init_unsigned(&field_bi, field_count);2734 bigint_init_unsigned(&field_bi, field_count);
2769 TypeTableEntry *tag_int_type = enum_tag_type->data.enum_tag.int_type;
2770 if (bigint_fits_in_bits(&field_bi, tag_int_type->data.integral.bit_count, false)) {2735 if (bigint_fits_in_bits(&field_bi, tag_int_type->data.integral.bit_count, false)) {
2771 LLVMValueRef end_val = LLVMConstInt(LLVMTypeOf(enum_tag_value), field_count, false);2736 LLVMValueRef end_val = LLVMConstInt(LLVMTypeOf(enum_tag_value), field_count, false);
2772 add_bounds_check(g, enum_tag_value, LLVMIntEQ, nullptr, LLVMIntULT, end_val);2737 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...@@ -2775,10 +2740,10 @@ static LLVMValueRef ir_render_enum_tag_name(CodeGen *g, IrExecutable *executable
27752740
2776 LLVMValueRef indices[] = {2741 LLVMValueRef indices[] = {
2777 LLVMConstNull(g->builtin_types.entry_usize->type_ref),2742 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,
2779 g->builtin_types.entry_usize, enum_tag_value),2744 g->builtin_types.entry_usize, enum_tag_value),
2780 };2745 };
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, "");
2782}2747}
27832748
2784static LLVMValueRef ir_render_field_parent_ptr(CodeGen *g, IrExecutable *executable,2749static 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...@@ -3352,48 +3317,24 @@ static LLVMValueRef ir_render_err_wrap_payload(CodeGen *g, IrExecutable *executa
3352 return instruction->tmp_ptr;3317 return instruction->tmp_ptr;
3353}3318}
33543319
3355static LLVMValueRef ir_render_enum_tag(CodeGen *g, IrExecutable *executable, IrInstructionEnumTag *instruction) {3320static LLVMValueRef ir_render_union_tag(CodeGen *g, IrExecutable *executable, IrInstructionUnionTag *instruction) {
3356 TypeTableEntry *enum_type = instruction->value->value.type;3321 TypeTableEntry *union_type = instruction->value->value.type;
3357 TypeTableEntry *tag_type = enum_type->data.enumeration.tag_type;3322 assert(union_type->data.unionation.gen_tag_index != SIZE_MAX);
3323
3324 TypeTableEntry *tag_type = union_type->data.unionation.tag_type;
3358 if (!type_has_bits(tag_type))3325 if (!type_has_bits(tag_type))
3359 return nullptr;3326 return nullptr;
33603327
3361 LLVMValueRef enum_val = ir_llvm_value(g, instruction->value);3328 LLVMValueRef union_val = ir_llvm_value(g, instruction->value);
3362 if (enum_type->data.enumeration.gen_field_count == 0)3329 if (union_type->data.unionation.gen_field_count == 0)
3363 return enum_val;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, "");
3366 TypeTableEntry *ptr_type = get_pointer_to_type(g, tag_type, false);3334 TypeTableEntry *ptr_type = get_pointer_to_type(g, tag_type, false);
3367 return get_handle_value(g, tag_field_ptr, tag_type, ptr_type);3335 return get_handle_value(g, tag_field_ptr, tag_type, ptr_type);
3368}3336}
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
3397static LLVMValueRef ir_render_struct_init(CodeGen *g, IrExecutable *executable, IrInstructionStructInit *instruction) {3338static LLVMValueRef ir_render_struct_init(CodeGen *g, IrExecutable *executable, IrInstructionStructInit *instruction) {
3398 for (size_t i = 0; i < instruction->field_count; i += 1) {3339 for (size_t i = 0; i < instruction->field_count; i += 1) {
3399 IrInstructionStructInitField *field = &instruction->fields[i];3340 IrInstructionStructInitField *field = &instruction->fields[i];
...@@ -3436,7 +3377,7 @@ static LLVMValueRef ir_render_union_init(CodeGen *g, IrExecutable *executable, I...@@ -3436,7 +3377,7 @@ static LLVMValueRef ir_render_union_init(CodeGen *g, IrExecutable *executable, I
3436 union_type->data.unionation.gen_tag_index, "");3377 union_type->data.unionation.gen_tag_index, "");
34373378
3438 LLVMValueRef tag_value = bigint_to_llvm_const(union_type->data.unionation.tag_type->type_ref,3379 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);
3440 gen_store_untyped(g, tag_value, tag_field_ptr, 0, false);3381 gen_store_untyped(g, tag_value, tag_field_ptr, 0, false);
34413382
3442 uncasted_union_ptr = LLVMBuildStructGEP(g->builder, instruction->tmp_ptr,3383 uncasted_union_ptr = LLVMBuildStructGEP(g->builder, instruction->tmp_ptr,
...@@ -3573,8 +3514,6 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,...@@ -3573,8 +3514,6 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
3573 return ir_render_call(g, executable, (IrInstructionCall *)instruction);3514 return ir_render_call(g, executable, (IrInstructionCall *)instruction);
3574 case IrInstructionIdStructFieldPtr:3515 case IrInstructionIdStructFieldPtr:
3575 return ir_render_struct_field_ptr(g, executable, (IrInstructionStructFieldPtr *)instruction);3516 return ir_render_struct_field_ptr(g, executable, (IrInstructionStructFieldPtr *)instruction);
3576 case IrInstructionIdEnumFieldPtr:
3577 return ir_render_enum_field_ptr(g, executable, (IrInstructionEnumFieldPtr *)instruction);
3578 case IrInstructionIdUnionFieldPtr:3517 case IrInstructionIdUnionFieldPtr:
3579 return ir_render_union_field_ptr(g, executable, (IrInstructionUnionFieldPtr *)instruction);3518 return ir_render_union_field_ptr(g, executable, (IrInstructionUnionFieldPtr *)instruction);
3580 case IrInstructionIdAsm:3519 case IrInstructionIdAsm:
...@@ -3629,10 +3568,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,...@@ -3629,10 +3568,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
3629 return ir_render_err_wrap_code(g, executable, (IrInstructionErrWrapCode *)instruction);3568 return ir_render_err_wrap_code(g, executable, (IrInstructionErrWrapCode *)instruction);
3630 case IrInstructionIdErrWrapPayload:3569 case IrInstructionIdErrWrapPayload:
3631 return ir_render_err_wrap_payload(g, executable, (IrInstructionErrWrapPayload *)instruction);3570 return ir_render_err_wrap_payload(g, executable, (IrInstructionErrWrapPayload *)instruction);
3632 case IrInstructionIdEnumTag:3571 case IrInstructionIdUnionTag:
3633 return ir_render_enum_tag(g, executable, (IrInstructionEnumTag *)instruction);3572 return ir_render_union_tag(g, executable, (IrInstructionUnionTag *)instruction);
3634 case IrInstructionIdInitEnum:
3635 return ir_render_init_enum(g, executable, (IrInstructionInitEnum *)instruction);
3636 case IrInstructionIdStructInit:3573 case IrInstructionIdStructInit:
3637 return ir_render_struct_init(g, executable, (IrInstructionStructInit *)instruction);3574 return ir_render_struct_init(g, executable, (IrInstructionStructInit *)instruction);
3638 case IrInstructionIdUnionInit:3575 case IrInstructionIdUnionInit:
...@@ -3768,7 +3705,6 @@ static LLVMValueRef pack_const_int(CodeGen *g, LLVMTypeRef big_int_type_ref, Con...@@ -3768,7 +3705,6 @@ static LLVMValueRef pack_const_int(CodeGen *g, LLVMTypeRef big_int_type_ref, Con
3768 case TypeTableEntryIdNullLit:3705 case TypeTableEntryIdNullLit:
3769 case TypeTableEntryIdErrorUnion:3706 case TypeTableEntryIdErrorUnion:
3770 case TypeTableEntryIdPureError:3707 case TypeTableEntryIdPureError:
3771 case TypeTableEntryIdEnumTag:
3772 case TypeTableEntryIdNamespace:3708 case TypeTableEntryIdNamespace:
3773 case TypeTableEntryIdBlock:3709 case TypeTableEntryIdBlock:
3774 case TypeTableEntryIdBoundFn:3710 case TypeTableEntryIdBoundFn:
...@@ -3780,7 +3716,6 @@ static LLVMValueRef pack_const_int(CodeGen *g, LLVMTypeRef big_int_type_ref, Con...@@ -3780,7 +3716,6 @@ static LLVMValueRef pack_const_int(CodeGen *g, LLVMTypeRef big_int_type_ref, Con
3780 return LLVMConstInt(big_int_type_ref, const_val->data.x_bool ? 1 : 0, false);3716 return LLVMConstInt(big_int_type_ref, const_val->data.x_bool ? 1 : 0, false);
3781 case TypeTableEntryIdEnum:3717 case TypeTableEntryIdEnum:
3782 {3718 {
3783 assert(type_entry->data.enumeration.gen_field_count == 0);
3784 assert(type_entry->data.enumeration.decl_node->data.container_decl.init_arg_expr != nullptr);3719 assert(type_entry->data.enumeration.decl_node->data.container_decl.init_arg_expr != nullptr);
3785 LLVMValueRef int_val = gen_const_val(g, const_val);3720 LLVMValueRef int_val = gen_const_val(g, const_val);
3786 return LLVMConstZExt(int_val, big_int_type_ref);3721 return LLVMConstZExt(int_val, big_int_type_ref);
...@@ -3852,7 +3787,6 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val) {...@@ -3852,7 +3787,6 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val) {
38523787
3853 switch (type_entry->id) {3788 switch (type_entry->id) {
3854 case TypeTableEntryIdInt:3789 case TypeTableEntryIdInt:
3855 case TypeTableEntryIdEnumTag:
3856 return bigint_to_llvm_const(type_entry->type_ref, &const_val->data.x_bigint);3790 return bigint_to_llvm_const(type_entry->type_ref, &const_val->data.x_bigint);
3857 case TypeTableEntryIdPureError:3791 case TypeTableEntryIdPureError:
3858 assert(const_val->data.x_pure_err);3792 assert(const_val->data.x_pure_err);
...@@ -4015,34 +3949,48 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val) {...@@ -4015,34 +3949,48 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val) {
4015 ConstExprValue *payload_value = const_val->data.x_union.payload;3949 ConstExprValue *payload_value = const_val->data.x_union.payload;
4016 assert(payload_value != nullptr);3950 assert(payload_value != nullptr);
40173951
4018 if (!type_has_bits(payload_value->type)) {3952 if (type_entry->data.unionation.gen_field_count == 0) {
4019 return LLVMGetUndef(union_type_ref);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 }
4020 }3959 }
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
4028 LLVMValueRef union_value_ref;3961 LLVMValueRef union_value_ref;
4029 {3962 bool make_unnamed_struct;
4030 if (pad_bytes == 0) {3963 if (!type_has_bits(payload_value->type)) {
4031 union_value_ref = correctly_typed_value;3964 if (type_entry->data.unionation.gen_tag_index == SIZE_MAX)
4032 } else {3965 return LLVMGetUndef(type_entry->type_ref);
4033 LLVMValueRef fields[2];3966
4034 fields[0] = correctly_typed_value;3967 union_value_ref = LLVMGetUndef(type_entry->data.unionation.most_aligned_union_member->type_ref);
4035 fields[1] = LLVMGetUndef(LLVMArrayType(LLVMInt8Type(), (unsigned)pad_bytes));3968 make_unnamed_struct = false;
4036 if (make_unnamed_struct || type_entry->data.unionation.gen_tag_index != SIZE_MAX) {3969 } else {
4037 union_value_ref = LLVMConstStruct(fields, 2, false);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;
4038 } else {3979 } 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 }
4040 }3988 }
4041 }3989 }
4042 }
40433990
4044 if (type_entry->data.unionation.gen_tag_index == SIZE_MAX) {3991 if (type_entry->data.unionation.gen_tag_index == SIZE_MAX) {
4045 return union_value_ref;3992 return union_value_ref;
3993 }
4046 }3994 }
40473995
4048 LLVMValueRef tag_value = bigint_to_llvm_const(type_entry->data.unionation.tag_type->type_ref,3996 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) {...@@ -4059,55 +4007,9 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val) {
4059 }4007 }
40604008
4061 }4009 }
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)) {4011 case TypeTableEntryIdEnum:
4077 uint64_t field_type_bytes = LLVMStoreSizeOfType(g->target_data_ref,4012 return bigint_to_llvm_const(type_entry->type_ref, &const_val->data.x_enum_tag);
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 }
4111 case TypeTableEntryIdFn:4013 case TypeTableEntryIdFn:
4112 return fn_llvm_value(g, const_val->data.x_fn.fn_entry);4014 return fn_llvm_value(g, const_val->data.x_fn.fn_entry);
4113 case TypeTableEntryIdPointer:4015 case TypeTableEntryIdPointer:
...@@ -4318,9 +4220,8 @@ static void generate_enum_name_tables(CodeGen *g) {...@@ -4318,9 +4220,8 @@ static void generate_enum_name_tables(CodeGen *g) {
43184220
43194221
4320 for (size_t enum_i = 0; enum_i < g->name_table_enums.length; enum_i += 1) {4222 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);4223 TypeTableEntry *enum_type = g->name_table_enums.at(enum_i);
4322 assert(enum_tag_type->id == TypeTableEntryIdEnumTag);4224 assert(enum_type->id == TypeTableEntryIdEnum);
4323 TypeTableEntry *enum_type = enum_tag_type->data.enum_tag.enum_type;
43244225
4325 size_t field_count = enum_type->data.enumeration.src_field_count;4226 size_t field_count = enum_type->data.enumeration.src_field_count;
4326 LLVMValueRef *values = allocate<LLVMValueRef>(field_count);4227 LLVMValueRef *values = allocate<LLVMValueRef>(field_count);
...@@ -4351,7 +4252,7 @@ static void generate_enum_name_tables(CodeGen *g) {...@@ -4351,7 +4252,7 @@ static void generate_enum_name_tables(CodeGen *g) {
4351 LLVMSetGlobalConstant(name_table, true);4252 LLVMSetGlobalConstant(name_table, true);
4352 LLVMSetUnnamedAddr(name_table, true);4253 LLVMSetUnnamedAddr(name_table, true);
4353 LLVMSetAlignment(name_table, LLVMABIAlignmentOfType(g->target_data_ref, LLVMTypeOf(name_table_init)));4254 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;
4355 }4256 }
4356}4257}
43574258
...@@ -4555,9 +4456,6 @@ static void do_code_gen(CodeGen *g) {...@@ -4555,9 +4456,6 @@ static void do_code_gen(CodeGen *g) {
4555 } else if (instruction->id == IrInstructionIdErrWrapCode) {4456 } else if (instruction->id == IrInstructionIdErrWrapCode) {
4556 IrInstructionErrWrapCode *err_wrap_code_instruction = (IrInstructionErrWrapCode *)instruction;4457 IrInstructionErrWrapCode *err_wrap_code_instruction = (IrInstructionErrWrapCode *)instruction;
4557 slot = &err_wrap_code_instruction->tmp_ptr;4458 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;
4561 } else {4459 } else {
4562 zig_unreachable();4460 zig_unreachable();
4563 }4461 }
...@@ -5054,7 +4952,7 @@ static void define_builtin_fns(CodeGen *g) {...@@ -5054,7 +4952,7 @@ static void define_builtin_fns(CodeGen *g) {
5054 create_builtin_fn(g, BuiltinFnIdTruncate, "truncate", 2);4952 create_builtin_fn(g, BuiltinFnIdTruncate, "truncate", 2);
5055 create_builtin_fn(g, BuiltinFnIdCompileErr, "compileError", 1);4953 create_builtin_fn(g, BuiltinFnIdCompileErr, "compileError", 1);
5056 create_builtin_fn(g, BuiltinFnIdCompileLog, "compileLog", SIZE_MAX);4954 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
5058 create_builtin_fn(g, BuiltinFnIdSetDebugSafety, "setDebugSafety", 2);4956 create_builtin_fn(g, BuiltinFnIdSetDebugSafety, "setDebugSafety", 2);
5059 create_builtin_fn(g, BuiltinFnIdSetFloatMode, "setFloatMode", 2);4957 create_builtin_fn(g, BuiltinFnIdSetFloatMode, "setFloatMode", 2);
5060 create_builtin_fn(g, BuiltinFnIdSetGlobalSection, "setGlobalSection", 2);4958 create_builtin_fn(g, BuiltinFnIdSetGlobalSection, "setGlobalSection", 2);
...@@ -5064,7 +4962,7 @@ static void define_builtin_fns(CodeGen *g) {...@@ -5064,7 +4962,7 @@ static void define_builtin_fns(CodeGen *g) {
5064 create_builtin_fn(g, BuiltinFnIdBitCast, "bitCast", 2);4962 create_builtin_fn(g, BuiltinFnIdBitCast, "bitCast", 2);
5065 create_builtin_fn(g, BuiltinFnIdIntToPtr, "intToPtr", 2);4963 create_builtin_fn(g, BuiltinFnIdIntToPtr, "intToPtr", 2);
5066 create_builtin_fn(g, BuiltinFnIdPtrToInt, "ptrToInt", 1);4964 create_builtin_fn(g, BuiltinFnIdPtrToInt, "ptrToInt", 1);
5067 create_builtin_fn(g, BuiltinFnIdEnumTagName, "enumTagName", 1); // TODO rename to memberName4965 create_builtin_fn(g, BuiltinFnIdTagName, "tagName", 1);
5068 create_builtin_fn(g, BuiltinFnIdEnumTagType, "EnumTagType", 1);4966 create_builtin_fn(g, BuiltinFnIdEnumTagType, "EnumTagType", 1);
5069 create_builtin_fn(g, BuiltinFnIdFieldParentPtr, "fieldParentPtr", 3);4967 create_builtin_fn(g, BuiltinFnIdFieldParentPtr, "fieldParentPtr", 3);
5070 create_builtin_fn(g, BuiltinFnIdOffsetOf, "offsetOf", 2);4968 create_builtin_fn(g, BuiltinFnIdOffsetOf, "offsetOf", 2);
...@@ -5681,7 +5579,6 @@ static void get_c_type(CodeGen *g, TypeTableEntry *type_entry, Buf *out_buf) {...@@ -5681,7 +5579,6 @@ static void get_c_type(CodeGen *g, TypeTableEntry *type_entry, Buf *out_buf) {
5681 case TypeTableEntryIdEnum:5579 case TypeTableEntryIdEnum:
5682 case TypeTableEntryIdUnion:5580 case TypeTableEntryIdUnion:
5683 case TypeTableEntryIdFn:5581 case TypeTableEntryIdFn:
5684 case TypeTableEntryIdEnumTag:
5685 zig_panic("TODO implement get_c_type for more types");5582 zig_panic("TODO implement get_c_type for more types");
5686 case TypeTableEntryIdInvalid:5583 case TypeTableEntryIdInvalid:
5687 case TypeTableEntryIdMetaType:5584 case TypeTableEntryIdMetaType:
src/ir.cpp+206-282
...@@ -223,10 +223,6 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionStructFieldPtr *...@@ -223,10 +223,6 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionStructFieldPtr *
223 return IrInstructionIdStructFieldPtr;223 return IrInstructionIdStructFieldPtr;
224}224}
225225
226static constexpr IrInstructionId ir_instruction_id(IrInstructionEnumFieldPtr *) {
227 return IrInstructionIdEnumFieldPtr;
228}
229
230static constexpr IrInstructionId ir_instruction_id(IrInstructionUnionFieldPtr *) {226static constexpr IrInstructionId ir_instruction_id(IrInstructionUnionFieldPtr *) {
231 return IrInstructionIdUnionFieldPtr;227 return IrInstructionIdUnionFieldPtr;
232}228}
...@@ -319,8 +315,8 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionCtz *) {...@@ -319,8 +315,8 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionCtz *) {
319 return IrInstructionIdCtz;315 return IrInstructionIdCtz;
320}316}
321317
322static constexpr IrInstructionId ir_instruction_id(IrInstructionEnumTag *) {318static constexpr IrInstructionId ir_instruction_id(IrInstructionUnionTag *) {
323 return IrInstructionIdEnumTag;319 return IrInstructionIdUnionTag;
324}320}
325321
326static constexpr IrInstructionId ir_instruction_id(IrInstructionImport *) {322static constexpr IrInstructionId ir_instruction_id(IrInstructionImport *) {
...@@ -479,10 +475,6 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionTestComptime *)...@@ -479,10 +475,6 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionTestComptime *)
479 return IrInstructionIdTestComptime;475 return IrInstructionIdTestComptime;
480}476}
481477
482static constexpr IrInstructionId ir_instruction_id(IrInstructionInitEnum *) {
483 return IrInstructionIdInitEnum;
484}
485
486static constexpr IrInstructionId ir_instruction_id(IrInstructionPtrCast *) {478static constexpr IrInstructionId ir_instruction_id(IrInstructionPtrCast *) {
487 return IrInstructionIdPtrCast;479 return IrInstructionIdPtrCast;
488}480}
...@@ -913,27 +905,6 @@ static IrInstruction *ir_build_struct_field_ptr_from(IrBuilder *irb, IrInstructi...@@ -913,27 +905,6 @@ static IrInstruction *ir_build_struct_field_ptr_from(IrBuilder *irb, IrInstructi
913 return new_instruction;905 return new_instruction;
914}906}
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
937static IrInstruction *ir_build_union_field_ptr(IrBuilder *irb, Scope *scope, AstNode *source_node,908static IrInstruction *ir_build_union_field_ptr(IrBuilder *irb, Scope *scope, AstNode *source_node,
938 IrInstruction *union_ptr, TypeUnionField *field)909 IrInstruction *union_ptr, TypeUnionField *field)
939{910{
...@@ -1528,8 +1499,8 @@ static IrInstruction *ir_build_switch_var(IrBuilder *irb, Scope *scope, AstNode...@@ -1528,8 +1499,8 @@ static IrInstruction *ir_build_switch_var(IrBuilder *irb, Scope *scope, AstNode
1528 return &instruction->base;1499 return &instruction->base;
1529}1500}
15301501
1531static IrInstruction *ir_build_enum_tag(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *value) {1502static IrInstruction *ir_build_union_tag(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *value) {
1532 IrInstructionEnumTag *instruction = ir_build_instruction<IrInstructionEnumTag>(irb, scope, source_node);1503 IrInstructionUnionTag *instruction = ir_build_instruction<IrInstructionUnionTag>(irb, scope, source_node);
1533 instruction->value = value;1504 instruction->value = value;
15341505
1535 ir_ref_instruction(value, irb->current_basic_block);1506 ir_ref_instruction(value, irb->current_basic_block);
...@@ -1537,13 +1508,6 @@ static IrInstruction *ir_build_enum_tag(IrBuilder *irb, Scope *scope, AstNode *s...@@ -1537,13 +1508,6 @@ static IrInstruction *ir_build_enum_tag(IrBuilder *irb, Scope *scope, AstNode *s
1537 return &instruction->base;1508 return &instruction->base;
1538}1509}
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
1547static IrInstruction *ir_build_import(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *name) {1511static IrInstruction *ir_build_import(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *name) {
1548 IrInstructionImport *instruction = ir_build_instruction<IrInstructionImport>(irb, scope, source_node);1512 IrInstructionImport *instruction = ir_build_instruction<IrInstructionImport>(irb, scope, source_node);
1549 instruction->name = name;1513 instruction->name = name;
...@@ -2033,28 +1997,6 @@ static IrInstruction *ir_build_test_comptime(IrBuilder *irb, Scope *scope, AstNo...@@ -2033,28 +1997,6 @@ static IrInstruction *ir_build_test_comptime(IrBuilder *irb, Scope *scope, AstNo
2033 return &instruction->base;1997 return &instruction->base;
2034}1998}
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
2058static IrInstruction *ir_build_ptr_cast(IrBuilder *irb, Scope *scope, AstNode *source_node,2000static IrInstruction *ir_build_ptr_cast(IrBuilder *irb, Scope *scope, AstNode *source_node,
2059 IrInstruction *dest_type, IrInstruction *ptr)2001 IrInstruction *dest_type, IrInstruction *ptr)
2060{2002{
...@@ -2481,13 +2423,6 @@ static IrInstruction *ir_instruction_structfieldptr_get_dep(IrInstructionStructF...@@ -2481,13 +2423,6 @@ static IrInstruction *ir_instruction_structfieldptr_get_dep(IrInstructionStructF
2481 }2423 }
2482}2424}
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
2491static IrInstruction *ir_instruction_unionfieldptr_get_dep(IrInstructionUnionFieldPtr *instruction, size_t index) {2426static IrInstruction *ir_instruction_unionfieldptr_get_dep(IrInstructionUnionFieldPtr *instruction, size_t index) {
2492 switch (index) {2427 switch (index) {
2493 case 0: return instruction->union_ptr;2428 case 0: return instruction->union_ptr;
...@@ -2657,7 +2592,7 @@ static IrInstruction *ir_instruction_maybewrap_get_dep(IrInstructionMaybeWrap *i...@@ -2657,7 +2592,7 @@ static IrInstruction *ir_instruction_maybewrap_get_dep(IrInstructionMaybeWrap *i
2657 }2592 }
2658}2593}
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) {
2661 switch (index) {2596 switch (index) {
2662 case 0: return instruction->value;2597 case 0: return instruction->value;
2663 default: return nullptr;2598 default: return nullptr;
...@@ -2943,13 +2878,6 @@ static IrInstruction *ir_instruction_testcomptime_get_dep(IrInstructionTestCompt...@@ -2943,13 +2878,6 @@ static IrInstruction *ir_instruction_testcomptime_get_dep(IrInstructionTestCompt
2943 }2878 }
2944}2879}
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
2953static IrInstruction *ir_instruction_ptrcast_get_dep(IrInstructionPtrCast *instruction,2881static IrInstruction *ir_instruction_ptrcast_get_dep(IrInstructionPtrCast *instruction,
2954 size_t index)2882 size_t index)
2955{2883{
...@@ -3184,8 +3112,6 @@ static IrInstruction *ir_instruction_get_dep(IrInstruction *instruction, size_t...@@ -3184,8 +3112,6 @@ static IrInstruction *ir_instruction_get_dep(IrInstruction *instruction, size_t
3184 return ir_instruction_fieldptr_get_dep((IrInstructionFieldPtr *) instruction, index);3112 return ir_instruction_fieldptr_get_dep((IrInstructionFieldPtr *) instruction, index);
3185 case IrInstructionIdStructFieldPtr:3113 case IrInstructionIdStructFieldPtr:
3186 return ir_instruction_structfieldptr_get_dep((IrInstructionStructFieldPtr *) instruction, index);3114 return ir_instruction_structfieldptr_get_dep((IrInstructionStructFieldPtr *) instruction, index);
3187 case IrInstructionIdEnumFieldPtr:
3188 return ir_instruction_enumfieldptr_get_dep((IrInstructionEnumFieldPtr *) instruction, index);
3189 case IrInstructionIdUnionFieldPtr:3115 case IrInstructionIdUnionFieldPtr:
3190 return ir_instruction_unionfieldptr_get_dep((IrInstructionUnionFieldPtr *) instruction, index);3116 return ir_instruction_unionfieldptr_get_dep((IrInstructionUnionFieldPtr *) instruction, index);
3191 case IrInstructionIdElemPtr:3117 case IrInstructionIdElemPtr:
...@@ -3234,8 +3160,8 @@ static IrInstruction *ir_instruction_get_dep(IrInstruction *instruction, size_t...@@ -3234,8 +3160,8 @@ static IrInstruction *ir_instruction_get_dep(IrInstruction *instruction, size_t
3234 return ir_instruction_unwrapmaybe_get_dep((IrInstructionUnwrapMaybe *) instruction, index);3160 return ir_instruction_unwrapmaybe_get_dep((IrInstructionUnwrapMaybe *) instruction, index);
3235 case IrInstructionIdMaybeWrap:3161 case IrInstructionIdMaybeWrap:
3236 return ir_instruction_maybewrap_get_dep((IrInstructionMaybeWrap *) instruction, index);3162 return ir_instruction_maybewrap_get_dep((IrInstructionMaybeWrap *) instruction, index);
3237 case IrInstructionIdEnumTag:3163 case IrInstructionIdUnionTag:
3238 return ir_instruction_enumtag_get_dep((IrInstructionEnumTag *) instruction, index);3164 return ir_instruction_uniontag_get_dep((IrInstructionUnionTag *) instruction, index);
3239 case IrInstructionIdClz:3165 case IrInstructionIdClz:
3240 return ir_instruction_clz_get_dep((IrInstructionClz *) instruction, index);3166 return ir_instruction_clz_get_dep((IrInstructionClz *) instruction, index);
3241 case IrInstructionIdCtz:3167 case IrInstructionIdCtz:
...@@ -3312,8 +3238,6 @@ static IrInstruction *ir_instruction_get_dep(IrInstruction *instruction, size_t...@@ -3312,8 +3238,6 @@ static IrInstruction *ir_instruction_get_dep(IrInstruction *instruction, size_t
3312 return ir_instruction_fnproto_get_dep((IrInstructionFnProto *) instruction, index);3238 return ir_instruction_fnproto_get_dep((IrInstructionFnProto *) instruction, index);
3313 case IrInstructionIdTestComptime:3239 case IrInstructionIdTestComptime:
3314 return ir_instruction_testcomptime_get_dep((IrInstructionTestComptime *) instruction, index);3240 return ir_instruction_testcomptime_get_dep((IrInstructionTestComptime *) instruction, index);
3315 case IrInstructionIdInitEnum:
3316 return ir_instruction_initenum_get_dep((IrInstructionInitEnum *) instruction, index);
3317 case IrInstructionIdPtrCast:3241 case IrInstructionIdPtrCast:
3318 return ir_instruction_ptrcast_get_dep((IrInstructionPtrCast *) instruction, index);3242 return ir_instruction_ptrcast_get_dep((IrInstructionPtrCast *) instruction, index);
3319 case IrInstructionIdBitCast:3243 case IrInstructionIdBitCast:
...@@ -4695,14 +4619,14 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo...@@ -4695,14 +4619,14 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
46954619
4696 return ir_build_ptr_to_int(irb, scope, node, arg0_value);4620 return ir_build_ptr_to_int(irb, scope, node, arg0_value);
4697 }4621 }
4698 case BuiltinFnIdEnumTagName:4622 case BuiltinFnIdTagName:
4699 {4623 {
4700 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);4624 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
4701 IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope);4625 IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope);
4702 if (arg0_value == irb->codegen->invalid_instruction)4626 if (arg0_value == irb->codegen->invalid_instruction)
4703 return arg0_value;4627 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);
4706 return ir_build_enum_tag_name(irb, scope, node, actual_tag);4630 return ir_build_enum_tag_name(irb, scope, node, actual_tag);
4707 }4631 }
4708 case BuiltinFnIdEnumTagType:4632 case BuiltinFnIdEnumTagType:
...@@ -8381,13 +8305,28 @@ static IrInstruction *ir_analyze_enum_to_int(IrAnalyze *ira, IrInstruction *sour...@@ -8381,13 +8305,28 @@ static IrInstruction *ir_analyze_enum_to_int(IrAnalyze *ira, IrInstruction *sour
8381{8305{
8382 assert(wanted_type->id == TypeTableEntryIdInt);8306 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
8384 if (instr_is_comptime(target)) {8323 if (instr_is_comptime(target)) {
8385 ConstExprValue *val = ir_resolve_const(ira, target, UndefBad);8324 ConstExprValue *val = ir_resolve_const(ira, target, UndefBad);
8386 if (!val)8325 if (!val)
8387 return ira->codegen->invalid_instruction;8326 return ira->codegen->invalid_instruction;
8388 IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,8327 IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,
8389 source_instr->source_node, wanted_type);8328 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);
8391 return result;8330 return result;
8392 }8331 }
83938332
...@@ -8397,6 +8336,31 @@ static IrInstruction *ir_analyze_enum_to_int(IrAnalyze *ira, IrInstruction *sour...@@ -8397,6 +8336,31 @@ static IrInstruction *ir_analyze_enum_to_int(IrAnalyze *ira, IrInstruction *sour
8397 return result;8336 return result;
8398}8337}
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
8400static IrInstruction *ir_analyze_undefined_to_anything(IrAnalyze *ira, IrInstruction *source_instr,8364static IrInstruction *ir_analyze_undefined_to_anything(IrAnalyze *ira, IrInstruction *source_instr,
8401 IrInstruction *target, TypeTableEntry *wanted_type)8365 IrInstruction *target, TypeTableEntry *wanted_type)
8402{8366{
...@@ -8452,6 +8416,22 @@ static IrInstruction *ir_analyze_int_to_enum(IrAnalyze *ira, IrInstruction *sour...@@ -8452,6 +8416,22 @@ static IrInstruction *ir_analyze_int_to_enum(IrAnalyze *ira, IrInstruction *sour
8452{8416{
8453 assert(wanted_type->id == TypeTableEntryIdEnum);8417 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
8455 if (instr_is_comptime(target)) {8435 if (instr_is_comptime(target)) {
8456 ConstExprValue *val = ir_resolve_const(ira, target, UndefBad);8436 ConstExprValue *val = ir_resolve_const(ira, target, UndefBad);
8457 if (!val)8437 if (!val)
...@@ -8469,7 +8449,7 @@ static IrInstruction *ir_analyze_int_to_enum(IrAnalyze *ira, IrInstruction *sour...@@ -8469,7 +8449,7 @@ static IrInstruction *ir_analyze_int_to_enum(IrAnalyze *ira, IrInstruction *sour
84698449
8470 IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,8450 IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,
8471 source_instr->source_node, wanted_type);8451 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);
8473 return result;8453 return result;
8474 }8454 }
84758455
...@@ -8907,39 +8887,24 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst...@@ -8907,39 +8887,24 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
8907 }8887 }
89088888
8909 // explicit cast from integer to enum type with no payload8889 // explicit cast from integer to enum type with no payload
8910 if (actual_type->id == TypeTableEntryIdInt &&8890 if (actual_type->id == TypeTableEntryIdInt && wanted_type->id == TypeTableEntryIdEnum) {
8911 wanted_type->id == TypeTableEntryIdEnum &&8891 return ir_analyze_int_to_enum(ira, source_instr, value, wanted_type);
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;
8925 }8892 }
89268893
8927 // explicit cast from enum type with no payload to integer8894 // explicit cast from enum type with no payload to integer
8928 if (wanted_type->id == TypeTableEntryIdInt &&8895 if (wanted_type->id == TypeTableEntryIdInt && actual_type->id == TypeTableEntryIdEnum) {
8929 actual_type->id == TypeTableEntryIdEnum &&8896 return ir_analyze_enum_to_int(ira, source_instr, value, wanted_type);
8930 actual_type->data.enumeration.gen_field_count == 0)8897 }
8931 {8898
8932 ensure_complete_type(ira->codegen, actual_type);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);
8933 if (type_is_invalid(actual_type))8902 if (type_is_invalid(actual_type))
8934 return ira->codegen->invalid_instruction;8903 return ira->codegen->invalid_instruction;
8935 if (wanted_type == actual_type->data.enumeration.tag_type->data.enum_tag.int_type) {8904
8936 return ir_analyze_enum_to_int(ira, source_instr, value, wanted_type);8905 if (actual_type->data.unionation.tag_type == wanted_type) {
8906 return ir_analyze_union_to_tag(ira, source_instr, value, wanted_type);
8937 }8907 }
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;
8943 }8908 }
89448909
8945 // explicit cast from undefined to anything8910 // explicit cast from undefined to anything
...@@ -9148,7 +9113,7 @@ static bool ir_resolve_atomic_order(IrAnalyze *ira, IrInstruction *value, Atomic...@@ -9148,7 +9113,7 @@ static bool ir_resolve_atomic_order(IrAnalyze *ira, IrInstruction *value, Atomic
9148 if (!const_val)9113 if (!const_val)
9149 return false;9114 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);
9152 return true;9117 return true;
9153}9118}
91549119
...@@ -9168,7 +9133,7 @@ static bool ir_resolve_global_linkage(IrAnalyze *ira, IrInstruction *value, Glob...@@ -9168,7 +9133,7 @@ static bool ir_resolve_global_linkage(IrAnalyze *ira, IrInstruction *value, Glob
9168 if (!const_val)9133 if (!const_val)
9169 return false;9134 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);
9172 return true;9137 return true;
9173}9138}
91749139
...@@ -9188,7 +9153,7 @@ static bool ir_resolve_float_mode(IrAnalyze *ira, IrInstruction *value, FloatMod...@@ -9188,7 +9153,7 @@ static bool ir_resolve_float_mode(IrAnalyze *ira, IrInstruction *value, FloatMod
9188 if (!const_val)9153 if (!const_val)
9189 return false;9154 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);
9192 return true;9157 return true;
9193}9158}
91949159
...@@ -9400,7 +9365,7 @@ static TypeTableEntry *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp...@@ -9400,7 +9365,7 @@ static TypeTableEntry *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp
9400 break;9365 break;
94019366
9402 case TypeTableEntryIdEnum:9367 case TypeTableEntryIdEnum:
9403 if (!is_equality_cmp || resolved_type->data.enumeration.gen_field_count != 0) {9368 if (!is_equality_cmp) {
9404 ir_add_error_node(ira, source_node,9369 ir_add_error_node(ira, source_node,
9405 buf_sprintf("operator not allowed for type '%s'", buf_ptr(&resolved_type->name)));9370 buf_sprintf("operator not allowed for type '%s'", buf_ptr(&resolved_type->name)));
9406 return ira->codegen->builtin_types.entry_invalid;9371 return ira->codegen->builtin_types.entry_invalid;
...@@ -9419,9 +9384,6 @@ static TypeTableEntry *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp...@@ -9419,9 +9384,6 @@ static TypeTableEntry *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp
9419 buf_sprintf("operator not allowed for type '%s'", buf_ptr(&resolved_type->name)));9384 buf_sprintf("operator not allowed for type '%s'", buf_ptr(&resolved_type->name)));
9420 return ira->codegen->builtin_types.entry_invalid;9385 return ira->codegen->builtin_types.entry_invalid;
94219386
9422 case TypeTableEntryIdEnumTag:
9423 zig_panic("TODO implement comparison for enum tag type");
9424
9425 case TypeTableEntryIdVar:9387 case TypeTableEntryIdVar:
9426 zig_unreachable();9388 zig_unreachable();
9427 }9389 }
...@@ -10170,7 +10132,6 @@ static VarClassRequired get_var_class_required(TypeTableEntry *type_entry) {...@@ -10170,7 +10132,6 @@ static VarClassRequired get_var_class_required(TypeTableEntry *type_entry) {
10170 case TypeTableEntryIdVoid:10132 case TypeTableEntryIdVoid:
10171 case TypeTableEntryIdPureError:10133 case TypeTableEntryIdPureError:
10172 case TypeTableEntryIdFn:10134 case TypeTableEntryIdFn:
10173 case TypeTableEntryIdEnumTag:
10174 return VarClassRequiredAny;10135 return VarClassRequiredAny;
10175 case TypeTableEntryIdNumLitFloat:10136 case TypeTableEntryIdNumLitFloat:
10176 case TypeTableEntryIdNumLitInt:10137 case TypeTableEntryIdNumLitInt:
...@@ -10913,7 +10874,6 @@ static TypeTableEntry *ir_analyze_unary_prefix_op_err(IrAnalyze *ira, IrInstruct...@@ -10913,7 +10874,6 @@ static TypeTableEntry *ir_analyze_unary_prefix_op_err(IrAnalyze *ira, IrInstruct
10913 case TypeTableEntryIdUnion:10874 case TypeTableEntryIdUnion:
10914 case TypeTableEntryIdFn:10875 case TypeTableEntryIdFn:
10915 case TypeTableEntryIdBoundFn:10876 case TypeTableEntryIdBoundFn:
10916 case TypeTableEntryIdEnumTag:
10917 {10877 {
10918 ConstExprValue *out_val = ir_build_const_from(ira, &un_op_instruction->base);10878 ConstExprValue *out_val = ir_build_const_from(ira, &un_op_instruction->base);
10919 TypeTableEntry *result_type = get_error_type(ira->codegen, meta_type);10879 TypeTableEntry *result_type = get_error_type(ira->codegen, meta_type);
...@@ -11001,7 +10961,6 @@ static TypeTableEntry *ir_analyze_maybe(IrAnalyze *ira, IrInstructionUnOp *un_op...@@ -11001,7 +10961,6 @@ static TypeTableEntry *ir_analyze_maybe(IrAnalyze *ira, IrInstructionUnOp *un_op
11001 case TypeTableEntryIdNamespace:10961 case TypeTableEntryIdNamespace:
11002 case TypeTableEntryIdBlock:10962 case TypeTableEntryIdBlock:
11003 case TypeTableEntryIdBoundFn:10963 case TypeTableEntryIdBoundFn:
11004 case TypeTableEntryIdEnumTag:
11005 case TypeTableEntryIdArgTuple:10964 case TypeTableEntryIdArgTuple:
11006 {10965 {
11007 ConstExprValue *out_val = ir_build_const_from(ira, &un_op_instruction->base);10966 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...@@ -11662,15 +11621,8 @@ static TypeTableEntry *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field
11662 field_ptr_instruction, container_ptr, container_type);11621 field_ptr_instruction, container_ptr, container_type);
11663 }11622 }
11664 } else if (bare_type->id == TypeTableEntryIdEnum) {11623 } else if (bare_type->id == TypeTableEntryIdEnum) {
11665 TypeEnumField *field = find_enum_type_field(bare_type, field_name);11624 return ir_analyze_container_member_access_inner(ira, bare_type, field_name,
11666 if (field) {11625 field_ptr_instruction, container_ptr, container_type);
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 }
11674 } else if (bare_type->id == TypeTableEntryIdUnion) {11626 } else if (bare_type->id == TypeTableEntryIdUnion) {
11675 TypeUnionField *field = find_union_type_field(bare_type, field_name);11627 TypeUnionField *field = find_union_type_field(bare_type, field_name);
11676 if (field) {11628 if (field) {
...@@ -11841,20 +11793,27 @@ static TypeTableEntry *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstru...@@ -11841,20 +11793,27 @@ static TypeTableEntry *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstru
1184111793
11842 TypeEnumField *field = find_enum_type_field(child_type, field_name);11794 TypeEnumField *field = find_enum_type_field(child_type, field_name);
11843 if (field) {11795 if (field) {
11844 if (field->type_entry->id == TypeTableEntryIdVoid) {11796 bool ptr_is_const = true;
11845 bool ptr_is_const = true;11797 bool ptr_is_volatile = false;
11846 bool ptr_is_volatile = false;11798 return ir_analyze_const_ptr(ira, &field_ptr_instruction->base,
11847 return ir_analyze_const_ptr(ira, &field_ptr_instruction->base,11799 create_const_enum(child_type, &field->value), child_type,
11848 create_const_enum_tag(child_type, &field->value), child_type,11800 ConstPtrMutComptimeConst, ptr_is_const, ptr_is_volatile);
11849 ConstPtrMutComptimeConst, ptr_is_const, ptr_is_volatile);11801 }
11850 } else {11802 } else if (child_type->id == TypeTableEntryIdUnion &&
11851 bool ptr_is_const = true;11803 (child_type->data.unionation.decl_node->data.container_decl.init_arg_expr != nullptr ||
11852 bool ptr_is_volatile = false;11804 child_type->data.unionation.decl_node->data.container_decl.auto_enum))
11853 return ir_analyze_const_ptr(ira, &field_ptr_instruction->base,11805 {
11854 create_const_bigint(child_type->data.enumeration.tag_type, &field->value),11806 ensure_complete_type(ira->codegen, child_type);
11855 child_type->data.enumeration.tag_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,
11856 ConstPtrMutComptimeConst, ptr_is_const, ptr_is_volatile);11816 ConstPtrMutComptimeConst, ptr_is_const, ptr_is_volatile);
11857 }
11858 }11817 }
11859 }11818 }
11860 ScopeDecls *container_scope = get_container_scope(child_type);11819 ScopeDecls *container_scope = get_container_scope(child_type);
...@@ -12163,7 +12122,6 @@ static TypeTableEntry *ir_analyze_instruction_typeof(IrAnalyze *ira, IrInstructi...@@ -12163,7 +12122,6 @@ static TypeTableEntry *ir_analyze_instruction_typeof(IrAnalyze *ira, IrInstructi
12163 case TypeTableEntryIdEnum:12122 case TypeTableEntryIdEnum:
12164 case TypeTableEntryIdUnion:12123 case TypeTableEntryIdUnion:
12165 case TypeTableEntryIdFn:12124 case TypeTableEntryIdFn:
12166 case TypeTableEntryIdEnumTag:
12167 case TypeTableEntryIdArgTuple:12125 case TypeTableEntryIdArgTuple:
12168 case TypeTableEntryIdOpaque:12126 case TypeTableEntryIdOpaque:
12169 {12127 {
...@@ -12511,7 +12469,6 @@ static TypeTableEntry *ir_analyze_instruction_slice_type(IrAnalyze *ira,...@@ -12511,7 +12469,6 @@ static TypeTableEntry *ir_analyze_instruction_slice_type(IrAnalyze *ira,
12511 case TypeTableEntryIdFn:12469 case TypeTableEntryIdFn:
12512 case TypeTableEntryIdNamespace:12470 case TypeTableEntryIdNamespace:
12513 case TypeTableEntryIdBoundFn:12471 case TypeTableEntryIdBoundFn:
12514 case TypeTableEntryIdEnumTag:
12515 {12472 {
12516 type_ensure_zero_bits_known(ira->codegen, child_type);12473 type_ensure_zero_bits_known(ira->codegen, child_type);
12517 TypeTableEntry *slice_ptr_type = get_pointer_to_type_extra(ira->codegen, child_type,12474 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,...@@ -12620,7 +12577,6 @@ static TypeTableEntry *ir_analyze_instruction_array_type(IrAnalyze *ira,
12620 case TypeTableEntryIdFn:12577 case TypeTableEntryIdFn:
12621 case TypeTableEntryIdNamespace:12578 case TypeTableEntryIdNamespace:
12622 case TypeTableEntryIdBoundFn:12579 case TypeTableEntryIdBoundFn:
12623 case TypeTableEntryIdEnumTag:
12624 {12580 {
12625 TypeTableEntry *result_type = get_array_type(ira->codegen, child_type, size);12581 TypeTableEntry *result_type = get_array_type(ira->codegen, child_type, size);
12626 ConstExprValue *out_val = ir_build_const_from(ira, &array_type_instruction->base);12582 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,...@@ -12671,7 +12627,6 @@ static TypeTableEntry *ir_analyze_instruction_size_of(IrAnalyze *ira,
12671 case TypeTableEntryIdPureError:12627 case TypeTableEntryIdPureError:
12672 case TypeTableEntryIdEnum:12628 case TypeTableEntryIdEnum:
12673 case TypeTableEntryIdUnion:12629 case TypeTableEntryIdUnion:
12674 case TypeTableEntryIdEnumTag:
12675 case TypeTableEntryIdFn:12630 case TypeTableEntryIdFn:
12676 {12631 {
12677 uint64_t size_in_bytes = type_size(ira->codegen, type_entry);12632 uint64_t size_in_bytes = type_size(ira->codegen, type_entry);
...@@ -12824,17 +12779,22 @@ static TypeTableEntry *ir_analyze_instruction_clz(IrAnalyze *ira, IrInstructionC...@@ -12824,17 +12779,22 @@ static TypeTableEntry *ir_analyze_instruction_clz(IrAnalyze *ira, IrInstructionC
12824 }12779 }
12825}12780}
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) {
12828 if (type_is_invalid(value->value.type))12783 if (type_is_invalid(value->value.type))
12829 return ira->codegen->invalid_instruction;12784 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) {
12832 ir_add_error(ira, source_instr,12791 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)));
12834 return ira->codegen->invalid_instruction;12793 return ira->codegen->invalid_instruction;
12835 }12794 }
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
12839 if (instr_is_comptime(value)) {12799 if (instr_is_comptime(value)) {
12840 ConstExprValue *val = ir_resolve_const(ira, value, UndefBad);12800 ConstExprValue *val = ir_resolve_const(ira, value, UndefBad);
...@@ -12845,11 +12805,11 @@ static IrInstruction *ir_analyze_enum_tag(IrAnalyze *ira, IrInstruction *source_...@@ -12845,11 +12805,11 @@ static IrInstruction *ir_analyze_enum_tag(IrAnalyze *ira, IrInstruction *source_
12845 source_instr->scope, source_instr->source_node);12805 source_instr->scope, source_instr->source_node);
12846 const_instruction->base.value.type = tag_type;12806 const_instruction->base.value.type = tag_type;
12847 const_instruction->base.value.special = ConstValSpecialStatic;12807 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);
12849 return &const_instruction->base;12809 return &const_instruction->base;
12850 }12810 }
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);
12853 result->value.type = tag_type;12813 result->value.type = tag_type;
12854 return result;12814 return result;
12855}12815}
...@@ -12880,7 +12840,7 @@ static TypeTableEntry *ir_analyze_instruction_switch_br(IrAnalyze *ira,...@@ -12880,7 +12840,7 @@ static TypeTableEntry *ir_analyze_instruction_switch_br(IrAnalyze *ira,
12880 return ir_unreach_error(ira);12840 return ir_unreach_error(ira);
1288112841
12882 if (case_value->value.type->id == TypeTableEntryIdEnum) {12842 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);
12884 if (type_is_invalid(case_value->value.type))12844 if (type_is_invalid(case_value->value.type))
12885 return ir_unreach_error(ira);12845 return ir_unreach_error(ira);
12886 }12846 }
...@@ -12927,7 +12887,7 @@ static TypeTableEntry *ir_analyze_instruction_switch_br(IrAnalyze *ira,...@@ -12927,7 +12887,7 @@ static TypeTableEntry *ir_analyze_instruction_switch_br(IrAnalyze *ira,
12927 continue;12887 continue;
1292812888
12929 if (new_value->value.type->id == TypeTableEntryIdEnum) {12889 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);
12931 if (type_is_invalid(new_value->value.type))12891 if (type_is_invalid(new_value->value.type))
12932 continue;12892 continue;
12933 }12893 }
...@@ -13009,34 +12969,54 @@ static TypeTableEntry *ir_analyze_instruction_switch_target(IrAnalyze *ira,...@@ -13009,34 +12969,54 @@ static TypeTableEntry *ir_analyze_instruction_switch_target(IrAnalyze *ira,
1300912969
13010 ir_build_load_ptr_from(&ira->new_irb, &switch_target_instruction->base, target_value_ptr);12970 ir_build_load_ptr_from(&ira->new_irb, &switch_target_instruction->base, target_value_ptr);
13011 return target_type;12971 return target_type;
13012 case TypeTableEntryIdEnum:12972 case TypeTableEntryIdUnion: {
13013 {12973 if (target_type->data.unionation.gen_tag_index == SIZE_MAX) {
13014 TypeTableEntry *tag_type = target_type->data.enumeration.tag_type;12974 ErrorMsg *msg = ir_add_error(ira, target_value_ptr,
13015 assert(tag_type != nullptr);12975 buf_sprintf("switch on union which has no attached enum"));
13016 if (pointee_val) {12976 add_error_note(ira->codegen, msg, target_type->data.unionation.decl_node,
13017 ConstExprValue *out_val = ir_build_const_from(ira, &switch_target_instruction->base);12977 buf_sprintf("union declared here"));
13018 bigint_init_bigint(&out_val->data.x_bigint, &pointee_val->data.x_enum.tag);12978 return ira->codegen->builtin_types.entry_invalid;
13019 return tag_type;12979 }
13020 }12980 TypeTableEntry *tag_type = target_type->data.unionation.tag_type;
1302112981 assert(tag_type != nullptr);
13022 IrInstruction *enum_value = ir_build_load_ptr(&ira->new_irb, switch_target_instruction->base.scope,12982 if (pointee_val) {
13023 switch_target_instruction->base.source_node, target_value_ptr);12983 ConstExprValue *out_val = ir_build_const_from(ira, &switch_target_instruction->base);
13024 enum_value->value.type = target_type;12984 bigint_init_bigint(&out_val->data.x_enum_tag, &pointee_val->data.x_union.tag);
13025 ir_build_enum_tag_from(&ira->new_irb, &switch_target_instruction->base, enum_value);
13026 return tag_type;12985 return tag_type;
13027 }12986 }
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 }
13028 case TypeTableEntryIdErrorUnion:13011 case TypeTableEntryIdErrorUnion:
13029 // see https://github.com/andrewrk/zig/issues/8313012 // see https://github.com/andrewrk/zig/issues/632
13030 zig_panic("TODO switch on error union");13013 zig_panic("TODO switch on error union");
13031 case TypeTableEntryIdEnumTag:
13032 zig_panic("TODO switch on enum tag type");
13033 case TypeTableEntryIdUnreachable:13014 case TypeTableEntryIdUnreachable:
13034 case TypeTableEntryIdArray:13015 case TypeTableEntryIdArray:
13035 case TypeTableEntryIdStruct:13016 case TypeTableEntryIdStruct:
13036 case TypeTableEntryIdUndefLit:13017 case TypeTableEntryIdUndefLit:
13037 case TypeTableEntryIdNullLit:13018 case TypeTableEntryIdNullLit:
13038 case TypeTableEntryIdMaybe:13019 case TypeTableEntryIdMaybe:
13039 case TypeTableEntryIdUnion:
13040 case TypeTableEntryIdBlock:13020 case TypeTableEntryIdBlock:
13041 case TypeTableEntryIdBoundFn:13021 case TypeTableEntryIdBoundFn:
13042 case TypeTableEntryIdArgTuple:13022 case TypeTableEntryIdArgTuple:
...@@ -13059,19 +13039,13 @@ static TypeTableEntry *ir_analyze_instruction_switch_var(IrAnalyze *ira, IrInstr...@@ -13059,19 +13039,13 @@ static TypeTableEntry *ir_analyze_instruction_switch_var(IrAnalyze *ira, IrInstr
1305913039
13060 assert(target_value_ptr->value.type->id == TypeTableEntryIdPointer);13040 assert(target_value_ptr->value.type->id == TypeTableEntryIdPointer);
13061 TypeTableEntry *target_type = target_value_ptr->value.type->data.pointer.child_type;13041 TypeTableEntry *target_type = target_value_ptr->value.type->data.pointer.child_type;
13062 if (target_type->id == TypeTableEntryIdEnum) {13042 if (target_type->id == TypeTableEntryIdUnion) {
13063 ConstExprValue *prong_val = ir_resolve_const(ira, prong_value, UndefBad);13043 ConstExprValue *prong_val = ir_resolve_const(ira, prong_value, UndefBad);
13064 if (!prong_val)13044 if (!prong_val)
13065 return ira->codegen->builtin_types.entry_invalid;13045 return ira->codegen->builtin_types.entry_invalid;
1306613046
13067 TypeEnumField *field;13047 assert(prong_value->value.type->id == TypeTableEntryIdEnum);
13068 if (prong_value->value.type->id == TypeTableEntryIdEnumTag) {13048 TypeUnionField *field = find_union_field_by_tag(target_type, &prong_val->data.x_enum_tag);
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 }
1307513049
13076 if (instr_is_comptime(target_value_ptr)) {13050 if (instr_is_comptime(target_value_ptr)) {
13077 ConstExprValue *target_val_ptr = ir_resolve_const(ira, target_value_ptr, UndefBad);13051 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...@@ -13082,11 +13056,11 @@ static TypeTableEntry *ir_analyze_instruction_switch_var(IrAnalyze *ira, IrInstr
13082 ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);13056 ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
13083 out_val->data.x_ptr.special = ConstPtrSpecialRef;13057 out_val->data.x_ptr.special = ConstPtrSpecialRef;
13084 out_val->data.x_ptr.mut = target_val_ptr->data.x_ptr.mut;13058 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;
13086 return get_pointer_to_type(ira->codegen, field->type_entry, target_val_ptr->type->data.pointer.is_const);13060 return get_pointer_to_type(ira->codegen, field->type_entry, target_val_ptr->type->data.pointer.is_const);
13087 }13061 }
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);
13090 return get_pointer_to_type(ira->codegen, field->type_entry,13064 return get_pointer_to_type(ira->codegen, field->type_entry,
13091 target_value_ptr->value.type->data.pointer.is_const);13065 target_value_ptr->value.type->data.pointer.is_const);
13092 } else {13066 } else {
...@@ -13096,10 +13070,10 @@ static TypeTableEntry *ir_analyze_instruction_switch_var(IrAnalyze *ira, IrInstr...@@ -13096,10 +13070,10 @@ static TypeTableEntry *ir_analyze_instruction_switch_var(IrAnalyze *ira, IrInstr
13096 }13070 }
13097}13071}
1309813072
13099static TypeTableEntry *ir_analyze_instruction_enum_tag(IrAnalyze *ira, IrInstructionEnumTag *enum_tag_instruction) {13073static TypeTableEntry *ir_analyze_instruction_union_tag(IrAnalyze *ira, IrInstructionUnionTag *instruction) {
13100 IrInstruction *value = enum_tag_instruction->value->other;13074 IrInstruction *value = instruction->value->other;
13101 IrInstruction *new_instruction = ir_analyze_enum_tag(ira, &enum_tag_instruction->base, value);13075 IrInstruction *new_instruction = ir_analyze_union_tag(ira, &instruction->base, value);
13102 ir_link_new_instruction(new_instruction, &enum_tag_instruction->base);13076 ir_link_new_instruction(new_instruction, &instruction->base);
13103 return new_instruction->value.type;13077 return new_instruction->value.type;
13104}13078}
1310513079
...@@ -13255,7 +13229,7 @@ static TypeTableEntry *ir_analyze_container_init_fields_union(IrAnalyze *ira, Ir...@@ -13255,7 +13229,7 @@ static TypeTableEntry *ir_analyze_container_init_fields_union(IrAnalyze *ira, Ir
1325513229
13256 ConstExprValue *out_val = ir_build_const_from(ira, instruction);13230 ConstExprValue *out_val = ir_build_const_from(ira, instruction);
13257 out_val->data.x_union.payload = field_val;13231 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
13260 ConstParent *parent = get_const_val_parent(ira->codegen, field_val);13234 ConstParent *parent = get_const_val_parent(ira->codegen, field_val);
13261 if (parent != nullptr) {13235 if (parent != nullptr) {
...@@ -13502,46 +13476,9 @@ static TypeTableEntry *ir_analyze_instruction_container_init_list(IrAnalyze *ira...@@ -13502,46 +13476,9 @@ static TypeTableEntry *ir_analyze_instruction_container_init_list(IrAnalyze *ira
13502 buf_ptr(&container_type->name)));13476 buf_ptr(&container_type->name)));
13503 return ira->codegen->builtin_types.entry_invalid;13477 return ira->codegen->builtin_types.entry_invalid;
13504 }13478 }
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;
13542 } else {13479 } else {
13543 ir_add_error(ira, container_type_value,13480 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)));
13545 return ira->codegen->builtin_types.entry_invalid;13482 return ira->codegen->builtin_types.entry_invalid;
13546 }13483 }
13547}13484}
...@@ -13584,8 +13521,8 @@ static TypeTableEntry *ir_analyze_min_max(IrAnalyze *ira, IrInstruction *source_...@@ -13584,8 +13521,8 @@ static TypeTableEntry *ir_analyze_min_max(IrAnalyze *ira, IrInstruction *source_
13584 eval_min_max_value(ira->codegen, target_type, out_val, is_max);13521 eval_min_max_value(ira->codegen, target_type, out_val, is_max);
13585 return target_type;13522 return target_type;
13586 }13523 }
13587 case TypeTableEntryIdEnumTag:13524 case TypeTableEntryIdEnum:
13588 zig_panic("TODO min/max value for enum tag type");13525 zig_panic("TODO min/max value for enum type");
13589 case TypeTableEntryIdVar:13526 case TypeTableEntryIdVar:
13590 case TypeTableEntryIdMetaType:13527 case TypeTableEntryIdMetaType:
13591 case TypeTableEntryIdUnreachable:13528 case TypeTableEntryIdUnreachable:
...@@ -13599,7 +13536,6 @@ static TypeTableEntry *ir_analyze_min_max(IrAnalyze *ira, IrInstruction *source_...@@ -13599,7 +13536,6 @@ static TypeTableEntry *ir_analyze_min_max(IrAnalyze *ira, IrInstruction *source_
13599 case TypeTableEntryIdMaybe:13536 case TypeTableEntryIdMaybe:
13600 case TypeTableEntryIdErrorUnion:13537 case TypeTableEntryIdErrorUnion:
13601 case TypeTableEntryIdPureError:13538 case TypeTableEntryIdPureError:
13602 case TypeTableEntryIdEnum:
13603 case TypeTableEntryIdUnion:13539 case TypeTableEntryIdUnion:
13604 case TypeTableEntryIdFn:13540 case TypeTableEntryIdFn:
13605 case TypeTableEntryIdNamespace:13541 case TypeTableEntryIdNamespace:
...@@ -13707,20 +13643,18 @@ static TypeTableEntry *ir_analyze_instruction_enum_tag_name(IrAnalyze *ira, IrIn...@@ -13707,20 +13643,18 @@ static TypeTableEntry *ir_analyze_instruction_enum_tag_name(IrAnalyze *ira, IrIn
13707 if (type_is_invalid(target->value.type))13643 if (type_is_invalid(target->value.type))
13708 return ira->codegen->builtin_types.entry_invalid;13644 return ira->codegen->builtin_types.entry_invalid;
1370913645
13710 assert(target->value.type->id == TypeTableEntryIdEnumTag);13646 assert(target->value.type->id == TypeTableEntryIdEnum);
1371113647
13712 if (instr_is_comptime(target)) {13648 if (instr_is_comptime(target)) {
13713 TypeTableEntry *enum_type = target->value.type->data.enum_tag.enum_type;13649 TypeEnumField *field = find_enum_field_by_tag(target->value.type, &target->value.data.x_bigint);
13714 uint64_t tag_value = bigint_as_unsigned(&target->value.data.x_bigint);
13715 TypeEnumField *field = &enum_type->data.enumeration.fields[tag_value];
13716 ConstExprValue *array_val = create_const_str_lit(ira->codegen, field->name);13650 ConstExprValue *array_val = create_const_str_lit(ira->codegen, field->name);
13717 ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);13651 ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
13718 init_const_slice(ira->codegen, out_val, array_val, 0, buf_len(field->name), true);13652 init_const_slice(ira->codegen, out_val, array_val, 0, buf_len(field->name), true);
13719 return out_val->type;13653 return out_val->type;
13720 }13654 }
1372113655
13722 if (!target->value.type->data.enum_tag.generate_name_table) {13656 if (!target->value.type->data.enumeration.generate_name_table) {
13723 target->value.type->data.enum_tag.generate_name_table = true;13657 target->value.type->data.enumeration.generate_name_table = true;
13724 ira->codegen->name_table_enums.append(target->value.type);13658 ira->codegen->name_table_enums.append(target->value.type);
13725 }13659 }
1372613660
...@@ -13869,7 +13803,7 @@ static TypeTableEntry *ir_analyze_instruction_type_id(IrAnalyze *ira,...@@ -13869,7 +13803,7 @@ static TypeTableEntry *ir_analyze_instruction_type_id(IrAnalyze *ira,
13869 TypeTableEntry *result_type = var_value->data.x_type;13803 TypeTableEntry *result_type = var_value->data.x_type;
1387013804
13871 ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);13805 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));
13873 return result_type;13807 return result_type;
13874}13808}
1387513809
...@@ -14698,14 +14632,14 @@ static TypeTableEntry *ir_analyze_instruction_member_type(IrAnalyze *ira, IrInst...@@ -14698,14 +14632,14 @@ static TypeTableEntry *ir_analyze_instruction_member_type(IrAnalyze *ira, IrInst
14698 ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);14632 ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
14699 out_val->data.x_type = field->type_entry;14633 out_val->data.x_type = field->type_entry;
14700 return ira->codegen->builtin_types.entry_type;14634 return ira->codegen->builtin_types.entry_type;
14701 } else if (container_type->id == TypeTableEntryIdEnum) {14635 } else if (container_type->id == TypeTableEntryIdUnion) {
14702 if (member_index >= container_type->data.enumeration.src_field_count) {14636 if (member_index >= container_type->data.unionation.src_field_count) {
14703 ir_add_error(ira, index_value,14637 ir_add_error(ira, index_value,
14704 buf_sprintf("member index %" ZIG_PRI_u64 " out of bounds; '%s' has %" PRIu32 " members",14638 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));
14706 return ira->codegen->builtin_types.entry_invalid;14640 return ira->codegen->builtin_types.entry_invalid;
14707 }14641 }
14708 TypeEnumField *field = &container_type->data.enumeration.fields[member_index];14642 TypeUnionField *field = &container_type->data.unionation.fields[member_index];
1470914643
14710 ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);14644 ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
14711 out_val->data.x_type = field->type_entry;14645 out_val->data.x_type = field->type_entry;
...@@ -14749,6 +14683,18 @@ static TypeTableEntry *ir_analyze_instruction_member_name(IrAnalyze *ira, IrInst...@@ -14749,6 +14683,18 @@ static TypeTableEntry *ir_analyze_instruction_member_name(IrAnalyze *ira, IrInst
14749 }14683 }
14750 TypeEnumField *field = &container_type->data.enumeration.fields[member_index];14684 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
14752 ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);14698 ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
14753 init_const_str_lit(ira->codegen, out_val, field->name);14699 init_const_str_lit(ira->codegen, out_val, field->name);
14754 return out_val->type;14700 return out_val->type;
...@@ -14819,7 +14765,6 @@ static TypeTableEntry *ir_analyze_instruction_align_of(IrAnalyze *ira, IrInstruc...@@ -14819,7 +14765,6 @@ static TypeTableEntry *ir_analyze_instruction_align_of(IrAnalyze *ira, IrInstruc
14819 case TypeTableEntryIdErrorUnion:14765 case TypeTableEntryIdErrorUnion:
14820 case TypeTableEntryIdPureError:14766 case TypeTableEntryIdPureError:
14821 case TypeTableEntryIdEnum:14767 case TypeTableEntryIdEnum:
14822 case TypeTableEntryIdEnumTag:
14823 case TypeTableEntryIdUnion:14768 case TypeTableEntryIdUnion:
14824 case TypeTableEntryIdFn:14769 case TypeTableEntryIdFn:
14825 {14770 {
...@@ -15125,10 +15070,9 @@ static TypeTableEntry *ir_analyze_instruction_check_switch_prongs(IrAnalyze *ira...@@ -15125,10 +15070,9 @@ static TypeTableEntry *ir_analyze_instruction_check_switch_prongs(IrAnalyze *ira
15125 if (type_is_invalid(switch_type))15070 if (type_is_invalid(switch_type))
15126 return ira->codegen->builtin_types.entry_invalid;15071 return ira->codegen->builtin_types.entry_invalid;
1512715072
15128 if (switch_type->id == TypeTableEntryIdEnumTag) {15073 if (switch_type->id == TypeTableEntryIdEnum) {
15129 TypeTableEntry *enum_type = switch_type->data.enum_tag.enum_type;
15130 HashMap<BigInt, AstNode *, bigint_hash, bigint_eql> field_prev_uses = {};15074 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
15133 for (size_t range_i = 0; range_i < instruction->range_count; range_i += 1) {15077 for (size_t range_i = 0; range_i < instruction->range_count; range_i += 1) {
15134 IrInstructionCheckSwitchProngsRange *range = &instruction->ranges[range_i];15078 IrInstructionCheckSwitchProngsRange *range = &instruction->ranges[range_i];
...@@ -15141,22 +15085,13 @@ static TypeTableEntry *ir_analyze_instruction_check_switch_prongs(IrAnalyze *ira...@@ -15141,22 +15085,13 @@ static TypeTableEntry *ir_analyze_instruction_check_switch_prongs(IrAnalyze *ira
15141 if (type_is_invalid(end_value->value.type))15085 if (type_is_invalid(end_value->value.type))
15142 return ira->codegen->builtin_types.entry_invalid;15086 return ira->codegen->builtin_types.entry_invalid;
1514315087
15088 assert(start_value->value.type->id == TypeTableEntryIdEnum);
15144 BigInt start_index;15089 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);
15145 BigInt end_index;15093 BigInt end_index;
15146 if (start_value->value.type->id == TypeTableEntryIdEnumTag) {15094 bigint_init_bigint(&end_index, &end_value->value.data.x_enum_tag);
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 }
1516015095
15161 BigInt field_index;15096 BigInt field_index;
15162 bigint_init_bigint(&field_index, &start_index);15097 bigint_init_bigint(&field_index, &start_index);
...@@ -15168,10 +15103,10 @@ static TypeTableEntry *ir_analyze_instruction_check_switch_prongs(IrAnalyze *ira...@@ -15168,10 +15103,10 @@ static TypeTableEntry *ir_analyze_instruction_check_switch_prongs(IrAnalyze *ira
15168 auto entry = field_prev_uses.put_unique(field_index, start_value->source_node);15103 auto entry = field_prev_uses.put_unique(field_index, start_value->source_node);
15169 if (entry) {15104 if (entry) {
15170 AstNode *prev_node = entry->value;15105 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);
15172 assert(enum_field != nullptr);15107 assert(enum_field != nullptr);
15173 ErrorMsg *msg = ir_add_error(ira, start_value,15108 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),
15175 buf_ptr(enum_field->name)));15110 buf_ptr(enum_field->name)));
15176 add_error_note(ira->codegen, msg, prev_node, buf_sprintf("other value is here"));15111 add_error_note(ira->codegen, msg, prev_node, buf_sprintf("other value is here"));
15177 }15112 }
...@@ -15179,13 +15114,13 @@ static TypeTableEntry *ir_analyze_instruction_check_switch_prongs(IrAnalyze *ira...@@ -15179,13 +15114,13 @@ static TypeTableEntry *ir_analyze_instruction_check_switch_prongs(IrAnalyze *ira
15179 }15114 }
15180 }15115 }
15181 if (!instruction->have_else_prong) {15116 if (!instruction->have_else_prong) {
15182 for (uint32_t i = 0; i < enum_type->data.enumeration.src_field_count; i += 1) {15117 for (uint32_t i = 0; i < switch_type->data.enumeration.src_field_count; i += 1) {
15183 TypeEnumField *enum_field = &enum_type->data.enumeration.fields[i];15118 TypeEnumField *enum_field = &switch_type->data.enumeration.fields[i];
1518415119
15185 auto entry = field_prev_uses.maybe_get(enum_field->value);15120 auto entry = field_prev_uses.maybe_get(enum_field->value);
15186 if (!entry) {15121 if (!entry) {
15187 ir_add_error(ira, &instruction->base,15122 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),
15189 buf_ptr(enum_field->name)));15124 buf_ptr(enum_field->name)));
15190 }15125 }
15191 }15126 }
...@@ -15481,8 +15416,6 @@ static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue...@@ -15481,8 +15416,6 @@ static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue
15481 zig_panic("TODO buf_write_value_bytes pure error type");15416 zig_panic("TODO buf_write_value_bytes pure error type");
15482 case TypeTableEntryIdEnum:15417 case TypeTableEntryIdEnum:
15483 zig_panic("TODO buf_write_value_bytes enum type");15418 zig_panic("TODO buf_write_value_bytes enum type");
15484 case TypeTableEntryIdEnumTag:
15485 zig_panic("TODO buf_write_value_bytes enum tag type");
15486 case TypeTableEntryIdFn:15419 case TypeTableEntryIdFn:
15487 zig_panic("TODO buf_write_value_bytes fn type");15420 zig_panic("TODO buf_write_value_bytes fn type");
15488 case TypeTableEntryIdUnion:15421 case TypeTableEntryIdUnion:
...@@ -15541,8 +15474,6 @@ static void buf_read_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue...@@ -15541,8 +15474,6 @@ static void buf_read_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue
15541 zig_panic("TODO buf_read_value_bytes pure error type");15474 zig_panic("TODO buf_read_value_bytes pure error type");
15542 case TypeTableEntryIdEnum:15475 case TypeTableEntryIdEnum:
15543 zig_panic("TODO buf_read_value_bytes enum type");15476 zig_panic("TODO buf_read_value_bytes enum type");
15544 case TypeTableEntryIdEnumTag:
15545 zig_panic("TODO buf_read_value_bytes enum tag type");
15546 case TypeTableEntryIdFn:15477 case TypeTableEntryIdFn:
15547 zig_panic("TODO buf_read_value_bytes fn type");15478 zig_panic("TODO buf_read_value_bytes fn type");
15548 case TypeTableEntryIdUnion:15479 case TypeTableEntryIdUnion:
...@@ -15920,11 +15851,8 @@ static TypeTableEntry *ir_analyze_instruction_enum_tag_type(IrAnalyze *ira, IrIn...@@ -15920,11 +15851,8 @@ static TypeTableEntry *ir_analyze_instruction_enum_tag_type(IrAnalyze *ira, IrIn
15920 if (type_is_invalid(enum_type))15851 if (type_is_invalid(enum_type))
15921 return ira->codegen->builtin_types.entry_invalid;15852 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
15926 ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);15854 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;
15928 return ira->codegen->builtin_types.entry_type;15856 return ira->codegen->builtin_types.entry_type;
15929}15857}
1593015858
...@@ -15938,9 +15866,7 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi...@@ -15938,9 +15866,7 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi
15938 case IrInstructionIdStructInit:15866 case IrInstructionIdStructInit:
15939 case IrInstructionIdUnionInit:15867 case IrInstructionIdUnionInit:
15940 case IrInstructionIdStructFieldPtr:15868 case IrInstructionIdStructFieldPtr:
15941 case IrInstructionIdEnumFieldPtr:
15942 case IrInstructionIdUnionFieldPtr:15869 case IrInstructionIdUnionFieldPtr:
15943 case IrInstructionIdInitEnum:
15944 case IrInstructionIdMaybeWrap:15870 case IrInstructionIdMaybeWrap:
15945 case IrInstructionIdErrWrapCode:15871 case IrInstructionIdErrWrapCode:
15946 case IrInstructionIdErrWrapPayload:15872 case IrInstructionIdErrWrapPayload:
...@@ -16012,8 +15938,8 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi...@@ -16012,8 +15938,8 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi
16012 return ir_analyze_instruction_switch_target(ira, (IrInstructionSwitchTarget *)instruction);15938 return ir_analyze_instruction_switch_target(ira, (IrInstructionSwitchTarget *)instruction);
16013 case IrInstructionIdSwitchVar:15939 case IrInstructionIdSwitchVar:
16014 return ir_analyze_instruction_switch_var(ira, (IrInstructionSwitchVar *)instruction);15940 return ir_analyze_instruction_switch_var(ira, (IrInstructionSwitchVar *)instruction);
16015 case IrInstructionIdEnumTag:15941 case IrInstructionIdUnionTag:
16016 return ir_analyze_instruction_enum_tag(ira, (IrInstructionEnumTag *)instruction);15942 return ir_analyze_instruction_union_tag(ira, (IrInstructionUnionTag *)instruction);
16017 case IrInstructionIdImport:15943 case IrInstructionIdImport:
16018 return ir_analyze_instruction_import(ira, (IrInstructionImport *)instruction);15944 return ir_analyze_instruction_import(ira, (IrInstructionImport *)instruction);
16019 case IrInstructionIdArrayLen:15945 case IrInstructionIdArrayLen:
...@@ -16260,7 +16186,6 @@ bool ir_has_side_effects(IrInstruction *instruction) {...@@ -16260,7 +16186,6 @@ bool ir_has_side_effects(IrInstruction *instruction) {
16260 case IrInstructionIdPtrTypeChild:16186 case IrInstructionIdPtrTypeChild:
16261 case IrInstructionIdArrayLen:16187 case IrInstructionIdArrayLen:
16262 case IrInstructionIdStructFieldPtr:16188 case IrInstructionIdStructFieldPtr:
16263 case IrInstructionIdEnumFieldPtr:
16264 case IrInstructionIdUnionFieldPtr:16189 case IrInstructionIdUnionFieldPtr:
16265 case IrInstructionIdArrayType:16190 case IrInstructionIdArrayType:
16266 case IrInstructionIdSliceType:16191 case IrInstructionIdSliceType:
...@@ -16271,7 +16196,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {...@@ -16271,7 +16196,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {
16271 case IrInstructionIdCtz:16196 case IrInstructionIdCtz:
16272 case IrInstructionIdSwitchVar:16197 case IrInstructionIdSwitchVar:
16273 case IrInstructionIdSwitchTarget:16198 case IrInstructionIdSwitchTarget:
16274 case IrInstructionIdEnumTag:16199 case IrInstructionIdUnionTag:
16275 case IrInstructionIdRef:16200 case IrInstructionIdRef:
16276 case IrInstructionIdMinValue:16201 case IrInstructionIdMinValue:
16277 case IrInstructionIdMaxValue:16202 case IrInstructionIdMaxValue:
...@@ -16293,7 +16218,6 @@ bool ir_has_side_effects(IrInstruction *instruction) {...@@ -16293,7 +16218,6 @@ bool ir_has_side_effects(IrInstruction *instruction) {
16293 case IrInstructionIdErrWrapPayload:16218 case IrInstructionIdErrWrapPayload:
16294 case IrInstructionIdFnProto:16219 case IrInstructionIdFnProto:
16295 case IrInstructionIdTestComptime:16220 case IrInstructionIdTestComptime:
16296 case IrInstructionIdInitEnum:
16297 case IrInstructionIdPtrCast:16221 case IrInstructionIdPtrCast:
16298 case IrInstructionIdBitCast:16222 case IrInstructionIdBitCast:
16299 case IrInstructionIdWidenOrShorten:16223 case IrInstructionIdWidenOrShorten:
src/ir_print.cpp+6-25
...@@ -291,7 +291,7 @@ static void ir_print_struct_init(IrPrint *irp, IrInstructionStructInit *instruct...@@ -291,7 +291,7 @@ static void ir_print_struct_init(IrPrint *irp, IrInstructionStructInit *instruct
291}291}
292292
293static void ir_print_union_init(IrPrint *irp, IrInstructionUnionInit *instruction) {293static 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
296 fprintf(irp->f, "%s {", buf_ptr(&instruction->union_type->name));296 fprintf(irp->f, "%s {", buf_ptr(&instruction->union_type->name));
297 fprintf(irp->f, ".%s = ", buf_ptr(field_name));297 fprintf(irp->f, ".%s = ", buf_ptr(field_name));
...@@ -361,17 +361,10 @@ static void ir_print_struct_field_ptr(IrPrint *irp, IrInstructionStructFieldPtr...@@ -361,17 +361,10 @@ static void ir_print_struct_field_ptr(IrPrint *irp, IrInstructionStructFieldPtr
361 fprintf(irp->f, ")");361 fprintf(irp->f, ")");
362}362}
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
371static void ir_print_union_field_ptr(IrPrint *irp, IrInstructionUnionFieldPtr *instruction) {364static void ir_print_union_field_ptr(IrPrint *irp, IrInstructionUnionFieldPtr *instruction) {
372 fprintf(irp->f, "@UnionFieldPtr(&");365 fprintf(irp->f, "@UnionFieldPtr(&");
373 ir_print_other_instruction(irp, instruction->union_ptr);366 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));
375 fprintf(irp->f, ")");368 fprintf(irp->f, ")");
376}369}
377370
...@@ -509,8 +502,8 @@ static void ir_print_switch_target(IrPrint *irp, IrInstructionSwitchTarget *inst...@@ -509,8 +502,8 @@ static void ir_print_switch_target(IrPrint *irp, IrInstructionSwitchTarget *inst
509 ir_print_other_instruction(irp, instruction->target_value_ptr);502 ir_print_other_instruction(irp, instruction->target_value_ptr);
510}503}
511504
512static void ir_print_enum_tag(IrPrint *irp, IrInstructionEnumTag *instruction) {505static void ir_print_union_tag(IrPrint *irp, IrInstructionUnionTag *instruction) {
513 fprintf(irp->f, "enumtag ");506 fprintf(irp->f, "uniontag ");
514 ir_print_other_instruction(irp, instruction->value);507 ir_print_other_instruction(irp, instruction->value);
515}508}
516509
...@@ -799,12 +792,6 @@ static void ir_print_test_comptime(IrPrint *irp, IrInstructionTestComptime *inst...@@ -799,12 +792,6 @@ static void ir_print_test_comptime(IrPrint *irp, IrInstructionTestComptime *inst
799 fprintf(irp->f, ")");792 fprintf(irp->f, ")");
800}793}
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
808static void ir_print_ptr_cast(IrPrint *irp, IrInstructionPtrCast *instruction) {795static void ir_print_ptr_cast(IrPrint *irp, IrInstructionPtrCast *instruction) {
809 fprintf(irp->f, "@ptrCast(");796 fprintf(irp->f, "@ptrCast(");
810 if (instruction->dest_type) {797 if (instruction->dest_type) {
...@@ -1078,9 +1065,6 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {...@@ -1078,9 +1065,6 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
1078 case IrInstructionIdStructFieldPtr:1065 case IrInstructionIdStructFieldPtr:
1079 ir_print_struct_field_ptr(irp, (IrInstructionStructFieldPtr *)instruction);1066 ir_print_struct_field_ptr(irp, (IrInstructionStructFieldPtr *)instruction);
1080 break;1067 break;
1081 case IrInstructionIdEnumFieldPtr:
1082 ir_print_enum_field_ptr(irp, (IrInstructionEnumFieldPtr *)instruction);
1083 break;
1084 case IrInstructionIdUnionFieldPtr:1068 case IrInstructionIdUnionFieldPtr:
1085 ir_print_union_field_ptr(irp, (IrInstructionUnionFieldPtr *)instruction);1069 ir_print_union_field_ptr(irp, (IrInstructionUnionFieldPtr *)instruction);
1086 break;1070 break;
...@@ -1123,8 +1107,8 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {...@@ -1123,8 +1107,8 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
1123 case IrInstructionIdSwitchTarget:1107 case IrInstructionIdSwitchTarget:
1124 ir_print_switch_target(irp, (IrInstructionSwitchTarget *)instruction);1108 ir_print_switch_target(irp, (IrInstructionSwitchTarget *)instruction);
1125 break;1109 break;
1126 case IrInstructionIdEnumTag:1110 case IrInstructionIdUnionTag:
1127 ir_print_enum_tag(irp, (IrInstructionEnumTag *)instruction);1111 ir_print_union_tag(irp, (IrInstructionUnionTag *)instruction);
1128 break;1112 break;
1129 case IrInstructionIdImport:1113 case IrInstructionIdImport:
1130 ir_print_import(irp, (IrInstructionImport *)instruction);1114 ir_print_import(irp, (IrInstructionImport *)instruction);
...@@ -1237,9 +1221,6 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {...@@ -1237,9 +1221,6 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
1237 case IrInstructionIdTestComptime:1221 case IrInstructionIdTestComptime:
1238 ir_print_test_comptime(irp, (IrInstructionTestComptime *)instruction);1222 ir_print_test_comptime(irp, (IrInstructionTestComptime *)instruction);
1239 break;1223 break;
1240 case IrInstructionIdInitEnum:
1241 ir_print_init_enum(irp, (IrInstructionInitEnum *)instruction);
1242 break;
1243 case IrInstructionIdPtrCast:1224 case IrInstructionIdPtrCast:
1244 ir_print_ptr_cast(irp, (IrInstructionPtrCast *)instruction);1225 ir_print_ptr_cast(irp, (IrInstructionPtrCast *)instruction);
1245 break;1226 break;
src/parser.cpp+25-4
...@@ -2377,7 +2377,9 @@ static AstNode *ast_parse_use(ParseContext *pc, size_t *token_index, VisibMod vi...@@ -2377,7 +2377,9 @@ static AstNode *ast_parse_use(ParseContext *pc, size_t *token_index, VisibMod vi
2377}2377}
23782378
2379/*2379/*
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) "}"
2381ContainerMember = (ContainerField | FnDef | GlobalVarDecl)2383ContainerMember = (ContainerField | FnDef | GlobalVarDecl)
2382ContainerField = Symbol option(":" PrefixOpExpression option("=" PrefixOpExpression ","2384ContainerField = Symbol option(":" PrefixOpExpression option("=" PrefixOpExpression ","
2383*/2385*/
...@@ -2414,7 +2416,28 @@ static AstNode *ast_parse_container_decl(ParseContext *pc, size_t *token_index,...@@ -2414,7 +2416,28 @@ static AstNode *ast_parse_container_decl(ParseContext *pc, size_t *token_index,
2414 AstNode *node = ast_create_node(pc, NodeTypeContainerDecl, first_token);2416 AstNode *node = ast_create_node(pc, NodeTypeContainerDecl, first_token);
2415 node->data.container_decl.layout = layout;2417 node->data.container_decl.layout = layout;
2416 node->data.container_decl.kind = kind;2418 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
2419 ast_eat_token(pc, token_index, TokenIdLBrace);2442 ast_eat_token(pc, token_index, TokenIdLBrace);
24202443
...@@ -2461,8 +2484,6 @@ static AstNode *ast_parse_container_decl(ParseContext *pc, size_t *token_index,...@@ -2461,8 +2484,6 @@ static AstNode *ast_parse_container_decl(ParseContext *pc, size_t *token_index,
2461 if (colon_token->id == TokenIdColon) {2484 if (colon_token->id == TokenIdColon) {
2462 *token_index += 1;2485 *token_index += 1;
2463 field_node->data.struct_field.type = ast_parse_prefix_op_expr(pc, token_index, true);2486 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);
2466 }2487 }
2467 Token *eq_token = &pc->tokens->at(*token_index);2488 Token *eq_token = &pc->tokens->at(*token_index);
2468 if (eq_token->id == TokenIdEq) {2489 if (eq_token->id == TokenIdEq) {
std/build.zig+21-21
...@@ -69,8 +69,8 @@ pub const Builder = struct {...@@ -69,8 +69,8 @@ pub const Builder = struct {
69 used: bool,69 used: bool,
70 };70 };
7171
72 const UserValue = enum {72 const UserValue = union(enum) {
73 Flag,73 Flag: void,
74 Scalar: []const u8,74 Scalar: []const u8,
75 List: ArrayList([]const u8),75 List: ArrayList([]const u8),
76 };76 };
...@@ -450,7 +450,7 @@ pub const Builder = struct {...@@ -450,7 +450,7 @@ pub const Builder = struct {
450 pub fn addUserInputOption(self: &Builder, name: []const u8, value: []const u8) -> bool {450 pub fn addUserInputOption(self: &Builder, name: []const u8, value: []const u8) -> bool {
451 if (%%self.user_input_options.put(name, UserInputOption {451 if (%%self.user_input_options.put(name, UserInputOption {
452 .name = name,452 .name = name,
453 .value = UserValue.Scalar { value },453 .value = UserValue { .Scalar = value },
454 .used = false,454 .used = false,
455 })) |*prev_value| {455 })) |*prev_value| {
456 // option already exists456 // option already exists
...@@ -462,7 +462,7 @@ pub const Builder = struct {...@@ -462,7 +462,7 @@ pub const Builder = struct {
462 %%list.append(value);462 %%list.append(value);
463 _ = %%self.user_input_options.put(name, UserInputOption {463 _ = %%self.user_input_options.put(name, UserInputOption {
464 .name = name,464 .name = name,
465 .value = UserValue.List { list },465 .value = UserValue { .List = list },
466 .used = false,466 .used = false,
467 });467 });
468 },468 },
...@@ -471,7 +471,7 @@ pub const Builder = struct {...@@ -471,7 +471,7 @@ pub const Builder = struct {
471 %%list.append(value);471 %%list.append(value);
472 _ = %%self.user_input_options.put(name, UserInputOption {472 _ = %%self.user_input_options.put(name, UserInputOption {
473 .name = name,473 .name = name,
474 .value = UserValue.List { *list },474 .value = UserValue { .List = *list },
475 .used = false,475 .used = false,
476 });476 });
477 },477 },
...@@ -487,7 +487,7 @@ pub const Builder = struct {...@@ -487,7 +487,7 @@ pub const Builder = struct {
487 pub fn addUserInputFlag(self: &Builder, name: []const u8) -> bool {487 pub fn addUserInputFlag(self: &Builder, name: []const u8) -> bool {
488 if (%%self.user_input_options.put(name, UserInputOption {488 if (%%self.user_input_options.put(name, UserInputOption {
489 .name = name,489 .name = name,
490 .value = UserValue.Flag,490 .value = UserValue {.Flag = {} },
491 .used = false,491 .used = false,
492 })) |*prev_value| {492 })) |*prev_value| {
493 switch (prev_value.value) {493 switch (prev_value.value) {
...@@ -685,8 +685,8 @@ const CrossTarget = struct {...@@ -685,8 +685,8 @@ const CrossTarget = struct {
685 environ: builtin.Environ,685 environ: builtin.Environ,
686};686};
687687
688const Target = enum {688const Target = union(enum) {
689 Native,689 Native: void,
690 Cross: CrossTarget,690 Cross: CrossTarget,
691691
692 pub fn oFileExt(self: &const Target) -> []const u8 {692 pub fn oFileExt(self: &const Target) -> []const u8 {
...@@ -844,7 +844,7 @@ pub const LibExeObjStep = struct {...@@ -844,7 +844,7 @@ pub const LibExeObjStep = struct {
844 .kind = kind,844 .kind = kind,
845 .root_src = root_src,845 .root_src = root_src,
846 .name = name,846 .name = name,
847 .target = Target.Native,847 .target = Target { .Native = {} },
848 .linker_script = null,848 .linker_script = null,
849 .link_libs = BufSet.init(builder.allocator),849 .link_libs = BufSet.init(builder.allocator),
850 .frameworks = BufSet.init(builder.allocator),850 .frameworks = BufSet.init(builder.allocator),
...@@ -879,7 +879,7 @@ pub const LibExeObjStep = struct {...@@ -879,7 +879,7 @@ pub const LibExeObjStep = struct {
879 .kind = kind,879 .kind = kind,
880 .version = *version,880 .version = *version,
881 .static = static,881 .static = static,
882 .target = Target.Native,882 .target = Target { .Native = {} },
883 .cflags = ArrayList([]const u8).init(builder.allocator),883 .cflags = ArrayList([]const u8).init(builder.allocator),
884 .source_files = ArrayList([]const u8).init(builder.allocator),884 .source_files = ArrayList([]const u8).init(builder.allocator),
885 .object_files = ArrayList([]const u8).init(builder.allocator),885 .object_files = ArrayList([]const u8).init(builder.allocator),
...@@ -948,8 +948,8 @@ pub const LibExeObjStep = struct {...@@ -948,8 +948,8 @@ pub const LibExeObjStep = struct {
948 pub fn setTarget(self: &LibExeObjStep, target_arch: builtin.Arch, target_os: builtin.Os,948 pub fn setTarget(self: &LibExeObjStep, target_arch: builtin.Arch, target_os: builtin.Os,
949 target_environ: builtin.Environ)949 target_environ: builtin.Environ)
950 {950 {
951 self.target = Target.Cross {951 self.target = Target {
952 CrossTarget {952 .Cross = CrossTarget {
953 .arch = target_arch,953 .arch = target_arch,
954 .os = target_os,954 .os = target_os,
955 .environ = target_environ,955 .environ = target_environ,
...@@ -1186,13 +1186,13 @@ pub const LibExeObjStep = struct {...@@ -1186,13 +1186,13 @@ pub const LibExeObjStep = struct {
1186 Target.Native => {},1186 Target.Native => {},
1187 Target.Cross => |cross_target| {1187 Target.Cross => |cross_target| {
1188 %%zig_args.append("--target-arch");1188 %%zig_args.append("--target-arch");
1189 %%zig_args.append(@enumTagName(cross_target.arch));1189 %%zig_args.append(@tagName(cross_target.arch));
11901190
1191 %%zig_args.append("--target-os");1191 %%zig_args.append("--target-os");
1192 %%zig_args.append(@enumTagName(cross_target.os));1192 %%zig_args.append(@tagName(cross_target.os));
11931193
1194 %%zig_args.append("--target-environ");1194 %%zig_args.append("--target-environ");
1195 %%zig_args.append(@enumTagName(cross_target.environ));1195 %%zig_args.append(@tagName(cross_target.environ));
1196 },1196 },
1197 }1197 }
11981198
...@@ -1553,7 +1553,7 @@ pub const TestStep = struct {...@@ -1553,7 +1553,7 @@ pub const TestStep = struct {
1553 .name_prefix = "",1553 .name_prefix = "",
1554 .filter = null,1554 .filter = null,
1555 .link_libs = BufSet.init(builder.allocator),1555 .link_libs = BufSet.init(builder.allocator),
1556 .target = Target.Native,1556 .target = Target { .Native = {} },
1557 .exec_cmd_args = null,1557 .exec_cmd_args = null,
1558 }1558 }
1559 }1559 }
...@@ -1581,8 +1581,8 @@ pub const TestStep = struct {...@@ -1581,8 +1581,8 @@ pub const TestStep = struct {
1581 pub fn setTarget(self: &TestStep, target_arch: builtin.Arch, target_os: builtin.Os,1581 pub fn setTarget(self: &TestStep, target_arch: builtin.Arch, target_os: builtin.Os,
1582 target_environ: builtin.Environ)1582 target_environ: builtin.Environ)
1583 {1583 {
1584 self.target = Target.Cross {1584 self.target = Target {
1585 CrossTarget {1585 .Cross = CrossTarget {
1586 .arch = target_arch,1586 .arch = target_arch,
1587 .os = target_os,1587 .os = target_os,
1588 .environ = target_environ,1588 .environ = target_environ,
...@@ -1620,13 +1620,13 @@ pub const TestStep = struct {...@@ -1620,13 +1620,13 @@ pub const TestStep = struct {
1620 Target.Native => {},1620 Target.Native => {},
1621 Target.Cross => |cross_target| {1621 Target.Cross => |cross_target| {
1622 %%zig_args.append("--target-arch");1622 %%zig_args.append("--target-arch");
1623 %%zig_args.append(@enumTagName(cross_target.arch));1623 %%zig_args.append(@tagName(cross_target.arch));
16241624
1625 %%zig_args.append("--target-os");1625 %%zig_args.append("--target-os");
1626 %%zig_args.append(@enumTagName(cross_target.os));1626 %%zig_args.append(@tagName(cross_target.os));
16271627
1628 %%zig_args.append("--target-environ");1628 %%zig_args.append("--target-environ");
1629 %%zig_args.append(@enumTagName(cross_target.environ));1629 %%zig_args.append(@tagName(cross_target.environ));
1630 },1630 },
1631 }1631 }
16321632
std/debug.zig+13-15
...@@ -280,7 +280,7 @@ const AbbrevAttr = struct {...@@ -280,7 +280,7 @@ const AbbrevAttr = struct {
280 form_id: u64,280 form_id: u64,
281};281};
282282
283const FormValue = enum {283const FormValue = union(enum) {
284 Address: u64,284 Address: u64,
285 Block: []u8,285 Block: []u8,
286 Const: Constant,286 Const: Constant,
...@@ -475,7 +475,7 @@ fn readAllocBytes(allocator: &mem.Allocator, in_stream: &io.InStream, size: usiz...@@ -475,7 +475,7 @@ fn readAllocBytes(allocator: &mem.Allocator, in_stream: &io.InStream, size: usiz
475475
476fn parseFormValueBlockLen(allocator: &mem.Allocator, in_stream: &io.InStream, size: usize) -> %FormValue {476fn parseFormValueBlockLen(allocator: &mem.Allocator, in_stream: &io.InStream, size: usize) -> %FormValue {
477 const buf = %return readAllocBytes(allocator, in_stream, size);477 const buf = %return readAllocBytes(allocator, in_stream, size);
478 return FormValue.Block { buf };478 return FormValue { .Block = buf };
479}479}
480480
481fn parseFormValueBlock(allocator: &mem.Allocator, in_stream: &io.InStream, size: usize) -> %FormValue {481fn 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:...@@ -484,7 +484,7 @@ fn parseFormValueBlock(allocator: &mem.Allocator, in_stream: &io.InStream, size:
484}484}
485485
486fn parseFormValueConstant(allocator: &mem.Allocator, in_stream: &io.InStream, signed: bool, size: usize) -> %FormValue {486fn parseFormValueConstant(allocator: &mem.Allocator, in_stream: &io.InStream, signed: bool, size: usize) -> %FormValue {
487 FormValue.Const { Constant {487 FormValue { .Const = Constant {
488 .signed = signed,488 .signed = signed,
489 .payload = %return readAllocBytes(allocator, in_stream, size),489 .payload = %return readAllocBytes(allocator, in_stream, size),
490 }}490 }}
...@@ -510,7 +510,7 @@ fn parseFormValueTargetAddrSize(in_stream: &io.InStream) -> %u64 {...@@ -510,7 +510,7 @@ fn parseFormValueTargetAddrSize(in_stream: &io.InStream) -> %u64 {
510510
511fn parseFormValueRefLen(allocator: &mem.Allocator, in_stream: &io.InStream, size: usize) -> %FormValue {511fn parseFormValueRefLen(allocator: &mem.Allocator, in_stream: &io.InStream, size: usize) -> %FormValue {
512 const buf = %return readAllocBytes(allocator, in_stream, size);512 const buf = %return readAllocBytes(allocator, in_stream, size);
513 return FormValue.Ref { buf };513 return FormValue { .Ref = buf };
514}514}
515515
516fn parseFormValueRef(allocator: &mem.Allocator, in_stream: &io.InStream, comptime T: type) -> %FormValue {516fn 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...@@ -520,7 +520,7 @@ fn parseFormValueRef(allocator: &mem.Allocator, in_stream: &io.InStream, comptim
520520
521fn parseFormValue(allocator: &mem.Allocator, in_stream: &io.InStream, form_id: u64, is_64: bool) -> %FormValue {521fn parseFormValue(allocator: &mem.Allocator, in_stream: &io.InStream, form_id: u64, is_64: bool) -> %FormValue {
522 return switch (form_id) {522 return switch (form_id) {
523 DW.FORM_addr => FormValue.Address { %return parseFormValueTargetAddrSize(in_stream) },523 DW.FORM_addr => FormValue { .Address = %return parseFormValueTargetAddrSize(in_stream) },
524 DW.FORM_block1 => parseFormValueBlock(allocator, in_stream, 1),524 DW.FORM_block1 => parseFormValueBlock(allocator, in_stream, 1),
525 DW.FORM_block2 => parseFormValueBlock(allocator, in_stream, 2),525 DW.FORM_block2 => parseFormValueBlock(allocator, in_stream, 2),
526 DW.FORM_block4 => parseFormValueBlock(allocator, in_stream, 4),526 DW.FORM_block4 => parseFormValueBlock(allocator, in_stream, 4),
...@@ -540,13 +540,11 @@ fn parseFormValue(allocator: &mem.Allocator, in_stream: &io.InStream, form_id: u...@@ -540,13 +540,11 @@ fn parseFormValue(allocator: &mem.Allocator, in_stream: &io.InStream, form_id: u
540 DW.FORM_exprloc => {540 DW.FORM_exprloc => {
541 const size = %return readULeb128(in_stream);541 const size = %return readULeb128(in_stream);
542 const buf = %return readAllocBytes(allocator, in_stream, size);542 const buf = %return readAllocBytes(allocator, in_stream, size);
543 return FormValue.ExprLoc { buf };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)
549 },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 = %return parseFormValueDwarfOffsetSize(in_stream, is_64) },
550548
551 DW.FORM_ref1 => parseFormValueRef(allocator, in_stream, u8),549 DW.FORM_ref1 => parseFormValueRef(allocator, in_stream, u8),
552 DW.FORM_ref2 => parseFormValueRef(allocator, in_stream, u16),550 DW.FORM_ref2 => parseFormValueRef(allocator, in_stream, u16),
...@@ -557,11 +555,11 @@ fn parseFormValue(allocator: &mem.Allocator, in_stream: &io.InStream, form_id: u...@@ -557,11 +555,11 @@ fn parseFormValue(allocator: &mem.Allocator, in_stream: &io.InStream, form_id: u
557 parseFormValueRefLen(allocator, in_stream, ref_len)555 parseFormValueRefLen(allocator, in_stream, ref_len)
558 },556 },
559557
560 DW.FORM_ref_addr => FormValue.RefAddr { %return parseFormValueDwarfOffsetSize(in_stream, is_64) },558 DW.FORM_ref_addr => FormValue { .RefAddr = %return parseFormValueDwarfOffsetSize(in_stream, is_64) },
561 DW.FORM_ref_sig8 => FormValue.RefSig8 { %return in_stream.readIntLe(u64) },559 DW.FORM_ref_sig8 => FormValue { .RefSig8 = %return in_stream.readIntLe(u64) },
562560
563 DW.FORM_string => FormValue.String { %return readStringRaw(allocator, in_stream) },561 DW.FORM_string => FormValue { .String = %return readStringRaw(allocator, in_stream) },
564 DW.FORM_strp => FormValue.StrPtr { %return parseFormValueDwarfOffsetSize(in_stream, is_64) },562 DW.FORM_strp => FormValue { .StrPtr = %return parseFormValueDwarfOffsetSize(in_stream, is_64) },
565 DW.FORM_indirect => {563 DW.FORM_indirect => {
566 const child_form_id = %return readULeb128(in_stream);564 const child_form_id = %return readULeb128(in_stream);
567 parseFormValue(allocator, in_stream, child_form_id, is_64)565 parseFormValue(allocator, in_stream, child_form_id, is_64)
std/os/child_process.zig+5-5
...@@ -58,7 +58,7 @@ pub const ChildProcess = struct {...@@ -58,7 +58,7 @@ pub const ChildProcess = struct {
58 err_pipe: if (is_windows) void else [2]i32,58 err_pipe: if (is_windows) void else [2]i32,
59 llnode: if (is_windows) void else LinkedList(&ChildProcess).Node,59 llnode: if (is_windows) void else LinkedList(&ChildProcess).Node,
6060
61 pub const Term = enum {61 pub const Term = union(enum) {
62 Exited: i32,62 Exited: i32,
63 Signal: i32,63 Signal: i32,
64 Stopped: i32,64 Stopped: i32,
...@@ -281,13 +281,13 @@ pub const ChildProcess = struct {...@@ -281,13 +281,13 @@ pub const ChildProcess = struct {
281281
282 fn statusToTerm(status: i32) -> Term {282 fn statusToTerm(status: i32) -> Term {
283 return if (posix.WIFEXITED(status)) {283 return if (posix.WIFEXITED(status)) {
284 Term.Exited { posix.WEXITSTATUS(status) }284 Term { .Exited = posix.WEXITSTATUS(status) }
285 } else if (posix.WIFSIGNALED(status)) {285 } else if (posix.WIFSIGNALED(status)) {
286 Term.Signal { posix.WTERMSIG(status) }286 Term { .Signal = posix.WTERMSIG(status) }
287 } else if (posix.WIFSTOPPED(status)) {287 } else if (posix.WIFSTOPPED(status)) {
288 Term.Stopped { posix.WSTOPSIG(status) }288 Term { .Stopped = posix.WSTOPSIG(status) }
289 } else {289 } else {
290 Term.Unknown { status }290 Term { .Unknown = status }
291 };291 };
292 }292 }
293293
std/os/path.zig+1-1
...@@ -1016,7 +1016,7 @@ pub fn real(allocator: &Allocator, pathname: []const u8) -> %[]u8 {...@@ -1016,7 +1016,7 @@ pub fn real(allocator: &Allocator, pathname: []const u8) -> %[]u8 {
10161016
1017 return os.readLink(allocator, proc_path);1017 return os.readLink(allocator, proc_path);
1018 },1018 },
1019 else => @compileError("TODO implement os.path.real for " ++ @enumTagName(builtin.os)),1019 else => @compileError("TODO implement os.path.real for " ++ @tagName(builtin.os)),
1020 }1020 }
1021}1021}
10221022
test/cases/bugs/394.zig+2-2
...@@ -1,9 +1,9 @@...@@ -1,9 +1,9 @@
1const E = enum { A: [9]u8, B: u64, };1const E = union(enum) { A: [9]u8, B: u64, };
2const S = struct { x: u8, y: E, };2const S = struct { x: u8, y: E, };
33
4const assert = @import("std").debug.assert;4const assert = @import("std").debug.assert;
55
6test "bug 394 fixed" {6test "bug 394 fixed" {
7 const x = S { .x = 3, .y = E.B {1} };7 const x = S { .x = 3, .y = E {.B = 1 } };
8 assert(x.x == 3);8 assert(x.x == 3);
9}9}
test/cases/enum.zig+12-12
...@@ -2,8 +2,8 @@ const assert = @import("std").debug.assert;...@@ -2,8 +2,8 @@ const assert = @import("std").debug.assert;
2const mem = @import("std").mem;2const mem = @import("std").mem;
33
4test "enum type" {4test "enum type" {
5 const foo1 = Foo.One {13};5 const foo1 = Foo{ .One = 13};
6 const foo2 = Foo.Two { Point { .x = 1234, .y = 5678, }};6 const foo2 = Foo{. Two = Point { .x = 1234, .y = 5678, }};
7 const bar = Bar.B;7 const bar = Bar.B;
88
9 assert(bar == Bar.B);9 assert(bar == Bar.B);
...@@ -24,12 +24,12 @@ const Point = struct {...@@ -24,12 +24,12 @@ const Point = struct {
24 x: u64,24 x: u64,
25 y: u64,25 y: u64,
26};26};
27const Foo = enum {27const Foo = union(enum) {
28 One: i32,28 One: i32,
29 Two: Point,29 Two: Point,
30 Three: void,30 Three: void,
31};31};
32const FooNoVoid = enum {32const FooNoVoid = union(enum) {
33 One: i32,33 One: i32,
34 Two: Point,34 Two: Point,
35};35};
...@@ -41,13 +41,13 @@ const Bar = enum {...@@ -41,13 +41,13 @@ const Bar = enum {
41};41};
4242
43fn returnAnInt(x: i32) -> Foo {43fn returnAnInt(x: i32) -> Foo {
44 Foo.One { x }44 Foo { .One = x }
45}45}
4646
4747
48test "constant enum with payload" {48test "constant enum with payload" {
49 var empty = AnEnumWithPayload.Empty;49 var empty = AnEnumWithPayload {.Empty = {}};
50 var full = AnEnumWithPayload.Full {13};50 var full = AnEnumWithPayload {.Full = 13};
51 shouldBeEmpty(empty);51 shouldBeEmpty(empty);
52 shouldBeNotEmpty(full);52 shouldBeNotEmpty(full);
53}53}
...@@ -66,8 +66,8 @@ fn shouldBeNotEmpty(x: &const AnEnumWithPayload) {...@@ -66,8 +66,8 @@ fn shouldBeNotEmpty(x: &const AnEnumWithPayload) {
66 }66 }
67}67}
6868
69const AnEnumWithPayload = enum {69const AnEnumWithPayload = union(enum) {
70 Empty,70 Empty: void,
71 Full: i32,71 Full: i32,
72};72};
7373
...@@ -109,13 +109,13 @@ const IntToEnumNumber = enum {...@@ -109,13 +109,13 @@ const IntToEnumNumber = enum {
109};109};
110110
111111
112test "@enumTagName" {112test "@tagName" {
113 assert(mem.eql(u8, testEnumTagNameBare(BareNumber.Three), "Three"));113 assert(mem.eql(u8, testEnumTagNameBare(BareNumber.Three), "Three"));
114 comptime assert(mem.eql(u8, testEnumTagNameBare(BareNumber.Three), "Three"));114 comptime assert(mem.eql(u8, testEnumTagNameBare(BareNumber.Three), "Three"));
115}115}
116116
117fn testEnumTagNameBare(n: BareNumber) -> []const u8 {117fn testEnumTagNameBare(n: BareNumber) -> []const u8 {
118 return @enumTagName(n);118 return @tagName(n);
119}119}
120120
121const BareNumber = enum {121const BareNumber = enum {
...@@ -132,7 +132,7 @@ test "enum alignment" {...@@ -132,7 +132,7 @@ test "enum alignment" {
132 }132 }
133}133}
134134
135const AlignTestEnum = enum {135const AlignTestEnum = union(enum) {
136 A: [9]u8,136 A: [9]u8,
137 B: u64,137 B: u64,
138};138};
test/cases/enum_with_members.zig+3-3
...@@ -2,7 +2,7 @@ const assert = @import("std").debug.assert;...@@ -2,7 +2,7 @@ const assert = @import("std").debug.assert;
2const mem = @import("std").mem;2const mem = @import("std").mem;
3const fmt = @import("std").fmt;3const fmt = @import("std").fmt;
44
5const ET = enum {5const ET = union(enum) {
6 SINT: i32,6 SINT: i32,
7 UINT: u32,7 UINT: u32,
88
...@@ -15,8 +15,8 @@ const ET = enum {...@@ -15,8 +15,8 @@ const ET = enum {
15};15};
1616
17test "enum with members" {17test "enum with members" {
18 const a = ET.SINT { -42 };18 const a = ET { .SINT = -42 };
19 const b = ET.UINT { 42 };19 const b = ET { .UINT = 42 };
20 var buf: [20]u8 = undefined;20 var buf: [20]u8 = undefined;
2121
22 assert(%%a.print(buf[0..]) == 3);22 assert(%%a.print(buf[0..]) == 3);
test/cases/misc.zig+9-7
...@@ -324,8 +324,8 @@ test "constant enum initialization with differing sizes" {...@@ -324,8 +324,8 @@ test "constant enum initialization with differing sizes" {
324 test3_1(test3_foo);324 test3_1(test3_foo);
325 test3_2(test3_bar);325 test3_2(test3_bar);
326}326}
327const Test3Foo = enum {327const Test3Foo = union(enum) {
328 One,328 One: void,
329 Two: f32,329 Two: f32,
330 Three: Test3Point,330 Three: Test3Point,
331};331};
...@@ -333,8 +333,8 @@ const Test3Point = struct {...@@ -333,8 +333,8 @@ const Test3Point = struct {
333 x: i32,333 x: i32,
334 y: i32,334 y: i32,
335};335};
336const test3_foo = Test3Foo.Three{Test3Point {.x = 3, .y = 4}};336const test3_foo = Test3Foo { .Three = Test3Point {.x = 3, .y = 4}};
337const test3_bar = Test3Foo.Two{13};337const test3_bar = Test3Foo { .Two = 13};
338fn test3_1(f: &const Test3Foo) {338fn test3_1(f: &const Test3Foo) {
339 switch (*f) {339 switch (*f) {
340 Test3Foo.Three => |pt| {340 Test3Foo.Three => |pt| {
...@@ -449,7 +449,8 @@ fn testArray2DConstDoublePtr(ptr: &const f32) {...@@ -449,7 +449,8 @@ fn testArray2DConstDoublePtr(ptr: &const f32) {
449const Tid = builtin.TypeId;449const Tid = builtin.TypeId;
450const AStruct = struct { x: i32, };450const AStruct = struct { x: i32, };
451const AnEnum = enum { One, Two, };451const 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
454test "@typeId" {455test "@typeId" {
455 comptime {456 comptime {
...@@ -474,8 +475,9 @@ test "@typeId" {...@@ -474,8 +475,9 @@ test "@typeId" {
474 assert(@typeId(%i32) == Tid.ErrorUnion);475 assert(@typeId(%i32) == Tid.ErrorUnion);
475 assert(@typeId(error) == Tid.Error);476 assert(@typeId(error) == Tid.Error);
476 assert(@typeId(AnEnum) == Tid.Enum);477 assert(@typeId(AnEnum) == Tid.Enum);
477 assert(@typeId(@typeOf(AnEnumWithPayload.One)) == Tid.EnumTag);478 assert(@typeId(@typeOf(AUnionEnum.One)) == Tid.Enum);
478 // TODO union479 assert(@typeId(AUnionEnum) == Tid.Union);
480 assert(@typeId(AUnion) == Tid.Union);
479 assert(@typeId(fn()) == Tid.Fn);481 assert(@typeId(fn()) == Tid.Fn);
480 assert(@typeId(@typeOf(builtin)) == Tid.Namespace);482 assert(@typeId(@typeOf(builtin)) == Tid.Namespace);
481 assert(@typeId(@typeOf({this})) == Tid.Block);483 assert(@typeId(@typeOf({this})) == Tid.Block);
test/cases/reflection.zig+2-2
...@@ -62,8 +62,8 @@ const Foo = struct {...@@ -62,8 +62,8 @@ const Foo = struct {
62 three: void,62 three: void,
63};63};
6464
65const Bar = enum {65const Bar = union(enum) {
66 One,66 One: void,
67 Two: i32,67 Two: i32,
68 Three: bool,68 Three: bool,
69 Four: f64,69 Four: f64,
test/cases/switch.zig+8-8
...@@ -83,14 +83,14 @@ const SwitchStatmentFoo = enum {...@@ -83,14 +83,14 @@ const SwitchStatmentFoo = enum {
8383
8484
85test "switch prong with variable" {85test "switch prong with variable" {
86 switchProngWithVarFn(SwitchProngWithVarEnum.One {13});86 switchProngWithVarFn(SwitchProngWithVarEnum { .One = 13});
87 switchProngWithVarFn(SwitchProngWithVarEnum.Two {13.0});87 switchProngWithVarFn(SwitchProngWithVarEnum { .Two = 13.0});
88 switchProngWithVarFn(SwitchProngWithVarEnum.Meh);88 switchProngWithVarFn(SwitchProngWithVarEnum { .Meh = {}});
89}89}
90const SwitchProngWithVarEnum = enum {90const SwitchProngWithVarEnum = union(enum) {
91 One: i32,91 One: i32,
92 Two: f32,92 Two: f32,
93 Meh,93 Meh: void,
94};94};
95fn switchProngWithVarFn(a: &const SwitchProngWithVarEnum) {95fn switchProngWithVarFn(a: &const SwitchProngWithVarEnum) {
96 switch(*a) {96 switch(*a) {
...@@ -112,7 +112,7 @@ test "switch on enum using pointer capture" {...@@ -112,7 +112,7 @@ test "switch on enum using pointer capture" {
112}112}
113113
114fn testSwitchEnumPtrCapture() {114fn testSwitchEnumPtrCapture() {
115 var value = SwitchProngWithVarEnum.One { 1234 };115 var value = SwitchProngWithVarEnum { .One = 1234 };
116 switch (value) {116 switch (value) {
117 SwitchProngWithVarEnum.One => |*x| *x += 1,117 SwitchProngWithVarEnum.One => |*x| *x += 1,
118 else => unreachable,118 else => unreachable,
...@@ -136,13 +136,13 @@ fn returnsFive() -> i32 {...@@ -136,13 +136,13 @@ fn returnsFive() -> i32 {
136}136}
137137
138138
139const Number = enum {139const Number = union(enum) {
140 One: u64,140 One: u64,
141 Two: u8,141 Two: u8,
142 Three: f32,142 Three: f32,
143};143};
144144
145const number = Number.Three { 1.23 };145const number = Number { .Three = 1.23 };
146146
147fn returnsFalse() -> bool {147fn returnsFalse() -> bool {
148 switch (number) {148 switch (number) {
test/cases/switch_prong_err_enum.zig+2-2
...@@ -9,14 +9,14 @@ fn readOnce() -> %u64 {...@@ -9,14 +9,14 @@ fn readOnce() -> %u64 {
99
10error InvalidDebugInfo;10error InvalidDebugInfo;
1111
12const FormValue = enum {12const FormValue = union(enum) {
13 Address: u64,13 Address: u64,
14 Other: bool,14 Other: bool,
15};15};
1616
17fn doThing(form_id: u64) -> %FormValue {17fn doThing(form_id: u64) -> %FormValue {
18 return switch (form_id) {18 return switch (form_id) {
19 17 => FormValue.Address { %return readOnce() },19 17 => FormValue { .Address = %return readOnce() },
20 else => error.InvalidDebugInfo,20 else => error.InvalidDebugInfo,
21 }21 }
22}22}
test/cases/switch_prong_implicit_cast.zig+4-4
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1const assert = @import("std").debug.assert;1const assert = @import("std").debug.assert;
22
3const FormValue = enum {3const FormValue = union(enum) {
4 One,4 One: void,
5 Two: bool,5 Two: bool,
6};6};
77
...@@ -9,8 +9,8 @@ error Whatever;...@@ -9,8 +9,8 @@ error Whatever;
99
10fn foo(id: u64) -> %FormValue {10fn foo(id: u64) -> %FormValue {
11 switch (id) {11 switch (id) {
12 2 => FormValue.Two { true },12 2 => FormValue { .Two = true },
13 1 => FormValue.One,13 1 => FormValue { .One = {} },
14 else => return error.Whatever,14 else => return error.Whatever,
15 }15 }
16}16}
test/cases/union.zig+32-3
...@@ -1,6 +1,6 @@...@@ -1,6 +1,6 @@
1const assert = @import("std").debug.assert;1const assert = @import("std").debug.assert;
22
3const Value = enum {3const Value = union(enum) {
4 Int: u64,4 Int: u64,
5 Array: [9]u8,5 Array: [9]u8,
6};6};
...@@ -10,8 +10,8 @@ const Agg = struct {...@@ -10,8 +10,8 @@ const Agg = struct {
10 val2: Value,10 val2: Value,
11};11};
1212
13const v1 = Value.Int { 1234 };13const v1 = Value { .Int = 1234 };
14const v2 = Value.Array { []u8{3} ** 9 };14const v2 = Value { .Array = []u8{3} ** 9 };
1515
16const err = (%Agg)(Agg {16const err = (%Agg)(Agg {
17 .val1 = v1,17 .val1 = v1,
...@@ -75,3 +75,32 @@ test "basic extern unions" {...@@ -75,3 +75,32 @@ test "basic extern unions" {
75 assert(foo.float == 12.34);75 assert(foo.float == 12.34);
76}76}
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) {...@@ -930,8 +930,8 @@ pub fn addCases(cases: &tests.CompileErrorContext) {
930 \\fn bad_eql_1(a: []u8, b: []u8) -> bool {930 \\fn bad_eql_1(a: []u8, b: []u8) -> bool {
931 \\ a == b931 \\ a == b
932 \\}932 \\}
933 \\const EnumWithData = enum {933 \\const EnumWithData = union(enum) {
934 \\ One,934 \\ One: void,
935 \\ Two: i32,935 \\ Two: i32,
936 \\};936 \\};
937 \\fn bad_eql_2(a: &const EnumWithData, b: &const EnumWithData) -> bool {937 \\fn bad_eql_2(a: &const EnumWithData, b: &const EnumWithData) -> bool {
...@@ -1145,19 +1145,19 @@ pub fn addCases(cases: &tests.CompileErrorContext) {...@@ -1145,19 +1145,19 @@ pub fn addCases(cases: &tests.CompileErrorContext) {
1145 \\const JasonHM = u8;1145 \\const JasonHM = u8;
1146 \\const JasonList = &JsonNode;1146 \\const JasonList = &JsonNode;
1147 \\1147 \\
1148 \\const JsonOA = enum {1148 \\const JsonOA = union(enum) {
1149 \\ JSONArray: JsonList,1149 \\ JSONArray: JsonList,
1150 \\ JSONObject: JasonHM,1150 \\ JSONObject: JasonHM,
1151 \\};1151 \\};
1152 \\1152 \\
1153 \\const JsonType = enum {1153 \\const JsonType = union(enum) {
1154 \\ JSONNull: void,1154 \\ JSONNull: void,
1155 \\ JSONInteger: isize,1155 \\ JSONInteger: isize,
1156 \\ JSONDouble: f64,1156 \\ JSONDouble: f64,
1157 \\ JSONBool: bool,1157 \\ JSONBool: bool,
1158 \\ JSONString: []u8,1158 \\ JSONString: []u8,
1159 \\ JSONArray,1159 \\ JSONArray: void,
1160 \\ JSONObject,1160 \\ JSONObject: void,
1161 \\};1161 \\};
1162 \\1162 \\
1163 \\pub const JsonNode = struct {1163 \\pub const JsonNode = struct {
...@@ -2138,7 +2138,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) {...@@ -2138,7 +2138,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) {
2138 \\2138 \\
2139 \\const MdText = ArrayList(u8);2139 \\const MdText = ArrayList(u8);
2140 \\2140 \\
2141 \\const MdNode = enum {2141 \\const MdNode = union(enum) {
2142 \\ Header: struct {2142 \\ Header: struct {
2143 \\ text: MdText,2143 \\ text: MdText,
2144 \\ weight: HeaderValue,2144 \\ weight: HeaderValue,
...@@ -2297,6 +2297,14 @@ pub fn addCases(cases: &tests.CompileErrorContext) {...@@ -2297,6 +2297,14 @@ pub fn addCases(cases: &tests.CompileErrorContext) {
2297 ,2297 ,
2298 ".tmp_source.zig:2:21: error: type 'i32' does not support @memberType");2298 ".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
2300 cases.add("@memberType struct out of bounds",2308 cases.add("@memberType struct out of bounds",
2301 \\comptime {2309 \\comptime {
2302 \\ _ = @memberType(Foo, 0);2310 \\ _ = @memberType(Foo, 0);
...@@ -2305,11 +2313,11 @@ pub fn addCases(cases: &tests.CompileErrorContext) {...@@ -2305,11 +2313,11 @@ pub fn addCases(cases: &tests.CompileErrorContext) {
2305 ,2313 ,
2306 ".tmp_source.zig:2:26: error: member index 0 out of bounds; 'Foo' has 0 members");2314 ".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",
2309 \\comptime {2317 \\comptime {
2310 \\ _ = @memberType(Foo, 1);2318 \\ _ = @memberType(Foo, 1);
2311 \\}2319 \\}
2312 \\const Foo = enum {A,};2320 \\const Foo = union {A: void,};
2313 ,2321 ,
2314 ".tmp_source.zig:2:26: error: member index 1 out of bounds; 'Foo' has 1 members");2322 ".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) {...@@ -2336,6 +2344,14 @@ pub fn addCases(cases: &tests.CompileErrorContext) {
2336 ,2344 ,
2337 ".tmp_source.zig:2:26: error: member index 1 out of bounds; 'Foo' has 1 members");2345 ".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
2339 cases.add("calling var args extern function, passing array instead of pointer",2355 cases.add("calling var args extern function, passing array instead of pointer",
2340 \\export fn entry() {2356 \\export fn entry() {
2341 \\ foo("hello");2357 \\ foo("hello");
...@@ -2466,7 +2482,8 @@ pub fn addCases(cases: &tests.CompileErrorContext) {...@@ -2466,7 +2482,8 @@ pub fn addCases(cases: &tests.CompileErrorContext) {
2466 \\ var x: MultipleChoice = undefined;2482 \\ var x: MultipleChoice = undefined;
2467 \\}2483 \\}
2468 ,2484 ,
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
2471 cases.add("enum with 0 fields",2488 cases.add("enum with 0 fields",
2472 \\const Foo = enum {};2489 \\const Foo = enum {};
...@@ -2490,4 +2507,21 @@ pub fn addCases(cases: &tests.CompileErrorContext) {...@@ -2490,4 +2507,21 @@ pub fn addCases(cases: &tests.CompileErrorContext) {
2490 ,2507 ,
2491 ".tmp_source.zig:6:9: error: enum tag value 60 already taken",2508 ".tmp_source.zig:6:9: error: enum tag value 60 already taken",
2492 ".tmp_source.zig:4:9: note: other occurrence here");2509 ".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");
2493}2527}
test/tests.zig+5-5
...@@ -150,8 +150,8 @@ pub fn addPkgTests(b: &build.Builder, test_filter: ?[]const u8, root_src: []cons...@@ -150,8 +150,8 @@ pub fn addPkgTests(b: &build.Builder, test_filter: ?[]const u8, root_src: []cons
150 continue;150 continue;
151 }151 }
152 const these_tests = b.addTest(root_src);152 const these_tests = b.addTest(root_src);
153 these_tests.setNamePrefix(b.fmt("{}-{}-{}-{}-{} ", name, @enumTagName(test_target.os),153 these_tests.setNamePrefix(b.fmt("{}-{}-{}-{}-{} ", name, @tagName(test_target.os),
154 @enumTagName(test_target.arch), @enumTagName(mode), if (link_libc) "c" else "bare"));154 @tagName(test_target.arch), @tagName(mode), if (link_libc) "c" else "bare"));
155 these_tests.setFilter(test_filter);155 these_tests.setFilter(test_filter);
156 these_tests.setBuildMode(mode);156 these_tests.setBuildMode(mode);
157 if (!is_native) {157 if (!is_native) {
...@@ -428,7 +428,7 @@ pub const CompareOutputContext = struct {...@@ -428,7 +428,7 @@ pub const CompareOutputContext = struct {
428 Special.None => {428 Special.None => {
429 for ([]Mode{Mode.Debug, Mode.ReleaseSafe, Mode.ReleaseFast}) |mode| {429 for ([]Mode{Mode.Debug, Mode.ReleaseSafe, Mode.ReleaseFast}) |mode| {
430 const annotated_case_name = %%fmt.allocPrint(self.b.allocator, "{} {} ({})",430 const annotated_case_name = %%fmt.allocPrint(self.b.allocator, "{} {} ({})",
431 "compare-output", case.name, @enumTagName(mode));431 "compare-output", case.name, @tagName(mode));
432 if (self.test_filter) |filter| {432 if (self.test_filter) |filter| {
433 if (mem.indexOf(u8, annotated_case_name, filter) == null)433 if (mem.indexOf(u8, annotated_case_name, filter) == null)
434 continue;434 continue;
...@@ -682,7 +682,7 @@ pub const CompileErrorContext = struct {...@@ -682,7 +682,7 @@ pub const CompileErrorContext = struct {
682682
683 for ([]Mode{Mode.Debug, Mode.ReleaseSafe, Mode.ReleaseFast}) |mode| {683 for ([]Mode{Mode.Debug, Mode.ReleaseSafe, Mode.ReleaseFast}) |mode| {
684 const annotated_case_name = %%fmt.allocPrint(self.b.allocator, "compile-error {} ({})",684 const annotated_case_name = %%fmt.allocPrint(self.b.allocator, "compile-error {} ({})",
685 case.name, @enumTagName(mode));685 case.name, @tagName(mode));
686 if (self.test_filter) |filter| {686 if (self.test_filter) |filter| {
687 if (mem.indexOf(u8, annotated_case_name, filter) == null)687 if (mem.indexOf(u8, annotated_case_name, filter) == null)
688 continue;688 continue;
...@@ -750,7 +750,7 @@ pub const BuildExamplesContext = struct {...@@ -750,7 +750,7 @@ pub const BuildExamplesContext = struct {
750750
751 for ([]Mode{Mode.Debug, Mode.ReleaseSafe, Mode.ReleaseFast}) |mode| {751 for ([]Mode{Mode.Debug, Mode.ReleaseSafe, Mode.ReleaseFast}) |mode| {
752 const annotated_case_name = %%fmt.allocPrint(self.b.allocator, "build {} ({})",752 const annotated_case_name = %%fmt.allocPrint(self.b.allocator, "build {} ({})",
753 root_src, @enumTagName(mode));753 root_src, @tagName(mode));
754 if (self.test_filter) |filter| {754 if (self.test_filter) |filter| {
755 if (mem.indexOf(u8, annotated_case_name, filter) == null)755 if (mem.indexOf(u8, annotated_case_name, filter) == null)
756 continue;756 continue;