| ... | @@ -14123,6 +14123,18 @@ static ZigType *ir_resolve_union_tag_type(IrAnalyze *ira, AstNode *source_node, | ... | @@ -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 | static IrInstGen *ir_analyze_enum_to_int(IrAnalyze *ira, IrInst *source_instr, IrInstGen *target) { | 14138 | static IrInstGen *ir_analyze_enum_to_int(IrAnalyze *ira, IrInst *source_instr, IrInstGen *target) { |
| 14127 | Error err; | 14139 | Error err; |
| 14128 | | 14140 | |
| ... | @@ -14151,10 +14163,7 @@ static IrInstGen *ir_analyze_enum_to_int(IrAnalyze *ira, IrInst *source_instr, I | ... | @@ -14151,10 +14163,7 @@ static IrInstGen *ir_analyze_enum_to_int(IrAnalyze *ira, IrInst *source_instr, I |
| 14151 | assert(tag_type->id == ZigTypeIdInt || tag_type->id == ZigTypeIdComptimeInt); | 14163 | assert(tag_type->id == ZigTypeIdInt || tag_type->id == ZigTypeIdComptimeInt); |
| 14152 | | 14164 | |
| 14153 | // If there is only one possible tag, then we know at comptime what it is. | 14165 | // If there is only one possible tag, then we know at comptime what it is. |
| 14154 | if (enum_type->data.enumeration.layout == ContainerLayoutAuto && | 14166 | if (can_fold_enum_type(enum_type)) { |
| 14155 | enum_type->data.enumeration.src_field_count == 1 && | | |
| 14156 | !enum_type->data.enumeration.non_exhaustive) | | |
| 14157 | { | | |
| 14158 | IrInstGen *result = ir_const(ira, source_instr, tag_type); | 14167 | IrInstGen *result = ir_const(ira, source_instr, tag_type); |
| 14159 | init_const_bigint(result->value, tag_type, | 14168 | init_const_bigint(result->value, tag_type, |
| 14160 | &enum_type->data.enumeration.fields[0].value); | 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,10 +14201,7 @@ static IrInstGen *ir_analyze_union_to_tag(IrAnalyze *ira, IrInst* source_instr, |
| 14192 | } | 14201 | } |
| 14193 | | 14202 | |
| 14194 | // If there is only 1 possible tag, then we know at comptime what it is. | 14203 | // If there is only 1 possible tag, then we know at comptime what it is. |
| 14195 | if (wanted_type->data.enumeration.layout == ContainerLayoutAuto && | 14204 | if (can_fold_enum_type(wanted_type)) { |
| 14196 | wanted_type->data.enumeration.src_field_count == 1 && | | |
| 14197 | !wanted_type->data.enumeration.non_exhaustive) | | |
| 14198 | { | | |
| 14199 | IrInstGen *result = ir_const(ira, source_instr, wanted_type); | 14205 | IrInstGen *result = ir_const(ira, source_instr, wanted_type); |
| 14200 | result->value->special = ConstValSpecialStatic; | 14206 | result->value->special = ConstValSpecialStatic; |
| 14201 | result->value->type = wanted_type; | 14207 | result->value->type = wanted_type; |
| ... | @@ -23837,7 +23843,8 @@ static IrInstGen *ir_analyze_instruction_switch_target(IrAnalyze *ira, | ... | @@ -23837,7 +23843,8 @@ static IrInstGen *ir_analyze_instruction_switch_target(IrAnalyze *ira, |
| 23837 | bigint_init_bigint(&result->value->data.x_enum_tag, &pointee_val->data.x_union.tag); | 23843 | bigint_init_bigint(&result->value->data.x_enum_tag, &pointee_val->data.x_union.tag); |
| 23838 | return result; | 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 | IrInstGen *result = ir_const(ira, &switch_target_instruction->base.base, tag_type); | 23848 | IrInstGen *result = ir_const(ira, &switch_target_instruction->base.base, tag_type); |
| 23842 | TypeEnumField *only_field = &tag_type->data.enumeration.fields[0]; | 23849 | TypeEnumField *only_field = &tag_type->data.enumeration.fields[0]; |
| 23843 | bigint_init_bigint(&result->value->data.x_enum_tag, &only_field->value); | 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,7 +23859,8 @@ static IrInstGen *ir_analyze_instruction_switch_target(IrAnalyze *ira, |
| 23852 | case ZigTypeIdEnum: { | 23859 | case ZigTypeIdEnum: { |
| 23853 | if ((err = type_resolve(ira->codegen, target_type, ResolveStatusZeroBitsKnown))) | 23860 | if ((err = type_resolve(ira->codegen, target_type, ResolveStatusZeroBitsKnown))) |
| 23854 | return ira->codegen->invalid_inst_gen; | 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 | TypeEnumField *only_field = &target_type->data.enumeration.fields[0]; | 23864 | TypeEnumField *only_field = &target_type->data.enumeration.fields[0]; |
| 23857 | IrInstGen *result = ir_const(ira, &switch_target_instruction->base.base, target_type); | 23865 | IrInstGen *result = ir_const(ira, &switch_target_instruction->base.base, target_type); |
| 23858 | bigint_init_bigint(&result->value->data.x_enum_tag, &only_field->value); | 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,7 +24595,9 @@ static IrInstGen *ir_analyze_instruction_enum_tag_name(IrAnalyze *ira, IrInstSrc |
| 24587 | if (type_is_invalid(target->value->type)) | 24595 | if (type_is_invalid(target->value->type)) |
| 24588 | return ira->codegen->invalid_inst_gen; | 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 | IrInstGen *result = ir_const(ira, &instruction->base.base, nullptr); | 24601 | IrInstGen *result = ir_const(ira, &instruction->base.base, nullptr); |
| 24592 | Buf *field_name = target->value->data.x_enum_literal; | 24602 | Buf *field_name = target->value->data.x_enum_literal; |
| 24593 | ZigValue *array_val = create_const_str_lit(ira->codegen, field_name)->data.x_ptr.data.ref.pointee; | 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,21 +24605,21 @@ static IrInstGen *ir_analyze_instruction_enum_tag_name(IrAnalyze *ira, IrInstSrc |
| 24595 | return result; | 24605 | return result; |
| 24596 | } | 24606 | } |
| 24597 | | 24607 | |
| 24598 | if (target->value->type->id == ZigTypeIdUnion) { | 24608 | if (target_type->id == ZigTypeIdUnion) { |
| 24599 | target = ir_analyze_union_tag(ira, &instruction->base.base, target, instruction->base.is_gen); | 24609 | target = ir_analyze_union_tag(ira, &instruction->base.base, target, instruction->base.is_gen); |
| 24600 | if (type_is_invalid(target->value->type)) | 24610 | if (type_is_invalid(target->value->type)) |
| 24601 | return ira->codegen->invalid_inst_gen; | 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 | ir_add_error(ira, &target->base, | 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 | return ira->codegen->invalid_inst_gen; | 24618 | return ira->codegen->invalid_inst_gen; |
| 24608 | } | 24619 | } |
| 24609 | | 24620 | |
| 24610 | if (target->value->type->data.enumeration.src_field_count == 1 && | 24621 | if (can_fold_enum_type(target_type)) { |
| 24611 | !target->value->type->data.enumeration.non_exhaustive) { | 24622 | TypeEnumField *only_field = &target_type->data.enumeration.fields[0]; |
| 24612 | TypeEnumField *only_field = &target->value->type->data.enumeration.fields[0]; | | |
| 24613 | ZigValue *array_val = create_const_str_lit(ira->codegen, only_field->name)->data.x_ptr.data.ref.pointee; | 24623 | ZigValue *array_val = create_const_str_lit(ira->codegen, only_field->name)->data.x_ptr.data.ref.pointee; |
| 24614 | IrInstGen *result = ir_const(ira, &instruction->base.base, nullptr); | 24624 | IrInstGen *result = ir_const(ira, &instruction->base.base, nullptr); |
| 24615 | init_const_slice(ira->codegen, result->value, array_val, 0, buf_len(only_field->name), true); | 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,9 +24627,9 @@ static IrInstGen *ir_analyze_instruction_enum_tag_name(IrAnalyze *ira, IrInstSrc |
| 24617 | } | 24627 | } |
| 24618 | | 24628 | |
| 24619 | if (instr_is_comptime(target)) { | 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 | return ira->codegen->invalid_inst_gen; | 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 | if (field == nullptr) { | 24633 | if (field == nullptr) { |
| 24624 | Buf *int_buf = buf_alloc(); | 24634 | Buf *int_buf = buf_alloc(); |
| 24625 | bigint_append_buf(int_buf, &target->value->data.x_bigint, 10); | 24635 | bigint_append_buf(int_buf, &target->value->data.x_bigint, 10); |