authorgravatar for emekankurumeh@outlook.comemekoi <emekankurumeh@outlook.com> 2019-02-09 18:04:38-06:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-02-18 11:43:45-05:00
log9b3013d2f6e416f31610f3dc94c5ff8b44836463
treee3a0ca37cf487db7aff284e0d7a53cf1ae38b68c
parentd2fb95af8804229181c4d28506ec37d94b9926e6
signature Commit is signed but in an unrecognized format.

make @enumToInt work on union(enum)

closes #1711

4 files changed, 50 insertions(+), 21 deletions(-)

doc/langref.html.in+1-1
...@@ -5662,7 +5662,7 @@ test "main" {...@@ -5662,7 +5662,7 @@ test "main" {
5662 {#header_open|@enumToInt#}5662 {#header_open|@enumToInt#}
5663 <pre>{#syntax#}@enumToInt(enum_value: var) var{#endsyntax#}</pre>5663 <pre>{#syntax#}@enumToInt(enum_value: var) var{#endsyntax#}</pre>
5664 <p>5664 <p>
5665 Converts an enumeration value into its integer tag type.5665 Converts an enumeration or tagged union value into its integer tag type.
5666 </p>5666 </p>
5667 <p>5667 <p>
5668 If the enum has only 1 possible value, the resut is a {#syntax#}comptime_int{#endsyntax#}5668 If the enum has only 1 possible value, the resut is a {#syntax#}comptime_int{#endsyntax#}
src/ir.cpp+42-13
...@@ -10312,6 +10312,10 @@ static IrInstruction *ir_analyze_enum_to_int(IrAnalyze *ira, IrInstruction *sour...@@ -10312,6 +10312,10 @@ static IrInstruction *ir_analyze_enum_to_int(IrAnalyze *ira, IrInstruction *sour
10312 assert(wanted_type->id == ZigTypeIdInt || wanted_type->id == ZigTypeIdComptimeInt);10312 assert(wanted_type->id == ZigTypeIdInt || wanted_type->id == ZigTypeIdComptimeInt);
1031310313
10314 ZigType *actual_type = target->value.type;10314 ZigType *actual_type = target->value.type;
10315
10316 if (actual_type->id == ZigTypeIdUnion)
10317 actual_type = actual_type->data.unionation.tag_type;
10318
10315 if ((err = ensure_complete_type(ira->codegen, actual_type)))10319 if ((err = ensure_complete_type(ira->codegen, actual_type)))
10316 return ira->codegen->invalid_instruction;10320 return ira->codegen->invalid_instruction;
1031710321
...@@ -10330,7 +10334,11 @@ static IrInstruction *ir_analyze_enum_to_int(IrAnalyze *ira, IrInstruction *sour...@@ -10330,7 +10334,11 @@ static IrInstruction *ir_analyze_enum_to_int(IrAnalyze *ira, IrInstruction *sour
10330 if (!val)10334 if (!val)
10331 return ira->codegen->invalid_instruction;10335 return ira->codegen->invalid_instruction;
10332 IrInstruction *result = ir_const(ira, source_instr, wanted_type);10336 IrInstruction *result = ir_const(ira, source_instr, wanted_type);
10333 init_const_bigint(&result->value, wanted_type, &val->data.x_enum_tag);10337 if (target->value.type->id == ZigTypeIdUnion)
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
10334 return result;10342 return result;
10335 }10343 }
1033610344
...@@ -10341,12 +10349,18 @@ static IrInstruction *ir_analyze_enum_to_int(IrAnalyze *ira, IrInstruction *sour...@@ -10341,12 +10349,18 @@ static IrInstruction *ir_analyze_enum_to_int(IrAnalyze *ira, IrInstruction *sour
10341 assert(wanted_type== ira->codegen->builtin_types.entry_num_lit_int);10349 assert(wanted_type== ira->codegen->builtin_types.entry_num_lit_int);
10342 IrInstruction *result = ir_const(ira, source_instr, wanted_type);10350 IrInstruction *result = ir_const(ira, source_instr, wanted_type);
10343 init_const_bigint(&result->value, wanted_type,10351 init_const_bigint(&result->value, wanted_type,
10344 &actual_type->data.enumeration.fields[0].value);10352 &actual_type->data.enumeration.fields[0].value);
10353
10345 return result;10354 return result;
10346 }10355 }
1034710356
10348 IrInstruction *result = ir_build_widen_or_shorten(&ira->new_irb, source_instr->scope,10357 IrInstruction *result = nullptr;
10349 source_instr->source_node, target);10358 if (target->value.type->id == ZigTypeIdUnion)
10359 result = ir_build_union_tag(&ira->new_irb, source_instr->scope,
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);
10350 result->value.type = wanted_type;10364 result->value.type = wanted_type;
10351 return result;10365 return result;
10352}10366}
...@@ -14358,12 +14372,12 @@ static Error ir_read_const_ptr(IrAnalyze *ira, CodeGen *codegen, AstNode *source...@@ -14358,12 +14372,12 @@ static Error ir_read_const_ptr(IrAnalyze *ira, CodeGen *codegen, AstNode *source
14358 if (dst_size == 0)14372 if (dst_size == 0)
14359 return ErrorNone;14373 return ErrorNone;
14360 opt_ir_add_error_node(ira, codegen, source_node,14374 opt_ir_add_error_node(ira, codegen, source_node,
14361 buf_sprintf("attempt to read %zu bytes from null pointer",14375 buf_sprintf("attempt to read %" ZIG_PRI_usize " bytes from null pointer",
14362 dst_size));14376 dst_size));
14363 return ErrorSemanticAnalyzeFail;14377 return ErrorSemanticAnalyzeFail;
14364 case ConstPtrSpecialRef: {14378 case ConstPtrSpecialRef: {
14365 opt_ir_add_error_node(ira, codegen, source_node,14379 opt_ir_add_error_node(ira, codegen, source_node,
14366 buf_sprintf("attempt to read %zu bytes from pointer to %s which is %zu bytes",14380 buf_sprintf("attempt to read %" ZIG_PRI_usize " bytes from pointer to %s which is %" ZIG_PRI_usize " bytes",
14367 dst_size, buf_ptr(&pointee->type->name), src_size));14381 dst_size, buf_ptr(&pointee->type->name), src_size));
14368 return ErrorSemanticAnalyzeFail;14382 return ErrorSemanticAnalyzeFail;
14369 }14383 }
...@@ -14377,7 +14391,7 @@ static Error ir_read_const_ptr(IrAnalyze *ira, CodeGen *codegen, AstNode *source...@@ -14377,7 +14391,7 @@ static Error ir_read_const_ptr(IrAnalyze *ira, CodeGen *codegen, AstNode *source
14377 src_size = elem_size * (array_val->type->data.array.len - elem_index);14391 src_size = elem_size * (array_val->type->data.array.len - elem_index);
14378 if (dst_size > src_size) {14392 if (dst_size > src_size) {
14379 opt_ir_add_error_node(ira, codegen, source_node,14393 opt_ir_add_error_node(ira, codegen, source_node,
14380 buf_sprintf("attempt to read %zu bytes from %s at index %" ZIG_PRI_usize " which is %zu bytes",14394 buf_sprintf("attempt to read %" ZIG_PRI_usize " bytes from %s at index %" ZIG_PRI_usize " which is %" ZIG_PRI_usize " bytes",
14381 dst_size, buf_ptr(&array_val->type->name), elem_index, src_size));14395 dst_size, buf_ptr(&array_val->type->name), elem_index, src_size));
14382 return ErrorSemanticAnalyzeFail;14396 return ErrorSemanticAnalyzeFail;
14383 }14397 }
...@@ -21960,21 +21974,36 @@ static IrInstruction *ir_analyze_instruction_bit_reverse(IrAnalyze *ira, IrInstr...@@ -21960,21 +21974,36 @@ static IrInstruction *ir_analyze_instruction_bit_reverse(IrAnalyze *ira, IrInstr
21960static IrInstruction *ir_analyze_instruction_enum_to_int(IrAnalyze *ira, IrInstructionEnumToInt *instruction) {21974static IrInstruction *ir_analyze_instruction_enum_to_int(IrAnalyze *ira, IrInstructionEnumToInt *instruction) {
21961 Error err;21975 Error err;
21962 IrInstruction *target = instruction->target->child;21976 IrInstruction *target = instruction->target->child;
21963 if (type_is_invalid(target->value.type))21977 ZigType *enum_type = target->value.type;
21978 if (type_is_invalid(enum_type))
21964 return ira->codegen->invalid_instruction;21979 return ira->codegen->invalid_instruction;
2196521980
21966 if (target->value.type->id != ZigTypeIdEnum) {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) {
21967 ir_add_error(ira, instruction->target,21996 ir_add_error(ira, instruction->target,
21968 buf_sprintf("expected enum, found type '%s'", buf_ptr(&target->value.type->name)));21997 buf_sprintf("expected enum or union(enum), found type '%s'", buf_ptr(&enum_type->name)));
21969 return ira->codegen->invalid_instruction;21998 return ira->codegen->invalid_instruction;
21970 }21999 }
2197122000
21972 if ((err = type_resolve(ira->codegen, target->value.type, ResolveStatusZeroBitsKnown)))22001 if ((err = type_resolve(ira->codegen, enum_type, ResolveStatusZeroBitsKnown)))
21973 return ira->codegen->invalid_instruction;22002 return ira->codegen->invalid_instruction;
2197422003
21975 ZigType *tag_type = target->value.type->data.enumeration.tag_int_type;22004 ZigType *int_type = enum_type->data.enumeration.tag_int_type;
2197622005
21977 return ir_analyze_enum_to_int(ira, &instruction->base, target, tag_type);22006 return ir_analyze_enum_to_int(ira, &instruction->base, target, int_type);
21978}22007}
2197922008
21980static IrInstruction *ir_analyze_instruction_int_to_enum(IrAnalyze *ira, IrInstructionIntToEnum *instruction) {22009static IrInstruction *ir_analyze_instruction_int_to_enum(IrAnalyze *ira, IrInstructionIntToEnum *instruction) {
src/target.cpp+2-1
...@@ -9,6 +9,7 @@...@@ -9,6 +9,7 @@
9#include "error.hpp"9#include "error.hpp"
10#include "target.hpp"10#include "target.hpp"
11#include "util.hpp"11#include "util.hpp"
12#include "os.hpp"
1213
13#include <stdio.h>14#include <stdio.h>
1415
...@@ -848,7 +849,7 @@ const char *target_lib_file_ext(ZigTarget *target, bool is_static, size_t versio...@@ -848,7 +849,7 @@ const char *target_lib_file_ext(ZigTarget *target, bool is_static, size_t versio
848 if (is_static) {849 if (is_static) {
849 return ".a";850 return ".a";
850 } else {851 } else {
851 return buf_ptr(buf_sprintf(".so.%zu", version_major));852 return buf_ptr(buf_sprintf(".so.%" ZIG_PRI_usize, version_major));
852 }853 }
853 }854 }
854}855}
test/stage1/behavior/union.zig+5-6
...@@ -126,7 +126,7 @@ const MultipleChoice = union(enum(u32)) {...@@ -126,7 +126,7 @@ const MultipleChoice = union(enum(u32)) {
126test "simple union(enum(u32))" {126test "simple union(enum(u32))" {
127 var x = MultipleChoice.C;127 var x = MultipleChoice.C;
128 expect(x == MultipleChoice.C);128 expect(x == MultipleChoice.C);
129 expect(@enumToInt(@TagType(MultipleChoice)(x)) == 60);129 expect(@enumToInt(x) == 60);
130}130}
131131
132const MultipleChoice2 = union(enum(u32)) {132const MultipleChoice2 = union(enum(u32)) {
...@@ -148,7 +148,7 @@ test "union(enum(u32)) with specified and unspecified tag values" {...@@ -148,7 +148,7 @@ test "union(enum(u32)) with specified and unspecified tag values" {
148}148}
149149
150fn testEnumWithSpecifiedAndUnspecifiedTagValues(x: MultipleChoice2) void {150fn testEnumWithSpecifiedAndUnspecifiedTagValues(x: MultipleChoice2) void {
151 expect(@enumToInt(@TagType(MultipleChoice2)(x)) == 60);151 expect(@enumToInt(x) == 60);
152 expect(1123 == switch (x) {152 expect(1123 == switch (x) {
153 MultipleChoice2.A => 1,153 MultipleChoice2.A => 1,
154 MultipleChoice2.B => 2,154 MultipleChoice2.B => 2,
...@@ -345,8 +345,7 @@ test "union with only 1 field casted to its enum type which has enum value speci...@@ -345,8 +345,7 @@ test "union with only 1 field casted to its enum type which has enum value speci
345345
346 var e = Expr{ .Literal = Literal{ .Bool = true } };346 var e = Expr{ .Literal = Literal{ .Bool = true } };
347 comptime expect(@TagType(Tag) == comptime_int);347 comptime expect(@TagType(Tag) == comptime_int);
348 var t = Tag(e);348 expect(Tag(e) == Expr.Literal);
349 expect(t == Expr.Literal);349 expect(@enumToInt(e) == 33);
350 expect(@enumToInt(t) == 33);350 comptime expect(@enumToInt(e) == 33);
351 comptime expect(@enumToInt(t) == 33);
352}351}