authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-12-26 02:36:04-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-12-26 02:36:04-05:00
log4664f793dc3fed2254863a5b6efc302c095890cb
tree1c52e0597e181d09ebf199797894945de1eb25f4
parent1b5d1877aea6c0db7fbe6f56ffe4412ce2cffff7

IR: pass enumToInt test


6 files changed, 124 insertions(+), 47 deletions(-)

src/all_types.hpp+7-2
...@@ -429,14 +429,12 @@ enum CastOp {...@@ -429,14 +429,12 @@ enum CastOp {
429 CastOpNoop, // fn call expr is a cast, but does nothing429 CastOpNoop, // fn call expr is a cast, but does nothing
430 CastOpPtrToInt,430 CastOpPtrToInt,
431 CastOpIntToPtr,431 CastOpIntToPtr,
432 CastOpWidenOrShorten,
433 CastOpErrToInt,432 CastOpErrToInt,
434 CastOpIntToFloat,433 CastOpIntToFloat,
435 CastOpFloatToInt,434 CastOpFloatToInt,
436 CastOpBoolToInt,435 CastOpBoolToInt,
437 CastOpResizeSlice,436 CastOpResizeSlice,
438 CastOpIntToEnum,437 CastOpIntToEnum,
439 CastOpEnumToInt,
440 CastOpBytesToSlice,438 CastOpBytesToSlice,
441};439};
442440
...@@ -1454,6 +1452,7 @@ enum IrInstructionId {...@@ -1454,6 +1452,7 @@ enum IrInstructionId {
1454 IrInstructionIdTestComptime,1452 IrInstructionIdTestComptime,
1455 IrInstructionIdInitEnum,1453 IrInstructionIdInitEnum,
1456 IrInstructionIdPointerReinterpret,1454 IrInstructionIdPointerReinterpret,
1455 IrInstructionIdWidenOrShorten,
1457};1456};
14581457
1459struct IrInstruction {1458struct IrInstruction {
...@@ -2096,6 +2095,12 @@ struct IrInstructionPointerReinterpret {...@@ -2096,6 +2095,12 @@ struct IrInstructionPointerReinterpret {
2096 IrInstruction *ptr;2095 IrInstruction *ptr;
2097};2096};
20982097
2098struct IrInstructionWidenOrShorten {
2099 IrInstruction base;
2100
2101 IrInstruction *target;
2102};
2103
2099enum LValPurpose {2104enum LValPurpose {
2100 LValPurposeNone,2105 LValPurposeNone,
2101 LValPurposeAssign,2106 LValPurposeAssign,
src/codegen.cpp+20-6
...@@ -973,9 +973,6 @@ static LLVMValueRef ir_render_cast(CodeGen *g, IrExecutable *executable,...@@ -973,9 +973,6 @@ static LLVMValueRef ir_render_cast(CodeGen *g, IrExecutable *executable,
973 return LLVMBuildPtrToInt(g->builder, expr_val, wanted_type->type_ref, "");973 return LLVMBuildPtrToInt(g->builder, expr_val, wanted_type->type_ref, "");
974 case CastOpIntToPtr:974 case CastOpIntToPtr:
975 return LLVMBuildIntToPtr(g->builder, expr_val, wanted_type->type_ref, "");975 return LLVMBuildIntToPtr(g->builder, expr_val, wanted_type->type_ref, "");
976 case CastOpWidenOrShorten:
977 return gen_widen_or_shorten(g, ir_want_debug_safety(g, &cast_instruction->base),
978 actual_type, wanted_type, expr_val);
979 case CastOpResizeSlice:976 case CastOpResizeSlice:
980 {977 {
981 assert(cast_instruction->tmp_ptr);978 assert(cast_instruction->tmp_ptr);
...@@ -1086,9 +1083,6 @@ static LLVMValueRef ir_render_cast(CodeGen *g, IrExecutable *executable,...@@ -1086,9 +1083,6 @@ static LLVMValueRef ir_render_cast(CodeGen *g, IrExecutable *executable,
1086 case CastOpIntToEnum:1083 case CastOpIntToEnum:
1087 return gen_widen_or_shorten(g, ir_want_debug_safety(g, &cast_instruction->base),1084 return gen_widen_or_shorten(g, ir_want_debug_safety(g, &cast_instruction->base),
1088 actual_type, wanted_type->data.enumeration.tag_type, expr_val);1085 actual_type, wanted_type->data.enumeration.tag_type, expr_val);
1089 case CastOpEnumToInt:
1090 return gen_widen_or_shorten(g, ir_want_debug_safety(g, &cast_instruction->base),
1091 actual_type->data.enumeration.tag_type, wanted_type, expr_val);
1092 }1086 }
1093 zig_unreachable();1087 zig_unreachable();
1094}1088}
...@@ -1101,6 +1095,24 @@ static LLVMValueRef ir_render_pointer_reinterpret(CodeGen *g, IrExecutable *exec...@@ -1101,6 +1095,24 @@ static LLVMValueRef ir_render_pointer_reinterpret(CodeGen *g, IrExecutable *exec
1101 return LLVMBuildBitCast(g->builder, ptr, wanted_type->type_ref, "");1095 return LLVMBuildBitCast(g->builder, ptr, wanted_type->type_ref, "");
1102}1096}
11031097
1098static LLVMValueRef ir_render_widen_or_shorten(CodeGen *g, IrExecutable *executable,
1099 IrInstructionWidenOrShorten *instruction)
1100{
1101 TypeTableEntry *actual_type = instruction->target->value.type;
1102 // TODO instead of this logic, use the Noop instruction to change the type from
1103 // enum_tag to the underlying int type
1104 TypeTableEntry *int_type;
1105 if (actual_type->id == TypeTableEntryIdEnum) {
1106 TypeTableEntry *tag_type = actual_type->data.enumeration.tag_type;
1107 assert(tag_type->id == TypeTableEntryIdEnumTag);
1108 int_type = tag_type->data.enum_tag.int_type;
1109 } else {
1110 int_type = actual_type;
1111 }
1112 LLVMValueRef target_val = ir_llvm_value(g, instruction->target);
1113 return gen_widen_or_shorten(g, ir_want_debug_safety(g, &instruction->base), int_type,
1114 instruction->base.value.type, target_val);
1115}
11041116
1105static LLVMValueRef ir_render_unreachable(CodeGen *g, IrExecutable *executable,1117static LLVMValueRef ir_render_unreachable(CodeGen *g, IrExecutable *executable,
1106 IrInstructionUnreachable *unreachable_instruction)1118 IrInstructionUnreachable *unreachable_instruction)
...@@ -2309,6 +2321,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,...@@ -2309,6 +2321,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
2309 return ir_render_struct_init(g, executable, (IrInstructionStructInit *)instruction);2321 return ir_render_struct_init(g, executable, (IrInstructionStructInit *)instruction);
2310 case IrInstructionIdPointerReinterpret:2322 case IrInstructionIdPointerReinterpret:
2311 return ir_render_pointer_reinterpret(g, executable, (IrInstructionPointerReinterpret *)instruction);2323 return ir_render_pointer_reinterpret(g, executable, (IrInstructionPointerReinterpret *)instruction);
2324 case IrInstructionIdWidenOrShorten:
2325 return ir_render_widen_or_shorten(g, executable, (IrInstructionWidenOrShorten *)instruction);
2312 case IrInstructionIdSwitchVar:2326 case IrInstructionIdSwitchVar:
2313 zig_panic("TODO render switch var instruction to LLVM");2327 zig_panic("TODO render switch var instruction to LLVM");
2314 case IrInstructionIdContainerInitList:2328 case IrInstructionIdContainerInitList:
src/ir.cpp+64-7
...@@ -455,6 +455,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionPointerReinterpr...@@ -455,6 +455,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionPointerReinterpr
455 return IrInstructionIdPointerReinterpret;455 return IrInstructionIdPointerReinterpret;
456}456}
457457
458static constexpr IrInstructionId ir_instruction_id(IrInstructionWidenOrShorten *) {
459 return IrInstructionIdWidenOrShorten;
460}
461
458template<typename T>462template<typename T>
459static T *ir_create_instruction(IrExecutable *exec, Scope *scope, AstNode *source_node) {463static T *ir_create_instruction(IrExecutable *exec, Scope *scope, AstNode *source_node) {
460 T *special_instruction = allocate<T>(1);464 T *special_instruction = allocate<T>(1);
...@@ -1883,6 +1887,18 @@ static IrInstruction *ir_build_pointer_reinterpret(IrBuilder *irb, Scope *scope,...@@ -1883,6 +1887,18 @@ static IrInstruction *ir_build_pointer_reinterpret(IrBuilder *irb, Scope *scope,
1883 return &instruction->base;1887 return &instruction->base;
1884}1888}
18851889
1890static IrInstruction *ir_build_widen_or_shorten(IrBuilder *irb, Scope *scope, AstNode *source_node,
1891 IrInstruction *target)
1892{
1893 IrInstructionWidenOrShorten *instruction = ir_build_instruction<IrInstructionWidenOrShorten>(
1894 irb, scope, source_node);
1895 instruction->target = target;
1896
1897 ir_ref_instruction(target);
1898
1899 return &instruction->base;
1900}
1901
1886static void ir_count_defers(IrBuilder *irb, Scope *inner_scope, Scope *outer_scope, size_t *results) {1902static void ir_count_defers(IrBuilder *irb, Scope *inner_scope, Scope *outer_scope, size_t *results) {
1887 results[ReturnKindUnconditional] = 0;1903 results[ReturnKindUnconditional] = 0;
1888 results[ReturnKindError] = 0;1904 results[ReturnKindError] = 0;
...@@ -4638,7 +4654,6 @@ static void eval_const_expr_implicit_cast(CastOp cast_op,...@@ -4638,7 +4654,6 @@ static void eval_const_expr_implicit_cast(CastOp cast_op,
4638 case CastOpNoCast:4654 case CastOpNoCast:
4639 zig_unreachable();4655 zig_unreachable();
4640 case CastOpNoop:4656 case CastOpNoop:
4641 case CastOpWidenOrShorten:
4642 *const_val = *other_val;4657 *const_val = *other_val;
4643 const_val->type = new_type;4658 const_val->type = new_type;
4644 break;4659 break;
...@@ -4684,10 +4699,6 @@ static void eval_const_expr_implicit_cast(CastOp cast_op,...@@ -4684,10 +4699,6 @@ static void eval_const_expr_implicit_cast(CastOp cast_op,
4684 const_val->special = ConstValSpecialStatic;4699 const_val->special = ConstValSpecialStatic;
4685 break;4700 break;
4686 }4701 }
4687 case CastOpEnumToInt:
4688 bignum_init_unsigned(&const_val->data.x_bignum, other_val->data.x_enum.tag);
4689 const_val->special = ConstValSpecialStatic;
4690 break;
4691 }4702 }
4692}4703}
4693static IrInstruction *ir_resolve_cast(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value,4704static IrInstruction *ir_resolve_cast(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value,
...@@ -5181,6 +5192,50 @@ static IrInstruction *ir_analyze_array_to_slice(IrAnalyze *ira, IrInstruction *s...@@ -5181,6 +5192,50 @@ static IrInstruction *ir_analyze_array_to_slice(IrAnalyze *ira, IrInstruction *s
5181 return result;5192 return result;
5182}5193}
51835194
5195static IrInstruction *ir_analyze_enum_to_int(IrAnalyze *ira, IrInstruction *source_instr,
5196 IrInstruction *target, TypeTableEntry *wanted_type)
5197{
5198 assert(wanted_type->id == TypeTableEntryIdInt);
5199
5200 if (instr_is_comptime(target)) {
5201 ConstExprValue *val = ir_resolve_const(ira, target, UndefBad);
5202 if (!val)
5203 return ira->codegen->invalid_instruction;
5204 IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,
5205 source_instr->source_node, wanted_type, val->depends_on_compile_var);
5206 init_const_unsigned_negative(&result->value, wanted_type, val->data.x_enum.tag, false);
5207 return result;
5208 }
5209
5210 IrInstruction *result = ir_build_widen_or_shorten(&ira->new_irb, source_instr->scope,
5211 source_instr->source_node, target);
5212 result->value.type = wanted_type;
5213 return result;
5214}
5215
5216static IrInstruction *ir_analyze_widen_or_shorten(IrAnalyze *ira, IrInstruction *source_instr,
5217 IrInstruction *target, TypeTableEntry *wanted_type)
5218{
5219 assert(wanted_type->id == TypeTableEntryIdInt || wanted_type->id == TypeTableEntryIdFloat);
5220
5221 if (instr_is_comptime(target)) {
5222 ConstExprValue *val = ir_resolve_const(ira, target, UndefBad);
5223 if (!val)
5224 return ira->codegen->invalid_instruction;
5225 IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,
5226 source_instr->source_node, wanted_type, val->depends_on_compile_var);
5227 result->value = *val;
5228 result->value.type = wanted_type;
5229 return result;
5230 }
5231
5232 IrInstruction *result = ir_build_widen_or_shorten(&ira->new_irb, source_instr->scope,
5233 source_instr->source_node, target);
5234 result->value.type = wanted_type;
5235 return result;
5236}
5237
5238
5184static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_instr,5239static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_instr,
5185 TypeTableEntry *wanted_type, IrInstruction *value)5240 TypeTableEntry *wanted_type, IrInstruction *value)
5186{5241{
...@@ -5233,7 +5288,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst...@@ -5233,7 +5288,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
5233 (wanted_type_canon->id == TypeTableEntryIdFloat &&5288 (wanted_type_canon->id == TypeTableEntryIdFloat &&
5234 actual_type_canon->id == TypeTableEntryIdFloat))5289 actual_type_canon->id == TypeTableEntryIdFloat))
5235 {5290 {
5236 return ir_resolve_cast(ira, source_instr, value, wanted_type, CastOpWidenOrShorten, false);5291 return ir_analyze_widen_or_shorten(ira, source_instr, value, wanted_type);
5237 }5292 }
52385293
5239 // explicit cast from int to float5294 // explicit cast from int to float
...@@ -5411,7 +5466,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst...@@ -5411,7 +5466,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
5411 actual_type->id == TypeTableEntryIdEnum &&5466 actual_type->id == TypeTableEntryIdEnum &&
5412 actual_type->data.enumeration.gen_field_count == 0)5467 actual_type->data.enumeration.gen_field_count == 0)
5413 {5468 {
5414 return ir_resolve_cast(ira, source_instr, value, wanted_type, CastOpEnumToInt, false);5469 return ir_analyze_enum_to_int(ira, source_instr, value, wanted_type);
5415 }5470 }
54165471
5417 // explicit cast from undefined to anything5472 // explicit cast from undefined to anything
...@@ -9882,6 +9937,7 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi...@@ -9882,6 +9937,7 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi
9882 switch (instruction->id) {9937 switch (instruction->id) {
9883 case IrInstructionIdInvalid:9938 case IrInstructionIdInvalid:
9884 case IrInstructionIdPointerReinterpret:9939 case IrInstructionIdPointerReinterpret:
9940 case IrInstructionIdWidenOrShorten:
9885 case IrInstructionIdStructInit:9941 case IrInstructionIdStructInit:
9886 case IrInstructionIdStructFieldPtr:9942 case IrInstructionIdStructFieldPtr:
9887 case IrInstructionIdEnumFieldPtr:9943 case IrInstructionIdEnumFieldPtr:
...@@ -10188,6 +10244,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {...@@ -10188,6 +10244,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {
10188 case IrInstructionIdTestComptime:10244 case IrInstructionIdTestComptime:
10189 case IrInstructionIdInitEnum:10245 case IrInstructionIdInitEnum:
10190 case IrInstructionIdPointerReinterpret:10246 case IrInstructionIdPointerReinterpret:
10247 case IrInstructionIdWidenOrShorten:
10191 return false;10248 return false;
10192 case IrInstructionIdAsm:10249 case IrInstructionIdAsm:
10193 {10250 {
src/ir_print.cpp+10-1
...@@ -923,11 +923,17 @@ static void ir_print_init_enum(IrPrint *irp, IrInstructionInitEnum *instruction)...@@ -923,11 +923,17 @@ static void ir_print_init_enum(IrPrint *irp, IrInstructionInitEnum *instruction)
923}923}
924924
925static void ir_print_pointer_reinterpret(IrPrint *irp, IrInstructionPointerReinterpret *instruction) {925static void ir_print_pointer_reinterpret(IrPrint *irp, IrInstructionPointerReinterpret *instruction) {
926 fprintf(irp->f, "(%s)(", buf_ptr(&instruction->base.value.type->name));926 fprintf(irp->f, "@pointerReinterpret(");
927 ir_print_other_instruction(irp, instruction->ptr);927 ir_print_other_instruction(irp, instruction->ptr);
928 fprintf(irp->f, ")");928 fprintf(irp->f, ")");
929}929}
930930
931static void ir_print_widen_or_shorten(IrPrint *irp, IrInstructionWidenOrShorten *instruction) {
932 fprintf(irp->f, "@widenOrShorten(");
933 ir_print_other_instruction(irp, instruction->target);
934 fprintf(irp->f, ")");
935}
936
931static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {937static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
932 ir_print_prefix(irp, instruction);938 ir_print_prefix(irp, instruction);
933 switch (instruction->id) {939 switch (instruction->id) {
...@@ -1170,6 +1176,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {...@@ -1170,6 +1176,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
1170 case IrInstructionIdPointerReinterpret:1176 case IrInstructionIdPointerReinterpret:
1171 ir_print_pointer_reinterpret(irp, (IrInstructionPointerReinterpret *)instruction);1177 ir_print_pointer_reinterpret(irp, (IrInstructionPointerReinterpret *)instruction);
1172 break;1178 break;
1179 case IrInstructionIdWidenOrShorten:
1180 ir_print_widen_or_shorten(irp, (IrInstructionWidenOrShorten *)instruction);
1181 break;
1173 }1182 }
1174 fprintf(irp->f, "\n");1183 fprintf(irp->f, "\n");
1175}1184}
test/cases/enum_to_int.zig deleted-31
...@@ -1,31 +0,0 @@
1const assert = @import("std").debug.assert;
2
3enum Number {
4 Zero,
5 One,
6 Two,
7 Three,
8 Four,
9}
10
11fn enumToInt() {
12 @setFnTest(this, true);
13
14 shouldEqual(false, Number.Zero, 0);
15 shouldEqual(false, Number.One, 1);
16 shouldEqual(false, Number.Two, 2);
17 shouldEqual(false, Number.Three, 3);
18 shouldEqual(false, Number.Four, 4);
19
20 shouldEqual(true, Number.Zero, 0);
21 shouldEqual(true, Number.One, 1);
22 shouldEqual(true, Number.Two, 2);
23 shouldEqual(true, Number.Three, 3);
24 shouldEqual(true, Number.Four, 4);
25}
26
27fn shouldEqual(inline static_eval: bool, n: Number, expected: usize) {
28 @setFnStaticEval(this, static_eval);
29
30 assert(usize(n) == expected);
31}
test/cases3/enum.zig+23
...@@ -73,6 +73,29 @@ const AnEnumWithPayload = enum {...@@ -73,6 +73,29 @@ const AnEnumWithPayload = enum {
7373
7474
7575
76const Number = enum {
77 Zero,
78 One,
79 Two,
80 Three,
81 Four,
82};
83
84fn enumToInt() {
85 @setFnTest(this);
86
87 shouldEqual(Number.Zero, 0);
88 shouldEqual(Number.One, 1);
89 shouldEqual(Number.Two, 2);
90 shouldEqual(Number.Three, 3);
91 shouldEqual(Number.Four, 4);
92}
93
94fn shouldEqual(n: Number, expected: usize) {
95 assert(usize(n) == expected);
96}
97
98// TODO import from std
76fn assert(ok: bool) {99fn assert(ok: bool) {
77 if (!ok)100 if (!ok)
78 @unreachable();101 @unreachable();