| ... | @@ -10305,63 +10305,75 @@ static IrInstruction *ir_analyze_array_to_slice(IrAnalyze *ira, IrInstruction *s | ... | @@ -10305,63 +10305,75 @@ static IrInstruction *ir_analyze_array_to_slice(IrAnalyze *ira, IrInstruction *s |
| 10305 | return result; | 10305 | return result; |
| 10306 | } | 10306 | } |
| 10307 | | 10307 | |
| 10308 | static IrInstruction *ir_analyze_enum_to_int(IrAnalyze *ira, IrInstruction *source_instr, | 10308 | static ZigType *ir_resolve_union_tag_type(IrAnalyze *ira, IrInstruction *source_instr, ZigType *union_type) { |
| 10309 | IrInstruction *target, ZigType *wanted_type) | 10309 | assert(union_type->id == ZigTypeIdUnion); |
| 10310 | { | 10310 | |
| 10311 | Error err; | 10311 | Error err; |
| 10312 | assert(wanted_type->id == ZigTypeIdInt || wanted_type->id == ZigTypeIdComptimeInt); | 10312 | if ((err = type_resolve(ira->codegen, union_type, ResolveStatusSizeKnown))) |
| | 10313 | return ira->codegen->builtin_types.entry_invalid; |
| 10313 | | 10314 | |
| 10314 | ZigType *actual_type = target->value.type; | 10315 | AstNode *decl_node = union_type->data.unionation.decl_node; |
| | 10316 | if (decl_node->data.container_decl.auto_enum || decl_node->data.container_decl.init_arg_expr != nullptr) { |
| | 10317 | assert(union_type->data.unionation.tag_type != nullptr); |
| | 10318 | return union_type->data.unionation.tag_type; |
| | 10319 | } else { |
| | 10320 | ErrorMsg *msg = ir_add_error(ira, source_instr, buf_sprintf("union '%s' has no tag", |
| | 10321 | buf_ptr(&union_type->name))); |
| | 10322 | add_error_note(ira->codegen, msg, decl_node, buf_sprintf("consider 'union(enum)' here")); |
| | 10323 | return ira->codegen->builtin_types.entry_invalid; |
| | 10324 | } |
| | 10325 | } |
| 10315 | | 10326 | |
| 10316 | if (actual_type->id == ZigTypeIdUnion) | 10327 | static IrInstruction *ir_analyze_enum_to_int(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *target) { |
| 10317 | actual_type = actual_type->data.unionation.tag_type; | 10328 | Error err; |
| 10318 | | 10329 | |
| 10319 | if ((err = ensure_complete_type(ira->codegen, actual_type))) | 10330 | IrInstruction *enum_target; |
| | 10331 | ZigType *enum_type; |
| | 10332 | if (target->value.type->id == ZigTypeIdUnion) { |
| | 10333 | enum_type = ir_resolve_union_tag_type(ira, target, target->value.type); |
| | 10334 | if (type_is_invalid(enum_type)) |
| | 10335 | return ira->codegen->invalid_instruction; |
| | 10336 | enum_target = ir_implicit_cast(ira, target, enum_type); |
| | 10337 | if (type_is_invalid(enum_target->value.type)) |
| | 10338 | return ira->codegen->invalid_instruction; |
| | 10339 | } else if (target->value.type->id == ZigTypeIdEnum) { |
| | 10340 | enum_target = target; |
| | 10341 | enum_type = target->value.type; |
| | 10342 | } else { |
| | 10343 | ir_add_error(ira, target, |
| | 10344 | buf_sprintf("expected enum, found type '%s'", buf_ptr(&target->value.type->name))); |
| 10320 | return ira->codegen->invalid_instruction; | 10345 | return ira->codegen->invalid_instruction; |
| | 10346 | } |
| 10321 | | 10347 | |
| 10322 | if (wanted_type != actual_type->data.enumeration.tag_int_type) { | 10348 | if ((err = type_resolve(ira->codegen, enum_type, ResolveStatusSizeKnown))) |
| 10323 | ir_add_error(ira, source_instr, | | |
| 10324 | buf_sprintf("enum to integer cast to '%s' instead of its tag type, '%s'", | | |
| 10325 | buf_ptr(&wanted_type->name), | | |
| 10326 | buf_ptr(&actual_type->data.enumeration.tag_int_type->name))); | | |
| 10327 | return ira->codegen->invalid_instruction; | 10349 | return ira->codegen->invalid_instruction; |
| 10328 | } | | |
| 10329 | | 10350 | |
| 10330 | assert(actual_type->id == ZigTypeIdEnum); | 10351 | ZigType *tag_type = enum_type->data.enumeration.tag_int_type; |
| | 10352 | assert(tag_type->id == ZigTypeIdInt || tag_type->id == ZigTypeIdComptimeInt); |
| 10331 | | 10353 | |
| 10332 | if (instr_is_comptime(target)) { | 10354 | if (instr_is_comptime(enum_target)) { |
| 10333 | ConstExprValue *val = ir_resolve_const(ira, target, UndefBad); | 10355 | ConstExprValue *val = ir_resolve_const(ira, enum_target, UndefBad); |
| 10334 | if (!val) | 10356 | if (!val) |
| 10335 | return ira->codegen->invalid_instruction; | 10357 | return ira->codegen->invalid_instruction; |
| 10336 | IrInstruction *result = ir_const(ira, source_instr, wanted_type); | 10358 | IrInstruction *result = ir_const(ira, source_instr, tag_type); |
| 10337 | if (target->value.type->id == ZigTypeIdUnion) | 10359 | init_const_bigint(&result->value, tag_type, &val->data.x_enum_tag); |
| 10338 | init_const_bigint(&result->value, wanted_type, &val->data.x_union.tag); | | |
| 10339 | else | | |
| 10340 | init_const_bigint(&result->value, wanted_type, &val->data.x_enum_tag); | | |
| 10341 | | | |
| 10342 | return result; | 10360 | return result; |
| 10343 | } | 10361 | } |
| 10344 | | 10362 | |
| 10345 | // If there is only one possible tag, then we know at comptime what it is. | 10363 | // If there is only one possible tag, then we know at comptime what it is. |
| 10346 | if (actual_type->data.enumeration.layout == ContainerLayoutAuto && | 10364 | if (enum_type->data.enumeration.layout == ContainerLayoutAuto && |
| 10347 | actual_type->data.enumeration.src_field_count == 1) | 10365 | enum_type->data.enumeration.src_field_count == 1) |
| 10348 | { | 10366 | { |
| 10349 | assert(wanted_type== ira->codegen->builtin_types.entry_num_lit_int); | 10367 | assert(tag_type == ira->codegen->builtin_types.entry_num_lit_int); |
| 10350 | IrInstruction *result = ir_const(ira, source_instr, wanted_type); | 10368 | IrInstruction *result = ir_const(ira, source_instr, tag_type); |
| 10351 | init_const_bigint(&result->value, wanted_type, | 10369 | init_const_bigint(&result->value, tag_type, |
| 10352 | &actual_type->data.enumeration.fields[0].value); | 10370 | &enum_type->data.enumeration.fields[0].value); |
| 10353 | | | |
| 10354 | return result; | 10371 | return result; |
| 10355 | } | 10372 | } |
| 10356 | | 10373 | |
| 10357 | IrInstruction *result = nullptr; | 10374 | IrInstruction *result = ir_build_widen_or_shorten(&ira->new_irb, source_instr->scope, |
| 10358 | if (target->value.type->id == ZigTypeIdUnion) | 10375 | source_instr->source_node, enum_target); |
| 10359 | result = ir_build_union_tag(&ira->new_irb, source_instr->scope, | 10376 | result->value.type = tag_type; |
| 10360 | source_instr->source_node, target); | | |
| 10361 | else | | |
| 10362 | result = ir_build_widen_or_shorten(&ira->new_irb, source_instr->scope, | | |
| 10363 | source_instr->source_node, target); | | |
| 10364 | result->value.type = wanted_type; | | |
| 10365 | return result; | 10377 | return result; |
| 10366 | } | 10378 | } |
| 10367 | | 10379 | |
| ... | @@ -21378,20 +21390,10 @@ static IrInstruction *ir_analyze_instruction_tag_type(IrAnalyze *ira, IrInstruct | ... | @@ -21378,20 +21390,10 @@ static IrInstruction *ir_analyze_instruction_tag_type(IrAnalyze *ira, IrInstruct |
| 21378 | | 21390 | |
| 21379 | return ir_const_type(ira, &instruction->base, enum_type->data.enumeration.tag_int_type); | 21391 | return ir_const_type(ira, &instruction->base, enum_type->data.enumeration.tag_int_type); |
| 21380 | } else if (enum_type->id == ZigTypeIdUnion) { | 21392 | } else if (enum_type->id == ZigTypeIdUnion) { |
| 21381 | if ((err = ensure_complete_type(ira->codegen, enum_type))) | 21393 | ZigType *tag_type = ir_resolve_union_tag_type(ira, instruction->target, enum_type); |
| 21382 | return ira->codegen->invalid_instruction; | 21394 | if (type_is_invalid(tag_type)) |
| 21383 | | | |
| 21384 | AstNode *decl_node = enum_type->data.unionation.decl_node; | | |
| 21385 | if (decl_node->data.container_decl.auto_enum || decl_node->data.container_decl.init_arg_expr != nullptr) { | | |
| 21386 | assert(enum_type->data.unionation.tag_type != nullptr); | | |
| 21387 | | | |
| 21388 | return ir_const_type(ira, &instruction->base, enum_type->data.unionation.tag_type); | | |
| 21389 | } else { | | |
| 21390 | ErrorMsg *msg = ir_add_error(ira, target_inst, buf_sprintf("union '%s' has no tag", | | |
| 21391 | buf_ptr(&enum_type->name))); | | |
| 21392 | add_error_note(ira->codegen, msg, decl_node, buf_sprintf("consider 'union(enum)' here")); | | |
| 21393 | return ira->codegen->invalid_instruction; | 21395 | return ira->codegen->invalid_instruction; |
| 21394 | } | 21396 | return ir_const_type(ira, &instruction->base, tag_type); |
| 21395 | } else { | 21397 | } else { |
| 21396 | ir_add_error(ira, target_inst, buf_sprintf("expected enum or union, found '%s'", | 21398 | ir_add_error(ira, target_inst, buf_sprintf("expected enum or union, found '%s'", |
| 21397 | buf_ptr(&enum_type->name))); | 21399 | buf_ptr(&enum_type->name))); |
| ... | @@ -21972,38 +21974,11 @@ static IrInstruction *ir_analyze_instruction_bit_reverse(IrAnalyze *ira, IrInstr | ... | @@ -21972,38 +21974,11 @@ static IrInstruction *ir_analyze_instruction_bit_reverse(IrAnalyze *ira, IrInstr |
| 21972 | | 21974 | |
| 21973 | | 21975 | |
| 21974 | static IrInstruction *ir_analyze_instruction_enum_to_int(IrAnalyze *ira, IrInstructionEnumToInt *instruction) { | 21976 | static IrInstruction *ir_analyze_instruction_enum_to_int(IrAnalyze *ira, IrInstructionEnumToInt *instruction) { |
| 21975 | Error err; | | |
| 21976 | IrInstruction *target = instruction->target->child; | 21977 | IrInstruction *target = instruction->target->child; |
| 21977 | ZigType *enum_type = target->value.type; | 21978 | if (type_is_invalid(target->value.type)) |
| 21978 | if (type_is_invalid(enum_type)) | | |
| 21979 | return ira->codegen->invalid_instruction; | | |
| 21980 | | | |
| 21981 | if (enum_type->id == ZigTypeIdUnion) { | | |
| 21982 | if ((err = ensure_complete_type(ira->codegen, enum_type))) | | |
| 21983 | return ira->codegen->invalid_instruction; | | |
| 21984 | | | |
| 21985 | AstNode *decl_node = enum_type->data.unionation.decl_node; | | |
| 21986 | if (decl_node->data.container_decl.auto_enum || decl_node->data.container_decl.init_arg_expr != nullptr) { | | |
| 21987 | assert(enum_type->data.unionation.tag_type != nullptr); | | |
| 21988 | enum_type = target->value.type->data.unionation.tag_type; | | |
| 21989 | } else { | | |
| 21990 | ErrorMsg *msg = ir_add_error(ira, target, buf_sprintf("union '%s' has no tag", | | |
| 21991 | buf_ptr(&enum_type->name))); | | |
| 21992 | add_error_note(ira->codegen, msg, decl_node, buf_sprintf("consider 'union(enum)' here")); | | |
| 21993 | return ira->codegen->invalid_instruction; | | |
| 21994 | } | | |
| 21995 | } else if (enum_type->id != ZigTypeIdEnum) { | | |
| 21996 | ir_add_error(ira, instruction->target, | | |
| 21997 | buf_sprintf("expected enum or union(enum), found type '%s'", buf_ptr(&enum_type->name))); | | |
| 21998 | return ira->codegen->invalid_instruction; | | |
| 21999 | } | | |
| 22000 | | | |
| 22001 | if ((err = type_resolve(ira->codegen, enum_type, ResolveStatusZeroBitsKnown))) | | |
| 22002 | return ira->codegen->invalid_instruction; | 21979 | return ira->codegen->invalid_instruction; |
| 22003 | | 21980 | |
| 22004 | ZigType *int_type = enum_type->data.enumeration.tag_int_type; | 21981 | return ir_analyze_enum_to_int(ira, &instruction->base, target); |
| 22005 | | | |
| 22006 | return ir_analyze_enum_to_int(ira, &instruction->base, target, int_type); | | |
| 22007 | } | 21982 | } |
| 22008 | | 21983 | |
| 22009 | static IrInstruction *ir_analyze_instruction_int_to_enum(IrAnalyze *ira, IrInstructionIntToEnum *instruction) { | 21984 | static IrInstruction *ir_analyze_instruction_int_to_enum(IrAnalyze *ira, IrInstructionIntToEnum *instruction) { |