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