authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-12-26 16:34:18-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-12-26 16:34:18-05:00
log66a83d87383cd8de62898171b6665cb1d70af231
treeff09db18060a350166cd07a9fb039b43d1a63e37
parentc8a7ab7eff0f261c47926cf0637e919d42e41940

IR: pass intToEnum test


6 files changed, 93 insertions(+), 33 deletions(-)

src/all_types.hpp+7-1
...@@ -437,7 +437,6 @@ enum CastOp {...@@ -437,7 +437,6 @@ enum CastOp {
437 CastOpFloatToInt,437 CastOpFloatToInt,
438 CastOpBoolToInt,438 CastOpBoolToInt,
439 CastOpResizeSlice,439 CastOpResizeSlice,
440 CastOpIntToEnum,
441 CastOpBytesToSlice,440 CastOpBytesToSlice,
442};441};
443442
...@@ -1458,6 +1457,7 @@ enum IrInstructionId {...@@ -1458,6 +1457,7 @@ enum IrInstructionId {
1458 IrInstructionIdWidenOrShorten,1457 IrInstructionIdWidenOrShorten,
1459 IrInstructionIdIntToPtr,1458 IrInstructionIdIntToPtr,
1460 IrInstructionIdPtrToInt,1459 IrInstructionIdPtrToInt,
1460 IrInstructionIdIntToEnum,
1461};1461};
14621462
1463struct IrInstruction {1463struct IrInstruction {
...@@ -2118,6 +2118,12 @@ struct IrInstructionIntToPtr {...@@ -2118,6 +2118,12 @@ struct IrInstructionIntToPtr {
2118 IrInstruction *target;2118 IrInstruction *target;
2119};2119};
21202120
2121struct IrInstructionIntToEnum {
2122 IrInstruction base;
2123
2124 IrInstruction *target;
2125};
2126
2121enum LValPurpose {2127enum LValPurpose {
2122 LValPurposeNone,2128 LValPurposeNone,
2123 LValPurposeAssign,2129 LValPurposeAssign,
src/codegen.cpp+20-4
...@@ -1075,10 +1075,6 @@ static LLVMValueRef ir_render_cast(CodeGen *g, IrExecutable *executable,...@@ -1075,10 +1075,6 @@ static LLVMValueRef ir_render_cast(CodeGen *g, IrExecutable *executable,
1075 assert(wanted_type->id == TypeTableEntryIdInt);1075 assert(wanted_type->id == TypeTableEntryIdInt);
1076 assert(actual_type->id == TypeTableEntryIdBool);1076 assert(actual_type->id == TypeTableEntryIdBool);
1077 return LLVMBuildZExt(g->builder, expr_val, wanted_type->type_ref, "");1077 return LLVMBuildZExt(g->builder, expr_val, wanted_type->type_ref, "");
1078
1079 case CastOpIntToEnum:
1080 return gen_widen_or_shorten(g, ir_want_debug_safety(g, &cast_instruction->base),
1081 actual_type, wanted_type->data.enumeration.tag_type, expr_val);
1082 }1078 }
1083 zig_unreachable();1079 zig_unreachable();
1084}1080}
...@@ -1122,6 +1118,24 @@ static LLVMValueRef ir_render_ptr_to_int(CodeGen *g, IrExecutable *executable, I...@@ -1122,6 +1118,24 @@ static LLVMValueRef ir_render_ptr_to_int(CodeGen *g, IrExecutable *executable, I
1122 return LLVMBuildPtrToInt(g->builder, target_val, wanted_type->type_ref, "");1118 return LLVMBuildPtrToInt(g->builder, target_val, wanted_type->type_ref, "");
1123}1119}
11241120
1121static LLVMValueRef ir_render_int_to_enum(CodeGen *g, IrExecutable *executable, IrInstructionIntToEnum *instruction) {
1122 TypeTableEntry *wanted_type = instruction->base.value.type;
1123 assert(wanted_type->id == TypeTableEntryIdEnum);
1124 TypeTableEntry *tag_type = wanted_type->data.enumeration.tag_type;
1125 TypeTableEntry *wanted_int_type;
1126 if (tag_type->id == TypeTableEntryIdEnumTag) {
1127 wanted_int_type = tag_type->data.enum_tag.int_type;
1128 } else if (tag_type->id == TypeTableEntryIdInt) {
1129 wanted_int_type = tag_type;
1130 } else {
1131 zig_unreachable();
1132 }
1133
1134 LLVMValueRef target_val = ir_llvm_value(g, instruction->target);
1135 return gen_widen_or_shorten(g, ir_want_debug_safety(g, &instruction->base),
1136 instruction->target->value.type, wanted_int_type, target_val);
1137}
1138
1125static LLVMValueRef ir_render_unreachable(CodeGen *g, IrExecutable *executable,1139static LLVMValueRef ir_render_unreachable(CodeGen *g, IrExecutable *executable,
1126 IrInstructionUnreachable *unreachable_instruction)1140 IrInstructionUnreachable *unreachable_instruction)
1127{1141{
...@@ -2359,6 +2373,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,...@@ -2359,6 +2373,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
2359 return ir_render_ptr_to_int(g, executable, (IrInstructionPtrToInt *)instruction);2373 return ir_render_ptr_to_int(g, executable, (IrInstructionPtrToInt *)instruction);
2360 case IrInstructionIdIntToPtr:2374 case IrInstructionIdIntToPtr:
2361 return ir_render_int_to_ptr(g, executable, (IrInstructionIntToPtr *)instruction);2375 return ir_render_int_to_ptr(g, executable, (IrInstructionIntToPtr *)instruction);
2376 case IrInstructionIdIntToEnum:
2377 return ir_render_int_to_enum(g, executable, (IrInstructionIntToEnum *)instruction);
2362 case IrInstructionIdContainerInitList:2378 case IrInstructionIdContainerInitList:
2363 return ir_render_container_init_list(g, executable, (IrInstructionContainerInitList *)instruction);2379 return ir_render_container_init_list(g, executable, (IrInstructionContainerInitList *)instruction);
2364 case IrInstructionIdSwitchVar:2380 case IrInstructionIdSwitchVar:
src/ir.cpp+40-11
...@@ -468,6 +468,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionIntToPtr *) {...@@ -468,6 +468,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionIntToPtr *) {
468 return IrInstructionIdIntToPtr;468 return IrInstructionIdIntToPtr;
469}469}
470470
471static constexpr IrInstructionId ir_instruction_id(IrInstructionIntToEnum *) {
472 return IrInstructionIdIntToEnum;
473}
474
471template<typename T>475template<typename T>
472static T *ir_create_instruction(IrExecutable *exec, Scope *scope, AstNode *source_node) {476static T *ir_create_instruction(IrExecutable *exec, Scope *scope, AstNode *source_node) {
473 T *special_instruction = allocate<T>(1);477 T *special_instruction = allocate<T>(1);
...@@ -1932,6 +1936,18 @@ static IrInstruction *ir_build_ptr_to_int(IrBuilder *irb, Scope *scope, AstNode...@@ -1932,6 +1936,18 @@ static IrInstruction *ir_build_ptr_to_int(IrBuilder *irb, Scope *scope, AstNode
1932 return &instruction->base;1936 return &instruction->base;
1933}1937}
19341938
1939static IrInstruction *ir_build_int_to_enum(IrBuilder *irb, Scope *scope, AstNode *source_node,
1940 IrInstruction *target)
1941{
1942 IrInstructionIntToEnum *instruction = ir_build_instruction<IrInstructionIntToEnum>(
1943 irb, scope, source_node);
1944 instruction->target = target;
1945
1946 ir_ref_instruction(target);
1947
1948 return &instruction->base;
1949}
1950
1935static void ir_count_defers(IrBuilder *irb, Scope *inner_scope, Scope *outer_scope, size_t *results) {1951static void ir_count_defers(IrBuilder *irb, Scope *inner_scope, Scope *outer_scope, size_t *results) {
1936 results[ReturnKindUnconditional] = 0;1952 results[ReturnKindUnconditional] = 0;
1937 results[ReturnKindError] = 0;1953 results[ReturnKindError] = 0;
...@@ -4720,16 +4736,6 @@ static void eval_const_expr_implicit_cast(CastOp cast_op,...@@ -4720,16 +4736,6 @@ static void eval_const_expr_implicit_cast(CastOp cast_op,
4720 bignum_init_unsigned(&const_val->data.x_bignum, other_val->data.x_bool ? 1 : 0);4736 bignum_init_unsigned(&const_val->data.x_bignum, other_val->data.x_bool ? 1 : 0);
4721 const_val->special = ConstValSpecialStatic;4737 const_val->special = ConstValSpecialStatic;
4722 break;4738 break;
4723 case CastOpIntToEnum:
4724 {
4725 uint64_t value = other_val->data.x_bignum.data.x_uint;
4726 assert(new_type->id == TypeTableEntryIdEnum);
4727 assert(value < new_type->data.enumeration.src_field_count);
4728 const_val->data.x_enum.tag = value;
4729 const_val->data.x_enum.payload = NULL;
4730 const_val->special = ConstValSpecialStatic;
4731 break;
4732 }
4733 }4739 }
4734}4740}
4735static IrInstruction *ir_resolve_cast(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value,4741static IrInstruction *ir_resolve_cast(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value,
...@@ -5311,6 +5317,27 @@ static IrInstruction *ir_analyze_int_to_ptr(IrAnalyze *ira, IrInstruction *sourc...@@ -5311,6 +5317,27 @@ static IrInstruction *ir_analyze_int_to_ptr(IrAnalyze *ira, IrInstruction *sourc
5311 return result;5317 return result;
5312}5318}
53135319
5320static IrInstruction *ir_analyze_int_to_enum(IrAnalyze *ira, IrInstruction *source_instr,
5321 IrInstruction *target, TypeTableEntry *wanted_type)
5322{
5323 assert(wanted_type->id == TypeTableEntryIdEnum);
5324
5325 if (instr_is_comptime(target)) {
5326 ConstExprValue *val = ir_resolve_const(ira, target, UndefBad);
5327 if (!val)
5328 return ira->codegen->invalid_instruction;
5329 IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,
5330 source_instr->source_node, wanted_type, val->depends_on_compile_var);
5331 result->value.data.x_enum.tag = val->data.x_bignum.data.x_uint;
5332 return result;
5333 }
5334
5335 IrInstruction *result = ir_build_int_to_enum(&ira->new_irb, source_instr->scope,
5336 source_instr->source_node, target);
5337 result->value.type = wanted_type;
5338 return result;
5339}
5340
5314static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_instr,5341static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_instr,
5315 TypeTableEntry *wanted_type, IrInstruction *value)5342 TypeTableEntry *wanted_type, IrInstruction *value)
5316{5343{
...@@ -5533,7 +5560,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst...@@ -5533,7 +5560,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
5533 wanted_type->id == TypeTableEntryIdEnum &&5560 wanted_type->id == TypeTableEntryIdEnum &&
5534 wanted_type->data.enumeration.gen_field_count == 0)5561 wanted_type->data.enumeration.gen_field_count == 0)
5535 {5562 {
5536 return ir_resolve_cast(ira, source_instr, value, wanted_type, CastOpIntToEnum, false);5563 return ir_analyze_int_to_enum(ira, source_instr, value, wanted_type);
5537 }5564 }
55385565
5539 // explicit cast from enum type with no payload to integer5566 // explicit cast from enum type with no payload to integer
...@@ -10016,6 +10043,7 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi...@@ -10016,6 +10043,7 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi
10016 case IrInstructionIdWidenOrShorten:10043 case IrInstructionIdWidenOrShorten:
10017 case IrInstructionIdIntToPtr:10044 case IrInstructionIdIntToPtr:
10018 case IrInstructionIdPtrToInt:10045 case IrInstructionIdPtrToInt:
10046 case IrInstructionIdIntToEnum:
10019 case IrInstructionIdStructInit:10047 case IrInstructionIdStructInit:
10020 case IrInstructionIdStructFieldPtr:10048 case IrInstructionIdStructFieldPtr:
10021 case IrInstructionIdEnumFieldPtr:10049 case IrInstructionIdEnumFieldPtr:
...@@ -10325,6 +10353,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {...@@ -10325,6 +10353,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {
10325 case IrInstructionIdWidenOrShorten:10353 case IrInstructionIdWidenOrShorten:
10326 case IrInstructionIdPtrToInt:10354 case IrInstructionIdPtrToInt:
10327 case IrInstructionIdIntToPtr:10355 case IrInstructionIdIntToPtr:
10356 case IrInstructionIdIntToEnum:
10328 return false;10357 return false;
10329 case IrInstructionIdAsm:10358 case IrInstructionIdAsm:
10330 {10359 {
src/ir_print.cpp+9
...@@ -952,6 +952,12 @@ static void ir_print_int_to_ptr(IrPrint *irp, IrInstructionIntToPtr *instruction...@@ -952,6 +952,12 @@ static void ir_print_int_to_ptr(IrPrint *irp, IrInstructionIntToPtr *instruction
952 fprintf(irp->f, ")");952 fprintf(irp->f, ")");
953}953}
954954
955static void ir_print_int_to_enum(IrPrint *irp, IrInstructionIntToEnum *instruction) {
956 fprintf(irp->f, "@intToEnum(");
957 ir_print_other_instruction(irp, instruction->target);
958 fprintf(irp->f, ")");
959}
960
955static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {961static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
956 ir_print_prefix(irp, instruction);962 ir_print_prefix(irp, instruction);
957 switch (instruction->id) {963 switch (instruction->id) {
...@@ -1203,6 +1209,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {...@@ -1203,6 +1209,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
1203 case IrInstructionIdIntToPtr:1209 case IrInstructionIdIntToPtr:
1204 ir_print_int_to_ptr(irp, (IrInstructionIntToPtr *)instruction);1210 ir_print_int_to_ptr(irp, (IrInstructionIntToPtr *)instruction);
1205 break;1211 break;
1212 case IrInstructionIdIntToEnum:
1213 ir_print_int_to_enum(irp, (IrInstructionIntToEnum *)instruction);
1214 break;
1206 }1215 }
1207 fprintf(irp->f, "\n");1216 fprintf(irp->f, "\n");
1208}1217}
test/cases/enum.zig+17
...@@ -96,6 +96,23 @@ fn shouldEqual(n: Number, expected: usize) {...@@ -96,6 +96,23 @@ fn shouldEqual(n: Number, expected: usize) {
96}96}
9797
9898
99fn intToEnum() {
100 @setFnTest(this);
101
102 testIntToEnumEval(3);
103}
104fn testIntToEnumEval(x: i32) {
105 assert(IntToEnumNumber(x) == IntToEnumNumber.Three);
106}
107const IntToEnumNumber = enum {
108 Zero,
109 One,
110 Two,
111 Three,
112 Four,
113};
114
115
99// TODO import from std116// TODO import from std
100fn assert(ok: bool) {117fn assert(ok: bool) {
101 if (!ok)118 if (!ok)
test/self_hosted.zig-17
...@@ -80,20 +80,3 @@ fn castSliceToU8Slice() {...@@ -80,20 +80,3 @@ fn castSliceToU8Slice() {
80 assert(bytes[10] == @maxValue(u8));80 assert(bytes[10] == @maxValue(u8));
81 assert(bytes[11] == @maxValue(u8));81 assert(bytes[11] == @maxValue(u8));
82}82}
83
84// TODO not passing
85fn intToEnum() {
86 @setFnTest(this);
87
88 testIntToEnumEval(3);
89}
90fn testIntToEnumEval(x: i32) {
91 assert(IntToEnumNumber(x) == IntToEnumNumber.Three);
92}
93const IntToEnumNumber = enum {
94 Zero,
95 One,
96 Two,
97 Three,
98 Four,
99};