authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-12-20 01:50:32-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-12-20 01:50:32-05:00
log1f6dacbb2f9a91a20309b271a31e781f11f81819
tree418c311fc703a4163ebf16cc90e89346b5113785
parentc10ae8622bc07baeea1fb81522b01fc6e953eaf6

IR: enum init support


12 files changed, 514 insertions(+), 607 deletions(-)

CMakeLists.txt-1
......@@ -46,7 +46,6 @@ set(ZIG_SOURCES
4646 "${CMAKE_SOURCE_DIR}/src/codegen.cpp"
4747 "${CMAKE_SOURCE_DIR}/src/errmsg.cpp"
4848 "${CMAKE_SOURCE_DIR}/src/error.cpp"
49 "${CMAKE_SOURCE_DIR}/src/eval.cpp"
5049 "${CMAKE_SOURCE_DIR}/src/ir.cpp"
5150 "${CMAKE_SOURCE_DIR}/src/ir_print.cpp"
5251 "${CMAKE_SOURCE_DIR}/src/link.cpp"
src/all_types.hpp+17
......@@ -848,6 +848,11 @@ struct TypeTableEntryEnum {
848848 bool complete;
849849};
850850
851struct TypeTableEntryEnumTag {
852 TypeTableEntry *enum_type;
853 TypeTableEntry *int_type;
854};
855
851856struct TypeTableEntryUnion {
852857 AstNode *decl_node;
853858 bool is_extern;
......@@ -914,6 +919,7 @@ enum TypeTableEntryId {
914919 TypeTableEntryIdErrorUnion,
915920 TypeTableEntryIdPureError,
916921 TypeTableEntryIdEnum,
922 TypeTableEntryIdEnumTag,
917923 TypeTableEntryIdUnion,
918924 TypeTableEntryIdFn,
919925 TypeTableEntryIdTypeDecl,
......@@ -940,6 +946,7 @@ struct TypeTableEntry {
940946 TypeTableEntryMaybe maybe;
941947 TypeTableEntryError error;
942948 TypeTableEntryEnum enumeration;
949 TypeTableEntryEnumTag enum_tag;
943950 TypeTableEntryUnion unionation;
944951 TypeTableEntryFn fn;
945952 TypeTableEntryTypeDecl type_decl;
......@@ -1452,6 +1459,7 @@ enum IrInstructionId {
14521459 IrInstructionIdErrWrapPayload,
14531460 IrInstructionIdFnProto,
14541461 IrInstructionIdTestComptime,
1462 IrInstructionIdInitEnum,
14551463};
14561464
14571465struct IrInstruction {
......@@ -2078,6 +2086,15 @@ struct IrInstructionTestComptime {
20782086 IrInstruction *value;
20792087};
20802088
2089struct IrInstructionInitEnum {
2090 IrInstruction base;
2091
2092 TypeTableEntry *enum_type;
2093 TypeEnumField *field;
2094 IrInstruction *init_value;
2095 LLVMValueRef tmp_ptr;
2096};
2097
20812098enum LValPurpose {
20822099 LValPurposeNone,
20832100 LValPurposeAssign,
src/analyze.cpp+183-11
......@@ -9,7 +9,6 @@
99#include "ast_render.hpp"
1010#include "config.h"
1111#include "error.hpp"
12#include "eval.hpp"
1312#include "ir.hpp"
1413#include "ir_print.hpp"
1514#include "os.hpp"
......@@ -252,6 +251,7 @@ bool type_is_complete(TypeTableEntry *type_entry) {
252251 case TypeTableEntryIdNamespace:
253252 case TypeTableEntryIdBlock:
254253 case TypeTableEntryIdBoundFn:
254 case TypeTableEntryIdEnumTag:
255255 return true;
256256 }
257257 zig_unreachable();
......@@ -677,14 +677,8 @@ TypeTableEntry *get_typedecl_type(CodeGen *g, const char *name, TypeTableEntry *
677677 entry->type_ref = child_type->type_ref;
678678 entry->di_type = child_type->di_type;
679679 entry->zero_bits = child_type->zero_bits;
680
681680 entry->data.type_decl.child_type = child_type;
682
683 if (child_type->id == TypeTableEntryIdTypeDecl) {
684 entry->data.type_decl.canonical_type = child_type->data.type_decl.canonical_type;
685 } else {
686 entry->data.type_decl.canonical_type = child_type;
687 }
681 entry->data.type_decl.canonical_type = get_underlying_type(child_type);
688682
689683 return entry;
690684}
......@@ -985,6 +979,7 @@ static TypeTableEntry *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *c
985979 case TypeTableEntryIdUnion:
986980 case TypeTableEntryIdFn:
987981 case TypeTableEntryIdTypeDecl:
982 case TypeTableEntryIdEnumTag:
988983 break;
989984 }
990985 FnTypeParamInfo *param_info = &fn_type_id.param_info[fn_type_id.next_param_index];
......@@ -1033,12 +1028,28 @@ static TypeTableEntry *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *c
10331028 case TypeTableEntryIdUnion:
10341029 case TypeTableEntryIdFn:
10351030 case TypeTableEntryIdTypeDecl:
1031 case TypeTableEntryIdEnumTag:
10361032 break;
10371033 }
10381034
10391035 return get_fn_type(g, &fn_type_id);
10401036}
10411037
1038static TypeTableEntry *create_enum_tag_type(CodeGen *g, TypeTableEntry *enum_type, TypeTableEntry *int_type) {
1039 TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdEnumTag);
1040
1041 buf_resize(&entry->name, 0);
1042 buf_appendf(&entry->name, "@enumTagType(%s)", buf_ptr(&enum_type->name));
1043
1044 entry->data.enum_tag.enum_type = enum_type;
1045 entry->data.enum_tag.int_type = int_type;
1046 entry->type_ref = int_type->type_ref;
1047 entry->di_type = int_type->di_type;
1048 entry->zero_bits = int_type->zero_bits;
1049
1050 return entry;
1051}
1052
10421053static void resolve_enum_type(CodeGen *g, TypeTableEntry *enum_type) {
10431054 // if you change this logic you likely must also change similar logic in parseh.cpp
10441055 assert(enum_type->id == TypeTableEntryIdEnum);
......@@ -1134,7 +1145,8 @@ static void resolve_enum_type(CodeGen *g, TypeTableEntry *enum_type) {
11341145 enum_type->data.enumeration.gen_field_count = gen_field_index;
11351146 enum_type->data.enumeration.union_type = biggest_union_member;
11361147
1137 TypeTableEntry *tag_type_entry = get_smallest_unsigned_int_type(g, field_count);
1148 TypeTableEntry *tag_int_type = get_smallest_unsigned_int_type(g, field_count);
1149 TypeTableEntry *tag_type_entry = create_enum_tag_type(g, enum_type, tag_int_type);
11381150 enum_type->data.enumeration.tag_type = tag_type_entry;
11391151
11401152 if (biggest_union_member) {
......@@ -1686,6 +1698,7 @@ TypeTableEntry *validate_var_type(CodeGen *g, AstNode *source_node, TypeTableEnt
16861698 case TypeTableEntryIdUnion:
16871699 case TypeTableEntryIdFn:
16881700 case TypeTableEntryIdBoundFn:
1701 case TypeTableEntryIdEnumTag:
16891702 return type_entry;
16901703 }
16911704 zig_unreachable();
......@@ -1890,6 +1903,7 @@ static bool type_has_codegen_value(TypeTableEntry *type_entry) {
18901903 case TypeTableEntryIdEnum:
18911904 case TypeTableEntryIdUnion:
18921905 case TypeTableEntryIdFn:
1906 case TypeTableEntryIdEnumTag:
18931907 return true;
18941908
18951909 case TypeTableEntryIdTypeDecl:
......@@ -2110,6 +2124,7 @@ static bool is_container(TypeTableEntry *type_entry) {
21102124 case TypeTableEntryIdNamespace:
21112125 case TypeTableEntryIdBlock:
21122126 case TypeTableEntryIdBoundFn:
2127 case TypeTableEntryIdEnumTag:
21132128 return false;
21142129 }
21152130 zig_unreachable();
......@@ -2159,6 +2174,7 @@ void resolve_container_type(CodeGen *g, TypeTableEntry *type_entry) {
21592174 case TypeTableEntryIdBoundFn:
21602175 case TypeTableEntryIdInvalid:
21612176 case TypeTableEntryIdVar:
2177 case TypeTableEntryIdEnumTag:
21622178 zig_unreachable();
21632179 }
21642180}
......@@ -2509,6 +2525,7 @@ bool handle_is_ptr(TypeTableEntry *type_entry) {
25092525 case TypeTableEntryIdPointer:
25102526 case TypeTableEntryIdPureError:
25112527 case TypeTableEntryIdFn:
2528 case TypeTableEntryIdEnumTag:
25122529 return false;
25132530 case TypeTableEntryIdArray:
25142531 case TypeTableEntryIdStruct:
......@@ -2650,6 +2667,8 @@ static uint32_t hash_const_val(TypeTableEntry *type, ConstExprValue *const_val)
26502667 return hash_ptr(const_val->data.x_import);
26512668 case TypeTableEntryIdBlock:
26522669 return hash_ptr(const_val->data.x_block);
2670 case TypeTableEntryIdEnumTag:
2671 return 983996406 + hash_const_val(type->data.enum_tag.int_type, const_val);
26532672 case TypeTableEntryIdBoundFn:
26542673 case TypeTableEntryIdInvalid:
26552674 case TypeTableEntryIdUnreachable:
......@@ -2794,16 +2813,18 @@ static TypeTableEntry *type_of_first_thing_in_memory(TypeTableEntry *type_entry)
27942813 case TypeTableEntryIdInt:
27952814 case TypeTableEntryIdFloat:
27962815 case TypeTableEntryIdPointer:
2816 case TypeTableEntryIdEnumTag:
27972817 return type_entry;
27982818 }
27992819 zig_unreachable();
28002820}
28012821
28022822bool type_requires_comptime(TypeTableEntry *type_entry) {
2803 switch (type_entry->id) {
2823 switch (get_underlying_type(type_entry)->id) {
28042824 case TypeTableEntryIdInvalid:
28052825 case TypeTableEntryIdUnreachable:
28062826 case TypeTableEntryIdVar:
2827 case TypeTableEntryIdTypeDecl:
28072828 zig_unreachable();
28082829 case TypeTableEntryIdNumLitFloat:
28092830 case TypeTableEntryIdNumLitInt:
......@@ -2820,7 +2841,6 @@ bool type_requires_comptime(TypeTableEntry *type_entry) {
28202841 case TypeTableEntryIdUnion:
28212842 case TypeTableEntryIdMaybe:
28222843 case TypeTableEntryIdErrorUnion:
2823 case TypeTableEntryIdTypeDecl:
28242844 case TypeTableEntryIdEnum:
28252845 case TypeTableEntryIdPureError:
28262846 case TypeTableEntryIdFn:
......@@ -2828,6 +2848,7 @@ bool type_requires_comptime(TypeTableEntry *type_entry) {
28282848 case TypeTableEntryIdInt:
28292849 case TypeTableEntryIdFloat:
28302850 case TypeTableEntryIdPointer:
2851 case TypeTableEntryIdEnumTag:
28312852 return false;
28322853 }
28332854 zig_unreachable();
......@@ -2933,3 +2954,154 @@ bool ir_get_var_is_comptime(VariableTableEntry *var) {
29332954 return var->is_comptime->static_value.data.x_bool;
29342955}
29352956
2957bool const_values_equal(ConstExprValue *a, ConstExprValue *b, TypeTableEntry *type_entry) {
2958 switch (type_entry->id) {
2959 case TypeTableEntryIdEnum:
2960 {
2961 ConstEnumValue *enum1 = &a->data.x_enum;
2962 ConstEnumValue *enum2 = &b->data.x_enum;
2963 if (enum1->tag == enum2->tag) {
2964 TypeEnumField *enum_field = &type_entry->data.enumeration.fields[enum1->tag];
2965 if (type_has_bits(enum_field->type_entry)) {
2966 zig_panic("TODO const expr analyze enum special value for equality");
2967 } else {
2968 return true;
2969 }
2970 }
2971 return false;
2972 }
2973 case TypeTableEntryIdMetaType:
2974 return a->data.x_type == b->data.x_type;
2975 case TypeTableEntryIdVoid:
2976 return true;
2977 case TypeTableEntryIdPureError:
2978 return a->data.x_pure_err == b->data.x_pure_err;
2979 case TypeTableEntryIdFn:
2980 return a->data.x_fn == b->data.x_fn;
2981 case TypeTableEntryIdBool:
2982 return a->data.x_bool == b->data.x_bool;
2983 case TypeTableEntryIdInt:
2984 case TypeTableEntryIdFloat:
2985 case TypeTableEntryIdNumLitFloat:
2986 case TypeTableEntryIdNumLitInt:
2987 return bignum_cmp_eq(&a->data.x_bignum, &b->data.x_bignum);
2988 case TypeTableEntryIdEnumTag:
2989 return const_values_equal(a, b, type_entry->data.enum_tag.int_type);
2990 case TypeTableEntryIdPointer:
2991 zig_panic("TODO");
2992 case TypeTableEntryIdArray:
2993 zig_panic("TODO");
2994 case TypeTableEntryIdStruct:
2995 zig_panic("TODO");
2996 case TypeTableEntryIdUnion:
2997 zig_panic("TODO");
2998 case TypeTableEntryIdUndefLit:
2999 zig_panic("TODO");
3000 case TypeTableEntryIdNullLit:
3001 zig_panic("TODO");
3002 case TypeTableEntryIdMaybe:
3003 zig_panic("TODO");
3004 case TypeTableEntryIdErrorUnion:
3005 zig_panic("TODO");
3006 case TypeTableEntryIdTypeDecl:
3007 zig_panic("TODO");
3008 case TypeTableEntryIdNamespace:
3009 zig_panic("TODO");
3010 case TypeTableEntryIdBlock:
3011 zig_panic("TODO");
3012 case TypeTableEntryIdBoundFn:
3013 case TypeTableEntryIdInvalid:
3014 case TypeTableEntryIdUnreachable:
3015 case TypeTableEntryIdVar:
3016 zig_unreachable();
3017 }
3018 zig_unreachable();
3019}
3020
3021static bool int_type_depends_on_compile_var(CodeGen *g, TypeTableEntry *int_type) {
3022 assert(int_type->id == TypeTableEntryIdInt);
3023
3024 for (size_t i = 0; i < CIntTypeCount; i += 1) {
3025 if (int_type == g->builtin_types.entry_c_int[i]) {
3026 return true;
3027 }
3028 }
3029 return false;
3030}
3031
3032static uint64_t max_unsigned_val(TypeTableEntry *type_entry) {
3033 assert(type_entry->id == TypeTableEntryIdInt);
3034 if (type_entry->data.integral.bit_count == 64) {
3035 return UINT64_MAX;
3036 } else if (type_entry->data.integral.bit_count == 32) {
3037 return UINT32_MAX;
3038 } else if (type_entry->data.integral.bit_count == 16) {
3039 return UINT16_MAX;
3040 } else if (type_entry->data.integral.bit_count == 8) {
3041 return UINT8_MAX;
3042 } else {
3043 zig_unreachable();
3044 }
3045}
3046
3047static int64_t max_signed_val(TypeTableEntry *type_entry) {
3048 assert(type_entry->id == TypeTableEntryIdInt);
3049 if (type_entry->data.integral.bit_count == 64) {
3050 return INT64_MAX;
3051 } else if (type_entry->data.integral.bit_count == 32) {
3052 return INT32_MAX;
3053 } else if (type_entry->data.integral.bit_count == 16) {
3054 return INT16_MAX;
3055 } else if (type_entry->data.integral.bit_count == 8) {
3056 return INT8_MAX;
3057 } else {
3058 zig_unreachable();
3059 }
3060}
3061
3062static int64_t min_signed_val(TypeTableEntry *type_entry) {
3063 assert(type_entry->id == TypeTableEntryIdInt);
3064 if (type_entry->data.integral.bit_count == 64) {
3065 return INT64_MIN;
3066 } else if (type_entry->data.integral.bit_count == 32) {
3067 return INT32_MIN;
3068 } else if (type_entry->data.integral.bit_count == 16) {
3069 return INT16_MIN;
3070 } else if (type_entry->data.integral.bit_count == 8) {
3071 return INT8_MIN;
3072 } else {
3073 zig_unreachable();
3074 }
3075}
3076
3077void eval_min_max_value(CodeGen *g, TypeTableEntry *type_entry, ConstExprValue *const_val, bool is_max) {
3078 if (type_entry->id == TypeTableEntryIdInt) {
3079 const_val->special = ConstValSpecialStatic;
3080 const_val->depends_on_compile_var = int_type_depends_on_compile_var(g, type_entry);
3081 if (is_max) {
3082 if (type_entry->data.integral.is_signed) {
3083 int64_t val = max_signed_val(type_entry);
3084 bignum_init_signed(&const_val->data.x_bignum, val);
3085 } else {
3086 uint64_t val = max_unsigned_val(type_entry);
3087 bignum_init_unsigned(&const_val->data.x_bignum, val);
3088 }
3089 } else {
3090 if (type_entry->data.integral.is_signed) {
3091 int64_t val = min_signed_val(type_entry);
3092 bignum_init_signed(&const_val->data.x_bignum, val);
3093 } else {
3094 bignum_init_unsigned(&const_val->data.x_bignum, 0);
3095 }
3096 }
3097 } else if (type_entry->id == TypeTableEntryIdFloat) {
3098 zig_panic("TODO analyze_min_max_value float");
3099 } else if (type_entry->id == TypeTableEntryIdBool) {
3100 const_val->special = ConstValSpecialStatic;
3101 const_val->data.x_bool = is_max;
3102 } else if (type_entry->id == TypeTableEntryIdVoid) {
3103 // nothing to do
3104 } else {
3105 zig_unreachable();
3106 }
3107}
src/analyze.hpp+2
......@@ -77,6 +77,8 @@ bool type_requires_comptime(TypeTableEntry *type_entry);
7777void ensure_complete_type(CodeGen *g, TypeTableEntry *type_entry);
7878void complete_enum(CodeGen *g, TypeTableEntry *enum_type);
7979bool ir_get_var_is_comptime(VariableTableEntry *var);
80bool const_values_equal(ConstExprValue *a, ConstExprValue *b, TypeTableEntry *type_entry);
81void eval_min_max_value(CodeGen *g, TypeTableEntry *type_entry, ConstExprValue *const_val, bool is_max);
8082
8183ScopeBlock *create_block_scope(AstNode *node, Scope *parent);
8284ScopeDefer *create_defer_scope(AstNode *node, Scope *parent);
src/codegen.cpp+13-1
......@@ -2144,6 +2144,10 @@ static LLVMValueRef ir_render_enum_tag(CodeGen *g, IrExecutable *executable, IrI
21442144 return get_handle_value(g, tag_field_ptr, tag_type);
21452145}
21462146
2147static LLVMValueRef ir_render_init_enum(CodeGen *g, IrExecutable *executable, IrInstructionInitEnum *instruction) {
2148 zig_panic("TODO ir_render_init_enum");
2149}
2150
21472151static void set_debug_location(CodeGen *g, IrInstruction *instruction) {
21482152 AstNode *source_node = instruction->source_node;
21492153 Scope *scope = instruction->scope;
......@@ -2278,6 +2282,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
22782282 return ir_render_err_wrap_payload(g, executable, (IrInstructionErrWrapPayload *)instruction);
22792283 case IrInstructionIdEnumTag:
22802284 return ir_render_enum_tag(g, executable, (IrInstructionEnumTag *)instruction);
2285 case IrInstructionIdInitEnum:
2286 return ir_render_init_enum(g, executable, (IrInstructionInitEnum *)instruction);
22812287 case IrInstructionIdSwitchVar:
22822288 zig_panic("TODO render switch var instruction to LLVM");
22832289 case IrInstructionIdContainerInitList:
......@@ -2497,6 +2503,8 @@ static LLVMValueRef gen_const_val(CodeGen *g, TypeTableEntry *type_entry, ConstE
24972503 }
24982504 case TypeTableEntryIdVoid:
24992505 return nullptr;
2506 case TypeTableEntryIdEnumTag:
2507 return gen_const_val(g, type_entry->data.enum_tag.int_type, const_val);
25002508 case TypeTableEntryIdInvalid:
25012509 case TypeTableEntryIdMetaType:
25022510 case TypeTableEntryIdUnreachable:
......@@ -2876,6 +2884,9 @@ static void do_code_gen(CodeGen *g) {
28762884 } else if (instruction->id == IrInstructionIdErrWrapCode) {
28772885 IrInstructionErrWrapCode *err_wrap_code_instruction = (IrInstructionErrWrapCode *)instruction;
28782886 slot = &err_wrap_code_instruction->tmp_ptr;
2887 } else if (instruction->id == IrInstructionIdInitEnum) {
2888 IrInstructionInitEnum *init_enum_instruction = (IrInstructionInitEnum *)instruction;
2889 slot = &init_enum_instruction->tmp_ptr;
28792890 } else {
28802891 zig_unreachable();
28812892 }
......@@ -3793,7 +3804,8 @@ static void get_c_type(CodeGen *g, TypeTableEntry *type_entry, Buf *out_buf) {
37933804 case TypeTableEntryIdUnion:
37943805 case TypeTableEntryIdFn:
37953806 case TypeTableEntryIdTypeDecl:
3796 zig_panic("TODO");
3807 case TypeTableEntryIdEnumTag:
3808 zig_panic("TODO implement get_c_type for more types");
37973809 case TypeTableEntryIdInvalid:
37983810 case TypeTableEntryIdMetaType:
37993811 case TypeTableEntryIdBoundFn:
src/eval.cpp deleted-429
......@@ -1,429 +0,0 @@
1/*
2 * Copyright (c) 2016 Andrew Kelley
3 *
4 * This file is part of zig, which is MIT licensed.
5 * See http://opensource.org/licenses/MIT
6 */
7
8#include "eval.hpp"
9#include "analyze.hpp"
10#include "error.hpp"
11
12bool const_values_equal(ConstExprValue *a, ConstExprValue *b, TypeTableEntry *type_entry) {
13 switch (type_entry->id) {
14 case TypeTableEntryIdEnum:
15 {
16 ConstEnumValue *enum1 = &a->data.x_enum;
17 ConstEnumValue *enum2 = &b->data.x_enum;
18 if (enum1->tag == enum2->tag) {
19 TypeEnumField *enum_field = &type_entry->data.enumeration.fields[enum1->tag];
20 if (type_has_bits(enum_field->type_entry)) {
21 zig_panic("TODO const expr analyze enum special value for equality");
22 } else {
23 return true;
24 }
25 }
26 return false;
27 }
28 case TypeTableEntryIdMetaType:
29 return a->data.x_type == b->data.x_type;
30 case TypeTableEntryIdVoid:
31 return true;
32 case TypeTableEntryIdPureError:
33 return a->data.x_pure_err == b->data.x_pure_err;
34 case TypeTableEntryIdFn:
35 return a->data.x_fn == b->data.x_fn;
36 case TypeTableEntryIdBool:
37 return a->data.x_bool == b->data.x_bool;
38 case TypeTableEntryIdInt:
39 case TypeTableEntryIdFloat:
40 case TypeTableEntryIdNumLitFloat:
41 case TypeTableEntryIdNumLitInt:
42 return bignum_cmp_eq(&a->data.x_bignum, &b->data.x_bignum);
43 case TypeTableEntryIdPointer:
44 zig_panic("TODO");
45 case TypeTableEntryIdArray:
46 zig_panic("TODO");
47 case TypeTableEntryIdStruct:
48 zig_panic("TODO");
49 case TypeTableEntryIdUnion:
50 zig_panic("TODO");
51 case TypeTableEntryIdUndefLit:
52 zig_panic("TODO");
53 case TypeTableEntryIdNullLit:
54 zig_panic("TODO");
55 case TypeTableEntryIdMaybe:
56 zig_panic("TODO");
57 case TypeTableEntryIdErrorUnion:
58 zig_panic("TODO");
59 case TypeTableEntryIdTypeDecl:
60 zig_panic("TODO");
61 case TypeTableEntryIdNamespace:
62 zig_panic("TODO");
63 case TypeTableEntryIdBlock:
64 zig_panic("TODO");
65 case TypeTableEntryIdBoundFn:
66 case TypeTableEntryIdInvalid:
67 case TypeTableEntryIdUnreachable:
68 case TypeTableEntryIdVar:
69 zig_unreachable();
70 }
71 zig_unreachable();
72}
73
74
75static bool eval_bool_bin_op_bool(bool a, BinOpType bin_op, bool b) {
76 if (bin_op == BinOpTypeBoolOr || bin_op == BinOpTypeAssignBoolOr) {
77 return a || b;
78 } else if (bin_op == BinOpTypeBoolAnd || bin_op == BinOpTypeAssignBoolAnd) {
79 return a && b;
80 } else {
81 zig_unreachable();
82 }
83}
84
85static uint64_t max_unsigned_val(TypeTableEntry *type_entry) {
86 assert(type_entry->id == TypeTableEntryIdInt);
87 if (type_entry->data.integral.bit_count == 64) {
88 return UINT64_MAX;
89 } else if (type_entry->data.integral.bit_count == 32) {
90 return UINT32_MAX;
91 } else if (type_entry->data.integral.bit_count == 16) {
92 return UINT16_MAX;
93 } else if (type_entry->data.integral.bit_count == 8) {
94 return UINT8_MAX;
95 } else {
96 zig_unreachable();
97 }
98}
99
100static int64_t max_signed_val(TypeTableEntry *type_entry) {
101 assert(type_entry->id == TypeTableEntryIdInt);
102 if (type_entry->data.integral.bit_count == 64) {
103 return INT64_MAX;
104 } else if (type_entry->data.integral.bit_count == 32) {
105 return INT32_MAX;
106 } else if (type_entry->data.integral.bit_count == 16) {
107 return INT16_MAX;
108 } else if (type_entry->data.integral.bit_count == 8) {
109 return INT8_MAX;
110 } else {
111 zig_unreachable();
112 }
113}
114
115static int64_t min_signed_val(TypeTableEntry *type_entry) {
116 assert(type_entry->id == TypeTableEntryIdInt);
117 if (type_entry->data.integral.bit_count == 64) {
118 return INT64_MIN;
119 } else if (type_entry->data.integral.bit_count == 32) {
120 return INT32_MIN;
121 } else if (type_entry->data.integral.bit_count == 16) {
122 return INT16_MIN;
123 } else if (type_entry->data.integral.bit_count == 8) {
124 return INT8_MIN;
125 } else {
126 zig_unreachable();
127 }
128}
129
130static int eval_const_expr_bin_op_bignum(ConstExprValue *op1_val, ConstExprValue *op2_val,
131 ConstExprValue *out_val, bool (*bignum_fn)(BigNum *, BigNum *, BigNum *),
132 TypeTableEntry *type, bool wrapping_op)
133{
134 bool overflow = bignum_fn(&out_val->data.x_bignum, &op1_val->data.x_bignum, &op2_val->data.x_bignum);
135 if (overflow) {
136 return ErrorOverflow;
137 }
138
139 if (type->id == TypeTableEntryIdInt && !bignum_fits_in_bits(&out_val->data.x_bignum,
140 type->data.integral.bit_count, type->data.integral.is_signed))
141 {
142 if (wrapping_op) {
143 if (type->data.integral.is_signed) {
144 out_val->data.x_bignum.data.x_uint = max_unsigned_val(type) - out_val->data.x_bignum.data.x_uint + 1;
145 out_val->data.x_bignum.is_negative = !out_val->data.x_bignum.is_negative;
146 } else if (out_val->data.x_bignum.is_negative) {
147 out_val->data.x_bignum.data.x_uint = max_unsigned_val(type) - out_val->data.x_bignum.data.x_uint + 1;
148 out_val->data.x_bignum.is_negative = false;
149 } else {
150 bignum_truncate(&out_val->data.x_bignum, type->data.integral.bit_count);
151 }
152 } else {
153 return ErrorOverflow;
154 }
155 }
156
157 out_val->special = ConstValSpecialStatic;
158 out_val->depends_on_compile_var = op1_val->depends_on_compile_var || op2_val->depends_on_compile_var;
159 return 0;
160}
161
162int eval_const_expr_bin_op(ConstExprValue *op1_val, TypeTableEntry *op1_type,
163 BinOpType bin_op, ConstExprValue *op2_val, TypeTableEntry *op2_type, ConstExprValue *out_val)
164{
165 assert(op1_val->special != ConstValSpecialRuntime);
166 assert(op2_val->special != ConstValSpecialRuntime);
167 assert(op1_type->id != TypeTableEntryIdInvalid);
168 assert(op2_type->id != TypeTableEntryIdInvalid);
169
170 switch (bin_op) {
171 case BinOpTypeAssign:
172 *out_val = *op2_val;
173 return 0;
174 case BinOpTypeBoolOr:
175 case BinOpTypeBoolAnd:
176 case BinOpTypeAssignBoolAnd:
177 case BinOpTypeAssignBoolOr:
178 assert(op1_type->id == TypeTableEntryIdBool);
179 assert(op2_type->id == TypeTableEntryIdBool);
180 out_val->data.x_bool = eval_bool_bin_op_bool(op1_val->data.x_bool, bin_op, op2_val->data.x_bool);
181 out_val->special = ConstValSpecialStatic;
182 out_val->depends_on_compile_var = op1_val->depends_on_compile_var || op2_val->depends_on_compile_var;
183 return 0;
184 case BinOpTypeCmpEq:
185 case BinOpTypeCmpNotEq:
186 case BinOpTypeCmpLessThan:
187 case BinOpTypeCmpGreaterThan:
188 case BinOpTypeCmpLessOrEq:
189 case BinOpTypeCmpGreaterOrEq:
190 {
191 bool type_can_gt_lt_cmp = (op1_type->id == TypeTableEntryIdNumLitFloat ||
192 op1_type->id == TypeTableEntryIdNumLitInt ||
193 op1_type->id == TypeTableEntryIdFloat ||
194 op1_type->id == TypeTableEntryIdInt);
195 bool answer;
196 if (type_can_gt_lt_cmp) {
197 bool (*bignum_cmp)(BigNum *, BigNum *);
198 if (bin_op == BinOpTypeCmpEq) {
199 bignum_cmp = bignum_cmp_eq;
200 } else if (bin_op == BinOpTypeCmpNotEq) {
201 bignum_cmp = bignum_cmp_neq;
202 } else if (bin_op == BinOpTypeCmpLessThan) {
203 bignum_cmp = bignum_cmp_lt;
204 } else if (bin_op == BinOpTypeCmpGreaterThan) {
205 bignum_cmp = bignum_cmp_gt;
206 } else if (bin_op == BinOpTypeCmpLessOrEq) {
207 bignum_cmp = bignum_cmp_lte;
208 } else if (bin_op == BinOpTypeCmpGreaterOrEq) {
209 bignum_cmp = bignum_cmp_gte;
210 } else {
211 zig_unreachable();
212 }
213
214 answer = bignum_cmp(&op1_val->data.x_bignum, &op2_val->data.x_bignum);
215 } else {
216 bool are_equal = const_values_equal(op1_val, op2_val, op1_type);
217 if (bin_op == BinOpTypeCmpEq) {
218 answer = are_equal;
219 } else if (bin_op == BinOpTypeCmpNotEq) {
220 answer = !are_equal;
221 } else {
222 zig_unreachable();
223 }
224 }
225
226 out_val->depends_on_compile_var =
227 op1_val->depends_on_compile_var || op2_val->depends_on_compile_var;
228 out_val->data.x_bool = answer;
229 out_val->special = ConstValSpecialStatic;
230 return 0;
231 }
232 case BinOpTypeAdd:
233 case BinOpTypeAssignPlus:
234 return eval_const_expr_bin_op_bignum(op1_val, op2_val, out_val, bignum_add, op1_type, false);
235 case BinOpTypeAddWrap:
236 case BinOpTypeAssignPlusWrap:
237 return eval_const_expr_bin_op_bignum(op1_val, op2_val, out_val, bignum_add, op1_type, true);
238 case BinOpTypeBinOr:
239 case BinOpTypeAssignBitOr:
240 return eval_const_expr_bin_op_bignum(op1_val, op2_val, out_val, bignum_or, op1_type, false);
241 case BinOpTypeBinXor:
242 case BinOpTypeAssignBitXor:
243 return eval_const_expr_bin_op_bignum(op1_val, op2_val, out_val, bignum_xor, op1_type, false);
244 case BinOpTypeBinAnd:
245 case BinOpTypeAssignBitAnd:
246 return eval_const_expr_bin_op_bignum(op1_val, op2_val, out_val, bignum_and, op1_type, false);
247 case BinOpTypeBitShiftLeft:
248 case BinOpTypeAssignBitShiftLeft:
249 return eval_const_expr_bin_op_bignum(op1_val, op2_val, out_val, bignum_shl, op1_type, false);
250 case BinOpTypeBitShiftLeftWrap:
251 case BinOpTypeAssignBitShiftLeftWrap:
252 return eval_const_expr_bin_op_bignum(op1_val, op2_val, out_val, bignum_shl, op1_type, true);
253 case BinOpTypeBitShiftRight:
254 case BinOpTypeAssignBitShiftRight:
255 return eval_const_expr_bin_op_bignum(op1_val, op2_val, out_val, bignum_shr, op1_type, false);
256 case BinOpTypeSub:
257 case BinOpTypeAssignMinus:
258 return eval_const_expr_bin_op_bignum(op1_val, op2_val, out_val, bignum_sub, op1_type, false);
259 case BinOpTypeSubWrap:
260 case BinOpTypeAssignMinusWrap:
261 return eval_const_expr_bin_op_bignum(op1_val, op2_val, out_val, bignum_sub, op1_type, true);
262 case BinOpTypeMult:
263 case BinOpTypeAssignTimes:
264 return eval_const_expr_bin_op_bignum(op1_val, op2_val, out_val, bignum_mul, op1_type, false);
265 case BinOpTypeMultWrap:
266 case BinOpTypeAssignTimesWrap:
267 return eval_const_expr_bin_op_bignum(op1_val, op2_val, out_val, bignum_mul, op1_type, true);
268 case BinOpTypeDiv:
269 case BinOpTypeAssignDiv:
270 {
271 bool is_int = false;
272 bool is_float = false;
273 if (op1_type->id == TypeTableEntryIdInt ||
274 op1_type->id == TypeTableEntryIdNumLitInt)
275 {
276 is_int = true;
277 } else if (op1_type->id == TypeTableEntryIdFloat ||
278 op1_type->id == TypeTableEntryIdNumLitFloat)
279 {
280 is_float = true;
281 }
282 if ((is_int && op2_val->data.x_bignum.data.x_uint == 0) ||
283 (is_float && op2_val->data.x_bignum.data.x_float == 0.0))
284 {
285 return ErrorDivByZero;
286 } else {
287 return eval_const_expr_bin_op_bignum(op1_val, op2_val, out_val, bignum_div, op1_type, false);
288 }
289 }
290 case BinOpTypeMod:
291 case BinOpTypeAssignMod:
292 return eval_const_expr_bin_op_bignum(op1_val, op2_val, out_val, bignum_mod, op1_type, false);
293 case BinOpTypeUnwrapMaybe:
294 zig_panic("TODO");
295 case BinOpTypeArrayCat:
296 case BinOpTypeArrayMult:
297 case BinOpTypeInvalid:
298 zig_unreachable();
299 }
300 zig_unreachable();
301}
302
303void eval_const_expr_implicit_cast(CastOp cast_op,
304 ConstExprValue *other_val, TypeTableEntry *other_type,
305 ConstExprValue *const_val, TypeTableEntry *new_type)
306{
307 const_val->depends_on_compile_var = other_val->depends_on_compile_var;
308 const_val->special = other_val->special;
309
310 assert(other_val != const_val);
311 switch (cast_op) {
312 case CastOpNoCast:
313 zig_unreachable();
314 case CastOpNoop:
315 case CastOpWidenOrShorten:
316 *const_val = *other_val;
317 break;
318 case CastOpPointerReinterpret:
319 zig_panic("TODO compile time pointer reinterpret");
320 break;
321 case CastOpPtrToInt:
322 case CastOpIntToPtr:
323 case CastOpResizeSlice:
324 case CastOpBytesToSlice:
325 // can't do it
326 break;
327 case CastOpToUnknownSizeArray:
328 {
329 assert(other_type->id == TypeTableEntryIdArray);
330 assert(other_val->data.x_array.size == other_type->data.array.len);
331
332 const_val->data.x_struct.fields = allocate<ConstExprValue>(2);
333 ConstExprValue *ptr_field = &const_val->data.x_struct.fields[slice_ptr_index];
334 ConstExprValue *len_field = &const_val->data.x_struct.fields[slice_len_index];
335
336 ptr_field->special = ConstValSpecialStatic;
337 ptr_field->data.x_ptr.base_ptr = other_val;
338
339 len_field->special = ConstValSpecialStatic;
340 bignum_init_unsigned(&len_field->data.x_bignum, other_type->data.array.len);
341
342 const_val->special = ConstValSpecialStatic;
343 break;
344 }
345 case CastOpErrToInt:
346 {
347 uint64_t value;
348 if (other_type->id == TypeTableEntryIdErrorUnion) {
349 value = other_val->data.x_err_union.err ? other_val->data.x_err_union.err->value : 0;
350 } else if (other_type->id == TypeTableEntryIdPureError) {
351 value = other_val->data.x_pure_err->value;
352 } else {
353 zig_unreachable();
354 }
355 bignum_init_unsigned(&const_val->data.x_bignum, value);
356 const_val->special = ConstValSpecialStatic;
357 break;
358 }
359 case CastOpIntToFloat:
360 bignum_cast_to_float(&const_val->data.x_bignum, &other_val->data.x_bignum);
361 const_val->special = ConstValSpecialStatic;
362 break;
363 case CastOpFloatToInt:
364 bignum_cast_to_int(&const_val->data.x_bignum, &other_val->data.x_bignum);
365 const_val->special = ConstValSpecialStatic;
366 break;
367 case CastOpBoolToInt:
368 bignum_init_unsigned(&const_val->data.x_bignum, other_val->data.x_bool ? 1 : 0);
369 const_val->special = ConstValSpecialStatic;
370 break;
371 case CastOpIntToEnum:
372 {
373 uint64_t value = other_val->data.x_bignum.data.x_uint;
374 assert(new_type->id == TypeTableEntryIdEnum);
375 assert(value < new_type->data.enumeration.src_field_count);
376 const_val->data.x_enum.tag = value;
377 const_val->data.x_enum.payload = NULL;
378 const_val->special = ConstValSpecialStatic;
379 break;
380 }
381 case CastOpEnumToInt:
382 bignum_init_unsigned(&const_val->data.x_bignum, other_val->data.x_enum.tag);
383 const_val->special = ConstValSpecialStatic;
384 break;
385 }
386}
387
388static bool int_type_depends_on_compile_var(CodeGen *g, TypeTableEntry *int_type) {
389 assert(int_type->id == TypeTableEntryIdInt);
390
391 for (size_t i = 0; i < CIntTypeCount; i += 1) {
392 if (int_type == g->builtin_types.entry_c_int[i]) {
393 return true;
394 }
395 }
396 return false;
397}
398
399void eval_min_max_value(CodeGen *g, TypeTableEntry *type_entry, ConstExprValue *const_val, bool is_max) {
400 if (type_entry->id == TypeTableEntryIdInt) {
401 const_val->special = ConstValSpecialStatic;
402 const_val->depends_on_compile_var = int_type_depends_on_compile_var(g, type_entry);
403 if (is_max) {
404 if (type_entry->data.integral.is_signed) {
405 int64_t val = max_signed_val(type_entry);
406 bignum_init_signed(&const_val->data.x_bignum, val);
407 } else {
408 uint64_t val = max_unsigned_val(type_entry);
409 bignum_init_unsigned(&const_val->data.x_bignum, val);
410 }
411 } else {
412 if (type_entry->data.integral.is_signed) {
413 int64_t val = min_signed_val(type_entry);
414 bignum_init_signed(&const_val->data.x_bignum, val);
415 } else {
416 bignum_init_unsigned(&const_val->data.x_bignum, 0);
417 }
418 }
419 } else if (type_entry->id == TypeTableEntryIdFloat) {
420 zig_panic("TODO analyze_min_max_value float");
421 } else if (type_entry->id == TypeTableEntryIdBool) {
422 const_val->special = ConstValSpecialStatic;
423 const_val->data.x_bool = is_max;
424 } else if (type_entry->id == TypeTableEntryIdVoid) {
425 // nothing to do
426 } else {
427 zig_unreachable();
428 }
429}
src/eval.hpp deleted-23
......@@ -1,23 +0,0 @@
1/*
2 * Copyright (c) 2016 Andrew Kelley
3 *
4 * This file is part of zig, which is MIT licensed.
5 * See http://opensource.org/licenses/MIT
6 */
7
8#ifndef ZIG_EVAL_HPP
9#define ZIG_EVAL_HPP
10
11#include "all_types.hpp"
12
13bool const_values_equal(ConstExprValue *a, ConstExprValue *b, TypeTableEntry *type_entry);
14int eval_const_expr_bin_op(ConstExprValue *op1_val, TypeTableEntry *op1_type,
15 BinOpType bin_op, ConstExprValue *op2_val, TypeTableEntry *op2_type, ConstExprValue *out_val);
16
17void eval_const_expr_implicit_cast(CastOp cast_op,
18 ConstExprValue *other_val, TypeTableEntry *other_type,
19 ConstExprValue *const_val, TypeTableEntry *new_type);
20
21void eval_min_max_value(CodeGen *g, TypeTableEntry *type_entry, ConstExprValue *const_val, bool is_max);
22
23#endif
src/ir.cpp+245-107
......@@ -8,7 +8,6 @@
88#include "analyze.hpp"
99#include "ast_render.hpp"
1010#include "error.hpp"
11#include "eval.hpp"
1211#include "ir.hpp"
1312#include "ir_print.hpp"
1413#include "os.hpp"
......@@ -447,6 +446,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionTestComptime *)
447446 return IrInstructionIdTestComptime;
448447}
449448
449static constexpr IrInstructionId ir_instruction_id(IrInstructionInitEnum *) {
450 return IrInstructionIdInitEnum;
451}
452
450453template<typename T>
451454static T *ir_create_instruction(IrExecutable *exec, Scope *scope, AstNode *source_node) {
452455 T *special_instruction = allocate<T>(1);
......@@ -1861,6 +1864,28 @@ static IrInstruction *ir_build_test_comptime(IrBuilder *irb, Scope *scope, AstNo
18611864 return &instruction->base;
18621865}
18631866
1867static IrInstruction *ir_build_init_enum(IrBuilder *irb, Scope *scope, AstNode *source_node,
1868 TypeTableEntry *enum_type, TypeEnumField *field, IrInstruction *init_value)
1869{
1870 IrInstructionInitEnum *instruction = ir_build_instruction<IrInstructionInitEnum>(irb, scope, source_node);
1871 instruction->enum_type = enum_type;
1872 instruction->field = field;
1873 instruction->init_value = init_value;
1874
1875 ir_ref_instruction(init_value);
1876
1877 return &instruction->base;
1878}
1879
1880static IrInstruction *ir_build_init_enum_from(IrBuilder *irb, IrInstruction *old_instruction,
1881 TypeTableEntry *enum_type, TypeEnumField *field, IrInstruction *init_value)
1882{
1883 IrInstruction *new_instruction = ir_build_init_enum(irb, old_instruction->scope, old_instruction->source_node,
1884 enum_type, field, init_value);
1885 ir_link_new_instruction(new_instruction, old_instruction);
1886 return new_instruction;
1887}
1888
18641889static void ir_count_defers(IrBuilder *irb, Scope *inner_scope, Scope *outer_scope, size_t *results) {
18651890 results[ReturnKindUnconditional] = 0;
18661891 results[ReturnKindError] = 0;
......@@ -4596,6 +4621,90 @@ static void ir_add_alloca(IrAnalyze *ira, IrInstruction *instruction, TypeTableE
45964621 }
45974622}
45984623
4624static void eval_const_expr_implicit_cast(CastOp cast_op,
4625 ConstExprValue *other_val, TypeTableEntry *other_type,
4626 ConstExprValue *const_val, TypeTableEntry *new_type)
4627{
4628 const_val->depends_on_compile_var = other_val->depends_on_compile_var;
4629 const_val->special = other_val->special;
4630
4631 assert(other_val != const_val);
4632 switch (cast_op) {
4633 case CastOpNoCast:
4634 zig_unreachable();
4635 case CastOpNoop:
4636 case CastOpWidenOrShorten:
4637 *const_val = *other_val;
4638 break;
4639 case CastOpPointerReinterpret:
4640 zig_panic("TODO compile time pointer reinterpret");
4641 break;
4642 case CastOpPtrToInt:
4643 case CastOpIntToPtr:
4644 case CastOpResizeSlice:
4645 case CastOpBytesToSlice:
4646 // can't do it
4647 break;
4648 case CastOpToUnknownSizeArray:
4649 {
4650 assert(other_type->id == TypeTableEntryIdArray);
4651 assert(other_val->data.x_array.size == other_type->data.array.len);
4652
4653 const_val->data.x_struct.fields = allocate<ConstExprValue>(2);
4654 ConstExprValue *ptr_field = &const_val->data.x_struct.fields[slice_ptr_index];
4655 ConstExprValue *len_field = &const_val->data.x_struct.fields[slice_len_index];
4656
4657 ptr_field->special = ConstValSpecialStatic;
4658 ptr_field->data.x_ptr.base_ptr = other_val;
4659
4660 len_field->special = ConstValSpecialStatic;
4661 bignum_init_unsigned(&len_field->data.x_bignum, other_type->data.array.len);
4662
4663 const_val->special = ConstValSpecialStatic;
4664 break;
4665 }
4666 case CastOpErrToInt:
4667 {
4668 uint64_t value;
4669 if (other_type->id == TypeTableEntryIdErrorUnion) {
4670 value = other_val->data.x_err_union.err ? other_val->data.x_err_union.err->value : 0;
4671 } else if (other_type->id == TypeTableEntryIdPureError) {
4672 value = other_val->data.x_pure_err->value;
4673 } else {
4674 zig_unreachable();
4675 }
4676 bignum_init_unsigned(&const_val->data.x_bignum, value);
4677 const_val->special = ConstValSpecialStatic;
4678 break;
4679 }
4680 case CastOpIntToFloat:
4681 bignum_cast_to_float(&const_val->data.x_bignum, &other_val->data.x_bignum);
4682 const_val->special = ConstValSpecialStatic;
4683 break;
4684 case CastOpFloatToInt:
4685 bignum_cast_to_int(&const_val->data.x_bignum, &other_val->data.x_bignum);
4686 const_val->special = ConstValSpecialStatic;
4687 break;
4688 case CastOpBoolToInt:
4689 bignum_init_unsigned(&const_val->data.x_bignum, other_val->data.x_bool ? 1 : 0);
4690 const_val->special = ConstValSpecialStatic;
4691 break;
4692 case CastOpIntToEnum:
4693 {
4694 uint64_t value = other_val->data.x_bignum.data.x_uint;
4695 assert(new_type->id == TypeTableEntryIdEnum);
4696 assert(value < new_type->data.enumeration.src_field_count);
4697 const_val->data.x_enum.tag = value;
4698 const_val->data.x_enum.payload = NULL;
4699 const_val->special = ConstValSpecialStatic;
4700 break;
4701 }
4702 case CastOpEnumToInt:
4703 bignum_init_unsigned(&const_val->data.x_bignum, other_val->data.x_enum.tag);
4704 const_val->special = ConstValSpecialStatic;
4705 break;
4706 }
4707}
45994708static IrInstruction *ir_resolve_cast(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value,
46004709 TypeTableEntry *wanted_type, CastOp cast_op, bool need_alloca)
46014710{
......@@ -5562,6 +5671,9 @@ static TypeTableEntry *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp
55625671 buf_sprintf("operator not allowed for type '%s'", buf_ptr(&resolved_type->name)));
55635672 return ira->codegen->builtin_types.entry_invalid;
55645673
5674 case TypeTableEntryIdEnumTag:
5675 zig_panic("TODO implement comparison for enum tag type");
5676
55655677 case TypeTableEntryIdVar:
55665678 zig_unreachable();
55675679 }
......@@ -6074,6 +6186,7 @@ static TypeTableEntry *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruc
60746186 case TypeTableEntryIdUnion:
60756187 case TypeTableEntryIdFn:
60766188 case TypeTableEntryIdBoundFn:
6189 case TypeTableEntryIdEnumTag:
60776190 // OK
60786191 break;
60796192 }
......@@ -6517,6 +6630,7 @@ static TypeTableEntry *ir_analyze_unary_prefix_op_err(IrAnalyze *ira, IrInstruct
65176630 case TypeTableEntryIdUnion:
65186631 case TypeTableEntryIdFn:
65196632 case TypeTableEntryIdBoundFn:
6633 case TypeTableEntryIdEnumTag:
65206634 {
65216635 ConstExprValue *out_val = ir_build_const_from(ira, &un_op_instruction->base,
65226636 value->static_value.depends_on_compile_var);
......@@ -6603,6 +6717,7 @@ static TypeTableEntry *ir_analyze_maybe(IrAnalyze *ira, IrInstructionUnOp *un_op
66036717 case TypeTableEntryIdNamespace:
66046718 case TypeTableEntryIdBlock:
66056719 case TypeTableEntryIdBoundFn:
6720 case TypeTableEntryIdEnumTag:
66066721 {
66076722 ConstExprValue *out_val = ir_build_const_from(ira, &un_op_instruction->base,
66086723 value->static_value.depends_on_compile_var);
......@@ -7175,7 +7290,11 @@ static TypeTableEntry *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstru
71757290 create_const_enum_tag(field->value), child_type, depends_on_compile_var,
71767291 ConstPtrSpecialNone, ptr_is_const);
71777292 } else {
7178 zig_panic("TODO enum tag type");
7293 bool ptr_is_const = true;
7294 return ir_analyze_const_ptr(ira, &field_ptr_instruction->base,
7295 create_const_unsigned_negative(field->value, false),
7296 child_type->data.enumeration.tag_type, depends_on_compile_var,
7297 ConstPtrSpecialNone, ptr_is_const);
71797298 }
71807299 }
71817300 }
......@@ -7377,6 +7496,7 @@ static TypeTableEntry *ir_analyze_instruction_typeof(IrAnalyze *ira, IrInstructi
73777496 case TypeTableEntryIdUnion:
73787497 case TypeTableEntryIdFn:
73797498 case TypeTableEntryIdTypeDecl:
7499 case TypeTableEntryIdEnumTag:
73807500 {
73817501 ConstExprValue *out_val = ir_build_const_from(ira, &typeof_instruction->base, false);
73827502 // TODO depends_on_compile_var should be set based on whether the type of the expression
......@@ -7596,6 +7716,7 @@ static TypeTableEntry *ir_analyze_instruction_slice_type(IrAnalyze *ira,
75967716 case TypeTableEntryIdFn:
75977717 case TypeTableEntryIdNamespace:
75987718 case TypeTableEntryIdBoundFn:
7719 case TypeTableEntryIdEnumTag:
75997720 {
76007721 TypeTableEntry *result_type = get_slice_type(ira->codegen, resolved_child_type, is_const);
76017722 ConstExprValue *out_val = ir_build_const_from(ira, &slice_type_instruction->base,
......@@ -7685,6 +7806,7 @@ static TypeTableEntry *ir_analyze_instruction_array_type(IrAnalyze *ira,
76857806 case TypeTableEntryIdFn:
76867807 case TypeTableEntryIdNamespace:
76877808 case TypeTableEntryIdBoundFn:
7809 case TypeTableEntryIdEnumTag:
76887810 {
76897811 TypeTableEntry *result_type = get_array_type(ira->codegen, child_type, size);
76907812 bool depends_on_compile_var = child_type_value->static_value.depends_on_compile_var ||
......@@ -7774,6 +7896,7 @@ static TypeTableEntry *ir_analyze_instruction_size_of(IrAnalyze *ira,
77747896 case TypeTableEntryIdPureError:
77757897 case TypeTableEntryIdEnum:
77767898 case TypeTableEntryIdUnion:
7899 case TypeTableEntryIdEnumTag:
77777900 {
77787901 uint64_t size_in_bytes = type_size(ira->codegen, type_entry);
77797902 bool depends_on_compile_var = false; // TODO types should be able to depend on compile var
......@@ -8089,6 +8212,8 @@ static TypeTableEntry *ir_analyze_instruction_switch_target(IrAnalyze *ira,
80898212 case TypeTableEntryIdErrorUnion:
80908213 // see https://github.com/andrewrk/zig/issues/83
80918214 zig_panic("TODO switch on error union");
8215 case TypeTableEntryIdEnumTag:
8216 zig_panic("TODO switch on enum tag type");
80928217 case TypeTableEntryIdUnreachable:
80938218 case TypeTableEntryIdArray:
80948219 case TypeTableEntryIdStruct:
......@@ -8347,86 +8472,133 @@ static TypeTableEntry *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstru
83478472
83488473static TypeTableEntry *ir_analyze_instruction_container_init_list(IrAnalyze *ira, IrInstructionContainerInitList *instruction) {
83498474 IrInstruction *container_type_value = instruction->container_type->other;
8350 TypeTableEntry *container_type = ir_resolve_type(ira, container_type_value);
8351 if (container_type->id == TypeTableEntryIdInvalid)
8475 if (container_type_value->type_entry->id == TypeTableEntryIdInvalid)
83528476 return ira->codegen->builtin_types.entry_invalid;
83538477
83548478 size_t elem_count = instruction->item_count;
8355 bool depends_on_compile_var = container_type_value->static_value.depends_on_compile_var;
8479 if (container_type_value->type_entry->id == TypeTableEntryIdMetaType) {
8480 TypeTableEntry *container_type = ir_resolve_type(ira, container_type_value);
8481 if (container_type->id == TypeTableEntryIdInvalid)
8482 return ira->codegen->builtin_types.entry_invalid;
83568483
8357 if (container_type->id == TypeTableEntryIdStruct && !is_slice(container_type) && elem_count == 0) {
8358 return ir_analyze_container_init_fields(ira, &instruction->base, container_type, 0, nullptr, depends_on_compile_var);
8359 } else if (is_slice(container_type)) {
8360 TypeTableEntry *pointer_type = container_type->data.structure.fields[slice_ptr_index].type_entry;
8361 assert(pointer_type->id == TypeTableEntryIdPointer);
8362 TypeTableEntry *child_type = pointer_type->data.pointer.child_type;
8484 bool depends_on_compile_var = container_type_value->static_value.depends_on_compile_var;
83638485
8364 ConstExprValue const_val = {};
8365 const_val.special = ConstValSpecialStatic;
8366 const_val.depends_on_compile_var = depends_on_compile_var;
8367 const_val.data.x_array.elements = allocate<ConstExprValue>(elem_count);
8368 const_val.data.x_array.size = elem_count;
8486 if (container_type->id == TypeTableEntryIdStruct && !is_slice(container_type) && elem_count == 0) {
8487 return ir_analyze_container_init_fields(ira, &instruction->base, container_type, 0, nullptr, depends_on_compile_var);
8488 } else if (is_slice(container_type)) {
8489 TypeTableEntry *pointer_type = container_type->data.structure.fields[slice_ptr_index].type_entry;
8490 assert(pointer_type->id == TypeTableEntryIdPointer);
8491 TypeTableEntry *child_type = pointer_type->data.pointer.child_type;
83698492
8370 FnTableEntry *fn_entry = exec_fn_entry(ira->new_irb.exec);
8371 bool outside_fn = (fn_entry == nullptr);
8493 ConstExprValue const_val = {};
8494 const_val.special = ConstValSpecialStatic;
8495 const_val.depends_on_compile_var = depends_on_compile_var;
8496 const_val.data.x_array.elements = allocate<ConstExprValue>(elem_count);
8497 const_val.data.x_array.size = elem_count;
83728498
8373 IrInstruction **new_items = allocate<IrInstruction *>(elem_count);
8499 FnTableEntry *fn_entry = exec_fn_entry(ira->new_irb.exec);
8500 bool outside_fn = (fn_entry == nullptr);
83748501
8375 IrInstruction *first_non_const_instruction = nullptr;
8502 IrInstruction **new_items = allocate<IrInstruction *>(elem_count);
83768503
8377 for (size_t i = 0; i < elem_count; i += 1) {
8378 IrInstruction *arg_value = instruction->items[i]->other;
8379 if (arg_value->type_entry->id == TypeTableEntryIdInvalid)
8380 return ira->codegen->builtin_types.entry_invalid;
8504 IrInstruction *first_non_const_instruction = nullptr;
83818505
8382 new_items[i] = arg_value;
8506 for (size_t i = 0; i < elem_count; i += 1) {
8507 IrInstruction *arg_value = instruction->items[i]->other;
8508 if (arg_value->type_entry->id == TypeTableEntryIdInvalid)
8509 return ira->codegen->builtin_types.entry_invalid;
83838510
8384 if (const_val.special == ConstValSpecialStatic) {
8385 if (outside_fn || arg_value->static_value.special != ConstValSpecialRuntime) {
8386 ConstExprValue *elem_val = ir_resolve_const(ira, arg_value, UndefBad);
8387 if (!elem_val)
8388 return ira->codegen->builtin_types.entry_invalid;
8511 new_items[i] = arg_value;
83898512
8390 const_val.data.x_array.elements[i] = *elem_val;
8391 const_val.depends_on_compile_var = const_val.depends_on_compile_var || elem_val->depends_on_compile_var;
8392 } else {
8393 first_non_const_instruction = arg_value;
8394 const_val.special = ConstValSpecialRuntime;
8513 if (const_val.special == ConstValSpecialStatic) {
8514 if (outside_fn || arg_value->static_value.special != ConstValSpecialRuntime) {
8515 ConstExprValue *elem_val = ir_resolve_const(ira, arg_value, UndefBad);
8516 if (!elem_val)
8517 return ira->codegen->builtin_types.entry_invalid;
8518
8519 const_val.data.x_array.elements[i] = *elem_val;
8520 const_val.depends_on_compile_var = const_val.depends_on_compile_var || elem_val->depends_on_compile_var;
8521 } else {
8522 first_non_const_instruction = arg_value;
8523 const_val.special = ConstValSpecialRuntime;
8524 }
83958525 }
83968526 }
8397 }
83988527
8399 TypeTableEntry *fixed_size_array_type = get_array_type(ira->codegen, child_type, elem_count);
8400 if (const_val.special == ConstValSpecialStatic) {
8401 ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base, const_val.depends_on_compile_var);
8402 *out_val = const_val;
8528 TypeTableEntry *fixed_size_array_type = get_array_type(ira->codegen, child_type, elem_count);
8529 if (const_val.special == ConstValSpecialStatic) {
8530 ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base, const_val.depends_on_compile_var);
8531 *out_val = const_val;
8532 return fixed_size_array_type;
8533 }
8534
8535 if (outside_fn) {
8536 ir_add_error_node(ira, first_non_const_instruction->source_node,
8537 buf_sprintf("unable to evaluate constant expression"));
8538 return ira->codegen->builtin_types.entry_invalid;
8539 }
8540
8541 IrInstruction *new_instruction = ir_build_container_init_list_from(&ira->new_irb, &instruction->base,
8542 container_type_value, elem_count, new_items);
8543 ir_add_alloca(ira, new_instruction, fixed_size_array_type);
84038544 return fixed_size_array_type;
8545 } else if (container_type->id == TypeTableEntryIdArray) {
8546 // same as slice init but we make a compile error if the length is wrong
8547 zig_panic("TODO array container init");
8548 } else if (container_type->id == TypeTableEntryIdVoid) {
8549 if (elem_count != 0) {
8550 ir_add_error_node(ira, instruction->base.source_node,
8551 buf_sprintf("void expression expects no arguments"));
8552 return ira->codegen->builtin_types.entry_invalid;
8553 }
8554 return ir_analyze_void(ira, &instruction->base);
8555 } else {
8556 ir_add_error_node(ira, instruction->base.source_node,
8557 buf_sprintf("type '%s' does not support array initialization",
8558 buf_ptr(&container_type->name)));
8559 return ira->codegen->builtin_types.entry_invalid;
84048560 }
8405
8406 if (outside_fn) {
8407 ir_add_error_node(ira, first_non_const_instruction->source_node,
8408 buf_sprintf("unable to evaluate constant expression"));
8561 } else if (container_type_value->type_entry->id == TypeTableEntryIdEnumTag) {
8562 // TODO I wrote this commit message when I had some sake
8563 // might be worth re-examining sober
8564 if (elem_count != 1) {
8565 ir_add_error(ira, &instruction->base, buf_sprintf("expected 1 elment"));
84098566 return ira->codegen->builtin_types.entry_invalid;
84108567 }
8568 ConstExprValue *tag_value = ir_resolve_const(ira, container_type_value, UndefBad);
8569 if (!tag_value)
8570 return ira->codegen->builtin_types.entry_invalid;
84118571
8412 IrInstruction *new_instruction = ir_build_container_init_list_from(&ira->new_irb, &instruction->base,
8413 container_type_value, elem_count, new_items);
8414 ir_add_alloca(ira, new_instruction, fixed_size_array_type);
8415 return fixed_size_array_type;
8416 } else if (container_type->id == TypeTableEntryIdArray) {
8417 // same as slice init but we make a compile error if the length is wrong
8418 zig_panic("TODO array container init");
8419 } else if (container_type->id == TypeTableEntryIdVoid) {
8420 if (elem_count != 0) {
8421 ir_add_error_node(ira, instruction->base.source_node,
8422 buf_sprintf("void expression expects no arguments"));
8572 TypeTableEntry *enum_type = container_type_value->type_entry->data.enum_tag.enum_type;
8573
8574 uint64_t tag_uint = tag_value->data.x_bignum.data.x_uint;
8575 TypeEnumField *field = &enum_type->data.enumeration.fields[tag_uint];
8576 TypeTableEntry *this_field_type = field->type_entry;
8577
8578 IrInstruction *init_value = instruction->items[0]->other;
8579
8580 IrInstruction *casted_init_value = ir_implicit_cast(ira, init_value, this_field_type);
8581 if (casted_init_value == ira->codegen->invalid_instruction)
84238582 return ira->codegen->builtin_types.entry_invalid;
8583
8584 if (instr_is_comptime(casted_init_value)) {
8585 ConstExprValue *init_val = ir_resolve_const(ira, casted_init_value, UndefOk);
8586 if (!init_val)
8587 return ira->codegen->builtin_types.entry_invalid;
8588 ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base,
8589 casted_init_value->static_value.depends_on_compile_var);
8590 out_val->data.x_enum.tag = tag_uint;
8591 out_val->data.x_enum.payload = init_val;
8592 return enum_type;
84248593 }
8425 return ir_analyze_void(ira, &instruction->base);
8594
8595 IrInstruction *new_instruction = ir_build_init_enum_from(&ira->new_irb, &instruction->base,
8596 enum_type, field, casted_init_value);
8597 ir_add_alloca(ira, new_instruction, enum_type);
8598 return enum_type;
84268599 } else {
8427 ir_add_error_node(ira, instruction->base.source_node,
8428 buf_sprintf("type '%s' does not support array initialization",
8429 buf_ptr(&container_type->name)));
8600 ir_add_error(ira, container_type_value,
8601 buf_sprintf("expected type, found '%s'", buf_ptr(&container_type_value->type_entry->name)));
84308602 return ira->codegen->builtin_types.entry_invalid;
84318603 }
84328604}
......@@ -8471,6 +8643,8 @@ static TypeTableEntry *ir_analyze_min_max(IrAnalyze *ira, IrInstruction *source_
84718643 eval_min_max_value(ira->codegen, canon_type, out_val, is_max);
84728644 return target_type;
84738645 }
8646 case TypeTableEntryIdEnumTag:
8647 zig_panic("TODO min/max value for enum tag type");
84748648 case TypeTableEntryIdVar:
84758649 case TypeTableEntryIdMetaType:
84768650 case TypeTableEntryIdUnreachable:
......@@ -8984,55 +9158,17 @@ static TypeTableEntry *ir_analyze_instruction_alloca(IrAnalyze *ira, IrInstructi
89849158 return ira->codegen->builtin_types.entry_invalid;
89859159
89869160 TypeTableEntry *child_type = ir_resolve_type(ira, type_value);
8987 TypeTableEntry *canon_type = get_underlying_type(child_type);
89889161
8989 if (count_value->static_value.special == ConstValSpecialStatic) {
8990 // this should be the same as an array declaration
8991
8992 uint64_t count;
8993 if (!ir_resolve_usize(ira, count_value, &count))
8994 return ira->codegen->builtin_types.entry_invalid;
8995
8996 zig_panic("TODO alloca with compile time known count");
8997 }
8998
8999 switch (canon_type->id) {
9000 case TypeTableEntryIdInvalid:
9001 case TypeTableEntryIdTypeDecl:
9002 zig_unreachable();
9003 case TypeTableEntryIdBool:
9004 case TypeTableEntryIdVoid:
9005 case TypeTableEntryIdInt:
9006 case TypeTableEntryIdFloat:
9007 case TypeTableEntryIdPointer:
9008 case TypeTableEntryIdArray:
9009 case TypeTableEntryIdStruct:
9010 case TypeTableEntryIdMaybe:
9011 case TypeTableEntryIdErrorUnion:
9012 case TypeTableEntryIdPureError:
9013 case TypeTableEntryIdEnum:
9014 case TypeTableEntryIdUnion:
9015 case TypeTableEntryIdFn:
9016 {
9017 TypeTableEntry *slice_type = get_slice_type(ira->codegen, child_type, false);
9018 IrInstruction *new_instruction = ir_build_alloca_from(&ira->new_irb, &instruction->base, type_value, count_value);
9019 ir_add_alloca(ira, new_instruction, slice_type);
9020 return slice_type;
9021 }
9022 case TypeTableEntryIdVar:
9023 case TypeTableEntryIdMetaType:
9024 case TypeTableEntryIdUnreachable:
9025 case TypeTableEntryIdNumLitFloat:
9026 case TypeTableEntryIdNumLitInt:
9027 case TypeTableEntryIdUndefLit:
9028 case TypeTableEntryIdNullLit:
9029 case TypeTableEntryIdNamespace:
9030 case TypeTableEntryIdBlock:
9031 case TypeTableEntryIdBoundFn:
9032 ir_add_error(ira, type_value,
9033 buf_sprintf("invalid alloca type '%s'", buf_ptr(&child_type->name)));
9034 // TODO if this is a typedecl, add error note showing the declaration of the type decl
9035 return ira->codegen->builtin_types.entry_invalid;
9162 if (type_requires_comptime(child_type)) {
9163 ir_add_error(ira, type_value,
9164 buf_sprintf("invalid alloca type '%s'", buf_ptr(&child_type->name)));
9165 // TODO if this is a typedecl, add error note showing the declaration of the type decl
9166 return ira->codegen->builtin_types.entry_invalid;
9167 } else {
9168 TypeTableEntry *slice_type = get_slice_type(ira->codegen, child_type, false);
9169 IrInstruction *new_instruction = ir_build_alloca_from(&ira->new_irb, &instruction->base, type_value, count_value);
9170 ir_add_alloca(ira, new_instruction, slice_type);
9171 return slice_type;
90369172 }
90379173 zig_unreachable();
90389174}
......@@ -9804,6 +9940,7 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi
98049940 case IrInstructionIdStructFieldPtr:
98059941 case IrInstructionIdEnumFieldPtr:
98069942 case IrInstructionIdStructInit:
9943 case IrInstructionIdInitEnum:
98079944 zig_panic("TODO analyze more instructions");
98089945 }
98099946 zig_unreachable();
......@@ -9959,6 +10096,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {
995910096 case IrInstructionIdErrWrapPayload:
996010097 case IrInstructionIdFnProto:
996110098 case IrInstructionIdTestComptime:
10099 case IrInstructionIdInitEnum:
996210100 return false;
996310101 case IrInstructionIdAsm:
996410102 {
src/ir_print.cpp+16
......@@ -183,6 +183,13 @@ static void ir_print_const_value(IrPrint *irp, TypeTableEntry *type_entry, Const
183183 fprintf(irp->f, "(pure error constant)");
184184 return;
185185 }
186 case TypeTableEntryIdEnumTag:
187 {
188 TypeTableEntry *enum_type = type_entry->data.enum_tag.enum_type;
189 TypeEnumField *field = &enum_type->data.enumeration.fields[const_val->data.x_bignum.data.x_uint];
190 fprintf(irp->f, "%s.%s", buf_ptr(&enum_type->name), buf_ptr(field->name));
191 return;
192 }
186193 }
187194 zig_unreachable();
188195}
......@@ -911,6 +918,12 @@ static void ir_print_test_comptime(IrPrint *irp, IrInstructionTestComptime *inst
911918 fprintf(irp->f, ")");
912919}
913920
921static void ir_print_init_enum(IrPrint *irp, IrInstructionInitEnum *instruction) {
922 fprintf(irp->f, "%s.%s { ", buf_ptr(&instruction->enum_type->name), buf_ptr(instruction->field->name));
923 ir_print_other_instruction(irp, instruction->init_value);
924 fprintf(irp->f, "{");
925}
926
914927static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
915928 ir_print_prefix(irp, instruction);
916929 switch (instruction->id) {
......@@ -1147,6 +1160,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
11471160 case IrInstructionIdTestComptime:
11481161 ir_print_test_comptime(irp, (IrInstructionTestComptime *)instruction);
11491162 break;
1163 case IrInstructionIdInitEnum:
1164 ir_print_init_enum(irp, (IrInstructionInitEnum *)instruction);
1165 break;
11501166 }
11511167 fprintf(irp->f, "\n");
11521168}
test/cases3/enum.zig created+37
......@@ -0,0 +1,37 @@
1fn enumType() {
2 @setFnTest(this);
3
4 const foo1 = Foo.One {13};
5 const foo2 = Foo.Two { Point { .x = 1234, .y = 5678, }};
6 const bar = Bar.B;
7
8 assert(bar == Bar.B);
9 assert(@memberCount(Foo) == 3);
10 assert(@memberCount(Bar) == 4);
11 const expected_foo_size = 16 + @sizeOf(usize);
12 assert(@sizeOf(Foo) == expected_foo_size);
13 assert(@sizeOf(Bar) == 1);
14}
15const Point = struct {
16 x: u64,
17 y: u64,
18};
19const Foo = enum {
20 One: i32,
21 Two: Point,
22 Three: void,
23};
24const Bar = enum {
25 A,
26 B,
27 C,
28 D,
29};
30
31fn assert(ok: bool) {
32 if (!ok)
33 @unreachable();
34}
35
36
37
test/self_hosted.zig-35
......@@ -333,41 +333,6 @@ fn maybeType() {
333333}
334334
335335
336fn enumType() {
337 @setFnTest(this, true);
338
339 const foo1 = EnumTypeFoo.One {13};
340 const foo2 = EnumTypeFoo.Two {EnumType { .x = 1234, .y = 5678, }};
341 const bar = EnumTypeBar.B;
342
343 assert(bar == EnumTypeBar.B);
344 assert(@memberCount(EnumTypeFoo) == 3);
345 assert(@memberCount(EnumTypeBar) == 4);
346 const expected_foo_size = switch (@compileVar("arch")) {
347 i386 => 20,
348 x86_64 => 24,
349 else => @unreachable(),
350 };
351 assert(@sizeOf(EnumTypeFoo) == expected_foo_size);
352 assert(@sizeOf(EnumTypeBar) == 1);
353}
354struct EnumType {
355 x: u64,
356 y: u64,
357}
358enum EnumTypeFoo {
359 One: i32,
360 Two: EnumType,
361 Three: void,
362}
363enum EnumTypeBar {
364 A,
365 B,
366 C,
367 D,
368}
369
370
371336fn arrayLiteral() {
372337 @setFnTest(this, true);
373338
test/self_hosted3.zig+1
......@@ -8,3 +8,4 @@ const test_for = @import("cases3/for.zig");
88const test_math = @import("cases3/math.zig");
99const test_generics = @import("cases3/generics.zig");
1010const test_defer = @import("cases3/defer.zig");
11const test_enum = @import("cases3/enum.zig");