| author | |
| committer | |
| log | 1f6dacbb2f9a91a20309b271a31e781f11f81819 |
| tree | 418c311fc703a4163ebf16cc90e89346b5113785 |
| parent | c10ae8622bc07baeea1fb81522b01fc6e953eaf6 |
12 files changed, 514 insertions(+), 607 deletions(-)
CMakeLists.txt-1| ... | @@ -46,7 +46,6 @@ set(ZIG_SOURCES | ... | @@ -46,7 +46,6 @@ set(ZIG_SOURCES |
| 46 | "${CMAKE_SOURCE_DIR}/src/codegen.cpp" | 46 | "${CMAKE_SOURCE_DIR}/src/codegen.cpp" |
| 47 | "${CMAKE_SOURCE_DIR}/src/errmsg.cpp" | 47 | "${CMAKE_SOURCE_DIR}/src/errmsg.cpp" |
| 48 | "${CMAKE_SOURCE_DIR}/src/error.cpp" | 48 | "${CMAKE_SOURCE_DIR}/src/error.cpp" |
| 49 | "${CMAKE_SOURCE_DIR}/src/eval.cpp" | ||
| 50 | "${CMAKE_SOURCE_DIR}/src/ir.cpp" | 49 | "${CMAKE_SOURCE_DIR}/src/ir.cpp" |
| 51 | "${CMAKE_SOURCE_DIR}/src/ir_print.cpp" | 50 | "${CMAKE_SOURCE_DIR}/src/ir_print.cpp" |
| 52 | "${CMAKE_SOURCE_DIR}/src/link.cpp" | 51 | "${CMAKE_SOURCE_DIR}/src/link.cpp" |
src/all_types.hpp+17| ... | @@ -848,6 +848,11 @@ struct TypeTableEntryEnum { | ... | @@ -848,6 +848,11 @@ struct TypeTableEntryEnum { |
| 848 | bool complete; | 848 | bool complete; |
| 849 | }; | 849 | }; |
| 850 | 850 | ||
| 851 | struct TypeTableEntryEnumTag { | ||
| 852 | TypeTableEntry *enum_type; | ||
| 853 | TypeTableEntry *int_type; | ||
| 854 | }; | ||
| 855 | |||
| 851 | struct TypeTableEntryUnion { | 856 | struct TypeTableEntryUnion { |
| 852 | AstNode *decl_node; | 857 | AstNode *decl_node; |
| 853 | bool is_extern; | 858 | bool is_extern; |
| ... | @@ -914,6 +919,7 @@ enum TypeTableEntryId { | ... | @@ -914,6 +919,7 @@ enum TypeTableEntryId { |
| 914 | TypeTableEntryIdErrorUnion, | 919 | TypeTableEntryIdErrorUnion, |
| 915 | TypeTableEntryIdPureError, | 920 | TypeTableEntryIdPureError, |
| 916 | TypeTableEntryIdEnum, | 921 | TypeTableEntryIdEnum, |
| 922 | TypeTableEntryIdEnumTag, | ||
| 917 | TypeTableEntryIdUnion, | 923 | TypeTableEntryIdUnion, |
| 918 | TypeTableEntryIdFn, | 924 | TypeTableEntryIdFn, |
| 919 | TypeTableEntryIdTypeDecl, | 925 | TypeTableEntryIdTypeDecl, |
| ... | @@ -940,6 +946,7 @@ struct TypeTableEntry { | ... | @@ -940,6 +946,7 @@ struct TypeTableEntry { |
| 940 | TypeTableEntryMaybe maybe; | 946 | TypeTableEntryMaybe maybe; |
| 941 | TypeTableEntryError error; | 947 | TypeTableEntryError error; |
| 942 | TypeTableEntryEnum enumeration; | 948 | TypeTableEntryEnum enumeration; |
| 949 | TypeTableEntryEnumTag enum_tag; | ||
| 943 | TypeTableEntryUnion unionation; | 950 | TypeTableEntryUnion unionation; |
| 944 | TypeTableEntryFn fn; | 951 | TypeTableEntryFn fn; |
| 945 | TypeTableEntryTypeDecl type_decl; | 952 | TypeTableEntryTypeDecl type_decl; |
| ... | @@ -1452,6 +1459,7 @@ enum IrInstructionId { | ... | @@ -1452,6 +1459,7 @@ enum IrInstructionId { |
| 1452 | IrInstructionIdErrWrapPayload, | 1459 | IrInstructionIdErrWrapPayload, |
| 1453 | IrInstructionIdFnProto, | 1460 | IrInstructionIdFnProto, |
| 1454 | IrInstructionIdTestComptime, | 1461 | IrInstructionIdTestComptime, |
| 1462 | IrInstructionIdInitEnum, | ||
| 1455 | }; | 1463 | }; |
| 1456 | 1464 | ||
| 1457 | struct IrInstruction { | 1465 | struct IrInstruction { |
| ... | @@ -2078,6 +2086,15 @@ struct IrInstructionTestComptime { | ... | @@ -2078,6 +2086,15 @@ struct IrInstructionTestComptime { |
| 2078 | IrInstruction *value; | 2086 | IrInstruction *value; |
| 2079 | }; | 2087 | }; |
| 2080 | 2088 | ||
| 2089 | struct IrInstructionInitEnum { | ||
| 2090 | IrInstruction base; | ||
| 2091 | |||
| 2092 | TypeTableEntry *enum_type; | ||
| 2093 | TypeEnumField *field; | ||
| 2094 | IrInstruction *init_value; | ||
| 2095 | LLVMValueRef tmp_ptr; | ||
| 2096 | }; | ||
| 2097 | |||
| 2081 | enum LValPurpose { | 2098 | enum LValPurpose { |
| 2082 | LValPurposeNone, | 2099 | LValPurposeNone, |
| 2083 | LValPurposeAssign, | 2100 | LValPurposeAssign, |
src/analyze.cpp+183-11| ... | @@ -9,7 +9,6 @@ | ... | @@ -9,7 +9,6 @@ |
| 9 | #include "ast_render.hpp" | 9 | #include "ast_render.hpp" |
| 10 | #include "config.h" | 10 | #include "config.h" |
| 11 | #include "error.hpp" | 11 | #include "error.hpp" |
| 12 | #include "eval.hpp" | ||
| 13 | #include "ir.hpp" | 12 | #include "ir.hpp" |
| 14 | #include "ir_print.hpp" | 13 | #include "ir_print.hpp" |
| 15 | #include "os.hpp" | 14 | #include "os.hpp" |
| ... | @@ -252,6 +251,7 @@ bool type_is_complete(TypeTableEntry *type_entry) { | ... | @@ -252,6 +251,7 @@ bool type_is_complete(TypeTableEntry *type_entry) { |
| 252 | case TypeTableEntryIdNamespace: | 251 | case TypeTableEntryIdNamespace: |
| 253 | case TypeTableEntryIdBlock: | 252 | case TypeTableEntryIdBlock: |
| 254 | case TypeTableEntryIdBoundFn: | 253 | case TypeTableEntryIdBoundFn: |
| 254 | case TypeTableEntryIdEnumTag: | ||
| 255 | return true; | 255 | return true; |
| 256 | } | 256 | } |
| 257 | zig_unreachable(); | 257 | zig_unreachable(); |
| ... | @@ -677,14 +677,8 @@ TypeTableEntry *get_typedecl_type(CodeGen *g, const char *name, TypeTableEntry * | ... | @@ -677,14 +677,8 @@ TypeTableEntry *get_typedecl_type(CodeGen *g, const char *name, TypeTableEntry * |
| 677 | entry->type_ref = child_type->type_ref; | 677 | entry->type_ref = child_type->type_ref; |
| 678 | entry->di_type = child_type->di_type; | 678 | entry->di_type = child_type->di_type; |
| 679 | entry->zero_bits = child_type->zero_bits; | 679 | entry->zero_bits = child_type->zero_bits; |
| 680 | |||
| 681 | entry->data.type_decl.child_type = child_type; | 680 | entry->data.type_decl.child_type = child_type; |
| 682 | 681 | entry->data.type_decl.canonical_type = get_underlying_type(child_type); | |
| 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 | } | ||
| 688 | 682 | ||
| 689 | return entry; | 683 | return entry; |
| 690 | } | 684 | } |
| ... | @@ -985,6 +979,7 @@ static TypeTableEntry *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *c | ... | @@ -985,6 +979,7 @@ static TypeTableEntry *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *c |
| 985 | case TypeTableEntryIdUnion: | 979 | case TypeTableEntryIdUnion: |
| 986 | case TypeTableEntryIdFn: | 980 | case TypeTableEntryIdFn: |
| 987 | case TypeTableEntryIdTypeDecl: | 981 | case TypeTableEntryIdTypeDecl: |
| 982 | case TypeTableEntryIdEnumTag: | ||
| 988 | break; | 983 | break; |
| 989 | } | 984 | } |
| 990 | FnTypeParamInfo *param_info = &fn_type_id.param_info[fn_type_id.next_param_index]; | 985 | 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 | ... | @@ -1033,12 +1028,28 @@ static TypeTableEntry *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *c |
| 1033 | case TypeTableEntryIdUnion: | 1028 | case TypeTableEntryIdUnion: |
| 1034 | case TypeTableEntryIdFn: | 1029 | case TypeTableEntryIdFn: |
| 1035 | case TypeTableEntryIdTypeDecl: | 1030 | case TypeTableEntryIdTypeDecl: |
| 1031 | case TypeTableEntryIdEnumTag: | ||
| 1036 | break; | 1032 | break; |
| 1037 | } | 1033 | } |
| 1038 | 1034 | ||
| 1039 | return get_fn_type(g, &fn_type_id); | 1035 | return get_fn_type(g, &fn_type_id); |
| 1040 | } | 1036 | } |
| 1041 | 1037 | ||
| 1038 | static 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 | |||
| 1042 | static void resolve_enum_type(CodeGen *g, TypeTableEntry *enum_type) { | 1053 | static void resolve_enum_type(CodeGen *g, TypeTableEntry *enum_type) { |
| 1043 | // if you change this logic you likely must also change similar logic in parseh.cpp | 1054 | // if you change this logic you likely must also change similar logic in parseh.cpp |
| 1044 | assert(enum_type->id == TypeTableEntryIdEnum); | 1055 | assert(enum_type->id == TypeTableEntryIdEnum); |
| ... | @@ -1134,7 +1145,8 @@ static void resolve_enum_type(CodeGen *g, TypeTableEntry *enum_type) { | ... | @@ -1134,7 +1145,8 @@ static void resolve_enum_type(CodeGen *g, TypeTableEntry *enum_type) { |
| 1134 | enum_type->data.enumeration.gen_field_count = gen_field_index; | 1145 | enum_type->data.enumeration.gen_field_count = gen_field_index; |
| 1135 | enum_type->data.enumeration.union_type = biggest_union_member; | 1146 | enum_type->data.enumeration.union_type = biggest_union_member; |
| 1136 | 1147 | ||
| 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); | ||
| 1138 | enum_type->data.enumeration.tag_type = tag_type_entry; | 1150 | enum_type->data.enumeration.tag_type = tag_type_entry; |
| 1139 | 1151 | ||
| 1140 | if (biggest_union_member) { | 1152 | if (biggest_union_member) { |
| ... | @@ -1686,6 +1698,7 @@ TypeTableEntry *validate_var_type(CodeGen *g, AstNode *source_node, TypeTableEnt | ... | @@ -1686,6 +1698,7 @@ TypeTableEntry *validate_var_type(CodeGen *g, AstNode *source_node, TypeTableEnt |
| 1686 | case TypeTableEntryIdUnion: | 1698 | case TypeTableEntryIdUnion: |
| 1687 | case TypeTableEntryIdFn: | 1699 | case TypeTableEntryIdFn: |
| 1688 | case TypeTableEntryIdBoundFn: | 1700 | case TypeTableEntryIdBoundFn: |
| 1701 | case TypeTableEntryIdEnumTag: | ||
| 1689 | return type_entry; | 1702 | return type_entry; |
| 1690 | } | 1703 | } |
| 1691 | zig_unreachable(); | 1704 | zig_unreachable(); |
| ... | @@ -1890,6 +1903,7 @@ static bool type_has_codegen_value(TypeTableEntry *type_entry) { | ... | @@ -1890,6 +1903,7 @@ static bool type_has_codegen_value(TypeTableEntry *type_entry) { |
| 1890 | case TypeTableEntryIdEnum: | 1903 | case TypeTableEntryIdEnum: |
| 1891 | case TypeTableEntryIdUnion: | 1904 | case TypeTableEntryIdUnion: |
| 1892 | case TypeTableEntryIdFn: | 1905 | case TypeTableEntryIdFn: |
| 1906 | case TypeTableEntryIdEnumTag: | ||
| 1893 | return true; | 1907 | return true; |
| 1894 | 1908 | ||
| 1895 | case TypeTableEntryIdTypeDecl: | 1909 | case TypeTableEntryIdTypeDecl: |
| ... | @@ -2110,6 +2124,7 @@ static bool is_container(TypeTableEntry *type_entry) { | ... | @@ -2110,6 +2124,7 @@ static bool is_container(TypeTableEntry *type_entry) { |
| 2110 | case TypeTableEntryIdNamespace: | 2124 | case TypeTableEntryIdNamespace: |
| 2111 | case TypeTableEntryIdBlock: | 2125 | case TypeTableEntryIdBlock: |
| 2112 | case TypeTableEntryIdBoundFn: | 2126 | case TypeTableEntryIdBoundFn: |
| 2127 | case TypeTableEntryIdEnumTag: | ||
| 2113 | return false; | 2128 | return false; |
| 2114 | } | 2129 | } |
| 2115 | zig_unreachable(); | 2130 | zig_unreachable(); |
| ... | @@ -2159,6 +2174,7 @@ void resolve_container_type(CodeGen *g, TypeTableEntry *type_entry) { | ... | @@ -2159,6 +2174,7 @@ void resolve_container_type(CodeGen *g, TypeTableEntry *type_entry) { |
| 2159 | case TypeTableEntryIdBoundFn: | 2174 | case TypeTableEntryIdBoundFn: |
| 2160 | case TypeTableEntryIdInvalid: | 2175 | case TypeTableEntryIdInvalid: |
| 2161 | case TypeTableEntryIdVar: | 2176 | case TypeTableEntryIdVar: |
| 2177 | case TypeTableEntryIdEnumTag: | ||
| 2162 | zig_unreachable(); | 2178 | zig_unreachable(); |
| 2163 | } | 2179 | } |
| 2164 | } | 2180 | } |
| ... | @@ -2509,6 +2525,7 @@ bool handle_is_ptr(TypeTableEntry *type_entry) { | ... | @@ -2509,6 +2525,7 @@ bool handle_is_ptr(TypeTableEntry *type_entry) { |
| 2509 | case TypeTableEntryIdPointer: | 2525 | case TypeTableEntryIdPointer: |
| 2510 | case TypeTableEntryIdPureError: | 2526 | case TypeTableEntryIdPureError: |
| 2511 | case TypeTableEntryIdFn: | 2527 | case TypeTableEntryIdFn: |
| 2528 | case TypeTableEntryIdEnumTag: | ||
| 2512 | return false; | 2529 | return false; |
| 2513 | case TypeTableEntryIdArray: | 2530 | case TypeTableEntryIdArray: |
| 2514 | case TypeTableEntryIdStruct: | 2531 | case TypeTableEntryIdStruct: |
| ... | @@ -2650,6 +2667,8 @@ static uint32_t hash_const_val(TypeTableEntry *type, ConstExprValue *const_val) | ... | @@ -2650,6 +2667,8 @@ static uint32_t hash_const_val(TypeTableEntry *type, ConstExprValue *const_val) |
| 2650 | return hash_ptr(const_val->data.x_import); | 2667 | return hash_ptr(const_val->data.x_import); |
| 2651 | case TypeTableEntryIdBlock: | 2668 | case TypeTableEntryIdBlock: |
| 2652 | return hash_ptr(const_val->data.x_block); | 2669 | 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); | ||
| 2653 | case TypeTableEntryIdBoundFn: | 2672 | case TypeTableEntryIdBoundFn: |
| 2654 | case TypeTableEntryIdInvalid: | 2673 | case TypeTableEntryIdInvalid: |
| 2655 | case TypeTableEntryIdUnreachable: | 2674 | case TypeTableEntryIdUnreachable: |
| ... | @@ -2794,16 +2813,18 @@ static TypeTableEntry *type_of_first_thing_in_memory(TypeTableEntry *type_entry) | ... | @@ -2794,16 +2813,18 @@ static TypeTableEntry *type_of_first_thing_in_memory(TypeTableEntry *type_entry) |
| 2794 | case TypeTableEntryIdInt: | 2813 | case TypeTableEntryIdInt: |
| 2795 | case TypeTableEntryIdFloat: | 2814 | case TypeTableEntryIdFloat: |
| 2796 | case TypeTableEntryIdPointer: | 2815 | case TypeTableEntryIdPointer: |
| 2816 | case TypeTableEntryIdEnumTag: | ||
| 2797 | return type_entry; | 2817 | return type_entry; |
| 2798 | } | 2818 | } |
| 2799 | zig_unreachable(); | 2819 | zig_unreachable(); |
| 2800 | } | 2820 | } |
| 2801 | 2821 | ||
| 2802 | bool type_requires_comptime(TypeTableEntry *type_entry) { | 2822 | bool type_requires_comptime(TypeTableEntry *type_entry) { |
| 2803 | switch (type_entry->id) { | 2823 | switch (get_underlying_type(type_entry)->id) { |
| 2804 | case TypeTableEntryIdInvalid: | 2824 | case TypeTableEntryIdInvalid: |
| 2805 | case TypeTableEntryIdUnreachable: | 2825 | case TypeTableEntryIdUnreachable: |
| 2806 | case TypeTableEntryIdVar: | 2826 | case TypeTableEntryIdVar: |
| 2827 | case TypeTableEntryIdTypeDecl: | ||
| 2807 | zig_unreachable(); | 2828 | zig_unreachable(); |
| 2808 | case TypeTableEntryIdNumLitFloat: | 2829 | case TypeTableEntryIdNumLitFloat: |
| 2809 | case TypeTableEntryIdNumLitInt: | 2830 | case TypeTableEntryIdNumLitInt: |
| ... | @@ -2820,7 +2841,6 @@ bool type_requires_comptime(TypeTableEntry *type_entry) { | ... | @@ -2820,7 +2841,6 @@ bool type_requires_comptime(TypeTableEntry *type_entry) { |
| 2820 | case TypeTableEntryIdUnion: | 2841 | case TypeTableEntryIdUnion: |
| 2821 | case TypeTableEntryIdMaybe: | 2842 | case TypeTableEntryIdMaybe: |
| 2822 | case TypeTableEntryIdErrorUnion: | 2843 | case TypeTableEntryIdErrorUnion: |
| 2823 | case TypeTableEntryIdTypeDecl: | ||
| 2824 | case TypeTableEntryIdEnum: | 2844 | case TypeTableEntryIdEnum: |
| 2825 | case TypeTableEntryIdPureError: | 2845 | case TypeTableEntryIdPureError: |
| 2826 | case TypeTableEntryIdFn: | 2846 | case TypeTableEntryIdFn: |
| ... | @@ -2828,6 +2848,7 @@ bool type_requires_comptime(TypeTableEntry *type_entry) { | ... | @@ -2828,6 +2848,7 @@ bool type_requires_comptime(TypeTableEntry *type_entry) { |
| 2828 | case TypeTableEntryIdInt: | 2848 | case TypeTableEntryIdInt: |
| 2829 | case TypeTableEntryIdFloat: | 2849 | case TypeTableEntryIdFloat: |
| 2830 | case TypeTableEntryIdPointer: | 2850 | case TypeTableEntryIdPointer: |
| 2851 | case TypeTableEntryIdEnumTag: | ||
| 2831 | return false; | 2852 | return false; |
| 2832 | } | 2853 | } |
| 2833 | zig_unreachable(); | 2854 | zig_unreachable(); |
| ... | @@ -2933,3 +2954,154 @@ bool ir_get_var_is_comptime(VariableTableEntry *var) { | ... | @@ -2933,3 +2954,154 @@ bool ir_get_var_is_comptime(VariableTableEntry *var) { |
| 2933 | return var->is_comptime->static_value.data.x_bool; | 2954 | return var->is_comptime->static_value.data.x_bool; |
| 2934 | } | 2955 | } |
| 2935 | 2956 | ||
| 2957 | bool 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 | |||
| 3021 | static 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 | |||
| 3032 | static 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 | |||
| 3047 | static 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 | |||
| 3062 | static 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 | |||
| 3077 | void 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); | ... | @@ -77,6 +77,8 @@ bool type_requires_comptime(TypeTableEntry *type_entry); |
| 77 | void ensure_complete_type(CodeGen *g, TypeTableEntry *type_entry); | 77 | void ensure_complete_type(CodeGen *g, TypeTableEntry *type_entry); |
| 78 | void complete_enum(CodeGen *g, TypeTableEntry *enum_type); | 78 | void complete_enum(CodeGen *g, TypeTableEntry *enum_type); |
| 79 | bool ir_get_var_is_comptime(VariableTableEntry *var); | 79 | bool ir_get_var_is_comptime(VariableTableEntry *var); |
| 80 | bool const_values_equal(ConstExprValue *a, ConstExprValue *b, TypeTableEntry *type_entry); | ||
| 81 | void eval_min_max_value(CodeGen *g, TypeTableEntry *type_entry, ConstExprValue *const_val, bool is_max); | ||
| 80 | 82 | ||
| 81 | ScopeBlock *create_block_scope(AstNode *node, Scope *parent); | 83 | ScopeBlock *create_block_scope(AstNode *node, Scope *parent); |
| 82 | ScopeDefer *create_defer_scope(AstNode *node, Scope *parent); | 84 | ScopeDefer *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 | ... | @@ -2144,6 +2144,10 @@ static LLVMValueRef ir_render_enum_tag(CodeGen *g, IrExecutable *executable, IrI |
| 2144 | return get_handle_value(g, tag_field_ptr, tag_type); | 2144 | return get_handle_value(g, tag_field_ptr, tag_type); |
| 2145 | } | 2145 | } |
| 2146 | 2146 | ||
| 2147 | static LLVMValueRef ir_render_init_enum(CodeGen *g, IrExecutable *executable, IrInstructionInitEnum *instruction) { | ||
| 2148 | zig_panic("TODO ir_render_init_enum"); | ||
| 2149 | } | ||
| 2150 | |||
| 2147 | static void set_debug_location(CodeGen *g, IrInstruction *instruction) { | 2151 | static void set_debug_location(CodeGen *g, IrInstruction *instruction) { |
| 2148 | AstNode *source_node = instruction->source_node; | 2152 | AstNode *source_node = instruction->source_node; |
| 2149 | Scope *scope = instruction->scope; | 2153 | Scope *scope = instruction->scope; |
| ... | @@ -2278,6 +2282,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, | ... | @@ -2278,6 +2282,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, |
| 2278 | return ir_render_err_wrap_payload(g, executable, (IrInstructionErrWrapPayload *)instruction); | 2282 | return ir_render_err_wrap_payload(g, executable, (IrInstructionErrWrapPayload *)instruction); |
| 2279 | case IrInstructionIdEnumTag: | 2283 | case IrInstructionIdEnumTag: |
| 2280 | return ir_render_enum_tag(g, executable, (IrInstructionEnumTag *)instruction); | 2284 | return ir_render_enum_tag(g, executable, (IrInstructionEnumTag *)instruction); |
| 2285 | case IrInstructionIdInitEnum: | ||
| 2286 | return ir_render_init_enum(g, executable, (IrInstructionInitEnum *)instruction); | ||
| 2281 | case IrInstructionIdSwitchVar: | 2287 | case IrInstructionIdSwitchVar: |
| 2282 | zig_panic("TODO render switch var instruction to LLVM"); | 2288 | zig_panic("TODO render switch var instruction to LLVM"); |
| 2283 | case IrInstructionIdContainerInitList: | 2289 | case IrInstructionIdContainerInitList: |
| ... | @@ -2497,6 +2503,8 @@ static LLVMValueRef gen_const_val(CodeGen *g, TypeTableEntry *type_entry, ConstE | ... | @@ -2497,6 +2503,8 @@ static LLVMValueRef gen_const_val(CodeGen *g, TypeTableEntry *type_entry, ConstE |
| 2497 | } | 2503 | } |
| 2498 | case TypeTableEntryIdVoid: | 2504 | case TypeTableEntryIdVoid: |
| 2499 | return nullptr; | 2505 | return nullptr; |
| 2506 | case TypeTableEntryIdEnumTag: | ||
| 2507 | return gen_const_val(g, type_entry->data.enum_tag.int_type, const_val); | ||
| 2500 | case TypeTableEntryIdInvalid: | 2508 | case TypeTableEntryIdInvalid: |
| 2501 | case TypeTableEntryIdMetaType: | 2509 | case TypeTableEntryIdMetaType: |
| 2502 | case TypeTableEntryIdUnreachable: | 2510 | case TypeTableEntryIdUnreachable: |
| ... | @@ -2876,6 +2884,9 @@ static void do_code_gen(CodeGen *g) { | ... | @@ -2876,6 +2884,9 @@ static void do_code_gen(CodeGen *g) { |
| 2876 | } else if (instruction->id == IrInstructionIdErrWrapCode) { | 2884 | } else if (instruction->id == IrInstructionIdErrWrapCode) { |
| 2877 | IrInstructionErrWrapCode *err_wrap_code_instruction = (IrInstructionErrWrapCode *)instruction; | 2885 | IrInstructionErrWrapCode *err_wrap_code_instruction = (IrInstructionErrWrapCode *)instruction; |
| 2878 | slot = &err_wrap_code_instruction->tmp_ptr; | 2886 | 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; | ||
| 2879 | } else { | 2890 | } else { |
| 2880 | zig_unreachable(); | 2891 | zig_unreachable(); |
| 2881 | } | 2892 | } |
| ... | @@ -3793,7 +3804,8 @@ static void get_c_type(CodeGen *g, TypeTableEntry *type_entry, Buf *out_buf) { | ... | @@ -3793,7 +3804,8 @@ static void get_c_type(CodeGen *g, TypeTableEntry *type_entry, Buf *out_buf) { |
| 3793 | case TypeTableEntryIdUnion: | 3804 | case TypeTableEntryIdUnion: |
| 3794 | case TypeTableEntryIdFn: | 3805 | case TypeTableEntryIdFn: |
| 3795 | case TypeTableEntryIdTypeDecl: | 3806 | case TypeTableEntryIdTypeDecl: |
| 3796 | zig_panic("TODO"); | 3807 | case TypeTableEntryIdEnumTag: |
| 3808 | zig_panic("TODO implement get_c_type for more types"); | ||
| 3797 | case TypeTableEntryIdInvalid: | 3809 | case TypeTableEntryIdInvalid: |
| 3798 | case TypeTableEntryIdMetaType: | 3810 | case TypeTableEntryIdMetaType: |
| 3799 | case TypeTableEntryIdBoundFn: | 3811 | 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 | |||
| 12 | bool 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 | |||
| 75 | static 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 | |||
| 85 | static 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 | |||
| 100 | static 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 | |||
| 115 | static 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 | |||
| 130 | static 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 | |||
| 162 | int 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 | |||
| 303 | void 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 | |||
| 388 | static 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 | |||
| 399 | void 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 | |||
| 13 | bool const_values_equal(ConstExprValue *a, ConstExprValue *b, TypeTableEntry *type_entry); | ||
| 14 | int 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 | |||
| 17 | void eval_const_expr_implicit_cast(CastOp cast_op, | ||
| 18 | ConstExprValue *other_val, TypeTableEntry *other_type, | ||
| 19 | ConstExprValue *const_val, TypeTableEntry *new_type); | ||
| 20 | |||
| 21 | void 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 @@ | ... | @@ -8,7 +8,6 @@ |
| 8 | #include "analyze.hpp" | 8 | #include "analyze.hpp" |
| 9 | #include "ast_render.hpp" | 9 | #include "ast_render.hpp" |
| 10 | #include "error.hpp" | 10 | #include "error.hpp" |
| 11 | #include "eval.hpp" | ||
| 12 | #include "ir.hpp" | 11 | #include "ir.hpp" |
| 13 | #include "ir_print.hpp" | 12 | #include "ir_print.hpp" |
| 14 | #include "os.hpp" | 13 | #include "os.hpp" |
| ... | @@ -447,6 +446,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionTestComptime *) | ... | @@ -447,6 +446,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionTestComptime *) |
| 447 | return IrInstructionIdTestComptime; | 446 | return IrInstructionIdTestComptime; |
| 448 | } | 447 | } |
| 449 | 448 | ||
| 449 | static constexpr IrInstructionId ir_instruction_id(IrInstructionInitEnum *) { | ||
| 450 | return IrInstructionIdInitEnum; | ||
| 451 | } | ||
| 452 | |||
| 450 | template<typename T> | 453 | template<typename T> |
| 451 | static T *ir_create_instruction(IrExecutable *exec, Scope *scope, AstNode *source_node) { | 454 | static T *ir_create_instruction(IrExecutable *exec, Scope *scope, AstNode *source_node) { |
| 452 | T *special_instruction = allocate<T>(1); | 455 | T *special_instruction = allocate<T>(1); |
| ... | @@ -1861,6 +1864,28 @@ static IrInstruction *ir_build_test_comptime(IrBuilder *irb, Scope *scope, AstNo | ... | @@ -1861,6 +1864,28 @@ static IrInstruction *ir_build_test_comptime(IrBuilder *irb, Scope *scope, AstNo |
| 1861 | return &instruction->base; | 1864 | return &instruction->base; |
| 1862 | } | 1865 | } |
| 1863 | 1866 | ||
| 1867 | static 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 | |||
| 1880 | static 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 | |||
| 1864 | static void ir_count_defers(IrBuilder *irb, Scope *inner_scope, Scope *outer_scope, size_t *results) { | 1889 | static void ir_count_defers(IrBuilder *irb, Scope *inner_scope, Scope *outer_scope, size_t *results) { |
| 1865 | results[ReturnKindUnconditional] = 0; | 1890 | results[ReturnKindUnconditional] = 0; |
| 1866 | results[ReturnKindError] = 0; | 1891 | results[ReturnKindError] = 0; |
| ... | @@ -4596,6 +4621,90 @@ static void ir_add_alloca(IrAnalyze *ira, IrInstruction *instruction, TypeTableE | ... | @@ -4596,6 +4621,90 @@ static void ir_add_alloca(IrAnalyze *ira, IrInstruction *instruction, TypeTableE |
| 4596 | } | 4621 | } |
| 4597 | } | 4622 | } |
| 4598 | 4623 | ||
| 4624 | static 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 | } | ||
| 4599 | static IrInstruction *ir_resolve_cast(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value, | 4708 | static IrInstruction *ir_resolve_cast(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value, |
| 4600 | TypeTableEntry *wanted_type, CastOp cast_op, bool need_alloca) | 4709 | TypeTableEntry *wanted_type, CastOp cast_op, bool need_alloca) |
| 4601 | { | 4710 | { |
| ... | @@ -5562,6 +5671,9 @@ static TypeTableEntry *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp | ... | @@ -5562,6 +5671,9 @@ static TypeTableEntry *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp |
| 5562 | buf_sprintf("operator not allowed for type '%s'", buf_ptr(&resolved_type->name))); | 5671 | buf_sprintf("operator not allowed for type '%s'", buf_ptr(&resolved_type->name))); |
| 5563 | return ira->codegen->builtin_types.entry_invalid; | 5672 | return ira->codegen->builtin_types.entry_invalid; |
| 5564 | 5673 | ||
| 5674 | case TypeTableEntryIdEnumTag: | ||
| 5675 | zig_panic("TODO implement comparison for enum tag type"); | ||
| 5676 | |||
| 5565 | case TypeTableEntryIdVar: | 5677 | case TypeTableEntryIdVar: |
| 5566 | zig_unreachable(); | 5678 | zig_unreachable(); |
| 5567 | } | 5679 | } |
| ... | @@ -6074,6 +6186,7 @@ static TypeTableEntry *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruc | ... | @@ -6074,6 +6186,7 @@ static TypeTableEntry *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruc |
| 6074 | case TypeTableEntryIdUnion: | 6186 | case TypeTableEntryIdUnion: |
| 6075 | case TypeTableEntryIdFn: | 6187 | case TypeTableEntryIdFn: |
| 6076 | case TypeTableEntryIdBoundFn: | 6188 | case TypeTableEntryIdBoundFn: |
| 6189 | case TypeTableEntryIdEnumTag: | ||
| 6077 | // OK | 6190 | // OK |
| 6078 | break; | 6191 | break; |
| 6079 | } | 6192 | } |
| ... | @@ -6517,6 +6630,7 @@ static TypeTableEntry *ir_analyze_unary_prefix_op_err(IrAnalyze *ira, IrInstruct | ... | @@ -6517,6 +6630,7 @@ static TypeTableEntry *ir_analyze_unary_prefix_op_err(IrAnalyze *ira, IrInstruct |
| 6517 | case TypeTableEntryIdUnion: | 6630 | case TypeTableEntryIdUnion: |
| 6518 | case TypeTableEntryIdFn: | 6631 | case TypeTableEntryIdFn: |
| 6519 | case TypeTableEntryIdBoundFn: | 6632 | case TypeTableEntryIdBoundFn: |
| 6633 | case TypeTableEntryIdEnumTag: | ||
| 6520 | { | 6634 | { |
| 6521 | ConstExprValue *out_val = ir_build_const_from(ira, &un_op_instruction->base, | 6635 | ConstExprValue *out_val = ir_build_const_from(ira, &un_op_instruction->base, |
| 6522 | value->static_value.depends_on_compile_var); | 6636 | value->static_value.depends_on_compile_var); |
| ... | @@ -6603,6 +6717,7 @@ static TypeTableEntry *ir_analyze_maybe(IrAnalyze *ira, IrInstructionUnOp *un_op | ... | @@ -6603,6 +6717,7 @@ static TypeTableEntry *ir_analyze_maybe(IrAnalyze *ira, IrInstructionUnOp *un_op |
| 6603 | case TypeTableEntryIdNamespace: | 6717 | case TypeTableEntryIdNamespace: |
| 6604 | case TypeTableEntryIdBlock: | 6718 | case TypeTableEntryIdBlock: |
| 6605 | case TypeTableEntryIdBoundFn: | 6719 | case TypeTableEntryIdBoundFn: |
| 6720 | case TypeTableEntryIdEnumTag: | ||
| 6606 | { | 6721 | { |
| 6607 | ConstExprValue *out_val = ir_build_const_from(ira, &un_op_instruction->base, | 6722 | ConstExprValue *out_val = ir_build_const_from(ira, &un_op_instruction->base, |
| 6608 | value->static_value.depends_on_compile_var); | 6723 | value->static_value.depends_on_compile_var); |
| ... | @@ -7175,7 +7290,11 @@ static TypeTableEntry *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstru | ... | @@ -7175,7 +7290,11 @@ static TypeTableEntry *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstru |
| 7175 | create_const_enum_tag(field->value), child_type, depends_on_compile_var, | 7290 | create_const_enum_tag(field->value), child_type, depends_on_compile_var, |
| 7176 | ConstPtrSpecialNone, ptr_is_const); | 7291 | ConstPtrSpecialNone, ptr_is_const); |
| 7177 | } else { | 7292 | } 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); | ||
| 7179 | } | 7298 | } |
| 7180 | } | 7299 | } |
| 7181 | } | 7300 | } |
| ... | @@ -7377,6 +7496,7 @@ static TypeTableEntry *ir_analyze_instruction_typeof(IrAnalyze *ira, IrInstructi | ... | @@ -7377,6 +7496,7 @@ static TypeTableEntry *ir_analyze_instruction_typeof(IrAnalyze *ira, IrInstructi |
| 7377 | case TypeTableEntryIdUnion: | 7496 | case TypeTableEntryIdUnion: |
| 7378 | case TypeTableEntryIdFn: | 7497 | case TypeTableEntryIdFn: |
| 7379 | case TypeTableEntryIdTypeDecl: | 7498 | case TypeTableEntryIdTypeDecl: |
| 7499 | case TypeTableEntryIdEnumTag: | ||
| 7380 | { | 7500 | { |
| 7381 | ConstExprValue *out_val = ir_build_const_from(ira, &typeof_instruction->base, false); | 7501 | ConstExprValue *out_val = ir_build_const_from(ira, &typeof_instruction->base, false); |
| 7382 | // TODO depends_on_compile_var should be set based on whether the type of the expression | 7502 | // 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, | ... | @@ -7596,6 +7716,7 @@ static TypeTableEntry *ir_analyze_instruction_slice_type(IrAnalyze *ira, |
| 7596 | case TypeTableEntryIdFn: | 7716 | case TypeTableEntryIdFn: |
| 7597 | case TypeTableEntryIdNamespace: | 7717 | case TypeTableEntryIdNamespace: |
| 7598 | case TypeTableEntryIdBoundFn: | 7718 | case TypeTableEntryIdBoundFn: |
| 7719 | case TypeTableEntryIdEnumTag: | ||
| 7599 | { | 7720 | { |
| 7600 | TypeTableEntry *result_type = get_slice_type(ira->codegen, resolved_child_type, is_const); | 7721 | TypeTableEntry *result_type = get_slice_type(ira->codegen, resolved_child_type, is_const); |
| 7601 | ConstExprValue *out_val = ir_build_const_from(ira, &slice_type_instruction->base, | 7722 | 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, | ... | @@ -7685,6 +7806,7 @@ static TypeTableEntry *ir_analyze_instruction_array_type(IrAnalyze *ira, |
| 7685 | case TypeTableEntryIdFn: | 7806 | case TypeTableEntryIdFn: |
| 7686 | case TypeTableEntryIdNamespace: | 7807 | case TypeTableEntryIdNamespace: |
| 7687 | case TypeTableEntryIdBoundFn: | 7808 | case TypeTableEntryIdBoundFn: |
| 7809 | case TypeTableEntryIdEnumTag: | ||
| 7688 | { | 7810 | { |
| 7689 | TypeTableEntry *result_type = get_array_type(ira->codegen, child_type, size); | 7811 | TypeTableEntry *result_type = get_array_type(ira->codegen, child_type, size); |
| 7690 | bool depends_on_compile_var = child_type_value->static_value.depends_on_compile_var || | 7812 | 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, | ... | @@ -7774,6 +7896,7 @@ static TypeTableEntry *ir_analyze_instruction_size_of(IrAnalyze *ira, |
| 7774 | case TypeTableEntryIdPureError: | 7896 | case TypeTableEntryIdPureError: |
| 7775 | case TypeTableEntryIdEnum: | 7897 | case TypeTableEntryIdEnum: |
| 7776 | case TypeTableEntryIdUnion: | 7898 | case TypeTableEntryIdUnion: |
| 7899 | case TypeTableEntryIdEnumTag: | ||
| 7777 | { | 7900 | { |
| 7778 | uint64_t size_in_bytes = type_size(ira->codegen, type_entry); | 7901 | uint64_t size_in_bytes = type_size(ira->codegen, type_entry); |
| 7779 | bool depends_on_compile_var = false; // TODO types should be able to depend on compile var | 7902 | 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, | ... | @@ -8089,6 +8212,8 @@ static TypeTableEntry *ir_analyze_instruction_switch_target(IrAnalyze *ira, |
| 8089 | case TypeTableEntryIdErrorUnion: | 8212 | case TypeTableEntryIdErrorUnion: |
| 8090 | // see https://github.com/andrewrk/zig/issues/83 | 8213 | // see https://github.com/andrewrk/zig/issues/83 |
| 8091 | zig_panic("TODO switch on error union"); | 8214 | zig_panic("TODO switch on error union"); |
| 8215 | case TypeTableEntryIdEnumTag: | ||
| 8216 | zig_panic("TODO switch on enum tag type"); | ||
| 8092 | case TypeTableEntryIdUnreachable: | 8217 | case TypeTableEntryIdUnreachable: |
| 8093 | case TypeTableEntryIdArray: | 8218 | case TypeTableEntryIdArray: |
| 8094 | case TypeTableEntryIdStruct: | 8219 | case TypeTableEntryIdStruct: |
| ... | @@ -8347,86 +8472,133 @@ static TypeTableEntry *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstru | ... | @@ -8347,86 +8472,133 @@ static TypeTableEntry *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstru |
| 8347 | 8472 | ||
| 8348 | static TypeTableEntry *ir_analyze_instruction_container_init_list(IrAnalyze *ira, IrInstructionContainerInitList *instruction) { | 8473 | static TypeTableEntry *ir_analyze_instruction_container_init_list(IrAnalyze *ira, IrInstructionContainerInitList *instruction) { |
| 8349 | IrInstruction *container_type_value = instruction->container_type->other; | 8474 | IrInstruction *container_type_value = instruction->container_type->other; |
| 8350 | TypeTableEntry *container_type = ir_resolve_type(ira, container_type_value); | 8475 | if (container_type_value->type_entry->id == TypeTableEntryIdInvalid) |
| 8351 | if (container_type->id == TypeTableEntryIdInvalid) | ||
| 8352 | return ira->codegen->builtin_types.entry_invalid; | 8476 | return ira->codegen->builtin_types.entry_invalid; |
| 8353 | 8477 | ||
| 8354 | size_t elem_count = instruction->item_count; | 8478 | 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; | ||
| 8356 | 8483 | ||
| 8357 | if (container_type->id == TypeTableEntryIdStruct && !is_slice(container_type) && elem_count == 0) { | 8484 | bool depends_on_compile_var = container_type_value->static_value.depends_on_compile_var; |
| 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; | ||
| 8363 | 8485 | ||
| 8364 | ConstExprValue const_val = {}; | 8486 | if (container_type->id == TypeTableEntryIdStruct && !is_slice(container_type) && elem_count == 0) { |
| 8365 | const_val.special = ConstValSpecialStatic; | 8487 | return ir_analyze_container_init_fields(ira, &instruction->base, container_type, 0, nullptr, depends_on_compile_var); |
| 8366 | const_val.depends_on_compile_var = depends_on_compile_var; | 8488 | } else if (is_slice(container_type)) { |
| 8367 | const_val.data.x_array.elements = allocate<ConstExprValue>(elem_count); | 8489 | TypeTableEntry *pointer_type = container_type->data.structure.fields[slice_ptr_index].type_entry; |
| 8368 | const_val.data.x_array.size = elem_count; | 8490 | assert(pointer_type->id == TypeTableEntryIdPointer); |
| 8491 | TypeTableEntry *child_type = pointer_type->data.pointer.child_type; | ||
| 8369 | 8492 | ||
| 8370 | FnTableEntry *fn_entry = exec_fn_entry(ira->new_irb.exec); | 8493 | ConstExprValue const_val = {}; |
| 8371 | bool outside_fn = (fn_entry == nullptr); | 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; | ||
| 8372 | 8498 | ||
| 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); | ||
| 8374 | 8501 | ||
| 8375 | IrInstruction *first_non_const_instruction = nullptr; | 8502 | IrInstruction **new_items = allocate<IrInstruction *>(elem_count); |
| 8376 | 8503 | ||
| 8377 | for (size_t i = 0; i < elem_count; i += 1) { | 8504 | IrInstruction *first_non_const_instruction = nullptr; |
| 8378 | IrInstruction *arg_value = instruction->items[i]->other; | ||
| 8379 | if (arg_value->type_entry->id == TypeTableEntryIdInvalid) | ||
| 8380 | return ira->codegen->builtin_types.entry_invalid; | ||
| 8381 | 8505 | ||
| 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; | ||
| 8383 | 8510 | ||
| 8384 | if (const_val.special == ConstValSpecialStatic) { | 8511 | new_items[i] = arg_value; |
| 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; | ||
| 8389 | 8512 | ||
| 8390 | const_val.data.x_array.elements[i] = *elem_val; | 8513 | if (const_val.special == ConstValSpecialStatic) { |
| 8391 | const_val.depends_on_compile_var = const_val.depends_on_compile_var || elem_val->depends_on_compile_var; | 8514 | if (outside_fn || arg_value->static_value.special != ConstValSpecialRuntime) { |
| 8392 | } else { | 8515 | ConstExprValue *elem_val = ir_resolve_const(ira, arg_value, UndefBad); |
| 8393 | first_non_const_instruction = arg_value; | 8516 | if (!elem_val) |
| 8394 | const_val.special = ConstValSpecialRuntime; | 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 | } | ||
| 8395 | } | 8525 | } |
| 8396 | } | 8526 | } |
| 8397 | } | ||
| 8398 | 8527 | ||
| 8399 | TypeTableEntry *fixed_size_array_type = get_array_type(ira->codegen, child_type, elem_count); | 8528 | TypeTableEntry *fixed_size_array_type = get_array_type(ira->codegen, child_type, elem_count); |
| 8400 | if (const_val.special == ConstValSpecialStatic) { | 8529 | if (const_val.special == ConstValSpecialStatic) { |
| 8401 | ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base, const_val.depends_on_compile_var); | 8530 | ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base, const_val.depends_on_compile_var); |
| 8402 | *out_val = const_val; | 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); | ||
| 8403 | return fixed_size_array_type; | 8544 | 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; | ||
| 8404 | } | 8560 | } |
| 8405 | 8561 | } else if (container_type_value->type_entry->id == TypeTableEntryIdEnumTag) { | |
| 8406 | if (outside_fn) { | 8562 | // TODO I wrote this commit message when I had some sake |
| 8407 | ir_add_error_node(ira, first_non_const_instruction->source_node, | 8563 | // might be worth re-examining sober |
| 8408 | buf_sprintf("unable to evaluate constant expression")); | 8564 | if (elem_count != 1) { |
| 8565 | ir_add_error(ira, &instruction->base, buf_sprintf("expected 1 elment")); | ||
| 8409 | return ira->codegen->builtin_types.entry_invalid; | 8566 | return ira->codegen->builtin_types.entry_invalid; |
| 8410 | } | 8567 | } |
| 8568 | ConstExprValue *tag_value = ir_resolve_const(ira, container_type_value, UndefBad); | ||
| 8569 | if (!tag_value) | ||
| 8570 | return ira->codegen->builtin_types.entry_invalid; | ||
| 8411 | 8571 | ||
| 8412 | IrInstruction *new_instruction = ir_build_container_init_list_from(&ira->new_irb, &instruction->base, | 8572 | TypeTableEntry *enum_type = container_type_value->type_entry->data.enum_tag.enum_type; |
| 8413 | container_type_value, elem_count, new_items); | 8573 | |
| 8414 | ir_add_alloca(ira, new_instruction, fixed_size_array_type); | 8574 | uint64_t tag_uint = tag_value->data.x_bignum.data.x_uint; |
| 8415 | return fixed_size_array_type; | 8575 | TypeEnumField *field = &enum_type->data.enumeration.fields[tag_uint]; |
| 8416 | } else if (container_type->id == TypeTableEntryIdArray) { | 8576 | TypeTableEntry *this_field_type = field->type_entry; |
| 8417 | // same as slice init but we make a compile error if the length is wrong | 8577 | |
| 8418 | zig_panic("TODO array container init"); | 8578 | IrInstruction *init_value = instruction->items[0]->other; |
| 8419 | } else if (container_type->id == TypeTableEntryIdVoid) { | 8579 | |
| 8420 | if (elem_count != 0) { | 8580 | IrInstruction *casted_init_value = ir_implicit_cast(ira, init_value, this_field_type); |
| 8421 | ir_add_error_node(ira, instruction->base.source_node, | 8581 | if (casted_init_value == ira->codegen->invalid_instruction) |
| 8422 | buf_sprintf("void expression expects no arguments")); | ||
| 8423 | return ira->codegen->builtin_types.entry_invalid; | 8582 | 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; | ||
| 8424 | } | 8593 | } |
| 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; | ||
| 8426 | } else { | 8599 | } else { |
| 8427 | ir_add_error_node(ira, instruction->base.source_node, | 8600 | ir_add_error(ira, container_type_value, |
| 8428 | buf_sprintf("type '%s' does not support array initialization", | 8601 | buf_sprintf("expected type, found '%s'", buf_ptr(&container_type_value->type_entry->name))); |
| 8429 | buf_ptr(&container_type->name))); | ||
| 8430 | return ira->codegen->builtin_types.entry_invalid; | 8602 | return ira->codegen->builtin_types.entry_invalid; |
| 8431 | } | 8603 | } |
| 8432 | } | 8604 | } |
| ... | @@ -8471,6 +8643,8 @@ static TypeTableEntry *ir_analyze_min_max(IrAnalyze *ira, IrInstruction *source_ | ... | @@ -8471,6 +8643,8 @@ static TypeTableEntry *ir_analyze_min_max(IrAnalyze *ira, IrInstruction *source_ |
| 8471 | eval_min_max_value(ira->codegen, canon_type, out_val, is_max); | 8643 | eval_min_max_value(ira->codegen, canon_type, out_val, is_max); |
| 8472 | return target_type; | 8644 | return target_type; |
| 8473 | } | 8645 | } |
| 8646 | case TypeTableEntryIdEnumTag: | ||
| 8647 | zig_panic("TODO min/max value for enum tag type"); | ||
| 8474 | case TypeTableEntryIdVar: | 8648 | case TypeTableEntryIdVar: |
| 8475 | case TypeTableEntryIdMetaType: | 8649 | case TypeTableEntryIdMetaType: |
| 8476 | case TypeTableEntryIdUnreachable: | 8650 | case TypeTableEntryIdUnreachable: |
| ... | @@ -8984,55 +9158,17 @@ static TypeTableEntry *ir_analyze_instruction_alloca(IrAnalyze *ira, IrInstructi | ... | @@ -8984,55 +9158,17 @@ static TypeTableEntry *ir_analyze_instruction_alloca(IrAnalyze *ira, IrInstructi |
| 8984 | return ira->codegen->builtin_types.entry_invalid; | 9158 | return ira->codegen->builtin_types.entry_invalid; |
| 8985 | 9159 | ||
| 8986 | TypeTableEntry *child_type = ir_resolve_type(ira, type_value); | 9160 | TypeTableEntry *child_type = ir_resolve_type(ira, type_value); |
| 8987 | TypeTableEntry *canon_type = get_underlying_type(child_type); | ||
| 8988 | 9161 | ||
| 8989 | if (count_value->static_value.special == ConstValSpecialStatic) { | 9162 | if (type_requires_comptime(child_type)) { |
| 8990 | // this should be the same as an array declaration | 9163 | ir_add_error(ira, type_value, |
| 8991 | 9164 | buf_sprintf("invalid alloca type '%s'", buf_ptr(&child_type->name))); | |
| 8992 | uint64_t count; | 9165 | // TODO if this is a typedecl, add error note showing the declaration of the type decl |
| 8993 | if (!ir_resolve_usize(ira, count_value, &count)) | 9166 | return ira->codegen->builtin_types.entry_invalid; |
| 8994 | return ira->codegen->builtin_types.entry_invalid; | 9167 | } else { |
| 8995 | 9168 | TypeTableEntry *slice_type = get_slice_type(ira->codegen, child_type, false); | |
| 8996 | zig_panic("TODO alloca with compile time known count"); | 9169 | IrInstruction *new_instruction = ir_build_alloca_from(&ira->new_irb, &instruction->base, type_value, count_value); |
| 8997 | } | 9170 | ir_add_alloca(ira, new_instruction, slice_type); |
| 8998 | 9171 | return slice_type; | |
| 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; | ||
| 9036 | } | 9172 | } |
| 9037 | zig_unreachable(); | 9173 | zig_unreachable(); |
| 9038 | } | 9174 | } |
| ... | @@ -9804,6 +9940,7 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi | ... | @@ -9804,6 +9940,7 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi |
| 9804 | case IrInstructionIdStructFieldPtr: | 9940 | case IrInstructionIdStructFieldPtr: |
| 9805 | case IrInstructionIdEnumFieldPtr: | 9941 | case IrInstructionIdEnumFieldPtr: |
| 9806 | case IrInstructionIdStructInit: | 9942 | case IrInstructionIdStructInit: |
| 9943 | case IrInstructionIdInitEnum: | ||
| 9807 | zig_panic("TODO analyze more instructions"); | 9944 | zig_panic("TODO analyze more instructions"); |
| 9808 | } | 9945 | } |
| 9809 | zig_unreachable(); | 9946 | zig_unreachable(); |
| ... | @@ -9959,6 +10096,7 @@ bool ir_has_side_effects(IrInstruction *instruction) { | ... | @@ -9959,6 +10096,7 @@ bool ir_has_side_effects(IrInstruction *instruction) { |
| 9959 | case IrInstructionIdErrWrapPayload: | 10096 | case IrInstructionIdErrWrapPayload: |
| 9960 | case IrInstructionIdFnProto: | 10097 | case IrInstructionIdFnProto: |
| 9961 | case IrInstructionIdTestComptime: | 10098 | case IrInstructionIdTestComptime: |
| 10099 | case IrInstructionIdInitEnum: | ||
| 9962 | return false; | 10100 | return false; |
| 9963 | case IrInstructionIdAsm: | 10101 | case IrInstructionIdAsm: |
| 9964 | { | 10102 | { |
src/ir_print.cpp+16| ... | @@ -183,6 +183,13 @@ static void ir_print_const_value(IrPrint *irp, TypeTableEntry *type_entry, Const | ... | @@ -183,6 +183,13 @@ static void ir_print_const_value(IrPrint *irp, TypeTableEntry *type_entry, Const |
| 183 | fprintf(irp->f, "(pure error constant)"); | 183 | fprintf(irp->f, "(pure error constant)"); |
| 184 | return; | 184 | return; |
| 185 | } | 185 | } |
| 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 | } | ||
| 186 | } | 193 | } |
| 187 | zig_unreachable(); | 194 | zig_unreachable(); |
| 188 | } | 195 | } |
| ... | @@ -911,6 +918,12 @@ static void ir_print_test_comptime(IrPrint *irp, IrInstructionTestComptime *inst | ... | @@ -911,6 +918,12 @@ static void ir_print_test_comptime(IrPrint *irp, IrInstructionTestComptime *inst |
| 911 | fprintf(irp->f, ")"); | 918 | fprintf(irp->f, ")"); |
| 912 | } | 919 | } |
| 913 | 920 | ||
| 921 | static 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 | |||
| 914 | static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) { | 927 | static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) { |
| 915 | ir_print_prefix(irp, instruction); | 928 | ir_print_prefix(irp, instruction); |
| 916 | switch (instruction->id) { | 929 | switch (instruction->id) { |
| ... | @@ -1147,6 +1160,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) { | ... | @@ -1147,6 +1160,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) { |
| 1147 | case IrInstructionIdTestComptime: | 1160 | case IrInstructionIdTestComptime: |
| 1148 | ir_print_test_comptime(irp, (IrInstructionTestComptime *)instruction); | 1161 | ir_print_test_comptime(irp, (IrInstructionTestComptime *)instruction); |
| 1149 | break; | 1162 | break; |
| 1163 | case IrInstructionIdInitEnum: | ||
| 1164 | ir_print_init_enum(irp, (IrInstructionInitEnum *)instruction); | ||
| 1165 | break; | ||
| 1150 | } | 1166 | } |
| 1151 | fprintf(irp->f, "\n"); | 1167 | fprintf(irp->f, "\n"); |
| 1152 | } | 1168 | } |
test/cases3/enum.zig created+37| ... | @@ -0,0 +1,37 @@ | ||
| 1 | fn 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 | } | ||
| 15 | const Point = struct { | ||
| 16 | x: u64, | ||
| 17 | y: u64, | ||
| 18 | }; | ||
| 19 | const Foo = enum { | ||
| 20 | One: i32, | ||
| 21 | Two: Point, | ||
| 22 | Three: void, | ||
| 23 | }; | ||
| 24 | const Bar = enum { | ||
| 25 | A, | ||
| 26 | B, | ||
| 27 | C, | ||
| 28 | D, | ||
| 29 | }; | ||
| 30 | |||
| 31 | fn assert(ok: bool) { | ||
| 32 | if (!ok) | ||
| 33 | @unreachable(); | ||
| 34 | } | ||
| 35 | |||
| 36 | |||
| 37 | |||
test/self_hosted.zig-35| ... | @@ -333,41 +333,6 @@ fn maybeType() { | ... | @@ -333,41 +333,6 @@ fn maybeType() { |
| 333 | } | 333 | } |
| 334 | 334 | ||
| 335 | 335 | ||
| 336 | fn 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 | } | ||
| 354 | struct EnumType { | ||
| 355 | x: u64, | ||
| 356 | y: u64, | ||
| 357 | } | ||
| 358 | enum EnumTypeFoo { | ||
| 359 | One: i32, | ||
| 360 | Two: EnumType, | ||
| 361 | Three: void, | ||
| 362 | } | ||
| 363 | enum EnumTypeBar { | ||
| 364 | A, | ||
| 365 | B, | ||
| 366 | C, | ||
| 367 | D, | ||
| 368 | } | ||
| 369 | |||
| 370 | |||
| 371 | fn arrayLiteral() { | 336 | fn arrayLiteral() { |
| 372 | @setFnTest(this, true); | 337 | @setFnTest(this, true); |
| 373 | 338 |
test/self_hosted3.zig+1| ... | @@ -8,3 +8,4 @@ const test_for = @import("cases3/for.zig"); | ... | @@ -8,3 +8,4 @@ const test_for = @import("cases3/for.zig"); |
| 8 | const test_math = @import("cases3/math.zig"); | 8 | const test_math = @import("cases3/math.zig"); |
| 9 | const test_generics = @import("cases3/generics.zig"); | 9 | const test_generics = @import("cases3/generics.zig"); |
| 10 | const test_defer = @import("cases3/defer.zig"); | 10 | const test_defer = @import("cases3/defer.zig"); |
| 11 | const test_enum = @import("cases3/enum.zig"); |