| author | |
| committer | |
| log | 0ad1239522c70418990dc7b9da4e128da7cdd1d5 |
| tree | 3a434788633db0a3d6e30f779fc1239a7513205a |
| parent | 137c8f5e8a6023db24f90555e968b592a4b843e4 |
* @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 #61824 files changed, 800 insertions(+), 950 deletions(-)
doc/langref.html.in+12-9| ... | ... | @@ -136,7 +136,7 @@ |
| 136 | 136 | <li><a href="#builtin-divFloor">@divFloor</a></li> |
| 137 | 137 | <li><a href="#builtin-divTrunc">@divTrunc</a></li> |
| 138 | 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 | 140 | <li><a href="#builtin-EnumTagType">@EnumTagType</a></li> |
| 141 | 141 | <li><a href="#builtin-errorName">@errorName</a></li> |
| 142 | 142 | <li><a href="#builtin-fence">@fence</a></li> |
| ... | ... | @@ -2165,7 +2165,7 @@ test "enum variant switch" { |
| 2165 | 2165 | }; |
| 2166 | 2166 | } |
| 2167 | 2167 | |
| 2168 | // The @enumTagName and @memberCount builtin functions can be used to | |
| 2168 | // The @memberName and @memberCount builtin functions can be used to | |
| 2169 | 2169 | // the string representation and number of members respectively. |
| 2170 | 2170 | const BuiltinType = enum { |
| 2171 | 2171 | A: f32, |
| ... | ... | @@ -2174,8 +2174,8 @@ const BuiltinType = enum { |
| 2174 | 2174 | }; |
| 2175 | 2175 | |
| 2176 | 2176 | test "enum builtins" { |
| 2177 | assert(mem.eql(u8, @enumTagName(BuiltinType.A { 0 }), "A")); | |
| 2178 | assert(mem.eql(u8, @enumTagName(BuiltinType.C), "C")); | |
| 2177 | assert(mem.eql(u8, @memberName(BuiltinType.A { 0 }), "A")); | |
| 2178 | assert(mem.eql(u8, @memberName(BuiltinType.C), "C")); | |
| 2179 | 2179 | assert(@memberCount(BuiltinType) == 3); |
| 2180 | 2180 | }</code></pre> |
| 2181 | 2181 | <pre><code class="sh">$ zig test enum.zig |
| ... | ... | @@ -2189,8 +2189,9 @@ Test 4/4 enum builtins...OK</code></pre> |
| 2189 | 2189 | </p> |
| 2190 | 2190 | <p>See also:</p> |
| 2191 | 2191 | <ul> |
| 2192 | <li><a href="#builtin-enumTagName">@enumTagName</a></li> | |
| 2192 | <li><a href="#builtin-memberName">@memberName</a></li> | |
| 2193 | 2193 | <li><a href="#builtin-memberCount">@memberCount</a></li> |
| 2194 | <li><a href="#builtin-tagName">@tagName</a></li> | |
| 2194 | 2195 | </ul> |
| 2195 | 2196 | <h2 id="union">union</h2> |
| 2196 | 2197 | <p>TODO union documentation</p> |
| ... | ... | @@ -4252,10 +4253,10 @@ test.zig:6:2: error: found compile log statement |
| 4252 | 4253 | <ul> |
| 4253 | 4254 | <li><a href="#builtin-import">@import</a></li> |
| 4254 | 4255 | </ul> |
| 4255 | <h3 id="builtin-enumTagName">@enumTagName</h3> | |
| 4256 | <pre><code class="zig">@enumTagName(value: var) -&gt; []const u8</code></pre> | |
| 4256 | <h3 id="builtin-tagName">@tagName</h3> | |
| 4257 | <pre><code class="zig">@tagName(value: var) -&gt; []const u8</code></pre> | |
| 4257 | 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 | 4260 | </p> |
| 4260 | 4261 | <h3 id="builtin-EnumTagType">@EnumTagType</h3> |
| 4261 | 4262 | <pre><code class="zig">@EnumTagType(T: type) -&gt; type</code></pre> |
| ... | ... | @@ -5843,7 +5844,9 @@ GroupedExpression = "(" Expression ")" |
| 5843 | 5844 | |
| 5844 | 5845 | KeywordLiteral = "true" | "false" | "null" | "continue" | "undefined" | "error" | "this" | "unreachable" |
| 5845 | 5846 | |
| 5846 | ContainerDecl = option("extern" | "packed") ("struct" | "union" | ("enum" option(GroupedExpression))) "{" many(ContainerMember) "}"</code></pre> | |
| 5847 | ContainerDecl = option("extern" | "packed") | |
| 5848 | ("struct" option(GroupedExpression) | "union" option("enum" option(GroupedExpression) | GroupedExpression) | ("enum" option(GroupedExpression))) | |
| 5849 | "{" many(ContainerMember) "}"</code></pre> | |
| 5847 | 5850 | <h2 id="zen">Zen</h2> |
| 5848 | 5851 | <ul> |
| 5849 | 5852 | <li>Communicate intent precisely.</li> |
src/all_types.hpp+9-50| ... | ... | @@ -97,11 +97,6 @@ struct ConstParent { |
| 97 | 97 | } data; |
| 98 | 98 | }; |
| 99 | 99 | |
| 100 | struct ConstEnumValue { | |
| 101 | BigInt tag; | |
| 102 | ConstExprValue *payload; | |
| 103 | }; | |
| 104 | ||
| 105 | 100 | struct ConstStructValue { |
| 106 | 101 | ConstExprValue *fields; |
| 107 | 102 | ConstParent parent; |
| ... | ... | @@ -249,7 +244,7 @@ struct ConstExprValue { |
| 249 | 244 | ConstExprValue *x_maybe; |
| 250 | 245 | ConstErrValue x_err_union; |
| 251 | 246 | ErrorTableEntry *x_pure_err; |
| 252 | ConstEnumValue x_enum; | |
| 247 | BigInt x_enum_tag; | |
| 253 | 248 | ConstStructValue x_struct; |
| 254 | 249 | ConstUnionValue x_union; |
| 255 | 250 | ConstArrayValue x_array; |
| ... | ... | @@ -345,15 +340,14 @@ struct TldCompTime { |
| 345 | 340 | |
| 346 | 341 | struct TypeEnumField { |
| 347 | 342 | Buf *name; |
| 348 | TypeTableEntry *type_entry; | |
| 349 | 343 | BigInt value; |
| 350 | uint32_t gen_index; | |
| 344 | uint32_t decl_index; | |
| 351 | 345 | }; |
| 352 | 346 | |
| 353 | 347 | struct TypeUnionField { |
| 354 | 348 | Buf *name; |
| 349 | TypeEnumField *enum_field; | |
| 355 | 350 | TypeTableEntry *type_entry; |
| 356 | BigInt value; | |
| 357 | 351 | uint32_t gen_index; |
| 358 | 352 | }; |
| 359 | 353 | |
| ... | ... | @@ -773,7 +767,8 @@ struct AstNodeContainerDecl { |
| 773 | 767 | ZigList<AstNode *> fields; |
| 774 | 768 | ZigList<AstNode *> decls; |
| 775 | 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 | }; |
| 778 | 773 | |
| 779 | 774 | struct AstNodeStructField { |
| ... | ... | @@ -1010,13 +1005,9 @@ struct TypeTableEntryEnum { |
| 1010 | 1005 | AstNode *decl_node; |
| 1011 | 1006 | ContainerLayout layout; |
| 1012 | 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 | 1008 | TypeEnumField *fields; |
| 1016 | 1009 | bool is_invalid; // true if any fields are invalid |
| 1017 | TypeTableEntry *tag_type; | |
| 1018 | 1010 | TypeTableEntry *tag_int_type; |
| 1019 | LLVMTypeRef union_type_ref; | |
| 1020 | 1011 | |
| 1021 | 1012 | ScopeDecls *decls_scope; |
| 1022 | 1013 | |
| ... | ... | @@ -1028,18 +1019,7 @@ struct TypeTableEntryEnum { |
| 1028 | 1019 | |
| 1029 | 1020 | bool zero_bits_loop_flag; |
| 1030 | 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 | }; | |
| 1039 | 1022 | |
| 1040 | struct TypeTableEntryEnumTag { | |
| 1041 | TypeTableEntry *enum_type; | |
| 1042 | TypeTableEntry *int_type; | |
| 1043 | 1023 | bool generate_name_table; |
| 1044 | 1024 | LLVMValueRef name_table; |
| 1045 | 1025 | }; |
| ... | ... | @@ -1054,7 +1034,7 @@ struct TypeTableEntryUnion { |
| 1054 | 1034 | uint32_t gen_field_count; |
| 1055 | 1035 | TypeUnionField *fields; |
| 1056 | 1036 | bool is_invalid; // true if any fields are invalid |
| 1057 | TypeTableEntry *tag_type; | |
| 1037 | TypeTableEntry *tag_type; // always an enum or null | |
| 1058 | 1038 | LLVMTypeRef union_type_ref; |
| 1059 | 1039 | |
| 1060 | 1040 | ScopeDecls *decls_scope; |
| ... | ... | @@ -1119,7 +1099,6 @@ enum TypeTableEntryId { |
| 1119 | 1099 | TypeTableEntryIdErrorUnion, |
| 1120 | 1100 | TypeTableEntryIdPureError, |
| 1121 | 1101 | TypeTableEntryIdEnum, |
| 1122 | TypeTableEntryIdEnumTag, | |
| 1123 | 1102 | TypeTableEntryIdUnion, |
| 1124 | 1103 | TypeTableEntryIdFn, |
| 1125 | 1104 | TypeTableEntryIdNamespace, |
| ... | ... | @@ -1148,7 +1127,6 @@ struct TypeTableEntry { |
| 1148 | 1127 | TypeTableEntryMaybe maybe; |
| 1149 | 1128 | TypeTableEntryError error; |
| 1150 | 1129 | TypeTableEntryEnum enumeration; |
| 1151 | TypeTableEntryEnumTag enum_tag; | |
| 1152 | 1130 | TypeTableEntryUnion unionation; |
| 1153 | 1131 | TypeTableEntryFn fn; |
| 1154 | 1132 | TypeTableEntryBoundFn bound_fn; |
| ... | ... | @@ -1287,7 +1265,7 @@ enum BuiltinFnId { |
| 1287 | 1265 | BuiltinFnIdBitCast, |
| 1288 | 1266 | BuiltinFnIdIntToPtr, |
| 1289 | 1267 | BuiltinFnIdPtrToInt, |
| 1290 | BuiltinFnIdEnumTagName, | |
| 1268 | BuiltinFnIdTagName, | |
| 1291 | 1269 | BuiltinFnIdEnumTagType, |
| 1292 | 1270 | BuiltinFnIdFieldParentPtr, |
| 1293 | 1271 | BuiltinFnIdOffsetOf, |
| ... | ... | @@ -1832,7 +1810,6 @@ enum IrInstructionId { |
| 1832 | 1810 | IrInstructionIdStorePtr, |
| 1833 | 1811 | IrInstructionIdFieldPtr, |
| 1834 | 1812 | IrInstructionIdStructFieldPtr, |
| 1835 | IrInstructionIdEnumFieldPtr, | |
| 1836 | 1813 | IrInstructionIdUnionFieldPtr, |
| 1837 | 1814 | IrInstructionIdElemPtr, |
| 1838 | 1815 | IrInstructionIdVarPtr, |
| ... | ... | @@ -1857,7 +1834,7 @@ enum IrInstructionId { |
| 1857 | 1834 | IrInstructionIdTestNonNull, |
| 1858 | 1835 | IrInstructionIdUnwrapMaybe, |
| 1859 | 1836 | IrInstructionIdMaybeWrap, |
| 1860 | IrInstructionIdEnumTag, | |
| 1837 | IrInstructionIdUnionTag, | |
| 1861 | 1838 | IrInstructionIdClz, |
| 1862 | 1839 | IrInstructionIdCtz, |
| 1863 | 1840 | IrInstructionIdImport, |
| ... | ... | @@ -1896,7 +1873,6 @@ enum IrInstructionId { |
| 1896 | 1873 | IrInstructionIdErrWrapPayload, |
| 1897 | 1874 | IrInstructionIdFnProto, |
| 1898 | 1875 | IrInstructionIdTestComptime, |
| 1899 | IrInstructionIdInitEnum, | |
| 1900 | 1876 | IrInstructionIdPtrCast, |
| 1901 | 1877 | IrInstructionIdBitCast, |
| 1902 | 1878 | IrInstructionIdWidenOrShorten, |
| ... | ... | @@ -2092,14 +2068,6 @@ struct IrInstructionStructFieldPtr { |
| 2092 | 2068 | bool is_const; |
| 2093 | 2069 | }; |
| 2094 | 2070 | |
| 2095 | struct IrInstructionEnumFieldPtr { | |
| 2096 | IrInstruction base; | |
| 2097 | ||
| 2098 | IrInstruction *enum_ptr; | |
| 2099 | TypeEnumField *field; | |
| 2100 | bool is_const; | |
| 2101 | }; | |
| 2102 | ||
| 2103 | 2071 | struct IrInstructionUnionFieldPtr { |
| 2104 | 2072 | IrInstruction base; |
| 2105 | 2073 | |
| ... | ... | @@ -2303,7 +2271,7 @@ struct IrInstructionClz { |
| 2303 | 2271 | IrInstruction *value; |
| 2304 | 2272 | }; |
| 2305 | 2273 | |
| 2306 | struct IrInstructionEnumTag { | |
| 2274 | struct IrInstructionUnionTag { | |
| 2307 | 2275 | IrInstruction base; |
| 2308 | 2276 | |
| 2309 | 2277 | IrInstruction *value; |
| ... | ... | @@ -2573,15 +2541,6 @@ struct IrInstructionTestComptime { |
| 2573 | 2541 | IrInstruction *value; |
| 2574 | 2542 | }; |
| 2575 | 2543 | |
| 2576 | struct IrInstructionInitEnum { | |
| 2577 | IrInstruction base; | |
| 2578 | ||
| 2579 | TypeTableEntry *enum_type; | |
| 2580 | TypeEnumField *field; | |
| 2581 | IrInstruction *init_value; | |
| 2582 | LLVMValueRef tmp_ptr; | |
| 2583 | }; | |
| 2584 | ||
| 2585 | 2544 | struct IrInstructionPtrCast { |
| 2586 | 2545 | IrInstruction base; |
| 2587 | 2546 |
src/analyze.cpp+301-306| ... | ... | @@ -223,7 +223,6 @@ bool type_is_complete(TypeTableEntry *type_entry) { |
| 223 | 223 | case TypeTableEntryIdNamespace: |
| 224 | 224 | case TypeTableEntryIdBlock: |
| 225 | 225 | case TypeTableEntryIdBoundFn: |
| 226 | case TypeTableEntryIdEnumTag: | |
| 227 | 226 | case TypeTableEntryIdArgTuple: |
| 228 | 227 | return true; |
| 229 | 228 | } |
| ... | ... | @@ -260,7 +259,6 @@ bool type_has_zero_bits_known(TypeTableEntry *type_entry) { |
| 260 | 259 | case TypeTableEntryIdNamespace: |
| 261 | 260 | case TypeTableEntryIdBlock: |
| 262 | 261 | case TypeTableEntryIdBoundFn: |
| 263 | case TypeTableEntryIdEnumTag: | |
| 264 | 262 | case TypeTableEntryIdArgTuple: |
| 265 | 263 | case TypeTableEntryIdOpaque: |
| 266 | 264 | return true; |
| ... | ... | @@ -1175,7 +1173,6 @@ static TypeTableEntry *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *c |
| 1175 | 1173 | case TypeTableEntryIdEnum: |
| 1176 | 1174 | case TypeTableEntryIdUnion: |
| 1177 | 1175 | case TypeTableEntryIdFn: |
| 1178 | case TypeTableEntryIdEnumTag: | |
| 1179 | 1176 | ensure_complete_type(g, type_entry); |
| 1180 | 1177 | if (fn_type_id.cc == CallingConventionUnspecified && !type_is_copyable(g, type_entry)) { |
| 1181 | 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 | 1236 | case TypeTableEntryIdEnum: |
| 1240 | 1237 | case TypeTableEntryIdUnion: |
| 1241 | 1238 | case TypeTableEntryIdFn: |
| 1242 | case TypeTableEntryIdEnumTag: | |
| 1243 | 1239 | break; |
| 1244 | 1240 | } |
| 1245 | 1241 | |
| ... | ... | @@ -1263,22 +1259,6 @@ bool type_is_invalid(TypeTableEntry *type_entry) { |
| 1263 | 1259 | } |
| 1264 | 1260 | |
| 1265 | 1261 | |
| 1266 | TypeTableEntry *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 | ||
| 1282 | 1262 | static void resolve_enum_type(CodeGen *g, TypeTableEntry *enum_type) { |
| 1283 | 1263 | assert(enum_type->id == TypeTableEntryIdEnum); |
| 1284 | 1264 | |
| ... | ... | @@ -1308,14 +1288,6 @@ static void resolve_enum_type(CodeGen *g, TypeTableEntry *enum_type) { |
| 1308 | 1288 | assert(enum_type->data.enumeration.fields); |
| 1309 | 1289 | ZigLLVMDIEnumerator **di_enumerators = allocate<ZigLLVMDIEnumerator*>(field_count); |
| 1310 | 1290 | |
| 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 | 1291 | Scope *scope = &enum_type->data.enumeration.decls_scope->base; |
| 1320 | 1292 | ImportTableEntry *import = get_scope_import(scope); |
| 1321 | 1293 | |
| ... | ... | @@ -1323,49 +1295,17 @@ static void resolve_enum_type(CodeGen *g, TypeTableEntry *enum_type) { |
| 1323 | 1295 | enum_type->data.enumeration.embedded_in_current = true; |
| 1324 | 1296 | |
| 1325 | 1297 | for (uint32_t i = 0; i < field_count; i += 1) { |
| 1326 | AstNode *field_node = decl_node->data.container_decl.fields.at(i); | |
| 1327 | TypeEnumField *type_enum_field = &enum_type->data.enumeration.fields[i]; | |
| 1328 | TypeTableEntry *field_type = type_enum_field->type_entry; | |
| 1329 | ||
| 1330 | di_enumerators[i] = ZigLLVMCreateDebugEnumerator(g->dbuilder, buf_ptr(type_enum_field->name), i); | |
| 1331 | ||
| 1332 | ensure_complete_type(g, field_type); | |
| 1333 | if (type_is_invalid(field_type)) { | |
| 1334 | enum_type->data.enumeration.is_invalid = true; | |
| 1335 | continue; | |
| 1336 | } | |
| 1337 | ||
| 1338 | if (!type_has_bits(field_type)) | |
| 1339 | continue; | |
| 1340 | ||
| 1341 | uint64_t store_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, field_type->type_ref); | |
| 1342 | uint64_t abi_align_in_bits = 8*LLVMABIAlignmentOfType(g->target_data_ref, field_type->type_ref); | |
| 1298 | TypeEnumField *enum_field = &enum_type->data.enumeration.fields[i]; | |
| 1343 | 1299 | |
| 1344 | assert(store_size_in_bits > 0); | |
| 1345 | assert(abi_align_in_bits > 0); | |
| 1346 | ||
| 1347 | union_inner_di_types[type_enum_field->gen_index] = ZigLLVMCreateDebugMemberType(g->dbuilder, | |
| 1348 | ZigLLVMTypeToScope(enum_type->di_type), buf_ptr(type_enum_field->name), | |
| 1349 | import->di_file, (unsigned)(field_node->line + 1), | |
| 1350 | store_size_in_bits, | |
| 1351 | abi_align_in_bits, | |
| 1352 | 0, | |
| 1353 | 0, field_type->di_type); | |
| 1354 | ||
| 1355 | biggest_size_in_bits = max(biggest_size_in_bits, store_size_in_bits); | |
| 1356 | ||
| 1357 | if (!most_aligned_union_member || abi_align_in_bits > biggest_align_in_bits) { | |
| 1358 | most_aligned_union_member = field_type; | |
| 1359 | biggest_align_in_bits = abi_align_in_bits; | |
| 1360 | size_of_most_aligned_member_in_bits = store_size_in_bits; | |
| 1361 | } | |
| 1300 | // TODO send patch to LLVM to support APInt in createEnumerator instead of int64_t | |
| 1301 | // http://lists.llvm.org/pipermail/llvm-dev/2017-December/119456.html | |
| 1302 | di_enumerators[i] = ZigLLVMCreateDebugEnumerator(g->dbuilder, buf_ptr(enum_field->name), | |
| 1303 | bigint_as_signed(&enum_field->value)); | |
| 1362 | 1304 | } |
| 1363 | 1305 | |
| 1364 | 1306 | // unset temporary flag |
| 1365 | 1307 | enum_type->data.enumeration.embedded_in_current = false; |
| 1366 | 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; | |
| 1369 | 1309 | |
| 1370 | 1310 | if (enum_type->data.enumeration.is_invalid) |
| 1371 | 1311 | return; |
| ... | ... | @@ -1391,117 +1331,20 @@ static void resolve_enum_type(CodeGen *g, TypeTableEntry *enum_type) { |
| 1391 | 1331 | } |
| 1392 | 1332 | |
| 1393 | 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; | |
| 1490 | 1334 | |
| 1491 | // create debug type for tag | |
| 1492 | uint64_t tag_debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, tag_type_entry->type_ref); | |
| 1493 | uint64_t tag_debug_align_in_bits = 8*LLVMABIAlignmentOfType(g->target_data_ref, tag_type_entry->type_ref); | |
| 1494 | ZigLLVMDIType *tag_di_type = ZigLLVMCreateDebugEnumerationType(g->dbuilder, | |
| 1495 | ZigLLVMFileToScope(import->di_file), buf_ptr(&enum_type->name), | |
| 1496 | import->di_file, (unsigned)(decl_node->line + 1), | |
| 1497 | tag_debug_size_in_bits, | |
| 1498 | tag_debug_align_in_bits, | |
| 1499 | di_enumerators, field_count, | |
| 1500 | tag_type_entry->di_type, ""); | |
| 1335 | // create debug type for tag | |
| 1336 | uint64_t tag_debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, tag_int_type->type_ref); | |
| 1337 | uint64_t tag_debug_align_in_bits = 8*LLVMABIAlignmentOfType(g->target_data_ref, tag_int_type->type_ref); | |
| 1338 | ZigLLVMDIType *tag_di_type = ZigLLVMCreateDebugEnumerationType(g->dbuilder, | |
| 1339 | ZigLLVMFileToScope(import->di_file), buf_ptr(&enum_type->name), | |
| 1340 | import->di_file, (unsigned)(decl_node->line + 1), | |
| 1341 | tag_debug_size_in_bits, | |
| 1342 | tag_debug_align_in_bits, | |
| 1343 | di_enumerators, field_count, | |
| 1344 | tag_int_type->di_type, ""); | |
| 1501 | 1345 | |
| 1502 | ZigLLVMReplaceTemporary(g->dbuilder, enum_type->di_type, tag_di_type); | |
| 1503 | enum_type->di_type = tag_di_type; | |
| 1504 | } | |
| 1346 | ZigLLVMReplaceTemporary(g->dbuilder, enum_type->di_type, tag_di_type); | |
| 1347 | enum_type->di_type = tag_di_type; | |
| 1505 | 1348 | } |
| 1506 | 1349 | |
| 1507 | 1350 | 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 | 1360 | case TypeTableEntryIdNullLit: |
| 1518 | 1361 | case TypeTableEntryIdErrorUnion: |
| 1519 | 1362 | case TypeTableEntryIdPureError: |
| 1520 | case TypeTableEntryIdEnumTag: | |
| 1521 | 1363 | case TypeTableEntryIdNamespace: |
| 1522 | 1364 | case TypeTableEntryIdBlock: |
| 1523 | 1365 | case TypeTableEntryIdBoundFn: |
| ... | ... | @@ -1541,8 +1383,7 @@ static bool type_allowed_in_packed_struct(TypeTableEntry *type_entry) { |
| 1541 | 1383 | return child_type->id == TypeTableEntryIdPointer || child_type->id == TypeTableEntryIdFn; |
| 1542 | 1384 | } |
| 1543 | 1385 | case TypeTableEntryIdEnum: |
| 1544 | return type_entry->data.enumeration.gen_field_count == 0 && | |
| 1545 | type_entry->data.enumeration.decl_node->data.container_decl.init_arg_expr != nullptr; | |
| 1386 | return type_entry->data.enumeration.decl_node->data.container_decl.init_arg_expr != nullptr; | |
| 1546 | 1387 | } |
| 1547 | 1388 | zig_unreachable(); |
| 1548 | 1389 | } |
| ... | ... | @@ -1850,6 +1691,7 @@ static void resolve_union_type(CodeGen *g, TypeTableEntry *union_type) { |
| 1850 | 1691 | if (union_type->data.unionation.embedded_in_current) { |
| 1851 | 1692 | if (!union_type->data.unionation.reported_infinite_err) { |
| 1852 | 1693 | union_type->data.unionation.reported_infinite_err = true; |
| 1694 | union_type->data.unionation.is_invalid = true; | |
| 1853 | 1695 | add_node_error(g, decl_node, buf_sprintf("union '%s' contains itself", buf_ptr(&union_type->name))); |
| 1854 | 1696 | } |
| 1855 | 1697 | return; |
| ... | ... | @@ -1871,8 +1713,7 @@ static void resolve_union_type(CodeGen *g, TypeTableEntry *union_type) { |
| 1871 | 1713 | uint64_t biggest_align_in_bits = 0; |
| 1872 | 1714 | uint64_t biggest_size_in_bits = 0; |
| 1873 | 1715 | |
| 1874 | bool auto_layout = (union_type->data.unionation.layout == ContainerLayoutAuto); | |
| 1875 | ZigLLVMDIEnumerator **di_enumerators = allocate<ZigLLVMDIEnumerator*>(field_count); | |
| 1716 | ZigLLVMDIEnumerator **di_enumerators; | |
| 1876 | 1717 | |
| 1877 | 1718 | Scope *scope = &union_type->data.unionation.decls_scope->base; |
| 1878 | 1719 | ImportTableEntry *import = get_scope_import(scope); |
| ... | ... | @@ -1880,10 +1721,77 @@ static void resolve_union_type(CodeGen *g, TypeTableEntry *union_type) { |
| 1880 | 1721 | // set temporary flag |
| 1881 | 1722 | union_type->data.unionation.embedded_in_current = true; |
| 1882 | 1723 | |
| 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 | 1790 | for (uint32_t i = 0; i < field_count; i += 1) { |
| 1884 | 1791 | AstNode *field_node = decl_node->data.container_decl.fields.at(i); |
| 1885 | TypeUnionField *type_union_field = &union_type->data.unionation.fields[i]; | |
| 1886 | TypeTableEntry *field_type = type_union_field->type_entry; | |
| 1792 | TypeUnionField *union_field = &union_type->data.unionation.fields[i]; | |
| 1793 | Buf *field_name = field_node->data.struct_field.name; | |
| 1794 | TypeTableEntry *field_type = union_field->type_entry; | |
| 1887 | 1795 | |
| 1888 | 1796 | ensure_complete_type(g, field_type); |
| 1889 | 1797 | if (type_is_invalid(field_type)) { |
| ... | ... | @@ -1891,19 +1799,68 @@ static void resolve_union_type(CodeGen *g, TypeTableEntry *union_type) { |
| 1891 | 1799 | continue; |
| 1892 | 1800 | } |
| 1893 | 1801 | |
| 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 | 1853 | if (!type_has_bits(field_type)) |
| 1895 | 1854 | continue; |
| 1896 | 1855 | |
| 1897 | di_enumerators[i] = ZigLLVMCreateDebugEnumerator(g->dbuilder, buf_ptr(type_union_field->name), i); | |
| 1898 | ||
| 1899 | 1856 | uint64_t store_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, field_type->type_ref); |
| 1900 | 1857 | uint64_t abi_align_in_bits = 8*LLVMABIAlignmentOfType(g->target_data_ref, field_type->type_ref); |
| 1901 | 1858 | |
| 1902 | 1859 | assert(store_size_in_bits > 0); |
| 1903 | 1860 | assert(abi_align_in_bits > 0); |
| 1904 | 1861 | |
| 1905 | union_inner_di_types[type_union_field->gen_index] = ZigLLVMCreateDebugMemberType(g->dbuilder, | |
| 1906 | ZigLLVMTypeToScope(union_type->di_type), buf_ptr(type_union_field->name), | |
| 1862 | union_inner_di_types[union_field->gen_index] = ZigLLVMCreateDebugMemberType(g->dbuilder, | |
| 1863 | ZigLLVMTypeToScope(union_type->di_type), buf_ptr(union_field->enum_field->name), | |
| 1907 | 1864 | import->di_file, (unsigned)(field_node->line + 1), |
| 1908 | 1865 | store_size_in_bits, |
| 1909 | 1866 | abi_align_in_bits, |
| ... | ... | @@ -1919,6 +1876,49 @@ static void resolve_union_type(CodeGen *g, TypeTableEntry *union_type) { |
| 1919 | 1876 | } |
| 1920 | 1877 | } |
| 1921 | 1878 | |
| 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 | 1922 | // unset temporary flag |
| 1923 | 1923 | union_type->data.unionation.embedded_in_current = false; |
| 1924 | 1924 | union_type->data.unionation.complete = true; |
| ... | ... | @@ -1950,11 +1950,9 @@ static void resolve_union_type(CodeGen *g, TypeTableEntry *union_type) { |
| 1950 | 1950 | |
| 1951 | 1951 | assert(most_aligned_union_member != nullptr); |
| 1952 | 1952 | |
| 1953 | bool want_safety = auto_layout && (field_count >= 2); | |
| 1954 | 1953 | uint64_t padding_in_bits = biggest_size_in_bits - size_of_most_aligned_member_in_bits; |
| 1955 | 1954 | |
| 1956 | ||
| 1957 | if (!want_safety) { | |
| 1955 | if (tag_type == nullptr) { | |
| 1958 | 1956 | if (padding_in_bits > 0) { |
| 1959 | 1957 | TypeTableEntry *u8_type = get_int_type(g, false, 8); |
| 1960 | 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 | 1992 | padding_array->type_ref, |
| 1995 | 1993 | }; |
| 1996 | 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 | 1997 | } else { |
| 1998 | 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 | 2003 | assert(8*LLVMStoreSizeOfType(g->target_data_ref, union_type_ref) >= biggest_size_in_bits); |
| 2004 | 2004 | |
| 2005 | 2005 | // create llvm type for root struct |
| 2006 | TypeTableEntry *tag_int_type = get_smallest_unsigned_int_type(g, field_count - 1); | |
| 2007 | TypeTableEntry *tag_type_entry = tag_int_type; | |
| 2008 | union_type->data.unionation.tag_type = tag_type_entry; | |
| 2006 | TypeTableEntry *tag_int_type = tag_type->data.enumeration.tag_int_type; | |
| 2009 | 2007 | uint64_t align_of_tag_in_bits = 8*LLVMABIAlignmentOfType(g->target_data_ref, tag_int_type->type_ref); |
| 2010 | 2008 | |
| 2011 | 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 | 2015 | } |
| 2018 | 2016 | |
| 2019 | 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 | 2019 | root_struct_element_types[union_type->data.unionation.gen_union_index] = union_type_ref; |
| 2022 | 2020 | LLVMStructSetBody(union_type->type_ref, root_struct_element_types, 2, false); |
| 2023 | 2021 | |
| 2024 | 2022 | |
| 2025 | 2023 | // create debug type for root struct |
| 2026 | 2024 | |
| 2027 | // create debug type for tag | |
| 2028 | uint64_t tag_debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, tag_type_entry->type_ref); | |
| 2029 | uint64_t tag_debug_align_in_bits = 8*LLVMABIAlignmentOfType(g->target_data_ref, tag_type_entry->type_ref); | |
| 2030 | ZigLLVMDIType *tag_di_type = ZigLLVMCreateDebugEnumerationType(g->dbuilder, | |
| 2031 | ZigLLVMTypeToScope(union_type->di_type), "AnonEnum", | |
| 2032 | import->di_file, (unsigned)(decl_node->line + 1), | |
| 2033 | tag_debug_size_in_bits, tag_debug_align_in_bits, di_enumerators, field_count, | |
| 2034 | tag_type_entry->di_type, ""); | |
| 2025 | uint64_t tag_debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, tag_type->type_ref); | |
| 2026 | uint64_t tag_debug_align_in_bits = 8*LLVMABIAlignmentOfType(g->target_data_ref, tag_type->type_ref); | |
| 2027 | if (create_enum_type) { | |
| 2028 | // create debug type for tag | |
| 2029 | ZigLLVMDIType *tag_di_type = ZigLLVMCreateDebugEnumerationType(g->dbuilder, | |
| 2030 | ZigLLVMTypeToScope(union_type->di_type), "AnonEnum", | |
| 2031 | import->di_file, (unsigned)(decl_node->line + 1), | |
| 2032 | tag_debug_size_in_bits, tag_debug_align_in_bits, di_enumerators, field_count, | |
| 2033 | tag_type->di_type, ""); | |
| 2034 | tag_type->di_type = tag_di_type; | |
| 2035 | } | |
| 2035 | 2036 | |
| 2036 | 2037 | // create debug type for union |
| 2037 | 2038 | ZigLLVMDIType *union_di_type = ZigLLVMCreateDebugUnionType(g->dbuilder, |
| ... | ... | @@ -2046,19 +2047,19 @@ static void resolve_union_type(CodeGen *g, TypeTableEntry *union_type) { |
| 2046 | 2047 | union_type->data.unionation.gen_tag_index); |
| 2047 | 2048 | |
| 2048 | 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 | 2051 | import->di_file, (unsigned)(decl_node->line + 1), |
| 2051 | 2052 | biggest_size_in_bits, |
| 2052 | 2053 | biggest_align_in_bits, |
| 2053 | 2054 | union_offset_in_bits, |
| 2054 | 2055 | 0, union_di_type); |
| 2055 | 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 | 2058 | import->di_file, (unsigned)(decl_node->line + 1), |
| 2058 | 2059 | tag_debug_size_in_bits, |
| 2059 | 2060 | tag_debug_align_in_bits, |
| 2060 | 2061 | tag_offset_in_bits, |
| 2061 | 0, tag_di_type); | |
| 2062 | 0, tag_type->di_type); | |
| 2062 | 2063 | |
| 2063 | 2064 | ZigLLVMDIType *di_root_members[2]; |
| 2064 | 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 | 2105 | enum_type->data.enumeration.fields = nullptr; |
| 2105 | 2106 | enum_type->data.enumeration.is_invalid = true; |
| 2106 | 2107 | enum_type->data.enumeration.zero_bits_loop_flag = false; |
| 2107 | enum_type->data.enumeration.gen_field_count = 0; | |
| 2108 | 2108 | enum_type->data.enumeration.zero_bits_known = true; |
| 2109 | 2109 | return; |
| 2110 | 2110 | } |
| ... | ... | @@ -2112,8 +2112,6 @@ static void resolve_enum_zero_bits(CodeGen *g, TypeTableEntry *enum_type) { |
| 2112 | 2112 | enum_type->data.enumeration.src_field_count = field_count; |
| 2113 | 2113 | enum_type->data.enumeration.fields = allocate<TypeEnumField>(field_count); |
| 2114 | 2114 | |
| 2115 | uint32_t biggest_align_bytes = 0; | |
| 2116 | ||
| 2117 | 2115 | Scope *scope = &enum_type->data.enumeration.decls_scope->base; |
| 2118 | 2116 | |
| 2119 | 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 | 2141 | } |
| 2144 | 2142 | } |
| 2145 | 2143 | enum_type->data.enumeration.tag_int_type = tag_int_type; |
| 2144 | enum_type->type_ref = tag_int_type->type_ref; | |
| 2146 | 2145 | |
| 2147 | uint32_t gen_field_index = 0; | |
| 2148 | 2146 | for (uint32_t field_i = 0; field_i < field_count; field_i += 1) { |
| 2149 | 2147 | AstNode *field_node = decl_node->data.container_decl.fields.at(field_i); |
| 2150 | 2148 | TypeEnumField *type_enum_field = &enum_type->data.enumeration.fields[field_i]; |
| 2151 | 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); | |
| 2153 | type_enum_field->type_entry = field_type; | |
| 2150 | type_enum_field->decl_index = field_i; | |
| 2151 | ||
| 2152 | if (field_node->data.struct_field.type != nullptr) { | |
| 2153 | ErrorMsg *msg = add_node_error(g, field_node->data.struct_field.type, | |
| 2154 | buf_sprintf("structs and unions, not enums, support field types")); | |
| 2155 | add_error_note(g, msg, decl_node, | |
| 2156 | buf_sprintf("consider 'union(enum)' here")); | |
| 2157 | } | |
| 2154 | 2158 | |
| 2155 | 2159 | AstNode *tag_value = field_node->data.struct_field.value; |
| 2156 | 2160 | |
| ... | ... | @@ -2179,23 +2183,6 @@ static void resolve_enum_zero_bits(CodeGen *g, TypeTableEntry *enum_type) { |
| 2179 | 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 | } |
| 2200 | 2187 | |
| 2201 | 2188 | // 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 | 2214 | } |
| 2228 | 2215 | |
| 2229 | 2216 | enum_type->data.enumeration.zero_bits_loop_flag = false; |
| 2230 | enum_type->data.enumeration.gen_field_count = gen_field_index; | |
| 2231 | enum_type->zero_bits = (gen_field_index == 0 && field_count < 2); | |
| 2217 | enum_type->zero_bits = (field_count < 2); | |
| 2232 | 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 | } |
| 2240 | 2220 | |
| 2241 | 2221 | 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 | 2259 | AstNode *field_node = decl_node->data.container_decl.fields.at(i); |
| 2280 | 2260 | TypeStructField *type_struct_field = &struct_type->data.structure.fields[i]; |
| 2281 | 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 | 2269 | TypeTableEntry *field_type = analyze_type_expr(g, scope, field_node->data.struct_field.type); |
| 2283 | 2270 | type_struct_field->type_entry = field_type; |
| 2284 | 2271 | type_struct_field->src_index = i; |
| ... | ... | @@ -2338,6 +2325,16 @@ static void resolve_union_zero_bits(CodeGen *g, TypeTableEntry *union_type) { |
| 2338 | 2325 | |
| 2339 | 2326 | assert(!union_type->data.unionation.fields); |
| 2340 | 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 | 2338 | union_type->data.unionation.src_field_count = field_count; |
| 2342 | 2339 | union_type->data.unionation.fields = allocate<TypeUnionField>(field_count); |
| 2343 | 2340 | |
| ... | ... | @@ -2348,17 +2345,23 @@ static void resolve_union_zero_bits(CodeGen *g, TypeTableEntry *union_type) { |
| 2348 | 2345 | uint32_t gen_field_index = 0; |
| 2349 | 2346 | for (uint32_t i = 0; i < field_count; i += 1) { |
| 2350 | 2347 | AstNode *field_node = decl_node->data.container_decl.fields.at(i); |
| 2351 | TypeUnionField *type_union_field = &union_type->data.unionation.fields[i]; | |
| 2352 | type_union_field->name = field_node->data.struct_field.name; | |
| 2353 | TypeTableEntry *field_type = analyze_type_expr(g, scope, field_node->data.struct_field.type); | |
| 2354 | type_union_field->type_entry = field_type; | |
| 2348 | TypeUnionField *union_field = &union_type->data.unionation.fields[i]; | |
| 2349 | union_field->name = field_node->data.struct_field.name; | |
| 2355 | 2350 | |
| 2356 | // TODO look for enum arg to union | |
| 2357 | bigint_init_unsigned(&type_union_field->value, i); | |
| 2351 | if (field_node->data.struct_field.type == nullptr) { | |
| 2352 | add_node_error(g, field_node, buf_sprintf("union field missing type")); | |
| 2353 | union_type->data.unionation.is_invalid = true; | |
| 2354 | continue; | |
| 2355 | } | |
| 2358 | 2356 | |
| 2359 | if (field_node->data.struct_field.value != nullptr) { | |
| 2360 | add_node_error(g, field_node->data.struct_field.value, | |
| 2361 | buf_sprintf("enums, not unions, support field assignment")); | |
| 2357 | TypeTableEntry *field_type = analyze_type_expr(g, scope, field_node->data.struct_field.type); | |
| 2358 | union_field->type_entry = field_type; | |
| 2359 | ||
| 2360 | if (field_node->data.struct_field.value != nullptr && !decl_node->data.container_decl.auto_enum) { | |
| 2361 | ErrorMsg *msg = add_node_error(g, field_node->data.struct_field.value, | |
| 2362 | buf_sprintf("non-enum union field assignment")); | |
| 2363 | add_error_note(g, msg, decl_node, | |
| 2364 | buf_sprintf("consider 'union(enum)' here")); | |
| 2362 | 2365 | } |
| 2363 | 2366 | |
| 2364 | 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 | 2373 | if (!type_has_bits(field_type)) |
| 2371 | 2374 | continue; |
| 2372 | 2375 | |
| 2373 | type_union_field->gen_index = gen_field_index; | |
| 2376 | union_field->gen_index = gen_field_index; | |
| 2374 | 2377 | gen_field_index += 1; |
| 2375 | 2378 | |
| 2376 | 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 | 2382 | } |
| 2380 | 2383 | } |
| 2381 | 2384 | |
| 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 | } | |
| 2383 | 2407 | |
| 2384 | 2408 | union_type->data.unionation.zero_bits_loop_flag = false; |
| 2385 | 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 | 2411 | union_type->data.unionation.zero_bits_known = true; |
| 2388 | 2412 | |
| 2389 | 2413 | // also compute abi_alignment |
| ... | ... | @@ -2848,7 +2872,6 @@ TypeTableEntry *validate_var_type(CodeGen *g, AstNode *source_node, TypeTableEnt |
| 2848 | 2872 | case TypeTableEntryIdUnion: |
| 2849 | 2873 | case TypeTableEntryIdFn: |
| 2850 | 2874 | case TypeTableEntryIdBoundFn: |
| 2851 | case TypeTableEntryIdEnumTag: | |
| 2852 | 2875 | return type_entry; |
| 2853 | 2876 | } |
| 2854 | 2877 | zig_unreachable(); |
| ... | ... | @@ -3265,19 +3288,20 @@ TypeUnionField *find_union_type_field(TypeTableEntry *type_entry, Buf *name) { |
| 3265 | 3288 | assert(type_entry->data.unionation.complete); |
| 3266 | 3289 | for (uint32_t i = 0; i < type_entry->data.unionation.src_field_count; i += 1) { |
| 3267 | 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 | 3292 | return field; |
| 3270 | 3293 | } |
| 3271 | 3294 | } |
| 3272 | 3295 | return nullptr; |
| 3273 | 3296 | } |
| 3274 | 3297 | |
| 3275 | static TypeUnionField *find_union_field_by_tag(TypeTableEntry *type_entry, const BigInt *tag) { | |
| 3298 | TypeUnionField *find_union_field_by_tag(TypeTableEntry *type_entry, const BigInt *tag) { | |
| 3276 | 3299 | assert(type_entry->id == TypeTableEntryIdUnion); |
| 3277 | 3300 | assert(type_entry->data.unionation.complete); |
| 3301 | assert(type_entry->data.unionation.gen_tag_index != SIZE_MAX); | |
| 3278 | 3302 | for (uint32_t i = 0; i < type_entry->data.unionation.src_field_count; i += 1) { |
| 3279 | 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 | 3305 | return field; |
| 3282 | 3306 | } |
| 3283 | 3307 | } |
| ... | ... | @@ -3323,7 +3347,6 @@ static bool is_container(TypeTableEntry *type_entry) { |
| 3323 | 3347 | case TypeTableEntryIdNamespace: |
| 3324 | 3348 | case TypeTableEntryIdBlock: |
| 3325 | 3349 | case TypeTableEntryIdBoundFn: |
| 3326 | case TypeTableEntryIdEnumTag: | |
| 3327 | 3350 | case TypeTableEntryIdArgTuple: |
| 3328 | 3351 | case TypeTableEntryIdOpaque: |
| 3329 | 3352 | return false; |
| ... | ... | @@ -3374,7 +3397,6 @@ void resolve_container_type(CodeGen *g, TypeTableEntry *type_entry) { |
| 3374 | 3397 | case TypeTableEntryIdBoundFn: |
| 3375 | 3398 | case TypeTableEntryIdInvalid: |
| 3376 | 3399 | case TypeTableEntryIdVar: |
| 3377 | case TypeTableEntryIdEnumTag: | |
| 3378 | 3400 | case TypeTableEntryIdArgTuple: |
| 3379 | 3401 | case TypeTableEntryIdOpaque: |
| 3380 | 3402 | zig_unreachable(); |
| ... | ... | @@ -3828,7 +3850,7 @@ bool handle_is_ptr(TypeTableEntry *type_entry) { |
| 3828 | 3850 | case TypeTableEntryIdPointer: |
| 3829 | 3851 | case TypeTableEntryIdPureError: |
| 3830 | 3852 | case TypeTableEntryIdFn: |
| 3831 | case TypeTableEntryIdEnumTag: | |
| 3853 | case TypeTableEntryIdEnum: | |
| 3832 | 3854 | return false; |
| 3833 | 3855 | case TypeTableEntryIdArray: |
| 3834 | 3856 | case TypeTableEntryIdStruct: |
| ... | ... | @@ -3836,9 +3858,6 @@ bool handle_is_ptr(TypeTableEntry *type_entry) { |
| 3836 | 3858 | return type_has_bits(type_entry); |
| 3837 | 3859 | case TypeTableEntryIdErrorUnion: |
| 3838 | 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 | 3861 | case TypeTableEntryIdMaybe: |
| 3843 | 3862 | return type_has_bits(type_entry->data.maybe.child_type) && |
| 3844 | 3863 | type_entry->data.maybe.child_type->id != TypeTableEntryIdPointer && |
| ... | ... | @@ -3980,7 +3999,6 @@ static uint32_t hash_const_val(ConstExprValue *const_val) { |
| 3980 | 3999 | return (uint32_t)4149439618; |
| 3981 | 4000 | case TypeTableEntryIdInt: |
| 3982 | 4001 | case TypeTableEntryIdNumLitInt: |
| 3983 | case TypeTableEntryIdEnumTag: | |
| 3984 | 4002 | { |
| 3985 | 4003 | uint32_t result = 1331471175; |
| 3986 | 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 | 4007 | } |
| 3990 | 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 | 4019 | case TypeTableEntryIdFloat: |
| 3993 | 4020 | switch (const_val->type->data.floating.bit_count) { |
| 3994 | 4021 | case 32: |
| ... | ... | @@ -4089,9 +4116,6 @@ static uint32_t hash_const_val(ConstExprValue *const_val) { |
| 4089 | 4116 | case TypeTableEntryIdPureError: |
| 4090 | 4117 | // TODO better hashing algorithm |
| 4091 | 4118 | return 2630160122; |
| 4092 | case TypeTableEntryIdEnum: | |
| 4093 | // TODO better hashing algorithm | |
| 4094 | return 31643936; | |
| 4095 | 4119 | case TypeTableEntryIdFn: |
| 4096 | 4120 | return 4133894920 ^ hash_ptr(const_val->data.x_fn.fn_entry); |
| 4097 | 4121 | case TypeTableEntryIdNamespace: |
| ... | ... | @@ -4224,7 +4248,6 @@ bool type_requires_comptime(TypeTableEntry *type_entry) { |
| 4224 | 4248 | case TypeTableEntryIdInt: |
| 4225 | 4249 | case TypeTableEntryIdFloat: |
| 4226 | 4250 | case TypeTableEntryIdPointer: |
| 4227 | case TypeTableEntryIdEnumTag: | |
| 4228 | 4251 | case TypeTableEntryIdVoid: |
| 4229 | 4252 | case TypeTableEntryIdUnreachable: |
| 4230 | 4253 | return false; |
| ... | ... | @@ -4295,6 +4318,7 @@ ConstExprValue *create_const_bigint(TypeTableEntry *type, const BigInt *bigint) |
| 4295 | 4318 | return const_val; |
| 4296 | 4319 | } |
| 4297 | 4320 | |
| 4321 | ||
| 4298 | 4322 | void init_const_unsigned_negative(ConstExprValue *const_val, TypeTableEntry *type, uint64_t x, bool negative) { |
| 4299 | 4323 | const_val->special = ConstValSpecialStatic; |
| 4300 | 4324 | const_val->type = type; |
| ... | ... | @@ -4358,18 +4382,19 @@ ConstExprValue *create_const_float(TypeTableEntry *type, double value) { |
| 4358 | 4382 | return const_val; |
| 4359 | 4383 | } |
| 4360 | 4384 | |
| 4361 | void init_const_enum_tag(ConstExprValue *const_val, TypeTableEntry *type, const BigInt *tag) { | |
| 4385 | void init_const_enum(ConstExprValue *const_val, TypeTableEntry *type, const BigInt *tag) { | |
| 4362 | 4386 | const_val->special = ConstValSpecialStatic; |
| 4363 | 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 | } |
| 4366 | 4390 | |
| 4367 | ConstExprValue *create_const_enum_tag(TypeTableEntry *type, const BigInt *tag) { | |
| 4391 | ConstExprValue *create_const_enum(TypeTableEntry *type, const BigInt *tag) { | |
| 4368 | 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 | 4394 | return const_val; |
| 4371 | 4395 | } |
| 4372 | 4396 | |
| 4397 | ||
| 4373 | 4398 | void init_const_bool(CodeGen *g, ConstExprValue *const_val, bool value) { |
| 4374 | 4399 | const_val->special = ConstValSpecialStatic; |
| 4375 | 4400 | const_val->type = g->builtin_types.entry_bool; |
| ... | ... | @@ -4567,20 +4592,8 @@ bool const_values_equal(ConstExprValue *a, ConstExprValue *b) { |
| 4567 | 4592 | switch (a->type->id) { |
| 4568 | 4593 | case TypeTableEntryIdOpaque: |
| 4569 | 4594 | zig_unreachable(); |
| 4570 | case TypeTableEntryIdEnum: { | |
| 4571 | ConstEnumValue *enum1 = &a->data.x_enum; | |
| 4572 | ConstEnumValue *enum2 = &b->data.x_enum; | |
| 4573 | if (bigint_cmp(&enum1->tag, &enum2->tag) == CmpEQ) { | |
| 4574 | TypeEnumField *field = find_enum_field_by_tag(a->type, &enum1->tag); | |
| 4575 | assert(field != nullptr); | |
| 4576 | if (type_has_bits(field->type_entry)) { | |
| 4577 | zig_panic("TODO const expr analyze enum field value for equality"); | |
| 4578 | } else { | |
| 4579 | return true; | |
| 4580 | } | |
| 4581 | } | |
| 4582 | return false; | |
| 4583 | } | |
| 4595 | case TypeTableEntryIdEnum: | |
| 4596 | return bigint_cmp(&a->data.x_enum_tag, &b->data.x_enum_tag) == CmpEQ; | |
| 4584 | 4597 | case TypeTableEntryIdUnion: { |
| 4585 | 4598 | ConstUnionValue *union1 = &a->data.x_union; |
| 4586 | 4599 | ConstUnionValue *union2 = &b->data.x_union; |
| ... | ... | @@ -4622,7 +4635,6 @@ bool const_values_equal(ConstExprValue *a, ConstExprValue *b) { |
| 4622 | 4635 | return bigfloat_cmp(&a->data.x_bigfloat, &b->data.x_bigfloat) == CmpEQ; |
| 4623 | 4636 | case TypeTableEntryIdInt: |
| 4624 | 4637 | case TypeTableEntryIdNumLitInt: |
| 4625 | case TypeTableEntryIdEnumTag: | |
| 4626 | 4638 | return bigint_cmp(&a->data.x_bigint, &b->data.x_bigint) == CmpEQ; |
| 4627 | 4639 | case TypeTableEntryIdPointer: |
| 4628 | 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 | 4961 | } |
| 4950 | 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 | 4966 | return; |
| 4954 | 4967 | } |
| 4955 | 4968 | case TypeTableEntryIdErrorUnion: |
| ... | ... | @@ -4967,14 +4980,6 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) { |
| 4967 | 4980 | buf_appendf(buf, "(pure error constant)"); |
| 4968 | 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 | 4983 | case TypeTableEntryIdArgTuple: |
| 4979 | 4984 | { |
| 4980 | 4985 | buf_appendf(buf, "(args value)"); |
| ... | ... | @@ -5036,7 +5041,6 @@ uint32_t type_id_hash(TypeId x) { |
| 5036 | 5041 | case TypeTableEntryIdErrorUnion: |
| 5037 | 5042 | case TypeTableEntryIdPureError: |
| 5038 | 5043 | case TypeTableEntryIdEnum: |
| 5039 | case TypeTableEntryIdEnumTag: | |
| 5040 | 5044 | case TypeTableEntryIdUnion: |
| 5041 | 5045 | case TypeTableEntryIdFn: |
| 5042 | 5046 | case TypeTableEntryIdNamespace: |
| ... | ... | @@ -5081,7 +5085,6 @@ bool type_id_eql(TypeId a, TypeId b) { |
| 5081 | 5085 | case TypeTableEntryIdErrorUnion: |
| 5082 | 5086 | case TypeTableEntryIdPureError: |
| 5083 | 5087 | case TypeTableEntryIdEnum: |
| 5084 | case TypeTableEntryIdEnumTag: | |
| 5085 | 5088 | case TypeTableEntryIdUnion: |
| 5086 | 5089 | case TypeTableEntryIdFn: |
| 5087 | 5090 | case TypeTableEntryIdNamespace: |
| ... | ... | @@ -5196,7 +5199,6 @@ static const TypeTableEntryId all_type_ids[] = { |
| 5196 | 5199 | TypeTableEntryIdErrorUnion, |
| 5197 | 5200 | TypeTableEntryIdPureError, |
| 5198 | 5201 | TypeTableEntryIdEnum, |
| 5199 | TypeTableEntryIdEnumTag, | |
| 5200 | 5202 | TypeTableEntryIdUnion, |
| 5201 | 5203 | TypeTableEntryIdFn, |
| 5202 | 5204 | TypeTableEntryIdNamespace, |
| ... | ... | @@ -5254,22 +5256,20 @@ size_t type_id_index(TypeTableEntryId id) { |
| 5254 | 5256 | return 15; |
| 5255 | 5257 | case TypeTableEntryIdEnum: |
| 5256 | 5258 | return 16; |
| 5257 | case TypeTableEntryIdEnumTag: | |
| 5258 | return 17; | |
| 5259 | 5259 | case TypeTableEntryIdUnion: |
| 5260 | return 18; | |
| 5260 | return 17; | |
| 5261 | 5261 | case TypeTableEntryIdFn: |
| 5262 | return 19; | |
| 5262 | return 18; | |
| 5263 | 5263 | case TypeTableEntryIdNamespace: |
| 5264 | return 20; | |
| 5264 | return 19; | |
| 5265 | 5265 | case TypeTableEntryIdBlock: |
| 5266 | return 21; | |
| 5266 | return 20; | |
| 5267 | 5267 | case TypeTableEntryIdBoundFn: |
| 5268 | return 22; | |
| 5268 | return 21; | |
| 5269 | 5269 | case TypeTableEntryIdArgTuple: |
| 5270 | return 23; | |
| 5270 | return 22; | |
| 5271 | 5271 | case TypeTableEntryIdOpaque: |
| 5272 | return 24; | |
| 5272 | return 23; | |
| 5273 | 5273 | } |
| 5274 | 5274 | zig_unreachable(); |
| 5275 | 5275 | } |
| ... | ... | @@ -5313,8 +5313,6 @@ const char *type_id_name(TypeTableEntryId id) { |
| 5313 | 5313 | return "Error"; |
| 5314 | 5314 | case TypeTableEntryIdEnum: |
| 5315 | 5315 | return "Enum"; |
| 5316 | case TypeTableEntryIdEnumTag: | |
| 5317 | return "EnumTag"; | |
| 5318 | 5316 | case TypeTableEntryIdUnion: |
| 5319 | 5317 | return "Union"; |
| 5320 | 5318 | case TypeTableEntryIdFn: |
| ... | ... | @@ -5381,9 +5379,6 @@ uint32_t get_abi_alignment(CodeGen *g, TypeTableEntry *type_entry) { |
| 5381 | 5379 | if (type_entry->id == TypeTableEntryIdStruct) { |
| 5382 | 5380 | assert(type_entry->data.structure.abi_alignment != 0); |
| 5383 | 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 | 5382 | } else if (type_entry->id == TypeTableEntryIdUnion) { |
| 5388 | 5383 | assert(type_entry->data.unionation.abi_alignment != 0); |
| 5389 | 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 | 65 | TypeEnumField *find_enum_type_field(TypeTableEntry *enum_type, Buf *name); |
| 66 | 66 | TypeUnionField *find_union_type_field(TypeTableEntry *type_entry, Buf *name); |
| 67 | 67 | TypeEnumField *find_enum_field_by_tag(TypeTableEntry *enum_type, const BigInt *tag); |
| 68 | TypeUnionField *find_union_field_by_tag(TypeTableEntry *type_entry, const BigInt *tag); | |
| 68 | 69 | |
| 69 | 70 | bool is_container_ref(TypeTableEntry *type_entry); |
| 70 | 71 | void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node); |
| ... | ... | @@ -126,8 +127,8 @@ ConstExprValue *create_const_usize(CodeGen *g, uint64_t x); |
| 126 | 127 | void init_const_float(ConstExprValue *const_val, TypeTableEntry *type, double value); |
| 127 | 128 | ConstExprValue *create_const_float(TypeTableEntry *type, double value); |
| 128 | 129 | |
| 129 | void init_const_enum_tag(ConstExprValue *const_val, TypeTableEntry *type, const BigInt *tag); | |
| 130 | ConstExprValue *create_const_enum_tag(TypeTableEntry *type, const BigInt *tag); | |
| 130 | void init_const_enum(ConstExprValue *const_val, TypeTableEntry *type, const BigInt *tag); | |
| 131 | ConstExprValue *create_const_enum(TypeTableEntry *type, const BigInt *tag); | |
| 131 | 132 | |
| 132 | 133 | void init_const_bool(CodeGen *g, ConstExprValue *const_val, bool value); |
| 133 | 134 | ConstExprValue *create_const_bool(CodeGen *g, bool value); |
| ... | ... | @@ -163,7 +164,6 @@ ConstExprValue *create_const_vals(size_t count); |
| 163 | 164 | |
| 164 | 165 | TypeTableEntry *make_int_type(CodeGen *g, bool is_signed, uint32_t size_in_bits); |
| 165 | 166 | ConstParent *get_const_val_parent(CodeGen *g, ConstExprValue *value); |
| 166 | TypeTableEntry *create_enum_tag_type(CodeGen *g, TypeTableEntry *enum_type, TypeTableEntry *int_type); | |
| 167 | 167 | void expand_undef_array(CodeGen *g, ConstExprValue *const_val); |
| 168 | 168 | void update_compile_var(CodeGen *g, Buf *name, ConstExprValue *value); |
| 169 | 169 |
src/ast_render.cpp+7| ... | ... | @@ -661,11 +661,18 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) { |
| 661 | 661 | const char *layout_str = layout_string(node->data.container_decl.layout); |
| 662 | 662 | const char *container_str = container_string(node->data.container_decl.kind); |
| 663 | 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 | 667 | if (node->data.container_decl.init_arg_expr != nullptr) { |
| 665 | 668 | fprintf(ar->f, "("); |
| 666 | 669 | render_node_grouped(ar, node->data.container_decl.init_arg_expr); |
| 667 | 670 | fprintf(ar->f, ")"); |
| 668 | 671 | } |
| 672 | if (node->data.container_decl.auto_enum) { | |
| 673 | fprintf(ar->f, ")"); | |
| 674 | } | |
| 675 | ||
| 669 | 676 | fprintf(ar->f, " {\n"); |
| 670 | 677 | ar->indent += ar->indent_size; |
| 671 | 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 | 1631 | LLVMIntPredicate pred = cmp_op_to_int_predicate(op_id, type_entry->data.integral.is_signed); |
| 1632 | 1632 | return LLVMBuildICmp(g->builder, pred, op1_value, op2_value, ""); |
| 1633 | 1633 | } else if (type_entry->id == TypeTableEntryIdEnum) { |
| 1634 | if (type_entry->data.enumeration.gen_field_count == 0) { | |
| 1635 | LLVMIntPredicate pred = cmp_op_to_int_predicate(op_id, false); | |
| 1636 | return LLVMBuildICmp(g->builder, pred, op1_value, op2_value, ""); | |
| 1637 | } else { | |
| 1638 | zig_unreachable(); | |
| 1639 | } | |
| 1634 | LLVMIntPredicate pred = cmp_op_to_int_predicate(op_id, false); | |
| 1635 | return LLVMBuildICmp(g->builder, pred, op1_value, op2_value, ""); | |
| 1640 | 1636 | } else if (type_entry->id == TypeTableEntryIdPureError || |
| 1641 | 1637 | type_entry->id == TypeTableEntryIdPointer || |
| 1642 | 1638 | type_entry->id == TypeTableEntryIdBool) |
| ... | ... | @@ -1920,9 +1916,7 @@ static LLVMValueRef ir_render_widen_or_shorten(CodeGen *g, IrExecutable *executa |
| 1920 | 1916 | // enum_tag to the underlying int type |
| 1921 | 1917 | TypeTableEntry *int_type; |
| 1922 | 1918 | if (actual_type->id == TypeTableEntryIdEnum) { |
| 1923 | TypeTableEntry *tag_type = actual_type->data.enumeration.tag_type; | |
| 1924 | assert(tag_type->id == TypeTableEntryIdEnumTag); | |
| 1925 | int_type = tag_type->data.enum_tag.int_type; | |
| 1919 | int_type = actual_type->data.enumeration.tag_int_type; | |
| 1926 | 1920 | } else { |
| 1927 | 1921 | int_type = actual_type; |
| 1928 | 1922 | } |
| ... | ... | @@ -1946,19 +1940,11 @@ static LLVMValueRef ir_render_ptr_to_int(CodeGen *g, IrExecutable *executable, I |
| 1946 | 1940 | static LLVMValueRef ir_render_int_to_enum(CodeGen *g, IrExecutable *executable, IrInstructionIntToEnum *instruction) { |
| 1947 | 1941 | TypeTableEntry *wanted_type = instruction->base.value.type; |
| 1948 | 1942 | assert(wanted_type->id == TypeTableEntryIdEnum); |
| 1949 | TypeTableEntry *tag_type = wanted_type->data.enumeration.tag_type; | |
| 1950 | TypeTableEntry *wanted_int_type; | |
| 1951 | if (tag_type->id == TypeTableEntryIdEnumTag) { | |
| 1952 | wanted_int_type = tag_type->data.enum_tag.int_type; | |
| 1953 | } else if (tag_type->id == TypeTableEntryIdInt) { | |
| 1954 | wanted_int_type = tag_type; | |
| 1955 | } else { | |
| 1956 | zig_unreachable(); | |
| 1957 | } | |
| 1943 | TypeTableEntry *tag_int_type = wanted_type->data.enumeration.tag_int_type; | |
| 1958 | 1944 | |
| 1959 | 1945 | LLVMValueRef target_val = ir_llvm_value(g, instruction->target); |
| 1960 | 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 | } |
| 1963 | 1949 | |
| 1964 | 1950 | static 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 | 2364 | return LLVMBuildStructGEP(g->builder, struct_ptr, (unsigned)field->gen_index, ""); |
| 2379 | 2365 | } |
| 2380 | 2366 | |
| 2381 | static 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 | ||
| 2402 | 2367 | static LLVMValueRef ir_render_union_field_ptr(CodeGen *g, IrExecutable *executable, |
| 2403 | 2368 | IrInstructionUnionFieldPtr *instruction) |
| 2404 | 2369 | { |
| ... | ... | @@ -2427,7 +2392,7 @@ static LLVMValueRef ir_render_union_field_ptr(CodeGen *g, IrExecutable *executab |
| 2427 | 2392 | |
| 2428 | 2393 | |
| 2429 | 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 | 2396 | LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn_val, "UnionCheckOk"); |
| 2432 | 2397 | LLVMBasicBlockRef bad_block = LLVMAppendBasicBlock(g->cur_fn_val, "UnionCheckFail"); |
| 2433 | 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 | 2719 | static LLVMValueRef ir_render_enum_tag_name(CodeGen *g, IrExecutable *executable, |
| 2755 | 2720 | IrInstructionEnumTagName *instruction) |
| 2756 | 2721 | { |
| 2757 | TypeTableEntry *enum_tag_type = instruction->target->value.type; | |
| 2758 | assert(enum_tag_type->data.enum_tag.generate_name_table); | |
| 2722 | TypeTableEntry *enum_type = instruction->target->value.type; | |
| 2723 | assert(enum_type->id == TypeTableEntryIdEnum); | |
| 2724 | assert(enum_type->data.enumeration.generate_name_table); | |
| 2759 | 2725 | |
| 2726 | TypeTableEntry *tag_int_type = enum_type->data.enumeration.tag_int_type; | |
| 2760 | 2727 | LLVMValueRef enum_tag_value = ir_llvm_value(g, instruction->target); |
| 2761 | 2728 | if (ir_want_debug_safety(g, &instruction->base)) { |
| 2762 | TypeTableEntry *enum_type = enum_tag_type->data.enum_tag.enum_type; | |
| 2763 | 2729 | size_t field_count = enum_type->data.enumeration.src_field_count; |
| 2764 | 2730 | |
| 2765 | // if the field_count can't fit in the bits of the enum_tag_type, then it can't possibly | |
| 2731 | // if the field_count can't fit in the bits of the enum_type, then it can't possibly | |
| 2766 | 2732 | // be the wrong value |
| 2767 | 2733 | BigInt field_bi; |
| 2768 | 2734 | bigint_init_unsigned(&field_bi, field_count); |
| 2769 | TypeTableEntry *tag_int_type = enum_tag_type->data.enum_tag.int_type; | |
| 2770 | 2735 | if (bigint_fits_in_bits(&field_bi, tag_int_type->data.integral.bit_count, false)) { |
| 2771 | 2736 | LLVMValueRef end_val = LLVMConstInt(LLVMTypeOf(enum_tag_value), field_count, false); |
| 2772 | 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 | 2740 | |
| 2776 | 2741 | LLVMValueRef indices[] = { |
| 2777 | 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 | 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 | } |
| 2783 | 2748 | |
| 2784 | 2749 | static 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 | 3317 | return instruction->tmp_ptr; |
| 3353 | 3318 | } |
| 3354 | 3319 | |
| 3355 | static LLVMValueRef ir_render_enum_tag(CodeGen *g, IrExecutable *executable, IrInstructionEnumTag *instruction) { | |
| 3356 | TypeTableEntry *enum_type = instruction->value->value.type; | |
| 3357 | TypeTableEntry *tag_type = enum_type->data.enumeration.tag_type; | |
| 3320 | static LLVMValueRef ir_render_union_tag(CodeGen *g, IrExecutable *executable, IrInstructionUnionTag *instruction) { | |
| 3321 | TypeTableEntry *union_type = instruction->value->value.type; | |
| 3322 | assert(union_type->data.unionation.gen_tag_index != SIZE_MAX); | |
| 3323 | ||
| 3324 | TypeTableEntry *tag_type = union_type->data.unionation.tag_type; | |
| 3358 | 3325 | if (!type_has_bits(tag_type)) |
| 3359 | 3326 | return nullptr; |
| 3360 | 3327 | |
| 3361 | LLVMValueRef enum_val = ir_llvm_value(g, instruction->value); | |
| 3362 | if (enum_type->data.enumeration.gen_field_count == 0) | |
| 3363 | return enum_val; | |
| 3328 | LLVMValueRef union_val = ir_llvm_value(g, instruction->value); | |
| 3329 | if (union_type->data.unionation.gen_field_count == 0) | |
| 3330 | return union_val; | |
| 3364 | 3331 | |
| 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 | 3334 | TypeTableEntry *ptr_type = get_pointer_to_type(g, tag_type, false); |
| 3367 | 3335 | return get_handle_value(g, tag_field_ptr, tag_type, ptr_type); |
| 3368 | 3336 | } |
| 3369 | 3337 | |
| 3370 | static 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 | ||
| 3397 | 3338 | static LLVMValueRef ir_render_struct_init(CodeGen *g, IrExecutable *executable, IrInstructionStructInit *instruction) { |
| 3398 | 3339 | for (size_t i = 0; i < instruction->field_count; i += 1) { |
| 3399 | 3340 | IrInstructionStructInitField *field = &instruction->fields[i]; |
| ... | ... | @@ -3436,7 +3377,7 @@ static LLVMValueRef ir_render_union_init(CodeGen *g, IrExecutable *executable, I |
| 3436 | 3377 | union_type->data.unionation.gen_tag_index, ""); |
| 3437 | 3378 | |
| 3438 | 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 | 3381 | gen_store_untyped(g, tag_value, tag_field_ptr, 0, false); |
| 3441 | 3382 | |
| 3442 | 3383 | uncasted_union_ptr = LLVMBuildStructGEP(g->builder, instruction->tmp_ptr, |
| ... | ... | @@ -3573,8 +3514,6 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, |
| 3573 | 3514 | return ir_render_call(g, executable, (IrInstructionCall *)instruction); |
| 3574 | 3515 | case IrInstructionIdStructFieldPtr: |
| 3575 | 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 | 3517 | case IrInstructionIdUnionFieldPtr: |
| 3579 | 3518 | return ir_render_union_field_ptr(g, executable, (IrInstructionUnionFieldPtr *)instruction); |
| 3580 | 3519 | case IrInstructionIdAsm: |
| ... | ... | @@ -3629,10 +3568,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, |
| 3629 | 3568 | return ir_render_err_wrap_code(g, executable, (IrInstructionErrWrapCode *)instruction); |
| 3630 | 3569 | case IrInstructionIdErrWrapPayload: |
| 3631 | 3570 | return ir_render_err_wrap_payload(g, executable, (IrInstructionErrWrapPayload *)instruction); |
| 3632 | case IrInstructionIdEnumTag: | |
| 3633 | return ir_render_enum_tag(g, executable, (IrInstructionEnumTag *)instruction); | |
| 3634 | case IrInstructionIdInitEnum: | |
| 3635 | return ir_render_init_enum(g, executable, (IrInstructionInitEnum *)instruction); | |
| 3571 | case IrInstructionIdUnionTag: | |
| 3572 | return ir_render_union_tag(g, executable, (IrInstructionUnionTag *)instruction); | |
| 3636 | 3573 | case IrInstructionIdStructInit: |
| 3637 | 3574 | return ir_render_struct_init(g, executable, (IrInstructionStructInit *)instruction); |
| 3638 | 3575 | case IrInstructionIdUnionInit: |
| ... | ... | @@ -3768,7 +3705,6 @@ static LLVMValueRef pack_const_int(CodeGen *g, LLVMTypeRef big_int_type_ref, Con |
| 3768 | 3705 | case TypeTableEntryIdNullLit: |
| 3769 | 3706 | case TypeTableEntryIdErrorUnion: |
| 3770 | 3707 | case TypeTableEntryIdPureError: |
| 3771 | case TypeTableEntryIdEnumTag: | |
| 3772 | 3708 | case TypeTableEntryIdNamespace: |
| 3773 | 3709 | case TypeTableEntryIdBlock: |
| 3774 | 3710 | case TypeTableEntryIdBoundFn: |
| ... | ... | @@ -3780,7 +3716,6 @@ static LLVMValueRef pack_const_int(CodeGen *g, LLVMTypeRef big_int_type_ref, Con |
| 3780 | 3716 | return LLVMConstInt(big_int_type_ref, const_val->data.x_bool ? 1 : 0, false); |
| 3781 | 3717 | case TypeTableEntryIdEnum: |
| 3782 | 3718 | { |
| 3783 | assert(type_entry->data.enumeration.gen_field_count == 0); | |
| 3784 | 3719 | assert(type_entry->data.enumeration.decl_node->data.container_decl.init_arg_expr != nullptr); |
| 3785 | 3720 | LLVMValueRef int_val = gen_const_val(g, const_val); |
| 3786 | 3721 | return LLVMConstZExt(int_val, big_int_type_ref); |
| ... | ... | @@ -3852,7 +3787,6 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val) { |
| 3852 | 3787 | |
| 3853 | 3788 | switch (type_entry->id) { |
| 3854 | 3789 | case TypeTableEntryIdInt: |
| 3855 | case TypeTableEntryIdEnumTag: | |
| 3856 | 3790 | return bigint_to_llvm_const(type_entry->type_ref, &const_val->data.x_bigint); |
| 3857 | 3791 | case TypeTableEntryIdPureError: |
| 3858 | 3792 | assert(const_val->data.x_pure_err); |
| ... | ... | @@ -4015,34 +3949,48 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val) { |
| 4015 | 3949 | ConstExprValue *payload_value = const_val->data.x_union.payload; |
| 4016 | 3950 | assert(payload_value != nullptr); |
| 4017 | 3951 | |
| 4018 | if (!type_has_bits(payload_value->type)) { | |
| 4019 | return LLVMGetUndef(union_type_ref); | |
| 3952 | if (type_entry->data.unionation.gen_field_count == 0) { | |
| 3953 | if (type_entry->data.unionation.gen_tag_index == SIZE_MAX) { | |
| 3954 | return nullptr; | |
| 3955 | } else { | |
| 3956 | return bigint_to_llvm_const(type_entry->data.unionation.tag_type->type_ref, | |
| 3957 | &const_val->data.x_union.tag); | |
| 3958 | } | |
| 4020 | 3959 | } |
| 4021 | 3960 | |
| 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 | 3961 | LLVMValueRef union_value_ref; |
| 4029 | { | |
| 4030 | if (pad_bytes == 0) { | |
| 4031 | union_value_ref = correctly_typed_value; | |
| 4032 | } else { | |
| 4033 | LLVMValueRef fields[2]; | |
| 4034 | fields[0] = correctly_typed_value; | |
| 4035 | fields[1] = LLVMGetUndef(LLVMArrayType(LLVMInt8Type(), (unsigned)pad_bytes)); | |
| 4036 | if (make_unnamed_struct || type_entry->data.unionation.gen_tag_index != SIZE_MAX) { | |
| 4037 | union_value_ref = LLVMConstStruct(fields, 2, false); | |
| 3962 | bool make_unnamed_struct; | |
| 3963 | if (!type_has_bits(payload_value->type)) { | |
| 3964 | if (type_entry->data.unionation.gen_tag_index == SIZE_MAX) | |
| 3965 | return LLVMGetUndef(type_entry->type_ref); | |
| 3966 | ||
| 3967 | union_value_ref = LLVMGetUndef(type_entry->data.unionation.most_aligned_union_member->type_ref); | |
| 3968 | make_unnamed_struct = false; | |
| 3969 | } else { | |
| 3970 | uint64_t field_type_bytes = LLVMStoreSizeOfType(g->target_data_ref, payload_value->type->type_ref); | |
| 3971 | uint64_t pad_bytes = type_entry->data.unionation.union_size_bytes - field_type_bytes; | |
| 3972 | LLVMValueRef correctly_typed_value = gen_const_val(g, payload_value); | |
| 3973 | make_unnamed_struct = is_llvm_value_unnamed_type(payload_value->type, correctly_typed_value) || | |
| 3974 | payload_value->type != type_entry->data.unionation.most_aligned_union_member; | |
| 3975 | ||
| 3976 | { | |
| 3977 | if (pad_bytes == 0) { | |
| 3978 | union_value_ref = correctly_typed_value; | |
| 4038 | 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 | } | |
| 4043 | 3990 | |
| 4044 | if (type_entry->data.unionation.gen_tag_index == SIZE_MAX) { | |
| 4045 | return union_value_ref; | |
| 3991 | if (type_entry->data.unionation.gen_tag_index == SIZE_MAX) { | |
| 3992 | return union_value_ref; | |
| 3993 | } | |
| 4046 | 3994 | } |
| 4047 | 3995 | |
| 4048 | 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 | 4007 | } |
| 4060 | 4008 | |
| 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; | |
| 4075 | 4010 | |
| 4076 | if (type_has_bits(enum_field->type_entry)) { | |
| 4077 | uint64_t field_type_bytes = LLVMStoreSizeOfType(g->target_data_ref, | |
| 4078 | enum_field->type_entry->type_ref); | |
| 4079 | uint64_t pad_bytes = type_entry->data.enumeration.union_size_bytes - field_type_bytes; | |
| 4080 | ||
| 4081 | ConstExprValue *payload_value = const_val->data.x_enum.payload; | |
| 4082 | LLVMValueRef correctly_typed_value = gen_const_val(g, payload_value); | |
| 4083 | ||
| 4084 | make_unnamed_struct = is_llvm_value_unnamed_type(payload_value->type, correctly_typed_value) || | |
| 4085 | payload_value->type != type_entry->data.enumeration.most_aligned_union_member; | |
| 4086 | ||
| 4087 | if (pad_bytes == 0) { | |
| 4088 | union_value = correctly_typed_value; | |
| 4089 | } else { | |
| 4090 | LLVMValueRef fields[] = { | |
| 4091 | correctly_typed_value, | |
| 4092 | LLVMGetUndef(LLVMArrayType(LLVMInt8Type(), (unsigned)pad_bytes)), | |
| 4093 | }; | |
| 4094 | union_value = LLVMConstStruct(fields, 2, false); | |
| 4095 | } | |
| 4096 | } else { | |
| 4097 | make_unnamed_struct = false; | |
| 4098 | union_value = LLVMGetUndef(union_type_ref); | |
| 4099 | } | |
| 4100 | LLVMValueRef fields[2]; | |
| 4101 | fields[type_entry->data.enumeration.gen_tag_index] = tag_value; | |
| 4102 | fields[type_entry->data.enumeration.gen_union_index] = union_value; | |
| 4103 | ||
| 4104 | if (make_unnamed_struct) { | |
| 4105 | return LLVMConstStruct(fields, 2, false); | |
| 4106 | } else { | |
| 4107 | return LLVMConstNamedStruct(type_entry->type_ref, fields, 2); | |
| 4108 | } | |
| 4109 | } | |
| 4110 | } | |
| 4011 | case TypeTableEntryIdEnum: | |
| 4012 | return bigint_to_llvm_const(type_entry->type_ref, &const_val->data.x_enum_tag); | |
| 4111 | 4013 | case TypeTableEntryIdFn: |
| 4112 | 4014 | return fn_llvm_value(g, const_val->data.x_fn.fn_entry); |
| 4113 | 4015 | case TypeTableEntryIdPointer: |
| ... | ... | @@ -4318,9 +4220,8 @@ static void generate_enum_name_tables(CodeGen *g) { |
| 4318 | 4220 | |
| 4319 | 4221 | |
| 4320 | 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); | |
| 4322 | assert(enum_tag_type->id == TypeTableEntryIdEnumTag); | |
| 4323 | TypeTableEntry *enum_type = enum_tag_type->data.enum_tag.enum_type; | |
| 4223 | TypeTableEntry *enum_type = g->name_table_enums.at(enum_i); | |
| 4224 | assert(enum_type->id == TypeTableEntryIdEnum); | |
| 4324 | 4225 | |
| 4325 | 4226 | size_t field_count = enum_type->data.enumeration.src_field_count; |
| 4326 | 4227 | LLVMValueRef *values = allocate<LLVMValueRef>(field_count); |
| ... | ... | @@ -4351,7 +4252,7 @@ static void generate_enum_name_tables(CodeGen *g) { |
| 4351 | 4252 | LLVMSetGlobalConstant(name_table, true); |
| 4352 | 4253 | LLVMSetUnnamedAddr(name_table, true); |
| 4353 | 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 | } |
| 4357 | 4258 | |
| ... | ... | @@ -4555,9 +4456,6 @@ static void do_code_gen(CodeGen *g) { |
| 4555 | 4456 | } else if (instruction->id == IrInstructionIdErrWrapCode) { |
| 4556 | 4457 | IrInstructionErrWrapCode *err_wrap_code_instruction = (IrInstructionErrWrapCode *)instruction; |
| 4557 | 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 | 4459 | } else { |
| 4562 | 4460 | zig_unreachable(); |
| 4563 | 4461 | } |
| ... | ... | @@ -5054,7 +4952,7 @@ static void define_builtin_fns(CodeGen *g) { |
| 5054 | 4952 | create_builtin_fn(g, BuiltinFnIdTruncate, "truncate", 2); |
| 5055 | 4953 | create_builtin_fn(g, BuiltinFnIdCompileErr, "compileError", 1); |
| 5056 | 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 | 4956 | create_builtin_fn(g, BuiltinFnIdSetDebugSafety, "setDebugSafety", 2); |
| 5059 | 4957 | create_builtin_fn(g, BuiltinFnIdSetFloatMode, "setFloatMode", 2); |
| 5060 | 4958 | create_builtin_fn(g, BuiltinFnIdSetGlobalSection, "setGlobalSection", 2); |
| ... | ... | @@ -5064,7 +4962,7 @@ static void define_builtin_fns(CodeGen *g) { |
| 5064 | 4962 | create_builtin_fn(g, BuiltinFnIdBitCast, "bitCast", 2); |
| 5065 | 4963 | create_builtin_fn(g, BuiltinFnIdIntToPtr, "intToPtr", 2); |
| 5066 | 4964 | create_builtin_fn(g, BuiltinFnIdPtrToInt, "ptrToInt", 1); |
| 5067 | create_builtin_fn(g, BuiltinFnIdEnumTagName, "enumTagName", 1); // TODO rename to memberName | |
| 4965 | create_builtin_fn(g, BuiltinFnIdTagName, "tagName", 1); | |
| 5068 | 4966 | create_builtin_fn(g, BuiltinFnIdEnumTagType, "EnumTagType", 1); |
| 5069 | 4967 | create_builtin_fn(g, BuiltinFnIdFieldParentPtr, "fieldParentPtr", 3); |
| 5070 | 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 | 5579 | case TypeTableEntryIdEnum: |
| 5682 | 5580 | case TypeTableEntryIdUnion: |
| 5683 | 5581 | case TypeTableEntryIdFn: |
| 5684 | case TypeTableEntryIdEnumTag: | |
| 5685 | 5582 | zig_panic("TODO implement get_c_type for more types"); |
| 5686 | 5583 | case TypeTableEntryIdInvalid: |
| 5687 | 5584 | case TypeTableEntryIdMetaType: |
src/ir.cpp+206-282| ... | ... | @@ -223,10 +223,6 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionStructFieldPtr * |
| 223 | 223 | return IrInstructionIdStructFieldPtr; |
| 224 | 224 | } |
| 225 | 225 | |
| 226 | static constexpr IrInstructionId ir_instruction_id(IrInstructionEnumFieldPtr *) { | |
| 227 | return IrInstructionIdEnumFieldPtr; | |
| 228 | } | |
| 229 | ||
| 230 | 226 | static constexpr IrInstructionId ir_instruction_id(IrInstructionUnionFieldPtr *) { |
| 231 | 227 | return IrInstructionIdUnionFieldPtr; |
| 232 | 228 | } |
| ... | ... | @@ -319,8 +315,8 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionCtz *) { |
| 319 | 315 | return IrInstructionIdCtz; |
| 320 | 316 | } |
| 321 | 317 | |
| 322 | static constexpr IrInstructionId ir_instruction_id(IrInstructionEnumTag *) { | |
| 323 | return IrInstructionIdEnumTag; | |
| 318 | static constexpr IrInstructionId ir_instruction_id(IrInstructionUnionTag *) { | |
| 319 | return IrInstructionIdUnionTag; | |
| 324 | 320 | } |
| 325 | 321 | |
| 326 | 322 | static constexpr IrInstructionId ir_instruction_id(IrInstructionImport *) { |
| ... | ... | @@ -479,10 +475,6 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionTestComptime *) |
| 479 | 475 | return IrInstructionIdTestComptime; |
| 480 | 476 | } |
| 481 | 477 | |
| 482 | static constexpr IrInstructionId ir_instruction_id(IrInstructionInitEnum *) { | |
| 483 | return IrInstructionIdInitEnum; | |
| 484 | } | |
| 485 | ||
| 486 | 478 | static constexpr IrInstructionId ir_instruction_id(IrInstructionPtrCast *) { |
| 487 | 479 | return IrInstructionIdPtrCast; |
| 488 | 480 | } |
| ... | ... | @@ -913,27 +905,6 @@ static IrInstruction *ir_build_struct_field_ptr_from(IrBuilder *irb, IrInstructi |
| 913 | 905 | return new_instruction; |
| 914 | 906 | } |
| 915 | 907 | |
| 916 | static 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 | ||
| 928 | static 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 | ||
| 937 | 908 | static IrInstruction *ir_build_union_field_ptr(IrBuilder *irb, Scope *scope, AstNode *source_node, |
| 938 | 909 | IrInstruction *union_ptr, TypeUnionField *field) |
| 939 | 910 | { |
| ... | ... | @@ -1528,8 +1499,8 @@ static IrInstruction *ir_build_switch_var(IrBuilder *irb, Scope *scope, AstNode |
| 1528 | 1499 | return &instruction->base; |
| 1529 | 1500 | } |
| 1530 | 1501 | |
| 1531 | static IrInstruction *ir_build_enum_tag(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *value) { | |
| 1532 | IrInstructionEnumTag *instruction = ir_build_instruction<IrInstructionEnumTag>(irb, scope, source_node); | |
| 1502 | static IrInstruction *ir_build_union_tag(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *value) { | |
| 1503 | IrInstructionUnionTag *instruction = ir_build_instruction<IrInstructionUnionTag>(irb, scope, source_node); | |
| 1533 | 1504 | instruction->value = value; |
| 1534 | 1505 | |
| 1535 | 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 | 1508 | return &instruction->base; |
| 1538 | 1509 | } |
| 1539 | 1510 | |
| 1540 | static 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 | ||
| 1547 | 1511 | static IrInstruction *ir_build_import(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *name) { |
| 1548 | 1512 | IrInstructionImport *instruction = ir_build_instruction<IrInstructionImport>(irb, scope, source_node); |
| 1549 | 1513 | instruction->name = name; |
| ... | ... | @@ -2033,28 +1997,6 @@ static IrInstruction *ir_build_test_comptime(IrBuilder *irb, Scope *scope, AstNo |
| 2033 | 1997 | return &instruction->base; |
| 2034 | 1998 | } |
| 2035 | 1999 | |
| 2036 | static 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 | ||
| 2049 | static 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 | ||
| 2058 | 2000 | static IrInstruction *ir_build_ptr_cast(IrBuilder *irb, Scope *scope, AstNode *source_node, |
| 2059 | 2001 | IrInstruction *dest_type, IrInstruction *ptr) |
| 2060 | 2002 | { |
| ... | ... | @@ -2481,13 +2423,6 @@ static IrInstruction *ir_instruction_structfieldptr_get_dep(IrInstructionStructF |
| 2481 | 2423 | } |
| 2482 | 2424 | } |
| 2483 | 2425 | |
| 2484 | static 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 | ||
| 2491 | 2426 | static IrInstruction *ir_instruction_unionfieldptr_get_dep(IrInstructionUnionFieldPtr *instruction, size_t index) { |
| 2492 | 2427 | switch (index) { |
| 2493 | 2428 | case 0: return instruction->union_ptr; |
| ... | ... | @@ -2657,7 +2592,7 @@ static IrInstruction *ir_instruction_maybewrap_get_dep(IrInstructionMaybeWrap *i |
| 2657 | 2592 | } |
| 2658 | 2593 | } |
| 2659 | 2594 | |
| 2660 | static IrInstruction *ir_instruction_enumtag_get_dep(IrInstructionEnumTag *instruction, size_t index) { | |
| 2595 | static IrInstruction *ir_instruction_uniontag_get_dep(IrInstructionUnionTag *instruction, size_t index) { | |
| 2661 | 2596 | switch (index) { |
| 2662 | 2597 | case 0: return instruction->value; |
| 2663 | 2598 | default: return nullptr; |
| ... | ... | @@ -2943,13 +2878,6 @@ static IrInstruction *ir_instruction_testcomptime_get_dep(IrInstructionTestCompt |
| 2943 | 2878 | } |
| 2944 | 2879 | } |
| 2945 | 2880 | |
| 2946 | static 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 | ||
| 2953 | 2881 | static IrInstruction *ir_instruction_ptrcast_get_dep(IrInstructionPtrCast *instruction, |
| 2954 | 2882 | size_t index) |
| 2955 | 2883 | { |
| ... | ... | @@ -3184,8 +3112,6 @@ static IrInstruction *ir_instruction_get_dep(IrInstruction *instruction, size_t |
| 3184 | 3112 | return ir_instruction_fieldptr_get_dep((IrInstructionFieldPtr *) instruction, index); |
| 3185 | 3113 | case IrInstructionIdStructFieldPtr: |
| 3186 | 3114 | return ir_instruction_structfieldptr_get_dep((IrInstructionStructFieldPtr *) instruction, index); |
| 3187 | case IrInstructionIdEnumFieldPtr: | |
| 3188 | return ir_instruction_enumfieldptr_get_dep((IrInstructionEnumFieldPtr *) instruction, index); | |
| 3189 | 3115 | case IrInstructionIdUnionFieldPtr: |
| 3190 | 3116 | return ir_instruction_unionfieldptr_get_dep((IrInstructionUnionFieldPtr *) instruction, index); |
| 3191 | 3117 | case IrInstructionIdElemPtr: |
| ... | ... | @@ -3234,8 +3160,8 @@ static IrInstruction *ir_instruction_get_dep(IrInstruction *instruction, size_t |
| 3234 | 3160 | return ir_instruction_unwrapmaybe_get_dep((IrInstructionUnwrapMaybe *) instruction, index); |
| 3235 | 3161 | case IrInstructionIdMaybeWrap: |
| 3236 | 3162 | return ir_instruction_maybewrap_get_dep((IrInstructionMaybeWrap *) instruction, index); |
| 3237 | case IrInstructionIdEnumTag: | |
| 3238 | return ir_instruction_enumtag_get_dep((IrInstructionEnumTag *) instruction, index); | |
| 3163 | case IrInstructionIdUnionTag: | |
| 3164 | return ir_instruction_uniontag_get_dep((IrInstructionUnionTag *) instruction, index); | |
| 3239 | 3165 | case IrInstructionIdClz: |
| 3240 | 3166 | return ir_instruction_clz_get_dep((IrInstructionClz *) instruction, index); |
| 3241 | 3167 | case IrInstructionIdCtz: |
| ... | ... | @@ -3312,8 +3238,6 @@ static IrInstruction *ir_instruction_get_dep(IrInstruction *instruction, size_t |
| 3312 | 3238 | return ir_instruction_fnproto_get_dep((IrInstructionFnProto *) instruction, index); |
| 3313 | 3239 | case IrInstructionIdTestComptime: |
| 3314 | 3240 | return ir_instruction_testcomptime_get_dep((IrInstructionTestComptime *) instruction, index); |
| 3315 | case IrInstructionIdInitEnum: | |
| 3316 | return ir_instruction_initenum_get_dep((IrInstructionInitEnum *) instruction, index); | |
| 3317 | 3241 | case IrInstructionIdPtrCast: |
| 3318 | 3242 | return ir_instruction_ptrcast_get_dep((IrInstructionPtrCast *) instruction, index); |
| 3319 | 3243 | case IrInstructionIdBitCast: |
| ... | ... | @@ -4695,14 +4619,14 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo |
| 4695 | 4619 | |
| 4696 | 4620 | return ir_build_ptr_to_int(irb, scope, node, arg0_value); |
| 4697 | 4621 | } |
| 4698 | case BuiltinFnIdEnumTagName: | |
| 4622 | case BuiltinFnIdTagName: | |
| 4699 | 4623 | { |
| 4700 | 4624 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); |
| 4701 | 4625 | IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope); |
| 4702 | 4626 | if (arg0_value == irb->codegen->invalid_instruction) |
| 4703 | 4627 | return arg0_value; |
| 4704 | 4628 | |
| 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 | 4630 | return ir_build_enum_tag_name(irb, scope, node, actual_tag); |
| 4707 | 4631 | } |
| 4708 | 4632 | case BuiltinFnIdEnumTagType: |
| ... | ... | @@ -8381,13 +8305,28 @@ static IrInstruction *ir_analyze_enum_to_int(IrAnalyze *ira, IrInstruction *sour |
| 8381 | 8305 | { |
| 8382 | 8306 | assert(wanted_type->id == TypeTableEntryIdInt); |
| 8383 | 8307 | |
| 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 | 8323 | if (instr_is_comptime(target)) { |
| 8385 | 8324 | ConstExprValue *val = ir_resolve_const(ira, target, UndefBad); |
| 8386 | 8325 | if (!val) |
| 8387 | 8326 | return ira->codegen->invalid_instruction; |
| 8388 | 8327 | IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope, |
| 8389 | 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 | 8330 | return result; |
| 8392 | 8331 | } |
| 8393 | 8332 | |
| ... | ... | @@ -8397,6 +8336,31 @@ static IrInstruction *ir_analyze_enum_to_int(IrAnalyze *ira, IrInstruction *sour |
| 8397 | 8336 | return result; |
| 8398 | 8337 | } |
| 8399 | 8338 | |
| 8339 | static 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 | ||
| 8400 | 8364 | static IrInstruction *ir_analyze_undefined_to_anything(IrAnalyze *ira, IrInstruction *source_instr, |
| 8401 | 8365 | IrInstruction *target, TypeTableEntry *wanted_type) |
| 8402 | 8366 | { |
| ... | ... | @@ -8452,6 +8416,22 @@ static IrInstruction *ir_analyze_int_to_enum(IrAnalyze *ira, IrInstruction *sour |
| 8452 | 8416 | { |
| 8453 | 8417 | assert(wanted_type->id == TypeTableEntryIdEnum); |
| 8454 | 8418 | |
| 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 | 8435 | if (instr_is_comptime(target)) { |
| 8456 | 8436 | ConstExprValue *val = ir_resolve_const(ira, target, UndefBad); |
| 8457 | 8437 | if (!val) |
| ... | ... | @@ -8469,7 +8449,7 @@ static IrInstruction *ir_analyze_int_to_enum(IrAnalyze *ira, IrInstruction *sour |
| 8469 | 8449 | |
| 8470 | 8450 | IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope, |
| 8471 | 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 | 8453 | return result; |
| 8474 | 8454 | } |
| 8475 | 8455 | |
| ... | ... | @@ -8907,39 +8887,24 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst |
| 8907 | 8887 | } |
| 8908 | 8888 | |
| 8909 | 8889 | // explicit cast from integer to enum type with no payload |
| 8910 | if (actual_type->id == TypeTableEntryIdInt && | |
| 8911 | wanted_type->id == TypeTableEntryIdEnum && | |
| 8912 | wanted_type->data.enumeration.gen_field_count == 0) | |
| 8913 | { | |
| 8914 | ensure_complete_type(ira->codegen, wanted_type); | |
| 8915 | if (type_is_invalid(wanted_type)) | |
| 8916 | return ira->codegen->invalid_instruction; | |
| 8917 | if (actual_type == wanted_type->data.enumeration.tag_type->data.enum_tag.int_type) { | |
| 8918 | return ir_analyze_int_to_enum(ira, source_instr, value, wanted_type); | |
| 8919 | } | |
| 8920 | ir_add_error(ira, source_instr, | |
| 8921 | buf_sprintf("integer to enum cast from '%s' instead of its tag type, '%s'", | |
| 8922 | buf_ptr(&actual_type->name), | |
| 8923 | buf_ptr(&wanted_type->data.enumeration.tag_type->data.enum_tag.int_type->name))); | |
| 8924 | return ira->codegen->invalid_instruction; | |
| 8890 | if (actual_type->id == TypeTableEntryIdInt && wanted_type->id == TypeTableEntryIdEnum) { | |
| 8891 | return ir_analyze_int_to_enum(ira, source_instr, value, wanted_type); | |
| 8925 | 8892 | } |
| 8926 | 8893 | |
| 8927 | 8894 | // explicit cast from enum type with no payload to integer |
| 8928 | if (wanted_type->id == TypeTableEntryIdInt && | |
| 8929 | actual_type->id == TypeTableEntryIdEnum && | |
| 8930 | actual_type->data.enumeration.gen_field_count == 0) | |
| 8931 | { | |
| 8932 | ensure_complete_type(ira->codegen, actual_type); | |
| 8895 | if (wanted_type->id == TypeTableEntryIdInt && actual_type->id == TypeTableEntryIdEnum) { | |
| 8896 | return ir_analyze_enum_to_int(ira, source_instr, value, wanted_type); | |
| 8897 | } | |
| 8898 | ||
| 8899 | // explicit cast from union to the enum type of the union | |
| 8900 | if (actual_type->id == TypeTableEntryIdUnion && wanted_type->id == TypeTableEntryIdEnum) { | |
| 8901 | type_ensure_zero_bits_known(ira->codegen, actual_type); | |
| 8933 | 8902 | if (type_is_invalid(actual_type)) |
| 8934 | 8903 | return ira->codegen->invalid_instruction; |
| 8935 | if (wanted_type == actual_type->data.enumeration.tag_type->data.enum_tag.int_type) { | |
| 8936 | return ir_analyze_enum_to_int(ira, source_instr, value, wanted_type); | |
| 8904 | ||
| 8905 | if (actual_type->data.unionation.tag_type == wanted_type) { | |
| 8906 | return ir_analyze_union_to_tag(ira, source_instr, value, wanted_type); | |
| 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 | } |
| 8944 | 8909 | |
| 8945 | 8910 | // explicit cast from undefined to anything |
| ... | ... | @@ -9148,7 +9113,7 @@ static bool ir_resolve_atomic_order(IrAnalyze *ira, IrInstruction *value, Atomic |
| 9148 | 9113 | if (!const_val) |
| 9149 | 9114 | return false; |
| 9150 | 9115 | |
| 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 | 9117 | return true; |
| 9153 | 9118 | } |
| 9154 | 9119 | |
| ... | ... | @@ -9168,7 +9133,7 @@ static bool ir_resolve_global_linkage(IrAnalyze *ira, IrInstruction *value, Glob |
| 9168 | 9133 | if (!const_val) |
| 9169 | 9134 | return false; |
| 9170 | 9135 | |
| 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 | 9137 | return true; |
| 9173 | 9138 | } |
| 9174 | 9139 | |
| ... | ... | @@ -9188,7 +9153,7 @@ static bool ir_resolve_float_mode(IrAnalyze *ira, IrInstruction *value, FloatMod |
| 9188 | 9153 | if (!const_val) |
| 9189 | 9154 | return false; |
| 9190 | 9155 | |
| 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 | 9157 | return true; |
| 9193 | 9158 | } |
| 9194 | 9159 | |
| ... | ... | @@ -9400,7 +9365,7 @@ static TypeTableEntry *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp |
| 9400 | 9365 | break; |
| 9401 | 9366 | |
| 9402 | 9367 | case TypeTableEntryIdEnum: |
| 9403 | if (!is_equality_cmp || resolved_type->data.enumeration.gen_field_count != 0) { | |
| 9368 | if (!is_equality_cmp) { | |
| 9404 | 9369 | ir_add_error_node(ira, source_node, |
| 9405 | 9370 | buf_sprintf("operator not allowed for type '%s'", buf_ptr(&resolved_type->name))); |
| 9406 | 9371 | return ira->codegen->builtin_types.entry_invalid; |
| ... | ... | @@ -9419,9 +9384,6 @@ static TypeTableEntry *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp |
| 9419 | 9384 | buf_sprintf("operator not allowed for type '%s'", buf_ptr(&resolved_type->name))); |
| 9420 | 9385 | return ira->codegen->builtin_types.entry_invalid; |
| 9421 | 9386 | |
| 9422 | case TypeTableEntryIdEnumTag: | |
| 9423 | zig_panic("TODO implement comparison for enum tag type"); | |
| 9424 | ||
| 9425 | 9387 | case TypeTableEntryIdVar: |
| 9426 | 9388 | zig_unreachable(); |
| 9427 | 9389 | } |
| ... | ... | @@ -10170,7 +10132,6 @@ static VarClassRequired get_var_class_required(TypeTableEntry *type_entry) { |
| 10170 | 10132 | case TypeTableEntryIdVoid: |
| 10171 | 10133 | case TypeTableEntryIdPureError: |
| 10172 | 10134 | case TypeTableEntryIdFn: |
| 10173 | case TypeTableEntryIdEnumTag: | |
| 10174 | 10135 | return VarClassRequiredAny; |
| 10175 | 10136 | case TypeTableEntryIdNumLitFloat: |
| 10176 | 10137 | case TypeTableEntryIdNumLitInt: |
| ... | ... | @@ -10913,7 +10874,6 @@ static TypeTableEntry *ir_analyze_unary_prefix_op_err(IrAnalyze *ira, IrInstruct |
| 10913 | 10874 | case TypeTableEntryIdUnion: |
| 10914 | 10875 | case TypeTableEntryIdFn: |
| 10915 | 10876 | case TypeTableEntryIdBoundFn: |
| 10916 | case TypeTableEntryIdEnumTag: | |
| 10917 | 10877 | { |
| 10918 | 10878 | ConstExprValue *out_val = ir_build_const_from(ira, &un_op_instruction->base); |
| 10919 | 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 | 10961 | case TypeTableEntryIdNamespace: |
| 11002 | 10962 | case TypeTableEntryIdBlock: |
| 11003 | 10963 | case TypeTableEntryIdBoundFn: |
| 11004 | case TypeTableEntryIdEnumTag: | |
| 11005 | 10964 | case TypeTableEntryIdArgTuple: |
| 11006 | 10965 | { |
| 11007 | 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 | 11621 | field_ptr_instruction, container_ptr, container_type); |
| 11663 | 11622 | } |
| 11664 | 11623 | } else if (bare_type->id == TypeTableEntryIdEnum) { |
| 11665 | TypeEnumField *field = find_enum_type_field(bare_type, field_name); | |
| 11666 | if (field) { | |
| 11667 | ir_build_enum_field_ptr_from(&ira->new_irb, &field_ptr_instruction->base, container_ptr, field); | |
| 11668 | return get_pointer_to_type_extra(ira->codegen, field->type_entry, is_const, is_volatile, | |
| 11669 | get_abi_alignment(ira->codegen, field->type_entry), 0, 0); | |
| 11670 | } else { | |
| 11671 | return ir_analyze_container_member_access_inner(ira, bare_type, field_name, | |
| 11672 | field_ptr_instruction, container_ptr, container_type); | |
| 11673 | } | |
| 11624 | return ir_analyze_container_member_access_inner(ira, bare_type, field_name, | |
| 11625 | field_ptr_instruction, container_ptr, container_type); | |
| 11674 | 11626 | } else if (bare_type->id == TypeTableEntryIdUnion) { |
| 11675 | 11627 | TypeUnionField *field = find_union_type_field(bare_type, field_name); |
| 11676 | 11628 | if (field) { |
| ... | ... | @@ -11841,20 +11793,27 @@ static TypeTableEntry *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstru |
| 11841 | 11793 | |
| 11842 | 11794 | TypeEnumField *field = find_enum_type_field(child_type, field_name); |
| 11843 | 11795 | if (field) { |
| 11844 | if (field->type_entry->id == TypeTableEntryIdVoid) { | |
| 11845 | bool ptr_is_const = true; | |
| 11846 | bool ptr_is_volatile = false; | |
| 11847 | return ir_analyze_const_ptr(ira, &field_ptr_instruction->base, | |
| 11848 | create_const_enum_tag(child_type, &field->value), child_type, | |
| 11849 | ConstPtrMutComptimeConst, ptr_is_const, ptr_is_volatile); | |
| 11850 | } else { | |
| 11851 | bool ptr_is_const = true; | |
| 11852 | bool ptr_is_volatile = false; | |
| 11853 | return ir_analyze_const_ptr(ira, &field_ptr_instruction->base, | |
| 11854 | create_const_bigint(child_type->data.enumeration.tag_type, &field->value), | |
| 11855 | child_type->data.enumeration.tag_type, | |
| 11796 | bool ptr_is_const = true; | |
| 11797 | bool ptr_is_volatile = false; | |
| 11798 | return ir_analyze_const_ptr(ira, &field_ptr_instruction->base, | |
| 11799 | create_const_enum(child_type, &field->value), child_type, | |
| 11800 | ConstPtrMutComptimeConst, ptr_is_const, ptr_is_volatile); | |
| 11801 | } | |
| 11802 | } else if (child_type->id == TypeTableEntryIdUnion && | |
| 11803 | (child_type->data.unionation.decl_node->data.container_decl.init_arg_expr != nullptr || | |
| 11804 | child_type->data.unionation.decl_node->data.container_decl.auto_enum)) | |
| 11805 | { | |
| 11806 | ensure_complete_type(ira->codegen, child_type); | |
| 11807 | if (type_is_invalid(child_type)) | |
| 11808 | return ira->codegen->builtin_types.entry_invalid; | |
| 11809 | TypeUnionField *field = find_union_type_field(child_type, field_name); | |
| 11810 | if (field) { | |
| 11811 | TypeTableEntry *enum_type = child_type->data.unionation.tag_type; | |
| 11812 | bool ptr_is_const = true; | |
| 11813 | bool ptr_is_volatile = false; | |
| 11814 | return ir_analyze_const_ptr(ira, &field_ptr_instruction->base, | |
| 11815 | create_const_enum(enum_type, &field->enum_field->value), enum_type, | |
| 11856 | 11816 | ConstPtrMutComptimeConst, ptr_is_const, ptr_is_volatile); |
| 11857 | } | |
| 11858 | 11817 | } |
| 11859 | 11818 | } |
| 11860 | 11819 | ScopeDecls *container_scope = get_container_scope(child_type); |
| ... | ... | @@ -12163,7 +12122,6 @@ static TypeTableEntry *ir_analyze_instruction_typeof(IrAnalyze *ira, IrInstructi |
| 12163 | 12122 | case TypeTableEntryIdEnum: |
| 12164 | 12123 | case TypeTableEntryIdUnion: |
| 12165 | 12124 | case TypeTableEntryIdFn: |
| 12166 | case TypeTableEntryIdEnumTag: | |
| 12167 | 12125 | case TypeTableEntryIdArgTuple: |
| 12168 | 12126 | case TypeTableEntryIdOpaque: |
| 12169 | 12127 | { |
| ... | ... | @@ -12511,7 +12469,6 @@ static TypeTableEntry *ir_analyze_instruction_slice_type(IrAnalyze *ira, |
| 12511 | 12469 | case TypeTableEntryIdFn: |
| 12512 | 12470 | case TypeTableEntryIdNamespace: |
| 12513 | 12471 | case TypeTableEntryIdBoundFn: |
| 12514 | case TypeTableEntryIdEnumTag: | |
| 12515 | 12472 | { |
| 12516 | 12473 | type_ensure_zero_bits_known(ira->codegen, child_type); |
| 12517 | 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 | 12577 | case TypeTableEntryIdFn: |
| 12621 | 12578 | case TypeTableEntryIdNamespace: |
| 12622 | 12579 | case TypeTableEntryIdBoundFn: |
| 12623 | case TypeTableEntryIdEnumTag: | |
| 12624 | 12580 | { |
| 12625 | 12581 | TypeTableEntry *result_type = get_array_type(ira->codegen, child_type, size); |
| 12626 | 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 | 12627 | case TypeTableEntryIdPureError: |
| 12672 | 12628 | case TypeTableEntryIdEnum: |
| 12673 | 12629 | case TypeTableEntryIdUnion: |
| 12674 | case TypeTableEntryIdEnumTag: | |
| 12675 | 12630 | case TypeTableEntryIdFn: |
| 12676 | 12631 | { |
| 12677 | 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 | 12779 | } |
| 12825 | 12780 | } |
| 12826 | 12781 | |
| 12827 | static IrInstruction *ir_analyze_enum_tag(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value) { | |
| 12782 | static IrInstruction *ir_analyze_union_tag(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value) { | |
| 12828 | 12783 | if (type_is_invalid(value->value.type)) |
| 12829 | 12784 | return ira->codegen->invalid_instruction; |
| 12830 | 12785 | |
| 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 | 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 | 12793 | return ira->codegen->invalid_instruction; |
| 12835 | 12794 | } |
| 12836 | 12795 | |
| 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); | |
| 12838 | 12798 | |
| 12839 | 12799 | if (instr_is_comptime(value)) { |
| 12840 | 12800 | ConstExprValue *val = ir_resolve_const(ira, value, UndefBad); |
| ... | ... | @@ -12845,11 +12805,11 @@ static IrInstruction *ir_analyze_enum_tag(IrAnalyze *ira, IrInstruction *source_ |
| 12845 | 12805 | source_instr->scope, source_instr->source_node); |
| 12846 | 12806 | const_instruction->base.value.type = tag_type; |
| 12847 | 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 | 12809 | return &const_instruction->base; |
| 12850 | 12810 | } |
| 12851 | 12811 | |
| 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 | 12813 | result->value.type = tag_type; |
| 12854 | 12814 | return result; |
| 12855 | 12815 | } |
| ... | ... | @@ -12880,7 +12840,7 @@ static TypeTableEntry *ir_analyze_instruction_switch_br(IrAnalyze *ira, |
| 12880 | 12840 | return ir_unreach_error(ira); |
| 12881 | 12841 | |
| 12882 | 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 | 12844 | if (type_is_invalid(case_value->value.type)) |
| 12885 | 12845 | return ir_unreach_error(ira); |
| 12886 | 12846 | } |
| ... | ... | @@ -12927,7 +12887,7 @@ static TypeTableEntry *ir_analyze_instruction_switch_br(IrAnalyze *ira, |
| 12927 | 12887 | continue; |
| 12928 | 12888 | |
| 12929 | 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 | 12891 | if (type_is_invalid(new_value->value.type)) |
| 12932 | 12892 | continue; |
| 12933 | 12893 | } |
| ... | ... | @@ -13009,34 +12969,54 @@ static TypeTableEntry *ir_analyze_instruction_switch_target(IrAnalyze *ira, |
| 13009 | 12969 | |
| 13010 | 12970 | ir_build_load_ptr_from(&ira->new_irb, &switch_target_instruction->base, target_value_ptr); |
| 13011 | 12971 | return target_type; |
| 13012 | case TypeTableEntryIdEnum: | |
| 13013 | { | |
| 13014 | TypeTableEntry *tag_type = target_type->data.enumeration.tag_type; | |
| 13015 | assert(tag_type != nullptr); | |
| 13016 | if (pointee_val) { | |
| 13017 | ConstExprValue *out_val = ir_build_const_from(ira, &switch_target_instruction->base); | |
| 13018 | bigint_init_bigint(&out_val->data.x_bigint, &pointee_val->data.x_enum.tag); | |
| 13019 | return tag_type; | |
| 13020 | } | |
| 13021 | ||
| 13022 | IrInstruction *enum_value = ir_build_load_ptr(&ira->new_irb, switch_target_instruction->base.scope, | |
| 13023 | switch_target_instruction->base.source_node, target_value_ptr); | |
| 13024 | enum_value->value.type = target_type; | |
| 13025 | ir_build_enum_tag_from(&ira->new_irb, &switch_target_instruction->base, enum_value); | |
| 12972 | case TypeTableEntryIdUnion: { | |
| 12973 | if (target_type->data.unionation.gen_tag_index == SIZE_MAX) { | |
| 12974 | ErrorMsg *msg = ir_add_error(ira, target_value_ptr, | |
| 12975 | buf_sprintf("switch on union which has no attached enum")); | |
| 12976 | add_error_note(ira->codegen, msg, target_type->data.unionation.decl_node, | |
| 12977 | buf_sprintf("union declared here")); | |
| 12978 | return ira->codegen->builtin_types.entry_invalid; | |
| 12979 | } | |
| 12980 | TypeTableEntry *tag_type = target_type->data.unionation.tag_type; | |
| 12981 | assert(tag_type != nullptr); | |
| 12982 | if (pointee_val) { | |
| 12983 | ConstExprValue *out_val = ir_build_const_from(ira, &switch_target_instruction->base); | |
| 12984 | bigint_init_bigint(&out_val->data.x_enum_tag, &pointee_val->data.x_union.tag); | |
| 13026 | 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 | 13011 | case TypeTableEntryIdErrorUnion: |
| 13029 | // see https://github.com/andrewrk/zig/issues/83 | |
| 13012 | // see https://github.com/andrewrk/zig/issues/632 | |
| 13030 | 13013 | zig_panic("TODO switch on error union"); |
| 13031 | case TypeTableEntryIdEnumTag: | |
| 13032 | zig_panic("TODO switch on enum tag type"); | |
| 13033 | 13014 | case TypeTableEntryIdUnreachable: |
| 13034 | 13015 | case TypeTableEntryIdArray: |
| 13035 | 13016 | case TypeTableEntryIdStruct: |
| 13036 | 13017 | case TypeTableEntryIdUndefLit: |
| 13037 | 13018 | case TypeTableEntryIdNullLit: |
| 13038 | 13019 | case TypeTableEntryIdMaybe: |
| 13039 | case TypeTableEntryIdUnion: | |
| 13040 | 13020 | case TypeTableEntryIdBlock: |
| 13041 | 13021 | case TypeTableEntryIdBoundFn: |
| 13042 | 13022 | case TypeTableEntryIdArgTuple: |
| ... | ... | @@ -13059,19 +13039,13 @@ static TypeTableEntry *ir_analyze_instruction_switch_var(IrAnalyze *ira, IrInstr |
| 13059 | 13039 | |
| 13060 | 13040 | assert(target_value_ptr->value.type->id == TypeTableEntryIdPointer); |
| 13061 | 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 | 13043 | ConstExprValue *prong_val = ir_resolve_const(ira, prong_value, UndefBad); |
| 13064 | 13044 | if (!prong_val) |
| 13065 | 13045 | return ira->codegen->builtin_types.entry_invalid; |
| 13066 | 13046 | |
| 13067 | TypeEnumField *field; | |
| 13068 | if (prong_value->value.type->id == TypeTableEntryIdEnumTag) { | |
| 13069 | field = find_enum_field_by_tag(target_type, &prong_val->data.x_bigint); | |
| 13070 | } else if (prong_value->value.type->id == TypeTableEntryIdEnum) { | |
| 13071 | field = find_enum_field_by_tag(target_type, &prong_val->data.x_enum.tag); | |
| 13072 | } else { | |
| 13073 | zig_unreachable(); | |
| 13074 | } | |
| 13047 | assert(prong_value->value.type->id == TypeTableEntryIdEnum); | |
| 13048 | TypeUnionField *field = find_union_field_by_tag(target_type, &prong_val->data.x_enum_tag); | |
| 13075 | 13049 | |
| 13076 | 13050 | if (instr_is_comptime(target_value_ptr)) { |
| 13077 | 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 | 13056 | ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base); |
| 13083 | 13057 | out_val->data.x_ptr.special = ConstPtrSpecialRef; |
| 13084 | 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 | 13060 | return get_pointer_to_type(ira->codegen, field->type_entry, target_val_ptr->type->data.pointer.is_const); |
| 13087 | 13061 | } |
| 13088 | 13062 | |
| 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 | 13064 | return get_pointer_to_type(ira->codegen, field->type_entry, |
| 13091 | 13065 | target_value_ptr->value.type->data.pointer.is_const); |
| 13092 | 13066 | } else { |
| ... | ... | @@ -13096,10 +13070,10 @@ static TypeTableEntry *ir_analyze_instruction_switch_var(IrAnalyze *ira, IrInstr |
| 13096 | 13070 | } |
| 13097 | 13071 | } |
| 13098 | 13072 | |
| 13099 | static TypeTableEntry *ir_analyze_instruction_enum_tag(IrAnalyze *ira, IrInstructionEnumTag *enum_tag_instruction) { | |
| 13100 | IrInstruction *value = enum_tag_instruction->value->other; | |
| 13101 | IrInstruction *new_instruction = ir_analyze_enum_tag(ira, &enum_tag_instruction->base, value); | |
| 13102 | ir_link_new_instruction(new_instruction, &enum_tag_instruction->base); | |
| 13073 | static TypeTableEntry *ir_analyze_instruction_union_tag(IrAnalyze *ira, IrInstructionUnionTag *instruction) { | |
| 13074 | IrInstruction *value = instruction->value->other; | |
| 13075 | IrInstruction *new_instruction = ir_analyze_union_tag(ira, &instruction->base, value); | |
| 13076 | ir_link_new_instruction(new_instruction, &instruction->base); | |
| 13103 | 13077 | return new_instruction->value.type; |
| 13104 | 13078 | } |
| 13105 | 13079 | |
| ... | ... | @@ -13255,7 +13229,7 @@ static TypeTableEntry *ir_analyze_container_init_fields_union(IrAnalyze *ira, Ir |
| 13255 | 13229 | |
| 13256 | 13230 | ConstExprValue *out_val = ir_build_const_from(ira, instruction); |
| 13257 | 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; | |
| 13259 | 13233 | |
| 13260 | 13234 | ConstParent *parent = get_const_val_parent(ira->codegen, field_val); |
| 13261 | 13235 | if (parent != nullptr) { |
| ... | ... | @@ -13502,46 +13476,9 @@ static TypeTableEntry *ir_analyze_instruction_container_init_list(IrAnalyze *ira |
| 13502 | 13476 | buf_ptr(&container_type->name))); |
| 13503 | 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 | 13479 | } else { |
| 13543 | 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 | 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 | 13521 | eval_min_max_value(ira->codegen, target_type, out_val, is_max); |
| 13585 | 13522 | return target_type; |
| 13586 | 13523 | } |
| 13587 | case TypeTableEntryIdEnumTag: | |
| 13588 | zig_panic("TODO min/max value for enum tag type"); | |
| 13524 | case TypeTableEntryIdEnum: | |
| 13525 | zig_panic("TODO min/max value for enum type"); | |
| 13589 | 13526 | case TypeTableEntryIdVar: |
| 13590 | 13527 | case TypeTableEntryIdMetaType: |
| 13591 | 13528 | case TypeTableEntryIdUnreachable: |
| ... | ... | @@ -13599,7 +13536,6 @@ static TypeTableEntry *ir_analyze_min_max(IrAnalyze *ira, IrInstruction *source_ |
| 13599 | 13536 | case TypeTableEntryIdMaybe: |
| 13600 | 13537 | case TypeTableEntryIdErrorUnion: |
| 13601 | 13538 | case TypeTableEntryIdPureError: |
| 13602 | case TypeTableEntryIdEnum: | |
| 13603 | 13539 | case TypeTableEntryIdUnion: |
| 13604 | 13540 | case TypeTableEntryIdFn: |
| 13605 | 13541 | case TypeTableEntryIdNamespace: |
| ... | ... | @@ -13707,20 +13643,18 @@ static TypeTableEntry *ir_analyze_instruction_enum_tag_name(IrAnalyze *ira, IrIn |
| 13707 | 13643 | if (type_is_invalid(target->value.type)) |
| 13708 | 13644 | return ira->codegen->builtin_types.entry_invalid; |
| 13709 | 13645 | |
| 13710 | assert(target->value.type->id == TypeTableEntryIdEnumTag); | |
| 13646 | assert(target->value.type->id == TypeTableEntryIdEnum); | |
| 13711 | 13647 | |
| 13712 | 13648 | if (instr_is_comptime(target)) { |
| 13713 | TypeTableEntry *enum_type = target->value.type->data.enum_tag.enum_type; | |
| 13714 | uint64_t tag_value = bigint_as_unsigned(&target->value.data.x_bigint); | |
| 13715 | TypeEnumField *field = &enum_type->data.enumeration.fields[tag_value]; | |
| 13649 | TypeEnumField *field = find_enum_field_by_tag(target->value.type, &target->value.data.x_bigint); | |
| 13716 | 13650 | ConstExprValue *array_val = create_const_str_lit(ira->codegen, field->name); |
| 13717 | 13651 | ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base); |
| 13718 | 13652 | init_const_slice(ira->codegen, out_val, array_val, 0, buf_len(field->name), true); |
| 13719 | 13653 | return out_val->type; |
| 13720 | 13654 | } |
| 13721 | 13655 | |
| 13722 | if (!target->value.type->data.enum_tag.generate_name_table) { | |
| 13723 | target->value.type->data.enum_tag.generate_name_table = true; | |
| 13656 | if (!target->value.type->data.enumeration.generate_name_table) { | |
| 13657 | target->value.type->data.enumeration.generate_name_table = true; | |
| 13724 | 13658 | ira->codegen->name_table_enums.append(target->value.type); |
| 13725 | 13659 | } |
| 13726 | 13660 | |
| ... | ... | @@ -13869,7 +13803,7 @@ static TypeTableEntry *ir_analyze_instruction_type_id(IrAnalyze *ira, |
| 13869 | 13803 | TypeTableEntry *result_type = var_value->data.x_type; |
| 13870 | 13804 | |
| 13871 | 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 | 13807 | return result_type; |
| 13874 | 13808 | } |
| 13875 | 13809 | |
| ... | ... | @@ -14698,14 +14632,14 @@ static TypeTableEntry *ir_analyze_instruction_member_type(IrAnalyze *ira, IrInst |
| 14698 | 14632 | ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base); |
| 14699 | 14633 | out_val->data.x_type = field->type_entry; |
| 14700 | 14634 | return ira->codegen->builtin_types.entry_type; |
| 14701 | } else if (container_type->id == TypeTableEntryIdEnum) { | |
| 14702 | if (member_index >= container_type->data.enumeration.src_field_count) { | |
| 14635 | } else if (container_type->id == TypeTableEntryIdUnion) { | |
| 14636 | if (member_index >= container_type->data.unionation.src_field_count) { | |
| 14703 | 14637 | ir_add_error(ira, index_value, |
| 14704 | 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 | 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]; | |
| 14709 | 14643 | |
| 14710 | 14644 | ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base); |
| 14711 | 14645 | out_val->data.x_type = field->type_entry; |
| ... | ... | @@ -14749,6 +14683,18 @@ static TypeTableEntry *ir_analyze_instruction_member_name(IrAnalyze *ira, IrInst |
| 14749 | 14683 | } |
| 14750 | 14684 | TypeEnumField *field = &container_type->data.enumeration.fields[member_index]; |
| 14751 | 14685 | |
| 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 | 14698 | ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base); |
| 14753 | 14699 | init_const_str_lit(ira->codegen, out_val, field->name); |
| 14754 | 14700 | return out_val->type; |
| ... | ... | @@ -14819,7 +14765,6 @@ static TypeTableEntry *ir_analyze_instruction_align_of(IrAnalyze *ira, IrInstruc |
| 14819 | 14765 | case TypeTableEntryIdErrorUnion: |
| 14820 | 14766 | case TypeTableEntryIdPureError: |
| 14821 | 14767 | case TypeTableEntryIdEnum: |
| 14822 | case TypeTableEntryIdEnumTag: | |
| 14823 | 14768 | case TypeTableEntryIdUnion: |
| 14824 | 14769 | case TypeTableEntryIdFn: |
| 14825 | 14770 | { |
| ... | ... | @@ -15125,10 +15070,9 @@ static TypeTableEntry *ir_analyze_instruction_check_switch_prongs(IrAnalyze *ira |
| 15125 | 15070 | if (type_is_invalid(switch_type)) |
| 15126 | 15071 | return ira->codegen->builtin_types.entry_invalid; |
| 15127 | 15072 | |
| 15128 | if (switch_type->id == TypeTableEntryIdEnumTag) { | |
| 15129 | TypeTableEntry *enum_type = switch_type->data.enum_tag.enum_type; | |
| 15073 | if (switch_type->id == TypeTableEntryIdEnum) { | |
| 15130 | 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); | |
| 15132 | 15076 | |
| 15133 | 15077 | for (size_t range_i = 0; range_i < instruction->range_count; range_i += 1) { |
| 15134 | 15078 | IrInstructionCheckSwitchProngsRange *range = &instruction->ranges[range_i]; |
| ... | ... | @@ -15141,22 +15085,13 @@ static TypeTableEntry *ir_analyze_instruction_check_switch_prongs(IrAnalyze *ira |
| 15141 | 15085 | if (type_is_invalid(end_value->value.type)) |
| 15142 | 15086 | return ira->codegen->builtin_types.entry_invalid; |
| 15143 | 15087 | |
| 15088 | assert(start_value->value.type->id == TypeTableEntryIdEnum); | |
| 15144 | 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 | 15093 | BigInt end_index; |
| 15146 | if (start_value->value.type->id == TypeTableEntryIdEnumTag) { | |
| 15147 | bigint_init_bigint(&start_index, &start_value->value.data.x_bigint); | |
| 15148 | } else if (start_value->value.type->id == TypeTableEntryIdEnum) { | |
| 15149 | bigint_init_bigint(&start_index, &start_value->value.data.x_enum.tag); | |
| 15150 | } else { | |
| 15151 | zig_unreachable(); | |
| 15152 | } | |
| 15153 | if (end_value->value.type->id == TypeTableEntryIdEnumTag) { | |
| 15154 | bigint_init_bigint(&end_index, &end_value->value.data.x_bigint); | |
| 15155 | } else if (end_value->value.type->id == TypeTableEntryIdEnum) { | |
| 15156 | bigint_init_bigint(&end_index, &end_value->value.data.x_enum.tag); | |
| 15157 | } else { | |
| 15158 | zig_unreachable(); | |
| 15159 | } | |
| 15094 | bigint_init_bigint(&end_index, &end_value->value.data.x_enum_tag); | |
| 15160 | 15095 | |
| 15161 | 15096 | BigInt field_index; |
| 15162 | 15097 | bigint_init_bigint(&field_index, &start_index); |
| ... | ... | @@ -15168,10 +15103,10 @@ static TypeTableEntry *ir_analyze_instruction_check_switch_prongs(IrAnalyze *ira |
| 15168 | 15103 | auto entry = field_prev_uses.put_unique(field_index, start_value->source_node); |
| 15169 | 15104 | if (entry) { |
| 15170 | 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 | 15107 | assert(enum_field != nullptr); |
| 15173 | 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 | 15110 | buf_ptr(enum_field->name))); |
| 15176 | 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 | 15114 | } |
| 15180 | 15115 | } |
| 15181 | 15116 | if (!instruction->have_else_prong) { |
| 15182 | for (uint32_t i = 0; i < enum_type->data.enumeration.src_field_count; i += 1) { | |
| 15183 | TypeEnumField *enum_field = &enum_type->data.enumeration.fields[i]; | |
| 15117 | for (uint32_t i = 0; i < switch_type->data.enumeration.src_field_count; i += 1) { | |
| 15118 | TypeEnumField *enum_field = &switch_type->data.enumeration.fields[i]; | |
| 15184 | 15119 | |
| 15185 | 15120 | auto entry = field_prev_uses.maybe_get(enum_field->value); |
| 15186 | 15121 | if (!entry) { |
| 15187 | 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 | 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 | 15416 | zig_panic("TODO buf_write_value_bytes pure error type"); |
| 15482 | 15417 | case TypeTableEntryIdEnum: |
| 15483 | 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 | 15419 | case TypeTableEntryIdFn: |
| 15487 | 15420 | zig_panic("TODO buf_write_value_bytes fn type"); |
| 15488 | 15421 | case TypeTableEntryIdUnion: |
| ... | ... | @@ -15541,8 +15474,6 @@ static void buf_read_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue |
| 15541 | 15474 | zig_panic("TODO buf_read_value_bytes pure error type"); |
| 15542 | 15475 | case TypeTableEntryIdEnum: |
| 15543 | 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 | 15477 | case TypeTableEntryIdFn: |
| 15547 | 15478 | zig_panic("TODO buf_read_value_bytes fn type"); |
| 15548 | 15479 | case TypeTableEntryIdUnion: |
| ... | ... | @@ -15920,11 +15851,8 @@ static TypeTableEntry *ir_analyze_instruction_enum_tag_type(IrAnalyze *ira, IrIn |
| 15920 | 15851 | if (type_is_invalid(enum_type)) |
| 15921 | 15852 | return ira->codegen->builtin_types.entry_invalid; |
| 15922 | 15853 | |
| 15923 | TypeTableEntry *non_int_tag_type = enum_type->data.enumeration.tag_type; | |
| 15924 | assert(non_int_tag_type->id == TypeTableEntryIdEnumTag); | |
| 15925 | ||
| 15926 | 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 | 15856 | return ira->codegen->builtin_types.entry_type; |
| 15929 | 15857 | } |
| 15930 | 15858 | |
| ... | ... | @@ -15938,9 +15866,7 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi |
| 15938 | 15866 | case IrInstructionIdStructInit: |
| 15939 | 15867 | case IrInstructionIdUnionInit: |
| 15940 | 15868 | case IrInstructionIdStructFieldPtr: |
| 15941 | case IrInstructionIdEnumFieldPtr: | |
| 15942 | 15869 | case IrInstructionIdUnionFieldPtr: |
| 15943 | case IrInstructionIdInitEnum: | |
| 15944 | 15870 | case IrInstructionIdMaybeWrap: |
| 15945 | 15871 | case IrInstructionIdErrWrapCode: |
| 15946 | 15872 | case IrInstructionIdErrWrapPayload: |
| ... | ... | @@ -16012,8 +15938,8 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi |
| 16012 | 15938 | return ir_analyze_instruction_switch_target(ira, (IrInstructionSwitchTarget *)instruction); |
| 16013 | 15939 | case IrInstructionIdSwitchVar: |
| 16014 | 15940 | return ir_analyze_instruction_switch_var(ira, (IrInstructionSwitchVar *)instruction); |
| 16015 | case IrInstructionIdEnumTag: | |
| 16016 | return ir_analyze_instruction_enum_tag(ira, (IrInstructionEnumTag *)instruction); | |
| 15941 | case IrInstructionIdUnionTag: | |
| 15942 | return ir_analyze_instruction_union_tag(ira, (IrInstructionUnionTag *)instruction); | |
| 16017 | 15943 | case IrInstructionIdImport: |
| 16018 | 15944 | return ir_analyze_instruction_import(ira, (IrInstructionImport *)instruction); |
| 16019 | 15945 | case IrInstructionIdArrayLen: |
| ... | ... | @@ -16260,7 +16186,6 @@ bool ir_has_side_effects(IrInstruction *instruction) { |
| 16260 | 16186 | case IrInstructionIdPtrTypeChild: |
| 16261 | 16187 | case IrInstructionIdArrayLen: |
| 16262 | 16188 | case IrInstructionIdStructFieldPtr: |
| 16263 | case IrInstructionIdEnumFieldPtr: | |
| 16264 | 16189 | case IrInstructionIdUnionFieldPtr: |
| 16265 | 16190 | case IrInstructionIdArrayType: |
| 16266 | 16191 | case IrInstructionIdSliceType: |
| ... | ... | @@ -16271,7 +16196,7 @@ bool ir_has_side_effects(IrInstruction *instruction) { |
| 16271 | 16196 | case IrInstructionIdCtz: |
| 16272 | 16197 | case IrInstructionIdSwitchVar: |
| 16273 | 16198 | case IrInstructionIdSwitchTarget: |
| 16274 | case IrInstructionIdEnumTag: | |
| 16199 | case IrInstructionIdUnionTag: | |
| 16275 | 16200 | case IrInstructionIdRef: |
| 16276 | 16201 | case IrInstructionIdMinValue: |
| 16277 | 16202 | case IrInstructionIdMaxValue: |
| ... | ... | @@ -16293,7 +16218,6 @@ bool ir_has_side_effects(IrInstruction *instruction) { |
| 16293 | 16218 | case IrInstructionIdErrWrapPayload: |
| 16294 | 16219 | case IrInstructionIdFnProto: |
| 16295 | 16220 | case IrInstructionIdTestComptime: |
| 16296 | case IrInstructionIdInitEnum: | |
| 16297 | 16221 | case IrInstructionIdPtrCast: |
| 16298 | 16222 | case IrInstructionIdBitCast: |
| 16299 | 16223 | case IrInstructionIdWidenOrShorten: |
src/ir_print.cpp+6-25| ... | ... | @@ -291,7 +291,7 @@ static void ir_print_struct_init(IrPrint *irp, IrInstructionStructInit *instruct |
| 291 | 291 | } |
| 292 | 292 | |
| 293 | 293 | static 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; | |
| 295 | 295 | |
| 296 | 296 | fprintf(irp->f, "%s {", buf_ptr(&instruction->union_type->name)); |
| 297 | 297 | fprintf(irp->f, ".%s = ", buf_ptr(field_name)); |
| ... | ... | @@ -361,17 +361,10 @@ static void ir_print_struct_field_ptr(IrPrint *irp, IrInstructionStructFieldPtr |
| 361 | 361 | fprintf(irp->f, ")"); |
| 362 | 362 | } |
| 363 | 363 | |
| 364 | static 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 | ||
| 371 | 364 | static void ir_print_union_field_ptr(IrPrint *irp, IrInstructionUnionFieldPtr *instruction) { |
| 372 | 365 | fprintf(irp->f, "@UnionFieldPtr(&"); |
| 373 | 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 | 368 | fprintf(irp->f, ")"); |
| 376 | 369 | } |
| 377 | 370 | |
| ... | ... | @@ -509,8 +502,8 @@ static void ir_print_switch_target(IrPrint *irp, IrInstructionSwitchTarget *inst |
| 509 | 502 | ir_print_other_instruction(irp, instruction->target_value_ptr); |
| 510 | 503 | } |
| 511 | 504 | |
| 512 | static void ir_print_enum_tag(IrPrint *irp, IrInstructionEnumTag *instruction) { | |
| 513 | fprintf(irp->f, "enumtag "); | |
| 505 | static void ir_print_union_tag(IrPrint *irp, IrInstructionUnionTag *instruction) { | |
| 506 | fprintf(irp->f, "uniontag "); | |
| 514 | 507 | ir_print_other_instruction(irp, instruction->value); |
| 515 | 508 | } |
| 516 | 509 | |
| ... | ... | @@ -799,12 +792,6 @@ static void ir_print_test_comptime(IrPrint *irp, IrInstructionTestComptime *inst |
| 799 | 792 | fprintf(irp->f, ")"); |
| 800 | 793 | } |
| 801 | 794 | |
| 802 | static 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 | ||
| 808 | 795 | static void ir_print_ptr_cast(IrPrint *irp, IrInstructionPtrCast *instruction) { |
| 809 | 796 | fprintf(irp->f, "@ptrCast("); |
| 810 | 797 | if (instruction->dest_type) { |
| ... | ... | @@ -1078,9 +1065,6 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) { |
| 1078 | 1065 | case IrInstructionIdStructFieldPtr: |
| 1079 | 1066 | ir_print_struct_field_ptr(irp, (IrInstructionStructFieldPtr *)instruction); |
| 1080 | 1067 | break; |
| 1081 | case IrInstructionIdEnumFieldPtr: | |
| 1082 | ir_print_enum_field_ptr(irp, (IrInstructionEnumFieldPtr *)instruction); | |
| 1083 | break; | |
| 1084 | 1068 | case IrInstructionIdUnionFieldPtr: |
| 1085 | 1069 | ir_print_union_field_ptr(irp, (IrInstructionUnionFieldPtr *)instruction); |
| 1086 | 1070 | break; |
| ... | ... | @@ -1123,8 +1107,8 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) { |
| 1123 | 1107 | case IrInstructionIdSwitchTarget: |
| 1124 | 1108 | ir_print_switch_target(irp, (IrInstructionSwitchTarget *)instruction); |
| 1125 | 1109 | break; |
| 1126 | case IrInstructionIdEnumTag: | |
| 1127 | ir_print_enum_tag(irp, (IrInstructionEnumTag *)instruction); | |
| 1110 | case IrInstructionIdUnionTag: | |
| 1111 | ir_print_union_tag(irp, (IrInstructionUnionTag *)instruction); | |
| 1128 | 1112 | break; |
| 1129 | 1113 | case IrInstructionIdImport: |
| 1130 | 1114 | ir_print_import(irp, (IrInstructionImport *)instruction); |
| ... | ... | @@ -1237,9 +1221,6 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) { |
| 1237 | 1221 | case IrInstructionIdTestComptime: |
| 1238 | 1222 | ir_print_test_comptime(irp, (IrInstructionTestComptime *)instruction); |
| 1239 | 1223 | break; |
| 1240 | case IrInstructionIdInitEnum: | |
| 1241 | ir_print_init_enum(irp, (IrInstructionInitEnum *)instruction); | |
| 1242 | break; | |
| 1243 | 1224 | case IrInstructionIdPtrCast: |
| 1244 | 1225 | ir_print_ptr_cast(irp, (IrInstructionPtrCast *)instruction); |
| 1245 | 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 | 2377 | } |
| 2378 | 2378 | |
| 2379 | 2379 | /* |
| 2380 | ContainerDecl = option("extern" | "packed") ("struct" | "union" | ("enum" option(GroupedExpression))) "{" many(ContainerMember) "}" | |
| 2380 | ContainerDecl = option("extern" | "packed") | |
| 2381 | ("struct" option(GroupedExpression) | "union" option("enum" option(GroupedExpression) | GroupedExpression) | ("enum" option(GroupedExpression))) | |
| 2382 | "{" many(ContainerMember) "}" | |
| 2381 | 2383 | ContainerMember = (ContainerField | FnDef | GlobalVarDecl) |
| 2382 | 2384 | ContainerField = Symbol option(":" PrefixOpExpression option("=" PrefixOpExpression "," |
| 2383 | 2385 | */ |
| ... | ... | @@ -2414,7 +2416,28 @@ static AstNode *ast_parse_container_decl(ParseContext *pc, size_t *token_index, |
| 2414 | 2416 | AstNode *node = ast_create_node(pc, NodeTypeContainerDecl, first_token); |
| 2415 | 2417 | node->data.container_decl.layout = layout; |
| 2416 | 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 | } | |
| 2418 | 2441 | |
| 2419 | 2442 | ast_eat_token(pc, token_index, TokenIdLBrace); |
| 2420 | 2443 | |
| ... | ... | @@ -2461,8 +2484,6 @@ static AstNode *ast_parse_container_decl(ParseContext *pc, size_t *token_index, |
| 2461 | 2484 | if (colon_token->id == TokenIdColon) { |
| 2462 | 2485 | *token_index += 1; |
| 2463 | 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 | 2488 | Token *eq_token = &pc->tokens->at(*token_index); |
| 2468 | 2489 | if (eq_token->id == TokenIdEq) { |
std/build.zig+21-21| ... | ... | @@ -69,8 +69,8 @@ pub const Builder = struct { |
| 69 | 69 | used: bool, |
| 70 | 70 | }; |
| 71 | 71 | |
| 72 | const UserValue = enum { | |
| 73 | Flag, | |
| 72 | const UserValue = union(enum) { | |
| 73 | Flag: void, | |
| 74 | 74 | Scalar: []const u8, |
| 75 | 75 | List: ArrayList([]const u8), |
| 76 | 76 | }; |
| ... | ... | @@ -450,7 +450,7 @@ pub const Builder = struct { |
| 450 | 450 | pub fn addUserInputOption(self: &Builder, name: []const u8, value: []const u8) -> bool { |
| 451 | 451 | if (%%self.user_input_options.put(name, UserInputOption { |
| 452 | 452 | .name = name, |
| 453 | .value = UserValue.Scalar { value }, | |
| 453 | .value = UserValue { .Scalar = value }, | |
| 454 | 454 | .used = false, |
| 455 | 455 | })) |*prev_value| { |
| 456 | 456 | // option already exists |
| ... | ... | @@ -462,7 +462,7 @@ pub const Builder = struct { |
| 462 | 462 | %%list.append(value); |
| 463 | 463 | _ = %%self.user_input_options.put(name, UserInputOption { |
| 464 | 464 | .name = name, |
| 465 | .value = UserValue.List { list }, | |
| 465 | .value = UserValue { .List = list }, | |
| 466 | 466 | .used = false, |
| 467 | 467 | }); |
| 468 | 468 | }, |
| ... | ... | @@ -471,7 +471,7 @@ pub const Builder = struct { |
| 471 | 471 | %%list.append(value); |
| 472 | 472 | _ = %%self.user_input_options.put(name, UserInputOption { |
| 473 | 473 | .name = name, |
| 474 | .value = UserValue.List { *list }, | |
| 474 | .value = UserValue { .List = *list }, | |
| 475 | 475 | .used = false, |
| 476 | 476 | }); |
| 477 | 477 | }, |
| ... | ... | @@ -487,7 +487,7 @@ pub const Builder = struct { |
| 487 | 487 | pub fn addUserInputFlag(self: &Builder, name: []const u8) -> bool { |
| 488 | 488 | if (%%self.user_input_options.put(name, UserInputOption { |
| 489 | 489 | .name = name, |
| 490 | .value = UserValue.Flag, | |
| 490 | .value = UserValue {.Flag = {} }, | |
| 491 | 491 | .used = false, |
| 492 | 492 | })) |*prev_value| { |
| 493 | 493 | switch (prev_value.value) { |
| ... | ... | @@ -685,8 +685,8 @@ const CrossTarget = struct { |
| 685 | 685 | environ: builtin.Environ, |
| 686 | 686 | }; |
| 687 | 687 | |
| 688 | const Target = enum { | |
| 689 | Native, | |
| 688 | const Target = union(enum) { | |
| 689 | Native: void, | |
| 690 | 690 | Cross: CrossTarget, |
| 691 | 691 | |
| 692 | 692 | pub fn oFileExt(self: &const Target) -> []const u8 { |
| ... | ... | @@ -844,7 +844,7 @@ pub const LibExeObjStep = struct { |
| 844 | 844 | .kind = kind, |
| 845 | 845 | .root_src = root_src, |
| 846 | 846 | .name = name, |
| 847 | .target = Target.Native, | |
| 847 | .target = Target { .Native = {} }, | |
| 848 | 848 | .linker_script = null, |
| 849 | 849 | .link_libs = BufSet.init(builder.allocator), |
| 850 | 850 | .frameworks = BufSet.init(builder.allocator), |
| ... | ... | @@ -879,7 +879,7 @@ pub const LibExeObjStep = struct { |
| 879 | 879 | .kind = kind, |
| 880 | 880 | .version = *version, |
| 881 | 881 | .static = static, |
| 882 | .target = Target.Native, | |
| 882 | .target = Target { .Native = {} }, | |
| 883 | 883 | .cflags = ArrayList([]const u8).init(builder.allocator), |
| 884 | 884 | .source_files = ArrayList([]const u8).init(builder.allocator), |
| 885 | 885 | .object_files = ArrayList([]const u8).init(builder.allocator), |
| ... | ... | @@ -948,8 +948,8 @@ pub const LibExeObjStep = struct { |
| 948 | 948 | pub fn setTarget(self: &LibExeObjStep, target_arch: builtin.Arch, target_os: builtin.Os, |
| 949 | 949 | target_environ: builtin.Environ) |
| 950 | 950 | { |
| 951 | self.target = Target.Cross { | |
| 952 | CrossTarget { | |
| 951 | self.target = Target { | |
| 952 | .Cross = CrossTarget { | |
| 953 | 953 | .arch = target_arch, |
| 954 | 954 | .os = target_os, |
| 955 | 955 | .environ = target_environ, |
| ... | ... | @@ -1186,13 +1186,13 @@ pub const LibExeObjStep = struct { |
| 1186 | 1186 | Target.Native => {}, |
| 1187 | 1187 | Target.Cross => |cross_target| { |
| 1188 | 1188 | %%zig_args.append("--target-arch"); |
| 1189 | %%zig_args.append(@enumTagName(cross_target.arch)); | |
| 1189 | %%zig_args.append(@tagName(cross_target.arch)); | |
| 1190 | 1190 | |
| 1191 | 1191 | %%zig_args.append("--target-os"); |
| 1192 | %%zig_args.append(@enumTagName(cross_target.os)); | |
| 1192 | %%zig_args.append(@tagName(cross_target.os)); | |
| 1193 | 1193 | |
| 1194 | 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 | } |
| 1198 | 1198 | |
| ... | ... | @@ -1553,7 +1553,7 @@ pub const TestStep = struct { |
| 1553 | 1553 | .name_prefix = "", |
| 1554 | 1554 | .filter = null, |
| 1555 | 1555 | .link_libs = BufSet.init(builder.allocator), |
| 1556 | .target = Target.Native, | |
| 1556 | .target = Target { .Native = {} }, | |
| 1557 | 1557 | .exec_cmd_args = null, |
| 1558 | 1558 | } |
| 1559 | 1559 | } |
| ... | ... | @@ -1581,8 +1581,8 @@ pub const TestStep = struct { |
| 1581 | 1581 | pub fn setTarget(self: &TestStep, target_arch: builtin.Arch, target_os: builtin.Os, |
| 1582 | 1582 | target_environ: builtin.Environ) |
| 1583 | 1583 | { |
| 1584 | self.target = Target.Cross { | |
| 1585 | CrossTarget { | |
| 1584 | self.target = Target { | |
| 1585 | .Cross = CrossTarget { | |
| 1586 | 1586 | .arch = target_arch, |
| 1587 | 1587 | .os = target_os, |
| 1588 | 1588 | .environ = target_environ, |
| ... | ... | @@ -1620,13 +1620,13 @@ pub const TestStep = struct { |
| 1620 | 1620 | Target.Native => {}, |
| 1621 | 1621 | Target.Cross => |cross_target| { |
| 1622 | 1622 | %%zig_args.append("--target-arch"); |
| 1623 | %%zig_args.append(@enumTagName(cross_target.arch)); | |
| 1623 | %%zig_args.append(@tagName(cross_target.arch)); | |
| 1624 | 1624 | |
| 1625 | 1625 | %%zig_args.append("--target-os"); |
| 1626 | %%zig_args.append(@enumTagName(cross_target.os)); | |
| 1626 | %%zig_args.append(@tagName(cross_target.os)); | |
| 1627 | 1627 | |
| 1628 | 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 | } |
| 1632 | 1632 |
std/debug.zig+13-15| ... | ... | @@ -280,7 +280,7 @@ const AbbrevAttr = struct { |
| 280 | 280 | form_id: u64, |
| 281 | 281 | }; |
| 282 | 282 | |
| 283 | const FormValue = enum { | |
| 283 | const FormValue = union(enum) { | |
| 284 | 284 | Address: u64, |
| 285 | 285 | Block: []u8, |
| 286 | 286 | Const: Constant, |
| ... | ... | @@ -475,7 +475,7 @@ fn readAllocBytes(allocator: &mem.Allocator, in_stream: &io.InStream, size: usiz |
| 475 | 475 | |
| 476 | 476 | fn parseFormValueBlockLen(allocator: &mem.Allocator, in_stream: &io.InStream, size: usize) -> %FormValue { |
| 477 | 477 | const buf = %return readAllocBytes(allocator, in_stream, size); |
| 478 | return FormValue.Block { buf }; | |
| 478 | return FormValue { .Block = buf }; | |
| 479 | 479 | } |
| 480 | 480 | |
| 481 | 481 | fn 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 | 484 | } |
| 485 | 485 | |
| 486 | 486 | fn parseFormValueConstant(allocator: &mem.Allocator, in_stream: &io.InStream, signed: bool, size: usize) -> %FormValue { |
| 487 | FormValue.Const { Constant { | |
| 487 | FormValue { .Const = Constant { | |
| 488 | 488 | .signed = signed, |
| 489 | 489 | .payload = %return readAllocBytes(allocator, in_stream, size), |
| 490 | 490 | }} |
| ... | ... | @@ -510,7 +510,7 @@ fn parseFormValueTargetAddrSize(in_stream: &io.InStream) -> %u64 { |
| 510 | 510 | |
| 511 | 511 | fn parseFormValueRefLen(allocator: &mem.Allocator, in_stream: &io.InStream, size: usize) -> %FormValue { |
| 512 | 512 | const buf = %return readAllocBytes(allocator, in_stream, size); |
| 513 | return FormValue.Ref { buf }; | |
| 513 | return FormValue { .Ref = buf }; | |
| 514 | 514 | } |
| 515 | 515 | |
| 516 | 516 | fn 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 | 520 | |
| 521 | 521 | fn parseFormValue(allocator: &mem.Allocator, in_stream: &io.InStream, form_id: u64, is_64: bool) -> %FormValue { |
| 522 | 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 | 524 | DW.FORM_block1 => parseFormValueBlock(allocator, in_stream, 1), |
| 525 | 525 | DW.FORM_block2 => parseFormValueBlock(allocator, in_stream, 2), |
| 526 | 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 | 540 | DW.FORM_exprloc => { |
| 541 | 541 | const size = %return readULeb128(in_stream); |
| 542 | 542 | const buf = %return readAllocBytes(allocator, in_stream, size); |
| 543 | return FormValue.ExprLoc { buf }; | |
| 544 | }, | |
| 545 | DW.FORM_flag => FormValue.Flag { (%return in_stream.readByte()) != 0 }, | |
| 546 | DW.FORM_flag_present => FormValue.Flag { true }, | |
| 547 | DW.FORM_sec_offset => FormValue.SecOffset { | |
| 548 | %return parseFormValueDwarfOffsetSize(in_stream, is_64) | |
| 543 | return FormValue { .ExprLoc = buf }; | |
| 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) }, | |
| 550 | 548 | |
| 551 | 549 | DW.FORM_ref1 => parseFormValueRef(allocator, in_stream, u8), |
| 552 | 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 | 555 | parseFormValueRefLen(allocator, in_stream, ref_len) |
| 558 | 556 | }, |
| 559 | 557 | |
| 560 | DW.FORM_ref_addr => FormValue.RefAddr { %return parseFormValueDwarfOffsetSize(in_stream, is_64) }, | |
| 561 | DW.FORM_ref_sig8 => FormValue.RefSig8 { %return in_stream.readIntLe(u64) }, | |
| 558 | DW.FORM_ref_addr => FormValue { .RefAddr = %return parseFormValueDwarfOffsetSize(in_stream, is_64) }, | |
| 559 | DW.FORM_ref_sig8 => FormValue { .RefSig8 = %return in_stream.readIntLe(u64) }, | |
| 562 | 560 | |
| 563 | DW.FORM_string => FormValue.String { %return readStringRaw(allocator, in_stream) }, | |
| 564 | DW.FORM_strp => FormValue.StrPtr { %return parseFormValueDwarfOffsetSize(in_stream, is_64) }, | |
| 561 | DW.FORM_string => FormValue { .String = %return readStringRaw(allocator, in_stream) }, | |
| 562 | DW.FORM_strp => FormValue { .StrPtr = %return parseFormValueDwarfOffsetSize(in_stream, is_64) }, | |
| 565 | 563 | DW.FORM_indirect => { |
| 566 | 564 | const child_form_id = %return readULeb128(in_stream); |
| 567 | 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 | 58 | err_pipe: if (is_windows) void else [2]i32, |
| 59 | 59 | llnode: if (is_windows) void else LinkedList(&ChildProcess).Node, |
| 60 | 60 | |
| 61 | pub const Term = enum { | |
| 61 | pub const Term = union(enum) { | |
| 62 | 62 | Exited: i32, |
| 63 | 63 | Signal: i32, |
| 64 | 64 | Stopped: i32, |
| ... | ... | @@ -281,13 +281,13 @@ pub const ChildProcess = struct { |
| 281 | 281 | |
| 282 | 282 | fn statusToTerm(status: i32) -> Term { |
| 283 | 283 | return if (posix.WIFEXITED(status)) { |
| 284 | Term.Exited { posix.WEXITSTATUS(status) } | |
| 284 | Term { .Exited = posix.WEXITSTATUS(status) } | |
| 285 | 285 | } else if (posix.WIFSIGNALED(status)) { |
| 286 | Term.Signal { posix.WTERMSIG(status) } | |
| 286 | Term { .Signal = posix.WTERMSIG(status) } | |
| 287 | 287 | } else if (posix.WIFSTOPPED(status)) { |
| 288 | Term.Stopped { posix.WSTOPSIG(status) } | |
| 288 | Term { .Stopped = posix.WSTOPSIG(status) } | |
| 289 | 289 | } else { |
| 290 | Term.Unknown { status } | |
| 290 | Term { .Unknown = status } | |
| 291 | 291 | }; |
| 292 | 292 | } |
| 293 | 293 |
std/os/path.zig+1-1| ... | ... | @@ -1016,7 +1016,7 @@ pub fn real(allocator: &Allocator, pathname: []const u8) -> %[]u8 { |
| 1016 | 1016 | |
| 1017 | 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 | } |
| 1022 | 1022 |
test/cases/bugs/394.zig+2-2| ... | ... | @@ -1,9 +1,9 @@ |
| 1 | const E = enum { A: [9]u8, B: u64, }; | |
| 1 | const E = union(enum) { A: [9]u8, B: u64, }; | |
| 2 | 2 | const S = struct { x: u8, y: E, }; |
| 3 | 3 | |
| 4 | 4 | const assert = @import("std").debug.assert; |
| 5 | 5 | |
| 6 | 6 | test "bug 394 fixed" { |
| 7 | const x = S { .x = 3, .y = E.B {1} }; | |
| 7 | const x = S { .x = 3, .y = E {.B = 1 } }; | |
| 8 | 8 | assert(x.x == 3); |
| 9 | 9 | } |
test/cases/enum.zig+12-12| ... | ... | @@ -2,8 +2,8 @@ const assert = @import("std").debug.assert; |
| 2 | 2 | const mem = @import("std").mem; |
| 3 | 3 | |
| 4 | 4 | test "enum type" { |
| 5 | const foo1 = Foo.One {13}; | |
| 6 | const foo2 = Foo.Two { Point { .x = 1234, .y = 5678, }}; | |
| 5 | const foo1 = Foo{ .One = 13}; | |
| 6 | const foo2 = Foo{. Two = Point { .x = 1234, .y = 5678, }}; | |
| 7 | 7 | const bar = Bar.B; |
| 8 | 8 | |
| 9 | 9 | assert(bar == Bar.B); |
| ... | ... | @@ -24,12 +24,12 @@ const Point = struct { |
| 24 | 24 | x: u64, |
| 25 | 25 | y: u64, |
| 26 | 26 | }; |
| 27 | const Foo = enum { | |
| 27 | const Foo = union(enum) { | |
| 28 | 28 | One: i32, |
| 29 | 29 | Two: Point, |
| 30 | 30 | Three: void, |
| 31 | 31 | }; |
| 32 | const FooNoVoid = enum { | |
| 32 | const FooNoVoid = union(enum) { | |
| 33 | 33 | One: i32, |
| 34 | 34 | Two: Point, |
| 35 | 35 | }; |
| ... | ... | @@ -41,13 +41,13 @@ const Bar = enum { |
| 41 | 41 | }; |
| 42 | 42 | |
| 43 | 43 | fn returnAnInt(x: i32) -> Foo { |
| 44 | Foo.One { x } | |
| 44 | Foo { .One = x } | |
| 45 | 45 | } |
| 46 | 46 | |
| 47 | 47 | |
| 48 | 48 | test "constant enum with payload" { |
| 49 | var empty = AnEnumWithPayload.Empty; | |
| 50 | var full = AnEnumWithPayload.Full {13}; | |
| 49 | var empty = AnEnumWithPayload {.Empty = {}}; | |
| 50 | var full = AnEnumWithPayload {.Full = 13}; | |
| 51 | 51 | shouldBeEmpty(empty); |
| 52 | 52 | shouldBeNotEmpty(full); |
| 53 | 53 | } |
| ... | ... | @@ -66,8 +66,8 @@ fn shouldBeNotEmpty(x: &const AnEnumWithPayload) { |
| 66 | 66 | } |
| 67 | 67 | } |
| 68 | 68 | |
| 69 | const AnEnumWithPayload = enum { | |
| 70 | Empty, | |
| 69 | const AnEnumWithPayload = union(enum) { | |
| 70 | Empty: void, | |
| 71 | 71 | Full: i32, |
| 72 | 72 | }; |
| 73 | 73 | |
| ... | ... | @@ -109,13 +109,13 @@ const IntToEnumNumber = enum { |
| 109 | 109 | }; |
| 110 | 110 | |
| 111 | 111 | |
| 112 | test "@enumTagName" { | |
| 112 | test "@tagName" { | |
| 113 | 113 | assert(mem.eql(u8, testEnumTagNameBare(BareNumber.Three), "Three")); |
| 114 | 114 | comptime assert(mem.eql(u8, testEnumTagNameBare(BareNumber.Three), "Three")); |
| 115 | 115 | } |
| 116 | 116 | |
| 117 | 117 | fn testEnumTagNameBare(n: BareNumber) -> []const u8 { |
| 118 | return @enumTagName(n); | |
| 118 | return @tagName(n); | |
| 119 | 119 | } |
| 120 | 120 | |
| 121 | 121 | const BareNumber = enum { |
| ... | ... | @@ -132,7 +132,7 @@ test "enum alignment" { |
| 132 | 132 | } |
| 133 | 133 | } |
| 134 | 134 | |
| 135 | const AlignTestEnum = enum { | |
| 135 | const AlignTestEnum = union(enum) { | |
| 136 | 136 | A: [9]u8, |
| 137 | 137 | B: u64, |
| 138 | 138 | }; |
test/cases/enum_with_members.zig+3-3| ... | ... | @@ -2,7 +2,7 @@ const assert = @import("std").debug.assert; |
| 2 | 2 | const mem = @import("std").mem; |
| 3 | 3 | const fmt = @import("std").fmt; |
| 4 | 4 | |
| 5 | const ET = enum { | |
| 5 | const ET = union(enum) { | |
| 6 | 6 | SINT: i32, |
| 7 | 7 | UINT: u32, |
| 8 | 8 | |
| ... | ... | @@ -15,8 +15,8 @@ const ET = enum { |
| 15 | 15 | }; |
| 16 | 16 | |
| 17 | 17 | test "enum with members" { |
| 18 | const a = ET.SINT { -42 }; | |
| 19 | const b = ET.UINT { 42 }; | |
| 18 | const a = ET { .SINT = -42 }; | |
| 19 | const b = ET { .UINT = 42 }; | |
| 20 | 20 | var buf: [20]u8 = undefined; |
| 21 | 21 | |
| 22 | 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 | 324 | test3_1(test3_foo); |
| 325 | 325 | test3_2(test3_bar); |
| 326 | 326 | } |
| 327 | const Test3Foo = enum { | |
| 328 | One, | |
| 327 | const Test3Foo = union(enum) { | |
| 328 | One: void, | |
| 329 | 329 | Two: f32, |
| 330 | 330 | Three: Test3Point, |
| 331 | 331 | }; |
| ... | ... | @@ -333,8 +333,8 @@ const Test3Point = struct { |
| 333 | 333 | x: i32, |
| 334 | 334 | y: i32, |
| 335 | 335 | }; |
| 336 | const test3_foo = Test3Foo.Three{Test3Point {.x = 3, .y = 4}}; | |
| 337 | const test3_bar = Test3Foo.Two{13}; | |
| 336 | const test3_foo = Test3Foo { .Three = Test3Point {.x = 3, .y = 4}}; | |
| 337 | const test3_bar = Test3Foo { .Two = 13}; | |
| 338 | 338 | fn test3_1(f: &const Test3Foo) { |
| 339 | 339 | switch (*f) { |
| 340 | 340 | Test3Foo.Three => |pt| { |
| ... | ... | @@ -449,7 +449,8 @@ fn testArray2DConstDoublePtr(ptr: &const f32) { |
| 449 | 449 | const Tid = builtin.TypeId; |
| 450 | 450 | const AStruct = struct { x: i32, }; |
| 451 | 451 | const AnEnum = enum { One, Two, }; |
| 452 | const AnEnumWithPayload = enum { One: i32, Two, }; | |
| 452 | const AUnionEnum = union(enum) { One: i32, Two: void, }; | |
| 453 | const AUnion = union { One: void, Two: void }; | |
| 453 | 454 | |
| 454 | 455 | test "@typeId" { |
| 455 | 456 | comptime { |
| ... | ... | @@ -474,8 +475,9 @@ test "@typeId" { |
| 474 | 475 | assert(@typeId(%i32) == Tid.ErrorUnion); |
| 475 | 476 | assert(@typeId(error) == Tid.Error); |
| 476 | 477 | assert(@typeId(AnEnum) == Tid.Enum); |
| 477 | assert(@typeId(@typeOf(AnEnumWithPayload.One)) == Tid.EnumTag); | |
| 478 | // TODO union | |
| 478 | assert(@typeId(@typeOf(AUnionEnum.One)) == Tid.Enum); | |
| 479 | assert(@typeId(AUnionEnum) == Tid.Union); | |
| 480 | assert(@typeId(AUnion) == Tid.Union); | |
| 479 | 481 | assert(@typeId(fn()) == Tid.Fn); |
| 480 | 482 | assert(@typeId(@typeOf(builtin)) == Tid.Namespace); |
| 481 | 483 | assert(@typeId(@typeOf({this})) == Tid.Block); |
test/cases/reflection.zig+2-2| ... | ... | @@ -62,8 +62,8 @@ const Foo = struct { |
| 62 | 62 | three: void, |
| 63 | 63 | }; |
| 64 | 64 | |
| 65 | const Bar = enum { | |
| 66 | One, | |
| 65 | const Bar = union(enum) { | |
| 66 | One: void, | |
| 67 | 67 | Two: i32, |
| 68 | 68 | Three: bool, |
| 69 | 69 | Four: f64, |
test/cases/switch.zig+8-8| ... | ... | @@ -83,14 +83,14 @@ const SwitchStatmentFoo = enum { |
| 83 | 83 | |
| 84 | 84 | |
| 85 | 85 | test "switch prong with variable" { |
| 86 | switchProngWithVarFn(SwitchProngWithVarEnum.One {13}); | |
| 87 | switchProngWithVarFn(SwitchProngWithVarEnum.Two {13.0}); | |
| 88 | switchProngWithVarFn(SwitchProngWithVarEnum.Meh); | |
| 86 | switchProngWithVarFn(SwitchProngWithVarEnum { .One = 13}); | |
| 87 | switchProngWithVarFn(SwitchProngWithVarEnum { .Two = 13.0}); | |
| 88 | switchProngWithVarFn(SwitchProngWithVarEnum { .Meh = {}}); | |
| 89 | 89 | } |
| 90 | const SwitchProngWithVarEnum = enum { | |
| 90 | const SwitchProngWithVarEnum = union(enum) { | |
| 91 | 91 | One: i32, |
| 92 | 92 | Two: f32, |
| 93 | Meh, | |
| 93 | Meh: void, | |
| 94 | 94 | }; |
| 95 | 95 | fn switchProngWithVarFn(a: &const SwitchProngWithVarEnum) { |
| 96 | 96 | switch(*a) { |
| ... | ... | @@ -112,7 +112,7 @@ test "switch on enum using pointer capture" { |
| 112 | 112 | } |
| 113 | 113 | |
| 114 | 114 | fn testSwitchEnumPtrCapture() { |
| 115 | var value = SwitchProngWithVarEnum.One { 1234 }; | |
| 115 | var value = SwitchProngWithVarEnum { .One = 1234 }; | |
| 116 | 116 | switch (value) { |
| 117 | 117 | SwitchProngWithVarEnum.One => |*x| *x += 1, |
| 118 | 118 | else => unreachable, |
| ... | ... | @@ -136,13 +136,13 @@ fn returnsFive() -> i32 { |
| 136 | 136 | } |
| 137 | 137 | |
| 138 | 138 | |
| 139 | const Number = enum { | |
| 139 | const Number = union(enum) { | |
| 140 | 140 | One: u64, |
| 141 | 141 | Two: u8, |
| 142 | 142 | Three: f32, |
| 143 | 143 | }; |
| 144 | 144 | |
| 145 | const number = Number.Three { 1.23 }; | |
| 145 | const number = Number { .Three = 1.23 }; | |
| 146 | 146 | |
| 147 | 147 | fn returnsFalse() -> bool { |
| 148 | 148 | switch (number) { |
test/cases/switch_prong_err_enum.zig+2-2| ... | ... | @@ -9,14 +9,14 @@ fn readOnce() -> %u64 { |
| 9 | 9 | |
| 10 | 10 | error InvalidDebugInfo; |
| 11 | 11 | |
| 12 | const FormValue = enum { | |
| 12 | const FormValue = union(enum) { | |
| 13 | 13 | Address: u64, |
| 14 | 14 | Other: bool, |
| 15 | 15 | }; |
| 16 | 16 | |
| 17 | 17 | fn doThing(form_id: u64) -> %FormValue { |
| 18 | 18 | return switch (form_id) { |
| 19 | 17 => FormValue.Address { %return readOnce() }, | |
| 19 | 17 => FormValue { .Address = %return readOnce() }, | |
| 20 | 20 | else => error.InvalidDebugInfo, |
| 21 | 21 | } |
| 22 | 22 | } |
test/cases/switch_prong_implicit_cast.zig+4-4| ... | ... | @@ -1,7 +1,7 @@ |
| 1 | 1 | const assert = @import("std").debug.assert; |
| 2 | 2 | |
| 3 | const FormValue = enum { | |
| 4 | One, | |
| 3 | const FormValue = union(enum) { | |
| 4 | One: void, | |
| 5 | 5 | Two: bool, |
| 6 | 6 | }; |
| 7 | 7 | |
| ... | ... | @@ -9,8 +9,8 @@ error Whatever; |
| 9 | 9 | |
| 10 | 10 | fn foo(id: u64) -> %FormValue { |
| 11 | 11 | switch (id) { |
| 12 | 2 => FormValue.Two { true }, | |
| 13 | 1 => FormValue.One, | |
| 12 | 2 => FormValue { .Two = true }, | |
| 13 | 1 => FormValue { .One = {} }, | |
| 14 | 14 | else => return error.Whatever, |
| 15 | 15 | } |
| 16 | 16 | } |
test/cases/union.zig+32-3| ... | ... | @@ -1,6 +1,6 @@ |
| 1 | 1 | const assert = @import("std").debug.assert; |
| 2 | 2 | |
| 3 | const Value = enum { | |
| 3 | const Value = union(enum) { | |
| 4 | 4 | Int: u64, |
| 5 | 5 | Array: [9]u8, |
| 6 | 6 | }; |
| ... | ... | @@ -10,8 +10,8 @@ const Agg = struct { |
| 10 | 10 | val2: Value, |
| 11 | 11 | }; |
| 12 | 12 | |
| 13 | const v1 = Value.Int { 1234 }; | |
| 14 | const v2 = Value.Array { []u8{3} ** 9 }; | |
| 13 | const v1 = Value { .Int = 1234 }; | |
| 14 | const v2 = Value { .Array = []u8{3} ** 9 }; | |
| 15 | 15 | |
| 16 | 16 | const err = (%Agg)(Agg { |
| 17 | 17 | .val1 = v1, |
| ... | ... | @@ -75,3 +75,32 @@ test "basic extern unions" { |
| 75 | 75 | assert(foo.float == 12.34); |
| 76 | 76 | } |
| 77 | 77 | |
| 78 | ||
| 79 | const Letter = enum { | |
| 80 | A, | |
| 81 | B, | |
| 82 | C, | |
| 83 | }; | |
| 84 | const Payload = union(Letter) { | |
| 85 | A: i32, | |
| 86 | B: f64, | |
| 87 | C: bool, | |
| 88 | }; | |
| 89 | ||
| 90 | test "union with specified enum tag" { | |
| 91 | doTest(); | |
| 92 | comptime doTest(); | |
| 93 | } | |
| 94 | ||
| 95 | fn doTest() { | |
| 96 | assert(bar(Payload {.A = 1234}) == -10); | |
| 97 | } | |
| 98 | ||
| 99 | fn 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 | 930 | \\fn bad_eql_1(a: []u8, b: []u8) -> bool { |
| 931 | 931 | \\ a == b |
| 932 | 932 | \\} |
| 933 | \\const EnumWithData = enum { | |
| 934 | \\ One, | |
| 933 | \\const EnumWithData = union(enum) { | |
| 934 | \\ One: void, | |
| 935 | 935 | \\ Two: i32, |
| 936 | 936 | \\}; |
| 937 | 937 | \\fn bad_eql_2(a: &const EnumWithData, b: &const EnumWithData) -> bool { |
| ... | ... | @@ -1145,19 +1145,19 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 1145 | 1145 | \\const JasonHM = u8; |
| 1146 | 1146 | \\const JasonList = &JsonNode; |
| 1147 | 1147 | \\ |
| 1148 | \\const JsonOA = enum { | |
| 1148 | \\const JsonOA = union(enum) { | |
| 1149 | 1149 | \\ JSONArray: JsonList, |
| 1150 | 1150 | \\ JSONObject: JasonHM, |
| 1151 | 1151 | \\}; |
| 1152 | 1152 | \\ |
| 1153 | \\const JsonType = enum { | |
| 1153 | \\const JsonType = union(enum) { | |
| 1154 | 1154 | \\ JSONNull: void, |
| 1155 | 1155 | \\ JSONInteger: isize, |
| 1156 | 1156 | \\ JSONDouble: f64, |
| 1157 | 1157 | \\ JSONBool: bool, |
| 1158 | 1158 | \\ JSONString: []u8, |
| 1159 | \\ JSONArray, | |
| 1160 | \\ JSONObject, | |
| 1159 | \\ JSONArray: void, | |
| 1160 | \\ JSONObject: void, | |
| 1161 | 1161 | \\}; |
| 1162 | 1162 | \\ |
| 1163 | 1163 | \\pub const JsonNode = struct { |
| ... | ... | @@ -2138,7 +2138,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 2138 | 2138 | \\ |
| 2139 | 2139 | \\const MdText = ArrayList(u8); |
| 2140 | 2140 | \\ |
| 2141 | \\const MdNode = enum { | |
| 2141 | \\const MdNode = union(enum) { | |
| 2142 | 2142 | \\ Header: struct { |
| 2143 | 2143 | \\ text: MdText, |
| 2144 | 2144 | \\ weight: HeaderValue, |
| ... | ... | @@ -2297,6 +2297,14 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 2297 | 2297 | , |
| 2298 | 2298 | ".tmp_source.zig:2:21: error: type 'i32' does not support @memberType"); |
| 2299 | 2299 | |
| 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 | 2308 | cases.add("@memberType struct out of bounds", |
| 2301 | 2309 | \\comptime { |
| 2302 | 2310 | \\ _ = @memberType(Foo, 0); |
| ... | ... | @@ -2305,11 +2313,11 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 2305 | 2313 | , |
| 2306 | 2314 | ".tmp_source.zig:2:26: error: member index 0 out of bounds; 'Foo' has 0 members"); |
| 2307 | 2315 | |
| 2308 | cases.add("@memberType enum out of bounds", | |
| 2316 | cases.add("@memberType union out of bounds", | |
| 2309 | 2317 | \\comptime { |
| 2310 | 2318 | \\ _ = @memberType(Foo, 1); |
| 2311 | 2319 | \\} |
| 2312 | \\const Foo = enum {A,}; | |
| 2320 | \\const Foo = union {A: void,}; | |
| 2313 | 2321 | , |
| 2314 | 2322 | ".tmp_source.zig:2:26: error: member index 1 out of bounds; 'Foo' has 1 members"); |
| 2315 | 2323 | |
| ... | ... | @@ -2336,6 +2344,14 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 2336 | 2344 | , |
| 2337 | 2345 | ".tmp_source.zig:2:26: error: member index 1 out of bounds; 'Foo' has 1 members"); |
| 2338 | 2346 | |
| 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 | 2355 | cases.add("calling var args extern function, passing array instead of pointer", |
| 2340 | 2356 | \\export fn entry() { |
| 2341 | 2357 | \\ foo("hello"); |
| ... | ... | @@ -2466,7 +2482,8 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 2466 | 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"); | |
| 2470 | 2487 | |
| 2471 | 2488 | cases.add("enum with 0 fields", |
| 2472 | 2489 | \\const Foo = enum {}; |
| ... | ... | @@ -2490,4 +2507,21 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 2490 | 2507 | , |
| 2491 | 2508 | ".tmp_source.zig:6:9: error: enum tag value 60 already taken", |
| 2492 | 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 | 150 | continue; |
| 151 | 151 | } |
| 152 | 152 | const these_tests = b.addTest(root_src); |
| 153 | these_tests.setNamePrefix(b.fmt("{}-{}-{}-{}-{} ", name, @enumTagName(test_target.os), | |
| 154 | @enumTagName(test_target.arch), @enumTagName(mode), if (link_libc) "c" else "bare")); | |
| 153 | these_tests.setNamePrefix(b.fmt("{}-{}-{}-{}-{} ", name, @tagName(test_target.os), | |
| 154 | @tagName(test_target.arch), @tagName(mode), if (link_libc) "c" else "bare")); | |
| 155 | 155 | these_tests.setFilter(test_filter); |
| 156 | 156 | these_tests.setBuildMode(mode); |
| 157 | 157 | if (!is_native) { |
| ... | ... | @@ -428,7 +428,7 @@ pub const CompareOutputContext = struct { |
| 428 | 428 | Special.None => { |
| 429 | 429 | for ([]Mode{Mode.Debug, Mode.ReleaseSafe, Mode.ReleaseFast}) |mode| { |
| 430 | 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 | 432 | if (self.test_filter) |filter| { |
| 433 | 433 | if (mem.indexOf(u8, annotated_case_name, filter) == null) |
| 434 | 434 | continue; |
| ... | ... | @@ -682,7 +682,7 @@ pub const CompileErrorContext = struct { |
| 682 | 682 | |
| 683 | 683 | for ([]Mode{Mode.Debug, Mode.ReleaseSafe, Mode.ReleaseFast}) |mode| { |
| 684 | 684 | const annotated_case_name = %%fmt.allocPrint(self.b.allocator, "compile-error {} ({})", |
| 685 | case.name, @enumTagName(mode)); | |
| 685 | case.name, @tagName(mode)); | |
| 686 | 686 | if (self.test_filter) |filter| { |
| 687 | 687 | if (mem.indexOf(u8, annotated_case_name, filter) == null) |
| 688 | 688 | continue; |
| ... | ... | @@ -750,7 +750,7 @@ pub const BuildExamplesContext = struct { |
| 750 | 750 | |
| 751 | 751 | for ([]Mode{Mode.Debug, Mode.ReleaseSafe, Mode.ReleaseFast}) |mode| { |
| 752 | 752 | const annotated_case_name = %%fmt.allocPrint(self.b.allocator, "build {} ({})", |
| 753 | root_src, @enumTagName(mode)); | |
| 753 | root_src, @tagName(mode)); | |
| 754 | 754 | if (self.test_filter) |filter| { |
| 755 | 755 | if (mem.indexOf(u8, annotated_case_name, filter) == null) |
| 756 | 756 | continue; |