| ... | ... | @@ -14123,6 +14123,18 @@ static ZigType *ir_resolve_union_tag_type(IrAnalyze *ira, AstNode *source_node, |
| 14123 | 14123 | } |
| 14124 | 14124 | } |
| 14125 | 14125 | |
| 14126 | static bool can_fold_enum_type(ZigType *ty) { |
| 14127 | assert(ty->id == ZigTypeIdEnum); |
| 14128 | // We can fold the enum type (and avoid any check, be it at runtime or at |
| 14129 | // compile time) iff it has only a single element and its tag type is |
| 14130 | // zero-sized. |
| 14131 | ZigType *tag_int_type = ty->data.enumeration.tag_int_type; |
| 14132 | return ty->data.enumeration.layout == ContainerLayoutAuto && |
| 14133 | ty->data.enumeration.src_field_count == 1 && |
| 14134 | !ty->data.enumeration.non_exhaustive && |
| 14135 | (tag_int_type->id == ZigTypeIdInt && tag_int_type->data.integral.bit_count == 0); |
| 14136 | } |
| 14137 | |
| 14126 | 14138 | static IrInstGen *ir_analyze_enum_to_int(IrAnalyze *ira, IrInst *source_instr, IrInstGen *target) { |
| 14127 | 14139 | Error err; |
| 14128 | 14140 | |
| ... | ... | @@ -14151,10 +14163,7 @@ static IrInstGen *ir_analyze_enum_to_int(IrAnalyze *ira, IrInst *source_instr, I |
| 14151 | 14163 | assert(tag_type->id == ZigTypeIdInt || tag_type->id == ZigTypeIdComptimeInt); |
| 14152 | 14164 | |
| 14153 | 14165 | // If there is only one possible tag, then we know at comptime what it is. |
| 14154 | | if (enum_type->data.enumeration.layout == ContainerLayoutAuto && |
| 14155 | | enum_type->data.enumeration.src_field_count == 1 && |
| 14156 | | !enum_type->data.enumeration.non_exhaustive) |
| 14157 | | { |
| 14166 | if (can_fold_enum_type(enum_type)) { |
| 14158 | 14167 | IrInstGen *result = ir_const(ira, source_instr, tag_type); |
| 14159 | 14168 | init_const_bigint(result->value, tag_type, |
| 14160 | 14169 | &enum_type->data.enumeration.fields[0].value); |
| ... | ... | @@ -14192,10 +14201,7 @@ static IrInstGen *ir_analyze_union_to_tag(IrAnalyze *ira, IrInst* source_instr, |
| 14192 | 14201 | } |
| 14193 | 14202 | |
| 14194 | 14203 | // If there is only 1 possible tag, then we know at comptime what it is. |
| 14195 | | if (wanted_type->data.enumeration.layout == ContainerLayoutAuto && |
| 14196 | | wanted_type->data.enumeration.src_field_count == 1 && |
| 14197 | | !wanted_type->data.enumeration.non_exhaustive) |
| 14198 | | { |
| 14204 | if (can_fold_enum_type(wanted_type)) { |
| 14199 | 14205 | IrInstGen *result = ir_const(ira, source_instr, wanted_type); |
| 14200 | 14206 | result->value->special = ConstValSpecialStatic; |
| 14201 | 14207 | result->value->type = wanted_type; |
| ... | ... | @@ -23837,7 +23843,8 @@ static IrInstGen *ir_analyze_instruction_switch_target(IrAnalyze *ira, |
| 23837 | 23843 | bigint_init_bigint(&result->value->data.x_enum_tag, &pointee_val->data.x_union.tag); |
| 23838 | 23844 | return result; |
| 23839 | 23845 | } |
| 23840 | | if (tag_type->data.enumeration.src_field_count == 1 && !tag_type->data.enumeration.non_exhaustive) { |
| 23846 | |
| 23847 | if (can_fold_enum_type(tag_type)) { |
| 23841 | 23848 | IrInstGen *result = ir_const(ira, &switch_target_instruction->base.base, tag_type); |
| 23842 | 23849 | TypeEnumField *only_field = &tag_type->data.enumeration.fields[0]; |
| 23843 | 23850 | bigint_init_bigint(&result->value->data.x_enum_tag, &only_field->value); |
| ... | ... | @@ -23852,7 +23859,8 @@ static IrInstGen *ir_analyze_instruction_switch_target(IrAnalyze *ira, |
| 23852 | 23859 | case ZigTypeIdEnum: { |
| 23853 | 23860 | if ((err = type_resolve(ira->codegen, target_type, ResolveStatusZeroBitsKnown))) |
| 23854 | 23861 | return ira->codegen->invalid_inst_gen; |
| 23855 | | if (target_type->data.enumeration.src_field_count == 1 && !target_type->data.enumeration.non_exhaustive) { |
| 23862 | |
| 23863 | if (can_fold_enum_type(target_type)) { |
| 23856 | 23864 | TypeEnumField *only_field = &target_type->data.enumeration.fields[0]; |
| 23857 | 23865 | IrInstGen *result = ir_const(ira, &switch_target_instruction->base.base, target_type); |
| 23858 | 23866 | bigint_init_bigint(&result->value->data.x_enum_tag, &only_field->value); |
| ... | ... | @@ -24587,7 +24595,9 @@ static IrInstGen *ir_analyze_instruction_enum_tag_name(IrAnalyze *ira, IrInstSrc |
| 24587 | 24595 | if (type_is_invalid(target->value->type)) |
| 24588 | 24596 | return ira->codegen->invalid_inst_gen; |
| 24589 | 24597 | |
| 24590 | | if (target->value->type->id == ZigTypeIdEnumLiteral) { |
| 24598 | ZigType *target_type = target->value->type; |
| 24599 | |
| 24600 | if (target_type->id == ZigTypeIdEnumLiteral) { |
| 24591 | 24601 | IrInstGen *result = ir_const(ira, &instruction->base.base, nullptr); |
| 24592 | 24602 | Buf *field_name = target->value->data.x_enum_literal; |
| 24593 | 24603 | ZigValue *array_val = create_const_str_lit(ira->codegen, field_name)->data.x_ptr.data.ref.pointee; |
| ... | ... | @@ -24595,21 +24605,21 @@ static IrInstGen *ir_analyze_instruction_enum_tag_name(IrAnalyze *ira, IrInstSrc |
| 24595 | 24605 | return result; |
| 24596 | 24606 | } |
| 24597 | 24607 | |
| 24598 | | if (target->value->type->id == ZigTypeIdUnion) { |
| 24608 | if (target_type->id == ZigTypeIdUnion) { |
| 24599 | 24609 | target = ir_analyze_union_tag(ira, &instruction->base.base, target, instruction->base.is_gen); |
| 24600 | 24610 | if (type_is_invalid(target->value->type)) |
| 24601 | 24611 | return ira->codegen->invalid_inst_gen; |
| 24612 | target_type = target->value->type; |
| 24602 | 24613 | } |
| 24603 | 24614 | |
| 24604 | | if (target->value->type->id != ZigTypeIdEnum) { |
| 24615 | if (target_type->id != ZigTypeIdEnum) { |
| 24605 | 24616 | ir_add_error(ira, &target->base, |
| 24606 | | buf_sprintf("expected enum tag, found '%s'", buf_ptr(&target->value->type->name))); |
| 24617 | buf_sprintf("expected enum tag, found '%s'", buf_ptr(&target_type->name))); |
| 24607 | 24618 | return ira->codegen->invalid_inst_gen; |
| 24608 | 24619 | } |
| 24609 | 24620 | |
| 24610 | | if (target->value->type->data.enumeration.src_field_count == 1 && |
| 24611 | | !target->value->type->data.enumeration.non_exhaustive) { |
| 24612 | | TypeEnumField *only_field = &target->value->type->data.enumeration.fields[0]; |
| 24621 | if (can_fold_enum_type(target_type)) { |
| 24622 | TypeEnumField *only_field = &target_type->data.enumeration.fields[0]; |
| 24613 | 24623 | ZigValue *array_val = create_const_str_lit(ira->codegen, only_field->name)->data.x_ptr.data.ref.pointee; |
| 24614 | 24624 | IrInstGen *result = ir_const(ira, &instruction->base.base, nullptr); |
| 24615 | 24625 | init_const_slice(ira->codegen, result->value, array_val, 0, buf_len(only_field->name), true); |
| ... | ... | @@ -24617,9 +24627,9 @@ static IrInstGen *ir_analyze_instruction_enum_tag_name(IrAnalyze *ira, IrInstSrc |
| 24617 | 24627 | } |
| 24618 | 24628 | |
| 24619 | 24629 | if (instr_is_comptime(target)) { |
| 24620 | | if ((err = type_resolve(ira->codegen, target->value->type, ResolveStatusZeroBitsKnown))) |
| 24630 | if ((err = type_resolve(ira->codegen, target_type, ResolveStatusZeroBitsKnown))) |
| 24621 | 24631 | return ira->codegen->invalid_inst_gen; |
| 24622 | | TypeEnumField *field = find_enum_field_by_tag(target->value->type, &target->value->data.x_bigint); |
| 24632 | TypeEnumField *field = find_enum_field_by_tag(target_type, &target->value->data.x_bigint); |
| 24623 | 24633 | if (field == nullptr) { |
| 24624 | 24634 | Buf *int_buf = buf_alloc(); |
| 24625 | 24635 | bigint_append_buf(int_buf, &target->value->data.x_bigint, 10); |