authorgravatar for thatlemon@gmail.comLemonBoy <thatlemon@gmail.com> 2020-12-05 18:59:55+01:00
committergravatar for thatlemon@gmail.comLemonBoy <thatlemon@gmail.com> 2020-12-05 20:14:04+01:00
log97f36d93f4766a8d225d19665309e825cdef72bf
treea2bf281da218754ddd558cbe0fc03d2e741ef145
parent0f7954831a881c899002eaf8c203aec35dedeeee

stage1: Don't fold single-element enums too aggressively

When the tag type is not a zero-sized type (eg. `enum(i32)`) we absolutely need to avoid constant-folding this values. Doing so masked any invalid input and, since the folding was not even applied consistently, introduced some hard to catch errors.

1 files changed, 29 insertions(+), 19 deletions(-)

src/stage1/ir.cpp+29-19
...@@ -14186,6 +14186,18 @@ static ZigType *ir_resolve_union_tag_type(IrAnalyze *ira, AstNode *source_node,...@@ -14186,6 +14186,18 @@ static ZigType *ir_resolve_union_tag_type(IrAnalyze *ira, AstNode *source_node,
14186 }14186 }
14187}14187}
1418814188
14189static 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
14189static IrInstGen *ir_analyze_enum_to_int(IrAnalyze *ira, IrInst *source_instr, IrInstGen *target) {14201static IrInstGen *ir_analyze_enum_to_int(IrAnalyze *ira, IrInst *source_instr, IrInstGen *target) {
14190 Error err;14202 Error err;
1419114203
...@@ -14214,10 +14226,7 @@ static IrInstGen *ir_analyze_enum_to_int(IrAnalyze *ira, IrInst *source_instr, I...@@ -14214,10 +14226,7 @@ static IrInstGen *ir_analyze_enum_to_int(IrAnalyze *ira, IrInst *source_instr, I
14214 assert(tag_type->id == ZigTypeIdInt || tag_type->id == ZigTypeIdComptimeInt);14226 assert(tag_type->id == ZigTypeIdInt || tag_type->id == ZigTypeIdComptimeInt);
1421514227
14216 // If there is only one possible tag, then we know at comptime what it is.14228 // If there is only one possible tag, then we know at comptime what it is.
14217 if (enum_type->data.enumeration.layout == ContainerLayoutAuto &&14229 if (can_fold_enum_type(enum_type)) {
14218 enum_type->data.enumeration.src_field_count == 1 &&
14219 !enum_type->data.enumeration.non_exhaustive)
14220 {
14221 IrInstGen *result = ir_const(ira, source_instr, tag_type);14230 IrInstGen *result = ir_const(ira, source_instr, tag_type);
14222 init_const_bigint(result->value, tag_type,14231 init_const_bigint(result->value, tag_type,
14223 &enum_type->data.enumeration.fields[0].value);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,10 +14264,7 @@ static IrInstGen *ir_analyze_union_to_tag(IrAnalyze *ira, IrInst* source_instr,
14255 }14264 }
1425614265
14257 // If there is only 1 possible tag, then we know at comptime what it is.14266 // If there is only 1 possible tag, then we know at comptime what it is.
14258 if (wanted_type->data.enumeration.layout == ContainerLayoutAuto &&14267 if (can_fold_enum_type(wanted_type)) {
14259 wanted_type->data.enumeration.src_field_count == 1 &&
14260 !wanted_type->data.enumeration.non_exhaustive)
14261 {
14262 IrInstGen *result = ir_const(ira, source_instr, wanted_type);14268 IrInstGen *result = ir_const(ira, source_instr, wanted_type);
14263 result->value->special = ConstValSpecialStatic;14269 result->value->special = ConstValSpecialStatic;
14264 result->value->type = wanted_type;14270 result->value->type = wanted_type;
...@@ -24039,7 +24045,8 @@ static IrInstGen *ir_analyze_instruction_switch_target(IrAnalyze *ira,...@@ -24039,7 +24045,8 @@ static IrInstGen *ir_analyze_instruction_switch_target(IrAnalyze *ira,
24039 bigint_init_bigint(&result->value->data.x_enum_tag, &pointee_val->data.x_union.tag);24045 bigint_init_bigint(&result->value->data.x_enum_tag, &pointee_val->data.x_union.tag);
24040 return result;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 IrInstGen *result = ir_const(ira, &switch_target_instruction->base.base, tag_type);24050 IrInstGen *result = ir_const(ira, &switch_target_instruction->base.base, tag_type);
24044 TypeEnumField *only_field = &tag_type->data.enumeration.fields[0];24051 TypeEnumField *only_field = &tag_type->data.enumeration.fields[0];
24045 bigint_init_bigint(&result->value->data.x_enum_tag, &only_field->value);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,7 +24061,8 @@ static IrInstGen *ir_analyze_instruction_switch_target(IrAnalyze *ira,
24054 case ZigTypeIdEnum: {24061 case ZigTypeIdEnum: {
24055 if ((err = type_resolve(ira->codegen, target_type, ResolveStatusZeroBitsKnown)))24062 if ((err = type_resolve(ira->codegen, target_type, ResolveStatusZeroBitsKnown)))
24056 return ira->codegen->invalid_inst_gen;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 TypeEnumField *only_field = &target_type->data.enumeration.fields[0];24066 TypeEnumField *only_field = &target_type->data.enumeration.fields[0];
24059 IrInstGen *result = ir_const(ira, &switch_target_instruction->base.base, target_type);24067 IrInstGen *result = ir_const(ira, &switch_target_instruction->base.base, target_type);
24060 bigint_init_bigint(&result->value->data.x_enum_tag, &only_field->value);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,7 +24797,9 @@ static IrInstGen *ir_analyze_instruction_enum_tag_name(IrAnalyze *ira, IrInstSrc
24789 if (type_is_invalid(target->value->type))24797 if (type_is_invalid(target->value->type))
24790 return ira->codegen->invalid_inst_gen;24798 return ira->codegen->invalid_inst_gen;
2479124799
24792 if (target->value->type->id == ZigTypeIdEnumLiteral) {24800 ZigType *target_type = target->value->type;
24801
24802 if (target_type->id == ZigTypeIdEnumLiteral) {
24793 IrInstGen *result = ir_const(ira, &instruction->base.base, nullptr);24803 IrInstGen *result = ir_const(ira, &instruction->base.base, nullptr);
24794 Buf *field_name = target->value->data.x_enum_literal;24804 Buf *field_name = target->value->data.x_enum_literal;
24795 ZigValue *array_val = create_const_str_lit(ira->codegen, field_name)->data.x_ptr.data.ref.pointee;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,21 +24807,21 @@ static IrInstGen *ir_analyze_instruction_enum_tag_name(IrAnalyze *ira, IrInstSrc
24797 return result;24807 return result;
24798 }24808 }
2479924809
24800 if (target->value->type->id == ZigTypeIdUnion) {24810 if (target_type->id == ZigTypeIdUnion) {
24801 target = ir_analyze_union_tag(ira, &instruction->base.base, target, instruction->base.is_gen);24811 target = ir_analyze_union_tag(ira, &instruction->base.base, target, instruction->base.is_gen);
24802 if (type_is_invalid(target->value->type))24812 if (type_is_invalid(target->value->type))
24803 return ira->codegen->invalid_inst_gen;24813 return ira->codegen->invalid_inst_gen;
24814 target_type = target->value->type;
24804 }24815 }
2480524816
24806 if (target->value->type->id != ZigTypeIdEnum) {24817 if (target_type->id != ZigTypeIdEnum) {
24807 ir_add_error(ira, &target->base,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 return ira->codegen->invalid_inst_gen;24820 return ira->codegen->invalid_inst_gen;
24810 }24821 }
2481124822
24812 if (target->value->type->data.enumeration.src_field_count == 1 &&24823 if (can_fold_enum_type(target_type)) {
24813 !target->value->type->data.enumeration.non_exhaustive) {24824 TypeEnumField *only_field = &target_type->data.enumeration.fields[0];
24814 TypeEnumField *only_field = &target->value->type->data.enumeration.fields[0];
24815 ZigValue *array_val = create_const_str_lit(ira->codegen, only_field->name)->data.x_ptr.data.ref.pointee;24825 ZigValue *array_val = create_const_str_lit(ira->codegen, only_field->name)->data.x_ptr.data.ref.pointee;
24816 IrInstGen *result = ir_const(ira, &instruction->base.base, nullptr);24826 IrInstGen *result = ir_const(ira, &instruction->base.base, nullptr);
24817 init_const_slice(ira->codegen, result->value, array_val, 0, buf_len(only_field->name), true);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,9 +24829,9 @@ static IrInstGen *ir_analyze_instruction_enum_tag_name(IrAnalyze *ira, IrInstSrc
24819 }24829 }
2482024830
24821 if (instr_is_comptime(target)) {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 return ira->codegen->invalid_inst_gen;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 if (field == nullptr) {24835 if (field == nullptr) {
24826 Buf *int_buf = buf_alloc();24836 Buf *int_buf = buf_alloc();
24827 bigint_append_buf(int_buf, &target->value->data.x_bigint, 10);24837 bigint_append_buf(int_buf, &target->value->data.x_bigint, 10);