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...@@ -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};
850850
851struct TypeTableEntryEnumTag {
852 TypeTableEntry *enum_type;
853 TypeTableEntry *int_type;
854};
855
851struct TypeTableEntryUnion {856struct 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};
14561464
1457struct IrInstruction {1465struct IrInstruction {
...@@ -2078,6 +2086,15 @@ struct IrInstructionTestComptime {...@@ -2078,6 +2086,15 @@ struct IrInstructionTestComptime {
2078 IrInstruction *value;2086 IrInstruction *value;
2079};2087};
20802088
2089struct IrInstructionInitEnum {
2090 IrInstruction base;
2091
2092 TypeTableEntry *enum_type;
2093 TypeEnumField *field;
2094 IrInstruction *init_value;
2095 LLVMValueRef tmp_ptr;
2096};
2097
2081enum LValPurpose {2098enum 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;
682681 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 }
688682
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 }
10381034
1039 return get_fn_type(g, &fn_type_id);1035 return get_fn_type(g, &fn_type_id);
1040}1036}
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
1042static void resolve_enum_type(CodeGen *g, TypeTableEntry *enum_type) {1053static void resolve_enum_type(CodeGen *g, TypeTableEntry *enum_type) {
1043 // if you change this logic you likely must also change similar logic in parseh.cpp1054 // 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;
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);
1138 enum_type->data.enumeration.tag_type = tag_type_entry;1150 enum_type->data.enumeration.tag_type = tag_type_entry;
11391151
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;
18941908
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}
28012821
2802bool type_requires_comptime(TypeTableEntry *type_entry) {2822bool 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}
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);...@@ -77,6 +77,8 @@ bool type_requires_comptime(TypeTableEntry *type_entry);
77void ensure_complete_type(CodeGen *g, TypeTableEntry *type_entry);77void ensure_complete_type(CodeGen *g, TypeTableEntry *type_entry);
78void complete_enum(CodeGen *g, TypeTableEntry *enum_type);78void complete_enum(CodeGen *g, TypeTableEntry *enum_type);
79bool ir_get_var_is_comptime(VariableTableEntry *var);79bool 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
81ScopeBlock *create_block_scope(AstNode *node, Scope *parent);83ScopeBlock *create_block_scope(AstNode *node, Scope *parent);
82ScopeDefer *create_defer_scope(AstNode *node, Scope *parent);84ScopeDefer *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}
21462146
2147static LLVMValueRef ir_render_init_enum(CodeGen *g, IrExecutable *executable, IrInstructionInitEnum *instruction) {
2148 zig_panic("TODO ir_render_init_enum");
2149}
2150
2147static void set_debug_location(CodeGen *g, IrInstruction *instruction) {2151static 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
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 @@...@@ -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}
449448
449static constexpr IrInstructionId ir_instruction_id(IrInstructionInitEnum *) {
450 return IrInstructionIdInitEnum;
451}
452
450template<typename T>453template<typename T>
451static T *ir_create_instruction(IrExecutable *exec, Scope *scope, AstNode *source_node) {454static 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}
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
1864static void ir_count_defers(IrBuilder *irb, Scope *inner_scope, Scope *outer_scope, size_t *results) {1889static 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}
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}
4599static IrInstruction *ir_resolve_cast(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value,4708static 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;
55645673
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 // OK6190 // 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 expression7502 // 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 var7902 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/838213 // 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
83478472
8348static TypeTableEntry *ir_analyze_instruction_container_init_list(IrAnalyze *ira, IrInstructionContainerInitList *instruction) {8473static 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;
83538477
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;
83568483
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;
83638485
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;
83698492
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;
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) {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;
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) {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;
83898512
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 }
83988527
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 }
84058561 } 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;
84118571
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 wrong8577
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;
89859159
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);
89889161
8989 if (count_value->static_value.special == ConstValSpecialStatic) {9162 if (type_requires_comptime(child_type)) {
8990 // this should be the same as an array declaration9163 ir_add_error(ira, type_value,
89919164 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 {
89959168 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);
89989171 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}
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
914static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {927static 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 @@
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() {...@@ -333,41 +333,6 @@ fn maybeType() {
333}333}
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
371fn arrayLiteral() {336fn arrayLiteral() {
372 @setFnTest(this, true);337 @setFnTest(this, true);
373338
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");
8const test_math = @import("cases3/math.zig");8const test_math = @import("cases3/math.zig");
9const test_generics = @import("cases3/generics.zig");9const test_generics = @import("cases3/generics.zig");
10const test_defer = @import("cases3/defer.zig");10const test_defer = @import("cases3/defer.zig");
11const test_enum = @import("cases3/enum.zig");