| ... | ... | @@ -14186,6 +14186,18 @@ static ZigType *ir_resolve_union_tag_type(IrAnalyze *ira, AstNode *source_node, |
| 14186 | 14186 | } |
| 14187 | 14187 | } |
| 14188 | 14188 | |
| 14189 | static bool can_fold_enum_type(ZigType *ty) { |
| 14190 | assert(ty->id == ZigTypeIdEnum); |
| 14191 | // We can fold the enum type (and avoid any check, be it at runtime or at |
| 14192 | // compile time) iff it has only a single element and its tag type is |
| 14193 | // zero-sized. |
| 14194 | ZigType *tag_int_type = ty->data.enumeration.tag_int_type; |
| 14195 | return ty->data.enumeration.layout == ContainerLayoutAuto && |
| 14196 | ty->data.enumeration.src_field_count == 1 && |
| 14197 | !ty->data.enumeration.non_exhaustive && |
| 14198 | (tag_int_type->id == ZigTypeIdInt && tag_int_type->data.integral.bit_count == 0); |
| 14199 | } |
| 14200 | |
| 14189 | 14201 | static IrInstGen *ir_analyze_enum_to_int(IrAnalyze *ira, IrInst *source_instr, IrInstGen *target) { |
| 14190 | 14202 | Error err; |
| 14191 | 14203 | |
| ... | ... | @@ -14214,10 +14226,7 @@ static IrInstGen *ir_analyze_enum_to_int(IrAnalyze *ira, IrInst *source_instr, I |
| 14214 | 14226 | assert(tag_type->id == ZigTypeIdInt || tag_type->id == ZigTypeIdComptimeInt); |
| 14215 | 14227 | |
| 14216 | 14228 | // If there is only one possible tag, then we know at comptime what it is. |
| 14217 | | if (enum_type->data.enumeration.layout == ContainerLayoutAuto && |
| 14218 | | enum_type->data.enumeration.src_field_count == 1 && |
| 14219 | | !enum_type->data.enumeration.non_exhaustive) |
| 14220 | | { |
| 14229 | if (can_fold_enum_type(enum_type)) { |
| 14221 | 14230 | IrInstGen *result = ir_const(ira, source_instr, tag_type); |
| 14222 | 14231 | init_const_bigint(result->value, tag_type, |
| 14223 | 14232 | &enum_type->data.enumeration.fields[0].value); |
| ... | ... | @@ -14255,10 +14264,7 @@ static IrInstGen *ir_analyze_union_to_tag(IrAnalyze *ira, IrInst* source_instr, |
| 14255 | 14264 | } |
| 14256 | 14265 | |
| 14257 | 14266 | // If there is only 1 possible tag, then we know at comptime what it is. |
| 14258 | | if (wanted_type->data.enumeration.layout == ContainerLayoutAuto && |
| 14259 | | wanted_type->data.enumeration.src_field_count == 1 && |
| 14260 | | !wanted_type->data.enumeration.non_exhaustive) |
| 14261 | | { |
| 14267 | if (can_fold_enum_type(wanted_type)) { |
| 14262 | 14268 | IrInstGen *result = ir_const(ira, source_instr, wanted_type); |
| 14263 | 14269 | result->value->special = ConstValSpecialStatic; |
| 14264 | 14270 | result->value->type = wanted_type; |
| ... | ... | @@ -24039,7 +24045,8 @@ static IrInstGen *ir_analyze_instruction_switch_target(IrAnalyze *ira, |
| 24039 | 24045 | bigint_init_bigint(&result->value->data.x_enum_tag, &pointee_val->data.x_union.tag); |
| 24040 | 24046 | return result; |
| 24041 | 24047 | } |
| 24042 | | if (tag_type->data.enumeration.src_field_count == 1 && !tag_type->data.enumeration.non_exhaustive) { |
| 24048 | |
| 24049 | if (can_fold_enum_type(tag_type)) { |
| 24043 | 24050 | IrInstGen *result = ir_const(ira, &switch_target_instruction->base.base, tag_type); |
| 24044 | 24051 | TypeEnumField *only_field = &tag_type->data.enumeration.fields[0]; |
| 24045 | 24052 | bigint_init_bigint(&result->value->data.x_enum_tag, &only_field->value); |
| ... | ... | @@ -24054,7 +24061,8 @@ static IrInstGen *ir_analyze_instruction_switch_target(IrAnalyze *ira, |
| 24054 | 24061 | case ZigTypeIdEnum: { |
| 24055 | 24062 | if ((err = type_resolve(ira->codegen, target_type, ResolveStatusZeroBitsKnown))) |
| 24056 | 24063 | return ira->codegen->invalid_inst_gen; |
| 24057 | | if (target_type->data.enumeration.src_field_count == 1 && !target_type->data.enumeration.non_exhaustive) { |
| 24064 | |
| 24065 | if (can_fold_enum_type(target_type)) { |
| 24058 | 24066 | TypeEnumField *only_field = &target_type->data.enumeration.fields[0]; |
| 24059 | 24067 | IrInstGen *result = ir_const(ira, &switch_target_instruction->base.base, target_type); |
| 24060 | 24068 | bigint_init_bigint(&result->value->data.x_enum_tag, &only_field->value); |
| ... | ... | @@ -24789,7 +24797,9 @@ static IrInstGen *ir_analyze_instruction_enum_tag_name(IrAnalyze *ira, IrInstSrc |
| 24789 | 24797 | if (type_is_invalid(target->value->type)) |
| 24790 | 24798 | return ira->codegen->invalid_inst_gen; |
| 24791 | 24799 | |
| 24792 | | if (target->value->type->id == ZigTypeIdEnumLiteral) { |
| 24800 | ZigType *target_type = target->value->type; |
| 24801 | |
| 24802 | if (target_type->id == ZigTypeIdEnumLiteral) { |
| 24793 | 24803 | IrInstGen *result = ir_const(ira, &instruction->base.base, nullptr); |
| 24794 | 24804 | Buf *field_name = target->value->data.x_enum_literal; |
| 24795 | 24805 | ZigValue *array_val = create_const_str_lit(ira->codegen, field_name)->data.x_ptr.data.ref.pointee; |
| ... | ... | @@ -24797,21 +24807,21 @@ static IrInstGen *ir_analyze_instruction_enum_tag_name(IrAnalyze *ira, IrInstSrc |
| 24797 | 24807 | return result; |
| 24798 | 24808 | } |
| 24799 | 24809 | |
| 24800 | | if (target->value->type->id == ZigTypeIdUnion) { |
| 24810 | if (target_type->id == ZigTypeIdUnion) { |
| 24801 | 24811 | target = ir_analyze_union_tag(ira, &instruction->base.base, target, instruction->base.is_gen); |
| 24802 | 24812 | if (type_is_invalid(target->value->type)) |
| 24803 | 24813 | return ira->codegen->invalid_inst_gen; |
| 24814 | target_type = target->value->type; |
| 24804 | 24815 | } |
| 24805 | 24816 | |
| 24806 | | if (target->value->type->id != ZigTypeIdEnum) { |
| 24817 | if (target_type->id != ZigTypeIdEnum) { |
| 24807 | 24818 | ir_add_error(ira, &target->base, |
| 24808 | | buf_sprintf("expected enum tag, found '%s'", buf_ptr(&target->value->type->name))); |
| 24819 | buf_sprintf("expected enum tag, found '%s'", buf_ptr(&target_type->name))); |
| 24809 | 24820 | return ira->codegen->invalid_inst_gen; |
| 24810 | 24821 | } |
| 24811 | 24822 | |
| 24812 | | if (target->value->type->data.enumeration.src_field_count == 1 && |
| 24813 | | !target->value->type->data.enumeration.non_exhaustive) { |
| 24814 | | TypeEnumField *only_field = &target->value->type->data.enumeration.fields[0]; |
| 24823 | if (can_fold_enum_type(target_type)) { |
| 24824 | TypeEnumField *only_field = &target_type->data.enumeration.fields[0]; |
| 24815 | 24825 | ZigValue *array_val = create_const_str_lit(ira->codegen, only_field->name)->data.x_ptr.data.ref.pointee; |
| 24816 | 24826 | IrInstGen *result = ir_const(ira, &instruction->base.base, nullptr); |
| 24817 | 24827 | init_const_slice(ira->codegen, result->value, array_val, 0, buf_len(only_field->name), true); |
| ... | ... | @@ -24819,9 +24829,9 @@ static IrInstGen *ir_analyze_instruction_enum_tag_name(IrAnalyze *ira, IrInstSrc |
| 24819 | 24829 | } |
| 24820 | 24830 | |
| 24821 | 24831 | if (instr_is_comptime(target)) { |
| 24822 | | if ((err = type_resolve(ira->codegen, target->value->type, ResolveStatusZeroBitsKnown))) |
| 24832 | if ((err = type_resolve(ira->codegen, target_type, ResolveStatusZeroBitsKnown))) |
| 24823 | 24833 | return ira->codegen->invalid_inst_gen; |
| 24824 | | TypeEnumField *field = find_enum_field_by_tag(target->value->type, &target->value->data.x_bigint); |
| 24834 | TypeEnumField *field = find_enum_field_by_tag(target_type, &target->value->data.x_bigint); |
| 24825 | 24835 | if (field == nullptr) { |
| 24826 | 24836 | Buf *int_buf = buf_alloc(); |
| 24827 | 24837 | bigint_append_buf(int_buf, &target->value->data.x_bigint, 10); |