| author | |
| committer | |
| log | 137c8f5e8a6023db24f90555e968b592a4b843e4 |
| tree | 822547a6857ad24dad7ed8c7d26720d17b7bcce7 |
| parent | 98237f7c0ba62099e85a8caf8fc09039845b224e |
also remove support for enums with 0 values
closes #30513 files changed, 451 insertions(+), 146 deletions(-)
doc/langref.html.in+1-1| ... | @@ -5709,7 +5709,7 @@ VariableDeclaration = option("comptime") ("var" | "const") Symbol option(":" Typ | ... | @@ -5709,7 +5709,7 @@ VariableDeclaration = option("comptime") ("var" | "const") Symbol option(":" Typ |
| 5709 | 5709 | ||
| 5710 | ContainerMember = (ContainerField | FnDef | GlobalVarDecl) | 5710 | ContainerMember = (ContainerField | FnDef | GlobalVarDecl) |
| 5711 | 5711 | ||
| 5712 | ContainerField = Symbol option(":" Expression) "," | 5712 | ContainerField = Symbol option(":" PrefixOpExpression option("=" PrefixOpExpression "," |
| 5713 | 5713 | ||
| 5714 | UseDecl = "use" Expression ";" | 5714 | UseDecl = "use" Expression ";" |
| 5715 | 5715 |
src/all_types.hpp+6-4| ... | @@ -98,7 +98,7 @@ struct ConstParent { | ... | @@ -98,7 +98,7 @@ struct ConstParent { |
| 98 | }; | 98 | }; |
| 99 | 99 | ||
| 100 | struct ConstEnumValue { | 100 | struct ConstEnumValue { |
| 101 | uint64_t tag; | 101 | BigInt tag; |
| 102 | ConstExprValue *payload; | 102 | ConstExprValue *payload; |
| 103 | }; | 103 | }; |
| 104 | 104 | ||
| ... | @@ -108,7 +108,7 @@ struct ConstStructValue { | ... | @@ -108,7 +108,7 @@ struct ConstStructValue { |
| 108 | }; | 108 | }; |
| 109 | 109 | ||
| 110 | struct ConstUnionValue { | 110 | struct ConstUnionValue { |
| 111 | uint64_t tag; | 111 | BigInt tag; |
| 112 | ConstExprValue *payload; | 112 | ConstExprValue *payload; |
| 113 | ConstParent parent; | 113 | ConstParent parent; |
| 114 | }; | 114 | }; |
| ... | @@ -346,14 +346,14 @@ struct TldCompTime { | ... | @@ -346,14 +346,14 @@ struct TldCompTime { |
| 346 | struct TypeEnumField { | 346 | struct TypeEnumField { |
| 347 | Buf *name; | 347 | Buf *name; |
| 348 | TypeTableEntry *type_entry; | 348 | TypeTableEntry *type_entry; |
| 349 | uint32_t value; | 349 | BigInt value; |
| 350 | uint32_t gen_index; | 350 | uint32_t gen_index; |
| 351 | }; | 351 | }; |
| 352 | 352 | ||
| 353 | struct TypeUnionField { | 353 | struct TypeUnionField { |
| 354 | Buf *name; | 354 | Buf *name; |
| 355 | TypeTableEntry *type_entry; | 355 | TypeTableEntry *type_entry; |
| 356 | uint32_t value; | 356 | BigInt value; |
| 357 | uint32_t gen_index; | 357 | uint32_t gen_index; |
| 358 | }; | 358 | }; |
| 359 | 359 | ||
| ... | @@ -780,6 +780,7 @@ struct AstNodeStructField { | ... | @@ -780,6 +780,7 @@ struct AstNodeStructField { |
| 780 | VisibMod visib_mod; | 780 | VisibMod visib_mod; |
| 781 | Buf *name; | 781 | Buf *name; |
| 782 | AstNode *type; | 782 | AstNode *type; |
| 783 | AstNode *value; | ||
| 783 | }; | 784 | }; |
| 784 | 785 | ||
| 785 | struct AstNodeStringLiteral { | 786 | struct AstNodeStringLiteral { |
| ... | @@ -1014,6 +1015,7 @@ struct TypeTableEntryEnum { | ... | @@ -1014,6 +1015,7 @@ struct TypeTableEntryEnum { |
| 1014 | TypeEnumField *fields; | 1015 | TypeEnumField *fields; |
| 1015 | bool is_invalid; // true if any fields are invalid | 1016 | bool is_invalid; // true if any fields are invalid |
| 1016 | TypeTableEntry *tag_type; | 1017 | TypeTableEntry *tag_type; |
| 1018 | TypeTableEntry *tag_int_type; | ||
| 1017 | LLVMTypeRef union_type_ref; | 1019 | LLVMTypeRef union_type_ref; |
| 1018 | 1020 | ||
| 1019 | ScopeDecls *decls_scope; | 1021 | ScopeDecls *decls_scope; |
src/analyze.cpp+182-52| ... | @@ -1390,30 +1390,7 @@ static void resolve_enum_type(CodeGen *g, TypeTableEntry *enum_type) { | ... | @@ -1390,30 +1390,7 @@ static void resolve_enum_type(CodeGen *g, TypeTableEntry *enum_type) { |
| 1390 | return; | 1390 | return; |
| 1391 | } | 1391 | } |
| 1392 | 1392 | ||
| 1393 | TypeTableEntry *tag_int_type = get_smallest_unsigned_int_type(g, field_count - 1); | 1393 | TypeTableEntry *tag_int_type = enum_type->data.enumeration.tag_int_type; |
| 1394 | if (decl_node->data.container_decl.init_arg_expr != nullptr) { | ||
| 1395 | TypeTableEntry *wanted_tag_int_type = analyze_type_expr(g, scope, decl_node->data.container_decl.init_arg_expr); | ||
| 1396 | if (type_is_invalid(wanted_tag_int_type)) { | ||
| 1397 | enum_type->data.enumeration.is_invalid = true; | ||
| 1398 | } else if (wanted_tag_int_type->id != TypeTableEntryIdInt) { | ||
| 1399 | enum_type->data.enumeration.is_invalid = true; | ||
| 1400 | add_node_error(g, decl_node->data.container_decl.init_arg_expr, | ||
| 1401 | buf_sprintf("expected integer, found '%s'", buf_ptr(&wanted_tag_int_type->name))); | ||
| 1402 | } else if (wanted_tag_int_type->data.integral.is_signed) { | ||
| 1403 | enum_type->data.enumeration.is_invalid = true; | ||
| 1404 | add_node_error(g, decl_node->data.container_decl.init_arg_expr, | ||
| 1405 | buf_sprintf("expected unsigned integer, found '%s'", buf_ptr(&wanted_tag_int_type->name))); | ||
| 1406 | } else if (wanted_tag_int_type->data.integral.bit_count < tag_int_type->data.integral.bit_count) { | ||
| 1407 | enum_type->data.enumeration.is_invalid = true; | ||
| 1408 | add_node_error(g, decl_node->data.container_decl.init_arg_expr, | ||
| 1409 | buf_sprintf("'%s' too small to hold all bits; must be at least '%s'", | ||
| 1410 | buf_ptr(&wanted_tag_int_type->name), buf_ptr(&tag_int_type->name))); | ||
| 1411 | } else { | ||
| 1412 | tag_int_type = wanted_tag_int_type; | ||
| 1413 | } | ||
| 1414 | } | ||
| 1415 | |||
| 1416 | |||
| 1417 | TypeTableEntry *tag_type_entry = create_enum_tag_type(g, enum_type, tag_int_type); | 1394 | TypeTableEntry *tag_type_entry = create_enum_tag_type(g, enum_type, tag_int_type); |
| 1418 | enum_type->data.enumeration.tag_type = tag_type_entry; | 1395 | enum_type->data.enumeration.tag_type = tag_type_entry; |
| 1419 | 1396 | ||
| ... | @@ -1683,7 +1660,6 @@ static void resolve_struct_type(CodeGen *g, TypeTableEntry *struct_type) { | ... | @@ -1683,7 +1660,6 @@ static void resolve_struct_type(CodeGen *g, TypeTableEntry *struct_type) { |
| 1683 | TypeTableEntry *field_type = type_struct_field->type_entry; | 1660 | TypeTableEntry *field_type = type_struct_field->type_entry; |
| 1684 | 1661 | ||
| 1685 | ensure_complete_type(g, field_type); | 1662 | ensure_complete_type(g, field_type); |
| 1686 | |||
| 1687 | if (type_is_invalid(field_type)) { | 1663 | if (type_is_invalid(field_type)) { |
| 1688 | struct_type->data.structure.is_invalid = true; | 1664 | struct_type->data.structure.is_invalid = true; |
| 1689 | break; | 1665 | break; |
| ... | @@ -2121,6 +2097,18 @@ static void resolve_enum_zero_bits(CodeGen *g, TypeTableEntry *enum_type) { | ... | @@ -2121,6 +2097,18 @@ static void resolve_enum_zero_bits(CodeGen *g, TypeTableEntry *enum_type) { |
| 2121 | 2097 | ||
| 2122 | assert(!enum_type->data.enumeration.fields); | 2098 | assert(!enum_type->data.enumeration.fields); |
| 2123 | uint32_t field_count = (uint32_t)decl_node->data.container_decl.fields.length; | 2099 | uint32_t field_count = (uint32_t)decl_node->data.container_decl.fields.length; |
| 2100 | if (field_count == 0) { | ||
| 2101 | add_node_error(g, decl_node, buf_sprintf("enums must have 1 or more fields")); | ||
| 2102 | |||
| 2103 | enum_type->data.enumeration.src_field_count = field_count; | ||
| 2104 | enum_type->data.enumeration.fields = nullptr; | ||
| 2105 | enum_type->data.enumeration.is_invalid = true; | ||
| 2106 | 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; | ||
| 2109 | return; | ||
| 2110 | } | ||
| 2111 | |||
| 2124 | enum_type->data.enumeration.src_field_count = field_count; | 2112 | enum_type->data.enumeration.src_field_count = field_count; |
| 2125 | enum_type->data.enumeration.fields = allocate<TypeEnumField>(field_count); | 2113 | enum_type->data.enumeration.fields = allocate<TypeEnumField>(field_count); |
| 2126 | 2114 | ||
| ... | @@ -2128,14 +2116,69 @@ static void resolve_enum_zero_bits(CodeGen *g, TypeTableEntry *enum_type) { | ... | @@ -2128,14 +2116,69 @@ static void resolve_enum_zero_bits(CodeGen *g, TypeTableEntry *enum_type) { |
| 2128 | 2116 | ||
| 2129 | Scope *scope = &enum_type->data.enumeration.decls_scope->base; | 2117 | Scope *scope = &enum_type->data.enumeration.decls_scope->base; |
| 2130 | 2118 | ||
| 2119 | HashMap<BigInt, AstNode *, bigint_hash, bigint_eql> occupied_tag_values = {}; | ||
| 2120 | occupied_tag_values.init(field_count); | ||
| 2121 | |||
| 2122 | TypeTableEntry *tag_int_type = get_smallest_unsigned_int_type(g, field_count - 1); | ||
| 2123 | |||
| 2124 | if (decl_node->data.container_decl.init_arg_expr != nullptr) { | ||
| 2125 | TypeTableEntry *wanted_tag_int_type = analyze_type_expr(g, scope, decl_node->data.container_decl.init_arg_expr); | ||
| 2126 | if (type_is_invalid(wanted_tag_int_type)) { | ||
| 2127 | enum_type->data.enumeration.is_invalid = true; | ||
| 2128 | } else if (wanted_tag_int_type->id != TypeTableEntryIdInt) { | ||
| 2129 | enum_type->data.enumeration.is_invalid = true; | ||
| 2130 | add_node_error(g, decl_node->data.container_decl.init_arg_expr, | ||
| 2131 | buf_sprintf("expected integer, found '%s'", buf_ptr(&wanted_tag_int_type->name))); | ||
| 2132 | } else if (wanted_tag_int_type->data.integral.is_signed) { | ||
| 2133 | enum_type->data.enumeration.is_invalid = true; | ||
| 2134 | add_node_error(g, decl_node->data.container_decl.init_arg_expr, | ||
| 2135 | buf_sprintf("expected unsigned integer, found '%s'", buf_ptr(&wanted_tag_int_type->name))); | ||
| 2136 | } else if (wanted_tag_int_type->data.integral.bit_count < tag_int_type->data.integral.bit_count) { | ||
| 2137 | enum_type->data.enumeration.is_invalid = true; | ||
| 2138 | add_node_error(g, decl_node->data.container_decl.init_arg_expr, | ||
| 2139 | buf_sprintf("'%s' too small to hold all bits; must be at least '%s'", | ||
| 2140 | buf_ptr(&wanted_tag_int_type->name), buf_ptr(&tag_int_type->name))); | ||
| 2141 | } else { | ||
| 2142 | tag_int_type = wanted_tag_int_type; | ||
| 2143 | } | ||
| 2144 | } | ||
| 2145 | enum_type->data.enumeration.tag_int_type = tag_int_type; | ||
| 2146 | |||
| 2131 | uint32_t gen_field_index = 0; | 2147 | uint32_t gen_field_index = 0; |
| 2132 | for (uint32_t i = 0; i < field_count; i += 1) { | 2148 | for (uint32_t field_i = 0; field_i < field_count; field_i += 1) { |
| 2133 | AstNode *field_node = decl_node->data.container_decl.fields.at(i); | 2149 | AstNode *field_node = decl_node->data.container_decl.fields.at(field_i); |
| 2134 | TypeEnumField *type_enum_field = &enum_type->data.enumeration.fields[i]; | 2150 | TypeEnumField *type_enum_field = &enum_type->data.enumeration.fields[field_i]; |
| 2135 | type_enum_field->name = field_node->data.struct_field.name; | 2151 | type_enum_field->name = field_node->data.struct_field.name; |
| 2136 | TypeTableEntry *field_type = analyze_type_expr(g, scope, field_node->data.struct_field.type); | 2152 | TypeTableEntry *field_type = analyze_type_expr(g, scope, field_node->data.struct_field.type); |
| 2137 | type_enum_field->type_entry = field_type; | 2153 | type_enum_field->type_entry = field_type; |
| 2138 | type_enum_field->value = i; | 2154 | |
| 2155 | AstNode *tag_value = field_node->data.struct_field.value; | ||
| 2156 | |||
| 2157 | // In this first pass we resolve explicit tag values. | ||
| 2158 | // In a second pass we will fill in the unspecified ones. | ||
| 2159 | if (tag_value != nullptr) { | ||
| 2160 | IrInstruction *result_inst = analyze_const_value(g, scope, tag_value, tag_int_type, nullptr); | ||
| 2161 | if (result_inst->value.type->id == TypeTableEntryIdInvalid) { | ||
| 2162 | enum_type->data.enumeration.is_invalid = true; | ||
| 2163 | continue; | ||
| 2164 | } | ||
| 2165 | assert(result_inst->value.special != ConstValSpecialRuntime); | ||
| 2166 | assert(result_inst->value.type->id == TypeTableEntryIdInt); | ||
| 2167 | auto entry = occupied_tag_values.put_unique(result_inst->value.data.x_bigint, tag_value); | ||
| 2168 | if (entry == nullptr) { | ||
| 2169 | bigint_init_bigint(&type_enum_field->value, &result_inst->value.data.x_bigint); | ||
| 2170 | } else { | ||
| 2171 | Buf *val_buf = buf_alloc(); | ||
| 2172 | bigint_append_buf(val_buf, &result_inst->value.data.x_bigint, 10); | ||
| 2173 | |||
| 2174 | ErrorMsg *msg = add_node_error(g, tag_value, | ||
| 2175 | buf_sprintf("enum tag value %s already taken", buf_ptr(val_buf))); | ||
| 2176 | add_error_note(g, msg, entry->value, | ||
| 2177 | buf_sprintf("other occurrence here")); | ||
| 2178 | enum_type->data.enumeration.is_invalid = true; | ||
| 2179 | continue; | ||
| 2180 | } | ||
| 2181 | } | ||
| 2139 | 2182 | ||
| 2140 | type_ensure_zero_bits_known(g, field_type); | 2183 | type_ensure_zero_bits_known(g, field_type); |
| 2141 | if (type_is_invalid(field_type)) { | 2184 | if (type_is_invalid(field_type)) { |
| ... | @@ -2155,6 +2198,34 @@ static void resolve_enum_zero_bits(CodeGen *g, TypeTableEntry *enum_type) { | ... | @@ -2155,6 +2198,34 @@ static void resolve_enum_zero_bits(CodeGen *g, TypeTableEntry *enum_type) { |
| 2155 | } | 2198 | } |
| 2156 | } | 2199 | } |
| 2157 | 2200 | ||
| 2201 | // Now iterate again and populate the unspecified tag values | ||
| 2202 | uint32_t next_maybe_unoccupied_index = 0; | ||
| 2203 | |||
| 2204 | for (uint32_t field_i = 0; field_i < field_count; field_i += 1) { | ||
| 2205 | AstNode *field_node = decl_node->data.container_decl.fields.at(field_i); | ||
| 2206 | TypeEnumField *type_enum_field = &enum_type->data.enumeration.fields[field_i]; | ||
| 2207 | AstNode *tag_value = field_node->data.struct_field.value; | ||
| 2208 | |||
| 2209 | if (tag_value == nullptr) { | ||
| 2210 | if (occupied_tag_values.size() == 0) { | ||
| 2211 | bigint_init_unsigned(&type_enum_field->value, next_maybe_unoccupied_index); | ||
| 2212 | next_maybe_unoccupied_index += 1; | ||
| 2213 | } else { | ||
| 2214 | BigInt proposed_value; | ||
| 2215 | for (;;) { | ||
| 2216 | bigint_init_unsigned(&proposed_value, next_maybe_unoccupied_index); | ||
| 2217 | next_maybe_unoccupied_index += 1; | ||
| 2218 | auto entry = occupied_tag_values.put_unique(proposed_value, field_node); | ||
| 2219 | if (entry != nullptr) { | ||
| 2220 | continue; | ||
| 2221 | } | ||
| 2222 | break; | ||
| 2223 | } | ||
| 2224 | bigint_init_bigint(&type_enum_field->value, &proposed_value); | ||
| 2225 | } | ||
| 2226 | } | ||
| 2227 | } | ||
| 2228 | |||
| 2158 | enum_type->data.enumeration.zero_bits_loop_flag = false; | 2229 | enum_type->data.enumeration.zero_bits_loop_flag = false; |
| 2159 | enum_type->data.enumeration.gen_field_count = gen_field_index; | 2230 | enum_type->data.enumeration.gen_field_count = gen_field_index; |
| 2160 | enum_type->zero_bits = (gen_field_index == 0 && field_count < 2); | 2231 | enum_type->zero_bits = (gen_field_index == 0 && field_count < 2); |
| ... | @@ -2162,7 +2233,6 @@ static void resolve_enum_zero_bits(CodeGen *g, TypeTableEntry *enum_type) { | ... | @@ -2162,7 +2233,6 @@ static void resolve_enum_zero_bits(CodeGen *g, TypeTableEntry *enum_type) { |
| 2162 | 2233 | ||
| 2163 | // also compute abi_alignment | 2234 | // also compute abi_alignment |
| 2164 | if (!enum_type->zero_bits) { | 2235 | if (!enum_type->zero_bits) { |
| 2165 | TypeTableEntry *tag_int_type = get_smallest_unsigned_int_type(g, field_count); | ||
| 2166 | uint32_t align_of_tag_in_bytes = LLVMABIAlignmentOfType(g->target_data_ref, tag_int_type->type_ref); | 2236 | uint32_t align_of_tag_in_bytes = LLVMABIAlignmentOfType(g->target_data_ref, tag_int_type->type_ref); |
| 2167 | enum_type->data.enumeration.abi_alignment = max(align_of_tag_in_bytes, biggest_align_bytes); | 2237 | enum_type->data.enumeration.abi_alignment = max(align_of_tag_in_bytes, biggest_align_bytes); |
| 2168 | } | 2238 | } |
| ... | @@ -2214,6 +2284,11 @@ static void resolve_struct_zero_bits(CodeGen *g, TypeTableEntry *struct_type) { | ... | @@ -2214,6 +2284,11 @@ static void resolve_struct_zero_bits(CodeGen *g, TypeTableEntry *struct_type) { |
| 2214 | type_struct_field->src_index = i; | 2284 | type_struct_field->src_index = i; |
| 2215 | type_struct_field->gen_index = SIZE_MAX; | 2285 | type_struct_field->gen_index = SIZE_MAX; |
| 2216 | 2286 | ||
| 2287 | if (field_node->data.struct_field.value != nullptr) { | ||
| 2288 | add_node_error(g, field_node->data.struct_field.value, | ||
| 2289 | buf_sprintf("enums, not structs, support field assignment")); | ||
| 2290 | } | ||
| 2291 | |||
| 2217 | type_ensure_zero_bits_known(g, field_type); | 2292 | type_ensure_zero_bits_known(g, field_type); |
| 2218 | if (type_is_invalid(field_type)) { | 2293 | if (type_is_invalid(field_type)) { |
| 2219 | struct_type->data.structure.is_invalid = true; | 2294 | struct_type->data.structure.is_invalid = true; |
| ... | @@ -2277,7 +2352,14 @@ static void resolve_union_zero_bits(CodeGen *g, TypeTableEntry *union_type) { | ... | @@ -2277,7 +2352,14 @@ static void resolve_union_zero_bits(CodeGen *g, TypeTableEntry *union_type) { |
| 2277 | type_union_field->name = field_node->data.struct_field.name; | 2352 | type_union_field->name = field_node->data.struct_field.name; |
| 2278 | TypeTableEntry *field_type = analyze_type_expr(g, scope, field_node->data.struct_field.type); | 2353 | TypeTableEntry *field_type = analyze_type_expr(g, scope, field_node->data.struct_field.type); |
| 2279 | type_union_field->type_entry = field_type; | 2354 | type_union_field->type_entry = field_type; |
| 2280 | type_union_field->value = i; | 2355 | |
| 2356 | // TODO look for enum arg to union | ||
| 2357 | bigint_init_unsigned(&type_union_field->value, i); | ||
| 2358 | |||
| 2359 | if (field_node->data.struct_field.value != nullptr) { | ||
| 2360 | add_node_error(g, field_node->data.struct_field.value, | ||
| 2361 | buf_sprintf("enums, not unions, support field assignment")); | ||
| 2362 | } | ||
| 2281 | 2363 | ||
| 2282 | type_ensure_zero_bits_known(g, field_type); | 2364 | type_ensure_zero_bits_known(g, field_type); |
| 2283 | if (type_is_invalid(field_type)) { | 2365 | if (type_is_invalid(field_type)) { |
| ... | @@ -3190,6 +3272,29 @@ TypeUnionField *find_union_type_field(TypeTableEntry *type_entry, Buf *name) { | ... | @@ -3190,6 +3272,29 @@ TypeUnionField *find_union_type_field(TypeTableEntry *type_entry, Buf *name) { |
| 3190 | return nullptr; | 3272 | return nullptr; |
| 3191 | } | 3273 | } |
| 3192 | 3274 | ||
| 3275 | static TypeUnionField *find_union_field_by_tag(TypeTableEntry *type_entry, const BigInt *tag) { | ||
| 3276 | assert(type_entry->id == TypeTableEntryIdUnion); | ||
| 3277 | assert(type_entry->data.unionation.complete); | ||
| 3278 | for (uint32_t i = 0; i < type_entry->data.unionation.src_field_count; i += 1) { | ||
| 3279 | TypeUnionField *field = &type_entry->data.unionation.fields[i]; | ||
| 3280 | if (bigint_cmp(&field->value, tag) == CmpEQ) { | ||
| 3281 | return field; | ||
| 3282 | } | ||
| 3283 | } | ||
| 3284 | return nullptr; | ||
| 3285 | } | ||
| 3286 | |||
| 3287 | TypeEnumField *find_enum_field_by_tag(TypeTableEntry *enum_type, const BigInt *tag) { | ||
| 3288 | for (uint32_t i = 0; i < enum_type->data.enumeration.src_field_count; i += 1) { | ||
| 3289 | TypeEnumField *field = &enum_type->data.enumeration.fields[i]; | ||
| 3290 | if (bigint_cmp(&field->value, tag) == CmpEQ) { | ||
| 3291 | return field; | ||
| 3292 | } | ||
| 3293 | } | ||
| 3294 | return nullptr; | ||
| 3295 | } | ||
| 3296 | |||
| 3297 | |||
| 3193 | static bool is_container(TypeTableEntry *type_entry) { | 3298 | static bool is_container(TypeTableEntry *type_entry) { |
| 3194 | switch (type_entry->id) { | 3299 | switch (type_entry->id) { |
| 3195 | case TypeTableEntryIdInvalid: | 3300 | case TypeTableEntryIdInvalid: |
| ... | @@ -4178,6 +4283,18 @@ ConstExprValue *create_const_c_str_lit(CodeGen *g, Buf *str) { | ... | @@ -4178,6 +4283,18 @@ ConstExprValue *create_const_c_str_lit(CodeGen *g, Buf *str) { |
| 4178 | return const_val; | 4283 | return const_val; |
| 4179 | } | 4284 | } |
| 4180 | 4285 | ||
| 4286 | void init_const_bigint(ConstExprValue *const_val, TypeTableEntry *type, const BigInt *bigint) { | ||
| 4287 | const_val->special = ConstValSpecialStatic; | ||
| 4288 | const_val->type = type; | ||
| 4289 | bigint_init_bigint(&const_val->data.x_bigint, bigint); | ||
| 4290 | } | ||
| 4291 | |||
| 4292 | ConstExprValue *create_const_bigint(TypeTableEntry *type, const BigInt *bigint) { | ||
| 4293 | ConstExprValue *const_val = create_const_vals(1); | ||
| 4294 | init_const_bigint(const_val, type, bigint); | ||
| 4295 | return const_val; | ||
| 4296 | } | ||
| 4297 | |||
| 4181 | void init_const_unsigned_negative(ConstExprValue *const_val, TypeTableEntry *type, uint64_t x, bool negative) { | 4298 | void init_const_unsigned_negative(ConstExprValue *const_val, TypeTableEntry *type, uint64_t x, bool negative) { |
| 4182 | const_val->special = ConstValSpecialStatic; | 4299 | const_val->special = ConstValSpecialStatic; |
| 4183 | const_val->type = type; | 4300 | const_val->type = type; |
| ... | @@ -4241,13 +4358,13 @@ ConstExprValue *create_const_float(TypeTableEntry *type, double value) { | ... | @@ -4241,13 +4358,13 @@ ConstExprValue *create_const_float(TypeTableEntry *type, double value) { |
| 4241 | return const_val; | 4358 | return const_val; |
| 4242 | } | 4359 | } |
| 4243 | 4360 | ||
| 4244 | void init_const_enum_tag(ConstExprValue *const_val, TypeTableEntry *type, uint64_t tag) { | 4361 | void init_const_enum_tag(ConstExprValue *const_val, TypeTableEntry *type, const BigInt *tag) { |
| 4245 | const_val->special = ConstValSpecialStatic; | 4362 | const_val->special = ConstValSpecialStatic; |
| 4246 | const_val->type = type; | 4363 | const_val->type = type; |
| 4247 | const_val->data.x_enum.tag = tag; | 4364 | bigint_init_bigint(&const_val->data.x_enum.tag, tag); |
| 4248 | } | 4365 | } |
| 4249 | 4366 | ||
| 4250 | ConstExprValue *create_const_enum_tag(TypeTableEntry *type, uint64_t tag) { | 4367 | ConstExprValue *create_const_enum_tag(TypeTableEntry *type, const BigInt *tag) { |
| 4251 | ConstExprValue *const_val = create_const_vals(1); | 4368 | ConstExprValue *const_val = create_const_vals(1); |
| 4252 | init_const_enum_tag(const_val, type, tag); | 4369 | init_const_enum_tag(const_val, type, tag); |
| 4253 | return const_val; | 4370 | return const_val; |
| ... | @@ -4450,20 +4567,35 @@ bool const_values_equal(ConstExprValue *a, ConstExprValue *b) { | ... | @@ -4450,20 +4567,35 @@ bool const_values_equal(ConstExprValue *a, ConstExprValue *b) { |
| 4450 | switch (a->type->id) { | 4567 | switch (a->type->id) { |
| 4451 | case TypeTableEntryIdOpaque: | 4568 | case TypeTableEntryIdOpaque: |
| 4452 | zig_unreachable(); | 4569 | zig_unreachable(); |
| 4453 | case TypeTableEntryIdEnum: | 4570 | case TypeTableEntryIdEnum: { |
| 4454 | { | 4571 | ConstEnumValue *enum1 = &a->data.x_enum; |
| 4455 | ConstEnumValue *enum1 = &a->data.x_enum; | 4572 | ConstEnumValue *enum2 = &b->data.x_enum; |
| 4456 | ConstEnumValue *enum2 = &b->data.x_enum; | 4573 | if (bigint_cmp(&enum1->tag, &enum2->tag) == CmpEQ) { |
| 4457 | if (enum1->tag == enum2->tag) { | 4574 | TypeEnumField *field = find_enum_field_by_tag(a->type, &enum1->tag); |
| 4458 | TypeEnumField *enum_field = &a->type->data.enumeration.fields[enum1->tag]; | 4575 | assert(field != nullptr); |
| 4459 | if (type_has_bits(enum_field->type_entry)) { | 4576 | if (type_has_bits(field->type_entry)) { |
| 4460 | zig_panic("TODO const expr analyze enum special value for equality"); | 4577 | zig_panic("TODO const expr analyze enum field value for equality"); |
| 4461 | } else { | 4578 | } else { |
| 4462 | return true; | 4579 | return true; |
| 4463 | } | ||
| 4464 | } | 4580 | } |
| 4465 | return false; | ||
| 4466 | } | 4581 | } |
| 4582 | return false; | ||
| 4583 | } | ||
| 4584 | case TypeTableEntryIdUnion: { | ||
| 4585 | ConstUnionValue *union1 = &a->data.x_union; | ||
| 4586 | ConstUnionValue *union2 = &b->data.x_union; | ||
| 4587 | |||
| 4588 | if (bigint_cmp(&union1->tag, &union2->tag) == CmpEQ) { | ||
| 4589 | TypeUnionField *field = find_union_field_by_tag(a->type, &union1->tag); | ||
| 4590 | assert(field != nullptr); | ||
| 4591 | if (type_has_bits(field->type_entry)) { | ||
| 4592 | zig_panic("TODO const expr analyze union field value for equality"); | ||
| 4593 | } else { | ||
| 4594 | return true; | ||
| 4595 | } | ||
| 4596 | } | ||
| 4597 | return false; | ||
| 4598 | } | ||
| 4467 | case TypeTableEntryIdMetaType: | 4599 | case TypeTableEntryIdMetaType: |
| 4468 | return a->data.x_type == b->data.x_type; | 4600 | return a->data.x_type == b->data.x_type; |
| 4469 | case TypeTableEntryIdVoid: | 4601 | case TypeTableEntryIdVoid: |
| ... | @@ -4544,8 +4676,6 @@ bool const_values_equal(ConstExprValue *a, ConstExprValue *b) { | ... | @@ -4544,8 +4676,6 @@ bool const_values_equal(ConstExprValue *a, ConstExprValue *b) { |
| 4544 | return false; | 4676 | return false; |
| 4545 | } | 4677 | } |
| 4546 | return true; | 4678 | return true; |
| 4547 | case TypeTableEntryIdUnion: | ||
| 4548 | zig_panic("TODO"); | ||
| 4549 | case TypeTableEntryIdUndefLit: | 4679 | case TypeTableEntryIdUndefLit: |
| 4550 | zig_panic("TODO"); | 4680 | zig_panic("TODO"); |
| 4551 | case TypeTableEntryIdNullLit: | 4681 | case TypeTableEntryIdNullLit: |
| ... | @@ -4855,11 +4985,10 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) { | ... | @@ -4855,11 +4985,10 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) { |
| 4855 | } | 4985 | } |
| 4856 | 4986 | ||
| 4857 | TypeTableEntry *make_int_type(CodeGen *g, bool is_signed, uint32_t size_in_bits) { | 4987 | TypeTableEntry *make_int_type(CodeGen *g, bool is_signed, uint32_t size_in_bits) { |
| 4858 | assert(size_in_bits > 0); | ||
| 4859 | |||
| 4860 | TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdInt); | 4988 | TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdInt); |
| 4861 | entry->is_copyable = true; | 4989 | entry->is_copyable = true; |
| 4862 | entry->type_ref = LLVMIntType(size_in_bits); | 4990 | entry->type_ref = (size_in_bits == 0) ? LLVMVoidType() : LLVMIntType(size_in_bits); |
| 4991 | entry->zero_bits = (size_in_bits == 0); | ||
| 4863 | 4992 | ||
| 4864 | const char u_or_i = is_signed ? 'i' : 'u'; | 4993 | const char u_or_i = is_signed ? 'i' : 'u'; |
| 4865 | buf_resize(&entry->name, 0); | 4994 | buf_resize(&entry->name, 0); |
| ... | @@ -4880,7 +5009,8 @@ TypeTableEntry *make_int_type(CodeGen *g, bool is_signed, uint32_t size_in_bits) | ... | @@ -4880,7 +5009,8 @@ TypeTableEntry *make_int_type(CodeGen *g, bool is_signed, uint32_t size_in_bits) |
| 4880 | } | 5009 | } |
| 4881 | } | 5010 | } |
| 4882 | 5011 | ||
| 4883 | uint64_t debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, entry->type_ref); | 5012 | uint64_t debug_size_in_bits = (size_in_bits == 0) ? |
| 5013 | 0 : (8*LLVMStoreSizeOfType(g->target_data_ref, entry->type_ref)); | ||
| 4884 | entry->di_type = ZigLLVMCreateDebugBasicType(g->dbuilder, buf_ptr(&entry->name), debug_size_in_bits, dwarf_tag); | 5014 | entry->di_type = ZigLLVMCreateDebugBasicType(g->dbuilder, buf_ptr(&entry->name), debug_size_in_bits, dwarf_tag); |
| 4885 | entry->data.integral.is_signed = is_signed; | 5015 | entry->data.integral.is_signed = is_signed; |
| 4886 | entry->data.integral.bit_count = size_in_bits; | 5016 | entry->data.integral.bit_count = size_in_bits; |
src/analyze.hpp+7-2| ... | @@ -64,6 +64,8 @@ TypeStructField *find_struct_type_field(TypeTableEntry *type_entry, Buf *name); | ... | @@ -64,6 +64,8 @@ TypeStructField *find_struct_type_field(TypeTableEntry *type_entry, Buf *name); |
| 64 | ScopeDecls *get_container_scope(TypeTableEntry *type_entry); | 64 | 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); | ||
| 68 | |||
| 67 | bool is_container_ref(TypeTableEntry *type_entry); | 69 | bool is_container_ref(TypeTableEntry *type_entry); |
| 68 | void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node); | 70 | void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node); |
| 69 | void scan_import(CodeGen *g, ImportTableEntry *import); | 71 | void scan_import(CodeGen *g, ImportTableEntry *import); |
| ... | @@ -109,6 +111,9 @@ ConstExprValue *create_const_str_lit(CodeGen *g, Buf *str); | ... | @@ -109,6 +111,9 @@ ConstExprValue *create_const_str_lit(CodeGen *g, Buf *str); |
| 109 | void init_const_c_str_lit(CodeGen *g, ConstExprValue *const_val, Buf *c_str); | 111 | void init_const_c_str_lit(CodeGen *g, ConstExprValue *const_val, Buf *c_str); |
| 110 | ConstExprValue *create_const_c_str_lit(CodeGen *g, Buf *c_str); | 112 | ConstExprValue *create_const_c_str_lit(CodeGen *g, Buf *c_str); |
| 111 | 113 | ||
| 114 | void init_const_bigint(ConstExprValue *const_val, TypeTableEntry *type, const BigInt *bigint); | ||
| 115 | ConstExprValue *create_const_bigint(TypeTableEntry *type, const BigInt *bigint); | ||
| 116 | |||
| 112 | void init_const_unsigned_negative(ConstExprValue *const_val, TypeTableEntry *type, uint64_t x, bool negative); | 117 | void init_const_unsigned_negative(ConstExprValue *const_val, TypeTableEntry *type, uint64_t x, bool negative); |
| 113 | ConstExprValue *create_const_unsigned_negative(TypeTableEntry *type, uint64_t x, bool negative); | 118 | ConstExprValue *create_const_unsigned_negative(TypeTableEntry *type, uint64_t x, bool negative); |
| 114 | 119 | ||
| ... | @@ -121,8 +126,8 @@ ConstExprValue *create_const_usize(CodeGen *g, uint64_t x); | ... | @@ -121,8 +126,8 @@ ConstExprValue *create_const_usize(CodeGen *g, uint64_t x); |
| 121 | void init_const_float(ConstExprValue *const_val, TypeTableEntry *type, double value); | 126 | void init_const_float(ConstExprValue *const_val, TypeTableEntry *type, double value); |
| 122 | ConstExprValue *create_const_float(TypeTableEntry *type, double value); | 127 | ConstExprValue *create_const_float(TypeTableEntry *type, double value); |
| 123 | 128 | ||
| 124 | void init_const_enum_tag(ConstExprValue *const_val, TypeTableEntry *type, uint64_t tag); | 129 | void init_const_enum_tag(ConstExprValue *const_val, TypeTableEntry *type, const BigInt *tag); |
| 125 | ConstExprValue *create_const_enum_tag(TypeTableEntry *type, uint64_t tag); | 130 | ConstExprValue *create_const_enum_tag(TypeTableEntry *type, const BigInt *tag); |
| 126 | 131 | ||
| 127 | void init_const_bool(CodeGen *g, ConstExprValue *const_val, bool value); | 132 | void init_const_bool(CodeGen *g, ConstExprValue *const_val, bool value); |
| 128 | ConstExprValue *create_const_bool(CodeGen *g, bool value); | 133 | ConstExprValue *create_const_bool(CodeGen *g, bool value); |
src/ast_render.cpp+4| ... | @@ -677,6 +677,10 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) { | ... | @@ -677,6 +677,10 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) { |
| 677 | fprintf(ar->f, ": "); | 677 | fprintf(ar->f, ": "); |
| 678 | render_node_grouped(ar, field_node->data.struct_field.type); | 678 | render_node_grouped(ar, field_node->data.struct_field.type); |
| 679 | } | 679 | } |
| 680 | if (field_node->data.struct_field.value != nullptr) { | ||
| 681 | fprintf(ar->f, "= "); | ||
| 682 | render_node_grouped(ar, field_node->data.struct_field.value); | ||
| 683 | } | ||
| 680 | fprintf(ar->f, ",\n"); | 684 | fprintf(ar->f, ",\n"); |
| 681 | } | 685 | } |
| 682 | 686 |
src/bigint.cpp+32| ... | @@ -1224,3 +1224,35 @@ Cmp bigint_cmp_zero(const BigInt *op) { | ... | @@ -1224,3 +1224,35 @@ Cmp bigint_cmp_zero(const BigInt *op) { |
| 1224 | } | 1224 | } |
| 1225 | return op->is_negative ? CmpLT : CmpGT; | 1225 | return op->is_negative ? CmpLT : CmpGT; |
| 1226 | } | 1226 | } |
| 1227 | |||
| 1228 | uint32_t bigint_hash(BigInt x) { | ||
| 1229 | if (x.digit_count == 0) { | ||
| 1230 | return 0; | ||
| 1231 | } else { | ||
| 1232 | return bigint_ptr(&x)[0]; | ||
| 1233 | } | ||
| 1234 | } | ||
| 1235 | |||
| 1236 | bool bigint_eql(BigInt a, BigInt b) { | ||
| 1237 | return bigint_cmp(&a, &b) == CmpEQ; | ||
| 1238 | } | ||
| 1239 | |||
| 1240 | void bigint_incr(BigInt *x) { | ||
| 1241 | if (x->digit_count == 0) { | ||
| 1242 | bigint_init_unsigned(x, 1); | ||
| 1243 | return; | ||
| 1244 | } | ||
| 1245 | |||
| 1246 | if (x->digit_count == 1 && x->data.digit != UINT64_MAX) { | ||
| 1247 | x->data.digit += 1; | ||
| 1248 | return; | ||
| 1249 | } | ||
| 1250 | |||
| 1251 | BigInt copy; | ||
| 1252 | bigint_init_bigint(&copy, x); | ||
| 1253 | |||
| 1254 | BigInt one; | ||
| 1255 | bigint_init_unsigned(&one, 1); | ||
| 1256 | |||
| 1257 | bigint_add(x, &copy, &one); | ||
| 1258 | } |
src/bigint.hpp+5| ... | @@ -88,6 +88,11 @@ size_t bigint_bits_needed(const BigInt *op); | ... | @@ -88,6 +88,11 @@ size_t bigint_bits_needed(const BigInt *op); |
| 88 | // convenience functions | 88 | // convenience functions |
| 89 | Cmp bigint_cmp_zero(const BigInt *op); | 89 | Cmp bigint_cmp_zero(const BigInt *op); |
| 90 | 90 | ||
| 91 | void bigint_incr(BigInt *value); | ||
| 92 | |||
| 91 | bool mul_u64_overflow(uint64_t op1, uint64_t op2, uint64_t *result); | 93 | bool mul_u64_overflow(uint64_t op1, uint64_t op2, uint64_t *result); |
| 92 | 94 | ||
| 95 | uint32_t bigint_hash(BigInt x); | ||
| 96 | bool bigint_eql(BigInt a, BigInt b); | ||
| 97 | |||
| 93 | #endif | 98 | #endif |
src/codegen.cpp+19-12| ... | @@ -1362,8 +1362,12 @@ static LLVMValueRef bigint_to_llvm_const(LLVMTypeRef type_ref, BigInt *bigint) { | ... | @@ -1362,8 +1362,12 @@ static LLVMValueRef bigint_to_llvm_const(LLVMTypeRef type_ref, BigInt *bigint) { |
| 1362 | if (bigint->digit_count == 0) { | 1362 | if (bigint->digit_count == 0) { |
| 1363 | return LLVMConstNull(type_ref); | 1363 | return LLVMConstNull(type_ref); |
| 1364 | } | 1364 | } |
| 1365 | LLVMValueRef unsigned_val = LLVMConstIntOfArbitraryPrecision(type_ref, | 1365 | LLVMValueRef unsigned_val; |
| 1366 | bigint->digit_count, bigint_ptr(bigint)); | 1366 | if (bigint->digit_count == 1) { |
| 1367 | unsigned_val = LLVMConstInt(type_ref, bigint_ptr(bigint)[0], false); | ||
| 1368 | } else { | ||
| 1369 | unsigned_val = LLVMConstIntOfArbitraryPrecision(type_ref, bigint->digit_count, bigint_ptr(bigint)); | ||
| 1370 | } | ||
| 1367 | if (bigint->is_negative) { | 1371 | if (bigint->is_negative) { |
| 1368 | return LLVMConstNeg(unsigned_val); | 1372 | return LLVMConstNeg(unsigned_val); |
| 1369 | } else { | 1373 | } else { |
| ... | @@ -2420,9 +2424,10 @@ static LLVMValueRef ir_render_union_field_ptr(CodeGen *g, IrExecutable *executab | ... | @@ -2420,9 +2424,10 @@ static LLVMValueRef ir_render_union_field_ptr(CodeGen *g, IrExecutable *executab |
| 2420 | if (ir_want_debug_safety(g, &instruction->base)) { | 2424 | if (ir_want_debug_safety(g, &instruction->base)) { |
| 2421 | LLVMValueRef tag_field_ptr = LLVMBuildStructGEP(g->builder, union_ptr, union_type->data.unionation.gen_tag_index, ""); | 2425 | LLVMValueRef tag_field_ptr = LLVMBuildStructGEP(g->builder, union_ptr, union_type->data.unionation.gen_tag_index, ""); |
| 2422 | LLVMValueRef tag_value = gen_load_untyped(g, tag_field_ptr, 0, false, ""); | 2426 | LLVMValueRef tag_value = gen_load_untyped(g, tag_field_ptr, 0, false, ""); |
| 2423 | LLVMValueRef expected_tag_value = LLVMConstInt(union_type->data.unionation.tag_type->type_ref, | ||
| 2424 | field->value, false); | ||
| 2425 | 2427 | ||
| 2428 | |||
| 2429 | LLVMValueRef expected_tag_value = bigint_to_llvm_const(union_type->data.unionation.tag_type->type_ref, | ||
| 2430 | &field->value); | ||
| 2426 | LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn_val, "UnionCheckOk"); | 2431 | LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn_val, "UnionCheckOk"); |
| 2427 | LLVMBasicBlockRef bad_block = LLVMAppendBasicBlock(g->cur_fn_val, "UnionCheckFail"); | 2432 | LLVMBasicBlockRef bad_block = LLVMAppendBasicBlock(g->cur_fn_val, "UnionCheckFail"); |
| 2428 | LLVMValueRef ok_val = LLVMBuildICmp(g->builder, LLVMIntEQ, tag_value, expected_tag_value, ""); | 2433 | LLVMValueRef ok_val = LLVMBuildICmp(g->builder, LLVMIntEQ, tag_value, expected_tag_value, ""); |
| ... | @@ -3364,9 +3369,9 @@ static LLVMValueRef ir_render_enum_tag(CodeGen *g, IrExecutable *executable, IrI | ... | @@ -3364,9 +3369,9 @@ static LLVMValueRef ir_render_enum_tag(CodeGen *g, IrExecutable *executable, IrI |
| 3364 | 3369 | ||
| 3365 | static LLVMValueRef ir_render_init_enum(CodeGen *g, IrExecutable *executable, IrInstructionInitEnum *instruction) { | 3370 | static LLVMValueRef ir_render_init_enum(CodeGen *g, IrExecutable *executable, IrInstructionInitEnum *instruction) { |
| 3366 | TypeTableEntry *enum_type = instruction->enum_type; | 3371 | TypeTableEntry *enum_type = instruction->enum_type; |
| 3367 | uint32_t value = instruction->field->value; | ||
| 3368 | LLVMTypeRef tag_type_ref = enum_type->data.enumeration.tag_type->type_ref; | 3372 | LLVMTypeRef tag_type_ref = enum_type->data.enumeration.tag_type->type_ref; |
| 3369 | LLVMValueRef tag_value = LLVMConstInt(tag_type_ref, value, false); | 3373 | |
| 3374 | LLVMValueRef tag_value = bigint_to_llvm_const(tag_type_ref, &instruction->field->value); | ||
| 3370 | 3375 | ||
| 3371 | if (enum_type->data.enumeration.gen_field_count == 0) | 3376 | if (enum_type->data.enumeration.gen_field_count == 0) |
| 3372 | return tag_value; | 3377 | return tag_value; |
| ... | @@ -3429,8 +3434,9 @@ static LLVMValueRef ir_render_union_init(CodeGen *g, IrExecutable *executable, I | ... | @@ -3429,8 +3434,9 @@ static LLVMValueRef ir_render_union_init(CodeGen *g, IrExecutable *executable, I |
| 3429 | if (union_type->data.unionation.gen_tag_index != SIZE_MAX) { | 3434 | if (union_type->data.unionation.gen_tag_index != SIZE_MAX) { |
| 3430 | LLVMValueRef tag_field_ptr = LLVMBuildStructGEP(g->builder, instruction->tmp_ptr, | 3435 | LLVMValueRef tag_field_ptr = LLVMBuildStructGEP(g->builder, instruction->tmp_ptr, |
| 3431 | union_type->data.unionation.gen_tag_index, ""); | 3436 | union_type->data.unionation.gen_tag_index, ""); |
| 3432 | LLVMValueRef tag_value = LLVMConstInt(union_type->data.unionation.tag_type->type_ref, | 3437 | |
| 3433 | type_union_field->value, false); | 3438 | LLVMValueRef tag_value = bigint_to_llvm_const(union_type->data.unionation.tag_type->type_ref, |
| 3439 | &type_union_field->value); | ||
| 3434 | gen_store_untyped(g, tag_value, tag_field_ptr, 0, false); | 3440 | gen_store_untyped(g, tag_value, tag_field_ptr, 0, false); |
| 3435 | 3441 | ||
| 3436 | uncasted_union_ptr = LLVMBuildStructGEP(g->builder, instruction->tmp_ptr, | 3442 | uncasted_union_ptr = LLVMBuildStructGEP(g->builder, instruction->tmp_ptr, |
| ... | @@ -4039,7 +4045,8 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val) { | ... | @@ -4039,7 +4045,8 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val) { |
| 4039 | return union_value_ref; | 4045 | return union_value_ref; |
| 4040 | } | 4046 | } |
| 4041 | 4047 | ||
| 4042 | LLVMValueRef tag_value = LLVMConstInt(type_entry->data.unionation.tag_type->type_ref, const_val->data.x_union.tag, false); | 4048 | LLVMValueRef tag_value = bigint_to_llvm_const(type_entry->data.unionation.tag_type->type_ref, |
| 4049 | &const_val->data.x_union.tag); | ||
| 4043 | 4050 | ||
| 4044 | LLVMValueRef fields[2]; | 4051 | LLVMValueRef fields[2]; |
| 4045 | fields[type_entry->data.unionation.gen_union_index] = union_value_ref; | 4052 | fields[type_entry->data.unionation.gen_union_index] = union_value_ref; |
| ... | @@ -4055,13 +4062,13 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val) { | ... | @@ -4055,13 +4062,13 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val) { |
| 4055 | case TypeTableEntryIdEnum: | 4062 | case TypeTableEntryIdEnum: |
| 4056 | { | 4063 | { |
| 4057 | LLVMTypeRef tag_type_ref = type_entry->data.enumeration.tag_type->type_ref; | 4064 | LLVMTypeRef tag_type_ref = type_entry->data.enumeration.tag_type->type_ref; |
| 4058 | LLVMValueRef tag_value = LLVMConstInt(tag_type_ref, const_val->data.x_enum.tag, false); | 4065 | LLVMValueRef tag_value = bigint_to_llvm_const(tag_type_ref, &const_val->data.x_enum.tag); |
| 4059 | if (type_entry->data.enumeration.gen_field_count == 0) { | 4066 | if (type_entry->data.enumeration.gen_field_count == 0) { |
| 4060 | return tag_value; | 4067 | return tag_value; |
| 4061 | } else { | 4068 | } else { |
| 4062 | LLVMTypeRef union_type_ref = type_entry->data.enumeration.union_type_ref; | 4069 | LLVMTypeRef union_type_ref = type_entry->data.enumeration.union_type_ref; |
| 4063 | TypeEnumField *enum_field = &type_entry->data.enumeration.fields[const_val->data.x_enum.tag]; | 4070 | TypeEnumField *enum_field = find_enum_field_by_tag(type_entry, &const_val->data.x_enum.tag); |
| 4064 | assert(enum_field->value == const_val->data.x_enum.tag); | 4071 | assert(bigint_cmp(&enum_field->value, &const_val->data.x_enum.tag) == CmpEQ); |
| 4065 | LLVMValueRef union_value; | 4072 | LLVMValueRef union_value; |
| 4066 | 4073 | ||
| 4067 | bool make_unnamed_struct; | 4074 | bool make_unnamed_struct; |
src/ir.cpp+66-43| ... | @@ -8387,7 +8387,7 @@ static IrInstruction *ir_analyze_enum_to_int(IrAnalyze *ira, IrInstruction *sour | ... | @@ -8387,7 +8387,7 @@ static IrInstruction *ir_analyze_enum_to_int(IrAnalyze *ira, IrInstruction *sour |
| 8387 | return ira->codegen->invalid_instruction; | 8387 | return ira->codegen->invalid_instruction; |
| 8388 | IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope, | 8388 | IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope, |
| 8389 | source_instr->source_node, wanted_type); | 8389 | source_instr->source_node, wanted_type); |
| 8390 | init_const_unsigned_negative(&result->value, wanted_type, val->data.x_enum.tag, false); | 8390 | init_const_bigint(&result->value, wanted_type, &val->data.x_enum.tag); |
| 8391 | return result; | 8391 | return result; |
| 8392 | } | 8392 | } |
| 8393 | 8393 | ||
| ... | @@ -8469,7 +8469,7 @@ static IrInstruction *ir_analyze_int_to_enum(IrAnalyze *ira, IrInstruction *sour | ... | @@ -8469,7 +8469,7 @@ static IrInstruction *ir_analyze_int_to_enum(IrAnalyze *ira, IrInstruction *sour |
| 8469 | 8469 | ||
| 8470 | IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope, | 8470 | IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope, |
| 8471 | source_instr->source_node, wanted_type); | 8471 | source_instr->source_node, wanted_type); |
| 8472 | result->value.data.x_enum.tag = bigint_as_unsigned(&val->data.x_bigint); | 8472 | bigint_init_bigint(&result->value.data.x_enum.tag, &val->data.x_bigint); |
| 8473 | return result; | 8473 | return result; |
| 8474 | } | 8474 | } |
| 8475 | 8475 | ||
| ... | @@ -9148,7 +9148,7 @@ static bool ir_resolve_atomic_order(IrAnalyze *ira, IrInstruction *value, Atomic | ... | @@ -9148,7 +9148,7 @@ static bool ir_resolve_atomic_order(IrAnalyze *ira, IrInstruction *value, Atomic |
| 9148 | if (!const_val) | 9148 | if (!const_val) |
| 9149 | return false; | 9149 | return false; |
| 9150 | 9150 | ||
| 9151 | *out = (AtomicOrder)const_val->data.x_enum.tag; | 9151 | *out = (AtomicOrder)bigint_as_unsigned(&const_val->data.x_enum.tag); |
| 9152 | return true; | 9152 | return true; |
| 9153 | } | 9153 | } |
| 9154 | 9154 | ||
| ... | @@ -9168,7 +9168,27 @@ static bool ir_resolve_global_linkage(IrAnalyze *ira, IrInstruction *value, Glob | ... | @@ -9168,7 +9168,27 @@ static bool ir_resolve_global_linkage(IrAnalyze *ira, IrInstruction *value, Glob |
| 9168 | if (!const_val) | 9168 | if (!const_val) |
| 9169 | return false; | 9169 | return false; |
| 9170 | 9170 | ||
| 9171 | *out = (GlobalLinkageId)const_val->data.x_enum.tag; | 9171 | *out = (GlobalLinkageId)bigint_as_unsigned(&const_val->data.x_enum.tag); |
| 9172 | return true; | ||
| 9173 | } | ||
| 9174 | |||
| 9175 | static bool ir_resolve_float_mode(IrAnalyze *ira, IrInstruction *value, FloatMode *out) { | ||
| 9176 | if (type_is_invalid(value->value.type)) | ||
| 9177 | return false; | ||
| 9178 | |||
| 9179 | ConstExprValue *float_mode_val = get_builtin_value(ira->codegen, "FloatMode"); | ||
| 9180 | assert(float_mode_val->type->id == TypeTableEntryIdMetaType); | ||
| 9181 | TypeTableEntry *float_mode_type = float_mode_val->data.x_type; | ||
| 9182 | |||
| 9183 | IrInstruction *casted_value = ir_implicit_cast(ira, value, float_mode_type); | ||
| 9184 | if (type_is_invalid(casted_value->value.type)) | ||
| 9185 | return false; | ||
| 9186 | |||
| 9187 | ConstExprValue *const_val = ir_resolve_const(ira, casted_value, UndefBad); | ||
| 9188 | if (!const_val) | ||
| 9189 | return false; | ||
| 9190 | |||
| 9191 | *out = (FloatMode)bigint_as_unsigned(&const_val->data.x_enum.tag); | ||
| 9172 | return true; | 9192 | return true; |
| 9173 | } | 9193 | } |
| 9174 | 9194 | ||
| ... | @@ -11825,13 +11845,13 @@ static TypeTableEntry *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstru | ... | @@ -11825,13 +11845,13 @@ static TypeTableEntry *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstru |
| 11825 | bool ptr_is_const = true; | 11845 | bool ptr_is_const = true; |
| 11826 | bool ptr_is_volatile = false; | 11846 | bool ptr_is_volatile = false; |
| 11827 | return ir_analyze_const_ptr(ira, &field_ptr_instruction->base, | 11847 | return ir_analyze_const_ptr(ira, &field_ptr_instruction->base, |
| 11828 | create_const_enum_tag(child_type, field->value), child_type, | 11848 | create_const_enum_tag(child_type, &field->value), child_type, |
| 11829 | ConstPtrMutComptimeConst, ptr_is_const, ptr_is_volatile); | 11849 | ConstPtrMutComptimeConst, ptr_is_const, ptr_is_volatile); |
| 11830 | } else { | 11850 | } else { |
| 11831 | bool ptr_is_const = true; | 11851 | bool ptr_is_const = true; |
| 11832 | bool ptr_is_volatile = false; | 11852 | bool ptr_is_volatile = false; |
| 11833 | return ir_analyze_const_ptr(ira, &field_ptr_instruction->base, | 11853 | return ir_analyze_const_ptr(ira, &field_ptr_instruction->base, |
| 11834 | create_const_unsigned_negative(child_type->data.enumeration.tag_type, field->value, false), | 11854 | create_const_bigint(child_type->data.enumeration.tag_type, &field->value), |
| 11835 | child_type->data.enumeration.tag_type, | 11855 | child_type->data.enumeration.tag_type, |
| 11836 | ConstPtrMutComptimeConst, ptr_is_const, ptr_is_volatile); | 11856 | ConstPtrMutComptimeConst, ptr_is_const, ptr_is_volatile); |
| 11837 | } | 11857 | } |
| ... | @@ -12420,21 +12440,11 @@ static TypeTableEntry *ir_analyze_instruction_set_float_mode(IrAnalyze *ira, | ... | @@ -12420,21 +12440,11 @@ static TypeTableEntry *ir_analyze_instruction_set_float_mode(IrAnalyze *ira, |
| 12420 | return ira->codegen->builtin_types.entry_invalid; | 12440 | return ira->codegen->builtin_types.entry_invalid; |
| 12421 | } | 12441 | } |
| 12422 | 12442 | ||
| 12423 | ConstExprValue *float_mode_val = get_builtin_value(ira->codegen, "FloatMode"); | ||
| 12424 | assert(float_mode_val->type->id == TypeTableEntryIdMetaType); | ||
| 12425 | TypeTableEntry *float_mode_enum_type = float_mode_val->data.x_type; | ||
| 12426 | |||
| 12427 | IrInstruction *float_mode_value = instruction->mode_value->other; | 12443 | IrInstruction *float_mode_value = instruction->mode_value->other; |
| 12428 | if (type_is_invalid(float_mode_value->value.type)) | ||
| 12429 | return ira->codegen->builtin_types.entry_invalid; | ||
| 12430 | IrInstruction *casted_value = ir_implicit_cast(ira, float_mode_value, float_mode_enum_type); | ||
| 12431 | if (type_is_invalid(casted_value->value.type)) | ||
| 12432 | return ira->codegen->builtin_types.entry_invalid; | ||
| 12433 | ConstExprValue *mode_val = ir_resolve_const(ira, casted_value, UndefBad); | ||
| 12434 | if (!mode_val) | ||
| 12435 | return ira->codegen->builtin_types.entry_invalid; | ||
| 12436 | 12444 | ||
| 12437 | bool want_fast_math = (mode_val->data.x_enum.tag == FloatModeOptimized); | 12445 | FloatMode float_mode_scalar; |
| 12446 | if (!ir_resolve_float_mode(ira, float_mode_value, &float_mode_scalar)) | ||
| 12447 | return ira->codegen->builtin_types.entry_invalid; | ||
| 12438 | 12448 | ||
| 12439 | AstNode *source_node = instruction->base.source_node; | 12449 | AstNode *source_node = instruction->base.source_node; |
| 12440 | if (*fast_math_set_node_ptr) { | 12450 | if (*fast_math_set_node_ptr) { |
| ... | @@ -12444,7 +12454,7 @@ static TypeTableEntry *ir_analyze_instruction_set_float_mode(IrAnalyze *ira, | ... | @@ -12444,7 +12454,7 @@ static TypeTableEntry *ir_analyze_instruction_set_float_mode(IrAnalyze *ira, |
| 12444 | return ira->codegen->builtin_types.entry_invalid; | 12454 | return ira->codegen->builtin_types.entry_invalid; |
| 12445 | } | 12455 | } |
| 12446 | *fast_math_set_node_ptr = source_node; | 12456 | *fast_math_set_node_ptr = source_node; |
| 12447 | *fast_math_off_ptr = !want_fast_math; | 12457 | *fast_math_off_ptr = (float_mode_scalar == FloatModeStrict); |
| 12448 | 12458 | ||
| 12449 | ir_build_const_from(ira, &instruction->base); | 12459 | ir_build_const_from(ira, &instruction->base); |
| 12450 | return ira->codegen->builtin_types.entry_void; | 12460 | return ira->codegen->builtin_types.entry_void; |
| ... | @@ -12835,7 +12845,7 @@ static IrInstruction *ir_analyze_enum_tag(IrAnalyze *ira, IrInstruction *source_ | ... | @@ -12835,7 +12845,7 @@ static IrInstruction *ir_analyze_enum_tag(IrAnalyze *ira, IrInstruction *source_ |
| 12835 | source_instr->scope, source_instr->source_node); | 12845 | source_instr->scope, source_instr->source_node); |
| 12836 | const_instruction->base.value.type = tag_type; | 12846 | const_instruction->base.value.type = tag_type; |
| 12837 | const_instruction->base.value.special = ConstValSpecialStatic; | 12847 | const_instruction->base.value.special = ConstValSpecialStatic; |
| 12838 | bigint_init_unsigned(&const_instruction->base.value.data.x_bigint, val->data.x_enum.tag); | 12848 | bigint_init_bigint(&const_instruction->base.value.data.x_bigint, &val->data.x_enum.tag); |
| 12839 | return &const_instruction->base; | 12849 | return &const_instruction->base; |
| 12840 | } | 12850 | } |
| 12841 | 12851 | ||
| ... | @@ -13005,7 +13015,7 @@ static TypeTableEntry *ir_analyze_instruction_switch_target(IrAnalyze *ira, | ... | @@ -13005,7 +13015,7 @@ static TypeTableEntry *ir_analyze_instruction_switch_target(IrAnalyze *ira, |
| 13005 | assert(tag_type != nullptr); | 13015 | assert(tag_type != nullptr); |
| 13006 | if (pointee_val) { | 13016 | if (pointee_val) { |
| 13007 | ConstExprValue *out_val = ir_build_const_from(ira, &switch_target_instruction->base); | 13017 | ConstExprValue *out_val = ir_build_const_from(ira, &switch_target_instruction->base); |
| 13008 | bigint_init_unsigned(&out_val->data.x_bigint, pointee_val->data.x_enum.tag); | 13018 | bigint_init_bigint(&out_val->data.x_bigint, &pointee_val->data.x_enum.tag); |
| 13009 | return tag_type; | 13019 | return tag_type; |
| 13010 | } | 13020 | } |
| 13011 | 13021 | ||
| ... | @@ -13056,9 +13066,9 @@ static TypeTableEntry *ir_analyze_instruction_switch_var(IrAnalyze *ira, IrInstr | ... | @@ -13056,9 +13066,9 @@ static TypeTableEntry *ir_analyze_instruction_switch_var(IrAnalyze *ira, IrInstr |
| 13056 | 13066 | ||
| 13057 | TypeEnumField *field; | 13067 | TypeEnumField *field; |
| 13058 | if (prong_value->value.type->id == TypeTableEntryIdEnumTag) { | 13068 | if (prong_value->value.type->id == TypeTableEntryIdEnumTag) { |
| 13059 | field = &target_type->data.enumeration.fields[bigint_as_unsigned(&prong_val->data.x_bigint)]; | 13069 | field = find_enum_field_by_tag(target_type, &prong_val->data.x_bigint); |
| 13060 | } else if (prong_value->value.type->id == TypeTableEntryIdEnum) { | 13070 | } else if (prong_value->value.type->id == TypeTableEntryIdEnum) { |
| 13061 | field = &target_type->data.enumeration.fields[prong_val->data.x_enum.tag]; | 13071 | field = find_enum_field_by_tag(target_type, &prong_val->data.x_enum.tag); |
| 13062 | } else { | 13072 | } else { |
| 13063 | zig_unreachable(); | 13073 | zig_unreachable(); |
| 13064 | } | 13074 | } |
| ... | @@ -13503,8 +13513,8 @@ static TypeTableEntry *ir_analyze_instruction_container_init_list(IrAnalyze *ira | ... | @@ -13503,8 +13513,8 @@ static TypeTableEntry *ir_analyze_instruction_container_init_list(IrAnalyze *ira |
| 13503 | 13513 | ||
| 13504 | TypeTableEntry *enum_type = container_type_value->value.type->data.enum_tag.enum_type; | 13514 | TypeTableEntry *enum_type = container_type_value->value.type->data.enum_tag.enum_type; |
| 13505 | 13515 | ||
| 13506 | uint64_t tag_uint = bigint_as_unsigned(&tag_value->data.x_bigint); | 13516 | TypeEnumField *field = find_enum_field_by_tag(enum_type, &tag_value->data.x_bigint); |
| 13507 | TypeEnumField *field = &enum_type->data.enumeration.fields[tag_uint]; | 13517 | assert(field != nullptr); |
| 13508 | TypeTableEntry *this_field_type = field->type_entry; | 13518 | TypeTableEntry *this_field_type = field->type_entry; |
| 13509 | 13519 | ||
| 13510 | IrInstruction *init_value = instruction->items[0]->other; | 13520 | IrInstruction *init_value = instruction->items[0]->other; |
| ... | @@ -13520,7 +13530,7 @@ static TypeTableEntry *ir_analyze_instruction_container_init_list(IrAnalyze *ira | ... | @@ -13520,7 +13530,7 @@ static TypeTableEntry *ir_analyze_instruction_container_init_list(IrAnalyze *ira |
| 13520 | if (!init_val) | 13530 | if (!init_val) |
| 13521 | return ira->codegen->builtin_types.entry_invalid; | 13531 | return ira->codegen->builtin_types.entry_invalid; |
| 13522 | ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base); | 13532 | ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base); |
| 13523 | out_val->data.x_enum.tag = tag_uint; | 13533 | bigint_init_bigint(&out_val->data.x_enum.tag, &tag_value->data.x_bigint); |
| 13524 | out_val->data.x_enum.payload = init_val; | 13534 | out_val->data.x_enum.payload = init_val; |
| 13525 | return enum_type; | 13535 | return enum_type; |
| 13526 | } | 13536 | } |
| ... | @@ -13859,7 +13869,7 @@ static TypeTableEntry *ir_analyze_instruction_type_id(IrAnalyze *ira, | ... | @@ -13859,7 +13869,7 @@ static TypeTableEntry *ir_analyze_instruction_type_id(IrAnalyze *ira, |
| 13859 | TypeTableEntry *result_type = var_value->data.x_type; | 13869 | TypeTableEntry *result_type = var_value->data.x_type; |
| 13860 | 13870 | ||
| 13861 | ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base); | 13871 | ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base); |
| 13862 | out_val->data.x_enum.tag = type_id_index(type_entry->id); | 13872 | bigint_init_unsigned(&out_val->data.x_enum.tag, type_id_index(type_entry->id)); |
| 13863 | return result_type; | 13873 | return result_type; |
| 13864 | } | 13874 | } |
| 13865 | 13875 | ||
| ... | @@ -15117,7 +15127,9 @@ static TypeTableEntry *ir_analyze_instruction_check_switch_prongs(IrAnalyze *ira | ... | @@ -15117,7 +15127,9 @@ static TypeTableEntry *ir_analyze_instruction_check_switch_prongs(IrAnalyze *ira |
| 15117 | 15127 | ||
| 15118 | if (switch_type->id == TypeTableEntryIdEnumTag) { | 15128 | if (switch_type->id == TypeTableEntryIdEnumTag) { |
| 15119 | TypeTableEntry *enum_type = switch_type->data.enum_tag.enum_type; | 15129 | TypeTableEntry *enum_type = switch_type->data.enum_tag.enum_type; |
| 15120 | AstNode **field_prev_uses = allocate<AstNode *>(enum_type->data.enumeration.src_field_count); | 15130 | HashMap<BigInt, AstNode *, bigint_hash, bigint_eql> field_prev_uses = {}; |
| 15131 | field_prev_uses.init(enum_type->data.enumeration.src_field_count); | ||
| 15132 | |||
| 15121 | for (size_t range_i = 0; range_i < instruction->range_count; range_i += 1) { | 15133 | for (size_t range_i = 0; range_i < instruction->range_count; range_i += 1) { |
| 15122 | IrInstructionCheckSwitchProngsRange *range = &instruction->ranges[range_i]; | 15134 | IrInstructionCheckSwitchProngsRange *range = &instruction->ranges[range_i]; |
| 15123 | 15135 | ||
| ... | @@ -15129,41 +15141,52 @@ static TypeTableEntry *ir_analyze_instruction_check_switch_prongs(IrAnalyze *ira | ... | @@ -15129,41 +15141,52 @@ static TypeTableEntry *ir_analyze_instruction_check_switch_prongs(IrAnalyze *ira |
| 15129 | if (type_is_invalid(end_value->value.type)) | 15141 | if (type_is_invalid(end_value->value.type)) |
| 15130 | return ira->codegen->builtin_types.entry_invalid; | 15142 | return ira->codegen->builtin_types.entry_invalid; |
| 15131 | 15143 | ||
| 15132 | size_t start_index; | 15144 | BigInt start_index; |
| 15133 | size_t end_index; | 15145 | BigInt end_index; |
| 15134 | if (start_value->value.type->id == TypeTableEntryIdEnumTag) { | 15146 | if (start_value->value.type->id == TypeTableEntryIdEnumTag) { |
| 15135 | start_index = bigint_as_unsigned(&start_value->value.data.x_bigint); | 15147 | bigint_init_bigint(&start_index, &start_value->value.data.x_bigint); |
| 15136 | } else if (start_value->value.type->id == TypeTableEntryIdEnum) { | 15148 | } else if (start_value->value.type->id == TypeTableEntryIdEnum) { |
| 15137 | start_index = start_value->value.data.x_enum.tag; | 15149 | bigint_init_bigint(&start_index, &start_value->value.data.x_enum.tag); |
| 15138 | } else { | 15150 | } else { |
| 15139 | zig_unreachable(); | 15151 | zig_unreachable(); |
| 15140 | } | 15152 | } |
| 15141 | if (end_value->value.type->id == TypeTableEntryIdEnumTag) { | 15153 | if (end_value->value.type->id == TypeTableEntryIdEnumTag) { |
| 15142 | end_index = bigint_as_unsigned(&end_value->value.data.x_bigint); | 15154 | bigint_init_bigint(&end_index, &end_value->value.data.x_bigint); |
| 15143 | } else if (end_value->value.type->id == TypeTableEntryIdEnum) { | 15155 | } else if (end_value->value.type->id == TypeTableEntryIdEnum) { |
| 15144 | end_index = end_value->value.data.x_enum.tag; | 15156 | bigint_init_bigint(&end_index, &end_value->value.data.x_enum.tag); |
| 15145 | } else { | 15157 | } else { |
| 15146 | zig_unreachable(); | 15158 | zig_unreachable(); |
| 15147 | } | 15159 | } |
| 15148 | 15160 | ||
| 15149 | for (size_t field_index = start_index; field_index <= end_index; field_index += 1) { | 15161 | BigInt field_index; |
| 15150 | AstNode *prev_node = field_prev_uses[field_index]; | 15162 | bigint_init_bigint(&field_index, &start_index); |
| 15151 | if (prev_node != nullptr) { | 15163 | for (;;) { |
| 15152 | TypeEnumField *type_enum_field = &enum_type->data.enumeration.fields[field_index]; | 15164 | Cmp cmp = bigint_cmp(&field_index, &end_index); |
| 15165 | if (cmp == CmpGT) { | ||
| 15166 | break; | ||
| 15167 | } | ||
| 15168 | auto entry = field_prev_uses.put_unique(field_index, start_value->source_node); | ||
| 15169 | if (entry) { | ||
| 15170 | AstNode *prev_node = entry->value; | ||
| 15171 | TypeEnumField *enum_field = find_enum_field_by_tag(enum_type, &field_index); | ||
| 15172 | assert(enum_field != nullptr); | ||
| 15153 | ErrorMsg *msg = ir_add_error(ira, start_value, | 15173 | ErrorMsg *msg = ir_add_error(ira, start_value, |
| 15154 | buf_sprintf("duplicate switch value: '%s.%s'", buf_ptr(&enum_type->name), | 15174 | buf_sprintf("duplicate switch value: '%s.%s'", buf_ptr(&enum_type->name), |
| 15155 | buf_ptr(type_enum_field->name))); | 15175 | buf_ptr(enum_field->name))); |
| 15156 | add_error_note(ira->codegen, msg, prev_node, buf_sprintf("other value is here")); | 15176 | add_error_note(ira->codegen, msg, prev_node, buf_sprintf("other value is here")); |
| 15157 | } | 15177 | } |
| 15158 | field_prev_uses[field_index] = start_value->source_node; | 15178 | bigint_incr(&field_index); |
| 15159 | } | 15179 | } |
| 15160 | } | 15180 | } |
| 15161 | if (!instruction->have_else_prong) { | 15181 | if (!instruction->have_else_prong) { |
| 15162 | for (uint32_t i = 0; i < enum_type->data.enumeration.src_field_count; i += 1) { | 15182 | for (uint32_t i = 0; i < enum_type->data.enumeration.src_field_count; i += 1) { |
| 15163 | if (field_prev_uses[i] == nullptr) { | 15183 | TypeEnumField *enum_field = &enum_type->data.enumeration.fields[i]; |
| 15184 | |||
| 15185 | auto entry = field_prev_uses.maybe_get(enum_field->value); | ||
| 15186 | if (!entry) { | ||
| 15164 | ir_add_error(ira, &instruction->base, | 15187 | ir_add_error(ira, &instruction->base, |
| 15165 | buf_sprintf("enumeration value '%s.%s' not handled in switch", buf_ptr(&enum_type->name), | 15188 | buf_sprintf("enumeration value '%s.%s' not handled in switch", buf_ptr(&enum_type->name), |
| 15166 | buf_ptr(enum_type->data.enumeration.fields[i].name))); | 15189 | buf_ptr(enum_field->name))); |
| 15167 | } | 15190 | } |
| 15168 | } | 15191 | } |
| 15169 | } | 15192 | } |
src/parser.cpp+25-23| ... | @@ -2379,7 +2379,7 @@ static AstNode *ast_parse_use(ParseContext *pc, size_t *token_index, VisibMod vi | ... | @@ -2379,7 +2379,7 @@ static AstNode *ast_parse_use(ParseContext *pc, size_t *token_index, VisibMod vi |
| 2379 | /* | 2379 | /* |
| 2380 | ContainerDecl = option("extern" | "packed") ("struct" | "union" | ("enum" option(GroupedExpression))) "{" many(ContainerMember) "}" | 2380 | ContainerDecl = option("extern" | "packed") ("struct" | "union" | ("enum" option(GroupedExpression))) "{" many(ContainerMember) "}" |
| 2381 | ContainerMember = (ContainerField | FnDef | GlobalVarDecl) | 2381 | ContainerMember = (ContainerField | FnDef | GlobalVarDecl) |
| 2382 | ContainerField = Symbol option(":" Expression) "," | 2382 | ContainerField = Symbol option(":" PrefixOpExpression option("=" PrefixOpExpression "," |
| 2383 | */ | 2383 | */ |
| 2384 | static AstNode *ast_parse_container_decl(ParseContext *pc, size_t *token_index, bool mandatory) { | 2384 | static AstNode *ast_parse_container_decl(ParseContext *pc, size_t *token_index, bool mandatory) { |
| 2385 | Token *first_token = &pc->tokens->at(*token_index); | 2385 | Token *first_token = &pc->tokens->at(*token_index); |
| ... | @@ -2414,10 +2414,7 @@ static AstNode *ast_parse_container_decl(ParseContext *pc, size_t *token_index, | ... | @@ -2414,10 +2414,7 @@ static AstNode *ast_parse_container_decl(ParseContext *pc, size_t *token_index, |
| 2414 | AstNode *node = ast_create_node(pc, NodeTypeContainerDecl, first_token); | 2414 | AstNode *node = ast_create_node(pc, NodeTypeContainerDecl, first_token); |
| 2415 | node->data.container_decl.layout = layout; | 2415 | node->data.container_decl.layout = layout; |
| 2416 | node->data.container_decl.kind = kind; | 2416 | node->data.container_decl.kind = kind; |
| 2417 | 2417 | node->data.container_decl.init_arg_expr = ast_parse_grouped_expr(pc, token_index, false); | |
| 2418 | if (kind == ContainerKindEnum || kind == ContainerKindStruct) { | ||
| 2419 | node->data.container_decl.init_arg_expr = ast_parse_grouped_expr(pc, token_index, false); | ||
| 2420 | } | ||
| 2421 | 2418 | ||
| 2422 | ast_eat_token(pc, token_index, TokenIdLBrace); | 2419 | ast_eat_token(pc, token_index, TokenIdLBrace); |
| 2423 | 2420 | ||
| ... | @@ -2456,31 +2453,35 @@ static AstNode *ast_parse_container_decl(ParseContext *pc, size_t *token_index, | ... | @@ -2456,31 +2453,35 @@ static AstNode *ast_parse_container_decl(ParseContext *pc, size_t *token_index, |
| 2456 | AstNode *field_node = ast_create_node(pc, NodeTypeStructField, token); | 2453 | AstNode *field_node = ast_create_node(pc, NodeTypeStructField, token); |
| 2457 | *token_index += 1; | 2454 | *token_index += 1; |
| 2458 | 2455 | ||
| 2456 | node->data.container_decl.fields.append(field_node); | ||
| 2459 | field_node->data.struct_field.visib_mod = visib_mod; | 2457 | field_node->data.struct_field.visib_mod = visib_mod; |
| 2460 | field_node->data.struct_field.name = token_buf(token); | 2458 | field_node->data.struct_field.name = token_buf(token); |
| 2461 | 2459 | ||
| 2462 | Token *token = &pc->tokens->at(*token_index); | 2460 | Token *colon_token = &pc->tokens->at(*token_index); |
| 2463 | if (token->id == TokenIdComma || token->id == TokenIdRBrace) { | 2461 | if (colon_token->id == TokenIdColon) { |
| 2464 | field_node->data.struct_field.type = ast_create_void_type_node(pc, token); | ||
| 2465 | *token_index += 1; | 2462 | *token_index += 1; |
| 2466 | node->data.container_decl.fields.append(field_node); | 2463 | field_node->data.struct_field.type = ast_parse_prefix_op_expr(pc, token_index, true); |
| 2467 | |||
| 2468 | if (token->id == TokenIdRBrace) { | ||
| 2469 | break; | ||
| 2470 | } | ||
| 2471 | } else { | 2464 | } else { |
| 2472 | ast_eat_token(pc, token_index, TokenIdColon); | 2465 | field_node->data.struct_field.type = ast_create_void_type_node(pc, colon_token); |
| 2473 | field_node->data.struct_field.type = ast_parse_expression(pc, token_index, true); | 2466 | } |
| 2474 | node->data.container_decl.fields.append(field_node); | 2467 | Token *eq_token = &pc->tokens->at(*token_index); |
| 2468 | if (eq_token->id == TokenIdEq) { | ||
| 2469 | *token_index += 1; | ||
| 2470 | field_node->data.struct_field.value = ast_parse_prefix_op_expr(pc, token_index, true); | ||
| 2471 | } | ||
| 2475 | 2472 | ||
| 2476 | Token *token = &pc->tokens->at(*token_index); | 2473 | Token *next_token = &pc->tokens->at(*token_index); |
| 2477 | if (token->id == TokenIdRBrace) { | 2474 | if (next_token->id == TokenIdComma) { |
| 2478 | *token_index += 1; | 2475 | *token_index += 1; |
| 2479 | break; | 2476 | continue; |
| 2480 | } else { | ||
| 2481 | ast_eat_token(pc, token_index, TokenIdComma); | ||
| 2482 | } | ||
| 2483 | } | 2477 | } |
| 2478 | |||
| 2479 | if (next_token->id == TokenIdRBrace) { | ||
| 2480 | *token_index += 1; | ||
| 2481 | break; | ||
| 2482 | } | ||
| 2483 | |||
| 2484 | ast_invalid_token_error(pc, next_token); | ||
| 2484 | } else { | 2485 | } else { |
| 2485 | ast_invalid_token_error(pc, token); | 2486 | ast_invalid_token_error(pc, token); |
| 2486 | } | 2487 | } |
| ... | @@ -2812,6 +2813,7 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont | ... | @@ -2812,6 +2813,7 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont |
| 2812 | break; | 2813 | break; |
| 2813 | case NodeTypeStructField: | 2814 | case NodeTypeStructField: |
| 2814 | visit_field(&node->data.struct_field.type, visit, context); | 2815 | visit_field(&node->data.struct_field.type, visit, context); |
| 2816 | visit_field(&node->data.struct_field.value, visit, context); | ||
| 2815 | break; | 2817 | break; |
| 2816 | case NodeTypeContainerInitExpr: | 2818 | case NodeTypeContainerInitExpr: |
| 2817 | visit_field(&node->data.container_init_expr.type, visit, context); | 2819 | visit_field(&node->data.container_init_expr.type, visit, context); |
std/sort.zig+1-1| ... | @@ -16,7 +16,7 @@ pub fn sort_stable(comptime T: type, array: []T, comptime cmp: fn(a: &const T, b | ... | @@ -16,7 +16,7 @@ pub fn sort_stable(comptime T: type, array: []T, comptime cmp: fn(a: &const T, b |
| 16 | }} | 16 | }} |
| 17 | } | 17 | } |
| 18 | 18 | ||
| 19 | /// Unstable sort using O(n) stack space. Currentl implemented as quicksort. | 19 | /// Unstable sort using O(n) stack space. Currently implemented as quicksort. |
| 20 | pub fn sort(comptime T: type, array: []T, comptime cmp: fn(a: &const T, b: &const T)->Cmp) { | 20 | pub fn sort(comptime T: type, array: []T, comptime cmp: fn(a: &const T, b: &const T)->Cmp) { |
| 21 | if (array.len > 0) { | 21 | if (array.len > 0) { |
| 22 | quicksort(T, array, 0, array.len - 1, cmp); | 22 | quicksort(T, array, 0, array.len - 1, cmp); |
test/cases/enum.zig+54-2| ... | @@ -137,7 +137,6 @@ const AlignTestEnum = enum { | ... | @@ -137,7 +137,6 @@ const AlignTestEnum = enum { |
| 137 | B: u64, | 137 | B: u64, |
| 138 | }; | 138 | }; |
| 139 | 139 | ||
| 140 | const ValueCount0 = enum {}; | ||
| 141 | const ValueCount1 = enum { I0 }; | 140 | const ValueCount1 = enum { I0 }; |
| 142 | const ValueCount2 = enum { I0, I1 }; | 141 | const ValueCount2 = enum { I0, I1 }; |
| 143 | const ValueCount256 = enum { | 142 | const ValueCount256 = enum { |
| ... | @@ -183,7 +182,6 @@ const ValueCount257 = enum { | ... | @@ -183,7 +182,6 @@ const ValueCount257 = enum { |
| 183 | 182 | ||
| 184 | test "enum sizes" { | 183 | test "enum sizes" { |
| 185 | comptime { | 184 | comptime { |
| 186 | assert(@sizeOf(ValueCount0) == 0); | ||
| 187 | assert(@sizeOf(ValueCount1) == 0); | 185 | assert(@sizeOf(ValueCount1) == 0); |
| 188 | assert(@sizeOf(ValueCount2) == 1); | 186 | assert(@sizeOf(ValueCount2) == 1); |
| 189 | assert(@sizeOf(ValueCount256) == 1); | 187 | assert(@sizeOf(ValueCount256) == 1); |
| ... | @@ -292,3 +290,57 @@ test "casting enum to its tag type" { | ... | @@ -292,3 +290,57 @@ test "casting enum to its tag type" { |
| 292 | fn testCastEnumToTagType(value: Small2) { | 290 | fn testCastEnumToTagType(value: Small2) { |
| 293 | assert(u2(value) == 1); | 291 | assert(u2(value) == 1); |
| 294 | } | 292 | } |
| 293 | |||
| 294 | const MultipleChoice = enum(u32) { | ||
| 295 | A = 20, | ||
| 296 | B = 40, | ||
| 297 | C = 60, | ||
| 298 | D = 1000, | ||
| 299 | }; | ||
| 300 | |||
| 301 | test "enum with specified tag values" { | ||
| 302 | testEnumWithSpecifiedTagValues(MultipleChoice.C); | ||
| 303 | comptime testEnumWithSpecifiedTagValues(MultipleChoice.C); | ||
| 304 | } | ||
| 305 | |||
| 306 | fn testEnumWithSpecifiedTagValues(x: MultipleChoice) { | ||
| 307 | assert(u32(x) == 60); | ||
| 308 | assert(1234 == switch (x) { | ||
| 309 | MultipleChoice.A => 1, | ||
| 310 | MultipleChoice.B => 2, | ||
| 311 | MultipleChoice.C => u32(1234), | ||
| 312 | MultipleChoice.D => 4, | ||
| 313 | }); | ||
| 314 | } | ||
| 315 | |||
| 316 | const MultipleChoice2 = enum(u32) { | ||
| 317 | Unspecified1, | ||
| 318 | A = 20, | ||
| 319 | Unspecified2, | ||
| 320 | B = 40, | ||
| 321 | Unspecified3, | ||
| 322 | C = 60, | ||
| 323 | Unspecified4, | ||
| 324 | D = 1000, | ||
| 325 | Unspecified5, | ||
| 326 | }; | ||
| 327 | |||
| 328 | test "enum with specified and unspecified tag values" { | ||
| 329 | testEnumWithSpecifiedAndUnspecifiedTagValues(MultipleChoice2.D); | ||
| 330 | comptime testEnumWithSpecifiedAndUnspecifiedTagValues(MultipleChoice2.D); | ||
| 331 | } | ||
| 332 | |||
| 333 | fn testEnumWithSpecifiedAndUnspecifiedTagValues(x: MultipleChoice2) { | ||
| 334 | assert(u32(x) == 1000); | ||
| 335 | assert(1234 == switch (x) { | ||
| 336 | MultipleChoice2.A => 1, | ||
| 337 | MultipleChoice2.B => 2, | ||
| 338 | MultipleChoice2.C => 3, | ||
| 339 | MultipleChoice2.D => u32(1234), | ||
| 340 | MultipleChoice2.Unspecified1 => 5, | ||
| 341 | MultipleChoice2.Unspecified2 => 6, | ||
| 342 | MultipleChoice2.Unspecified3 => 7, | ||
| 343 | MultipleChoice2.Unspecified4 => 8, | ||
| 344 | MultipleChoice2.Unspecified5 => 9, | ||
| 345 | }); | ||
| 346 | } |
test/compile_errors.zig+49-6| ... | @@ -2307,11 +2307,11 @@ pub fn addCases(cases: &tests.CompileErrorContext) { | ... | @@ -2307,11 +2307,11 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 2307 | 2307 | ||
| 2308 | cases.add("@memberType enum out of bounds", | 2308 | cases.add("@memberType enum out of bounds", |
| 2309 | \\comptime { | 2309 | \\comptime { |
| 2310 | \\ _ = @memberType(Foo, 0); | 2310 | \\ _ = @memberType(Foo, 1); |
| 2311 | \\} | 2311 | \\} |
| 2312 | \\const Foo = enum {}; | 2312 | \\const Foo = enum {A,}; |
| 2313 | , | 2313 | , |
| 2314 | ".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 1 out of bounds; 'Foo' has 1 members"); |
| 2315 | 2315 | ||
| 2316 | cases.add("@memberName on unsupported type", | 2316 | cases.add("@memberName on unsupported type", |
| 2317 | \\comptime { | 2317 | \\comptime { |
| ... | @@ -2330,11 +2330,11 @@ pub fn addCases(cases: &tests.CompileErrorContext) { | ... | @@ -2330,11 +2330,11 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 2330 | 2330 | ||
| 2331 | cases.add("@memberName enum out of bounds", | 2331 | cases.add("@memberName enum out of bounds", |
| 2332 | \\comptime { | 2332 | \\comptime { |
| 2333 | \\ _ = @memberName(Foo, 0); | 2333 | \\ _ = @memberName(Foo, 1); |
| 2334 | \\} | 2334 | \\} |
| 2335 | \\const Foo = enum {}; | 2335 | \\const Foo = enum {A,}; |
| 2336 | , | 2336 | , |
| 2337 | ".tmp_source.zig:2:26: error: member index 0 out of bounds; 'Foo' has 0 members"); | 2337 | ".tmp_source.zig:2:26: error: member index 1 out of bounds; 'Foo' has 1 members"); |
| 2338 | 2338 | ||
| 2339 | cases.add("calling var args extern function, passing array instead of pointer", | 2339 | cases.add("calling var args extern function, passing array instead of pointer", |
| 2340 | \\export fn entry() { | 2340 | \\export fn entry() { |
| ... | @@ -2447,4 +2447,47 @@ pub fn addCases(cases: &tests.CompileErrorContext) { | ... | @@ -2447,4 +2447,47 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 2447 | \\} | 2447 | \\} |
| 2448 | , | 2448 | , |
| 2449 | ".tmp_source.zig:1:19: error: expected unsigned integer, found 'i2'"); | 2449 | ".tmp_source.zig:1:19: error: expected unsigned integer, found 'i2'"); |
| 2450 | |||
| 2451 | cases.add("struct fields with value assignments", | ||
| 2452 | \\const MultipleChoice = struct { | ||
| 2453 | \\ A: i32 = 20, | ||
| 2454 | \\}; | ||
| 2455 | \\export fn entry() { | ||
| 2456 | \\ var x: MultipleChoice = undefined; | ||
| 2457 | \\} | ||
| 2458 | , | ||
| 2459 | ".tmp_source.zig:2:14: error: enums, not structs, support field assignment"); | ||
| 2460 | |||
| 2461 | cases.add("union fields with value assignments", | ||
| 2462 | \\const MultipleChoice = union { | ||
| 2463 | \\ A: i32 = 20, | ||
| 2464 | \\}; | ||
| 2465 | \\export fn entry() { | ||
| 2466 | \\ var x: MultipleChoice = undefined; | ||
| 2467 | \\} | ||
| 2468 | , | ||
| 2469 | ".tmp_source.zig:2:14: error: enums, not unions, support field assignment"); | ||
| 2470 | |||
| 2471 | cases.add("enum with 0 fields", | ||
| 2472 | \\const Foo = enum {}; | ||
| 2473 | \\export fn entry() -> usize { | ||
| 2474 | \\ return @sizeOf(Foo); | ||
| 2475 | \\} | ||
| 2476 | , | ||
| 2477 | ".tmp_source.zig:1:13: error: enums must have 1 or more fields"); | ||
| 2478 | |||
| 2479 | cases.add("enum value already taken", | ||
| 2480 | \\const MultipleChoice = enum(u32) { | ||
| 2481 | \\ A = 20, | ||
| 2482 | \\ B = 40, | ||
| 2483 | \\ C = 60, | ||
| 2484 | \\ D = 1000, | ||
| 2485 | \\ E = 60, | ||
| 2486 | \\}; | ||
| 2487 | \\export fn entry() { | ||
| 2488 | \\ var x = MultipleChoice.C; | ||
| 2489 | \\} | ||
| 2490 | , | ||
| 2491 | ".tmp_source.zig:6:9: error: enum tag value 60 already taken", | ||
| 2492 | ".tmp_source.zig:4:9: note: other occurrence here"); | ||
| 2450 | } | 2493 | } |