authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-11-17 04:00:02-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-11-17 04:00:02-05:00
log62d0d88b56b909cf9f9f7a78a8222acd0f37b6cb
treec61b610a3c43bad96f28cc46385f2843c2dd2633
parenta55555c99e9bcc1424c8650ab44570caf593bcdc

IR: pointers to constants don't copy data


8 files changed, 263 insertions(+), 313 deletions(-)

src/all_types.hpp+21-14
......@@ -51,17 +51,24 @@ struct ConstEnumValue {
5151};
5252
5353struct ConstStructValue {
54 ConstExprValue **fields;
54 ConstExprValue *fields;
5555};
5656
5757struct ConstArrayValue {
58 ConstExprValue **fields;
58 ConstExprValue *elements;
59 // This will be the same as `len` from the type, but we duplicate the information
60 // in the constant value so that pointers pointing to arrays can see this size.
61 size_t size;
5962};
6063
6164struct ConstPtrValue {
62 ConstExprValue **ptr;
63 // len should almost always be 1. exceptions include C strings
64 uint64_t len;
65 ConstExprValue *base_ptr;
66 // If index is SIZE_MAX, then base_ptr points directly to child type.
67 // Otherwise base_ptr points to an array const val and index is offset
68 // in object units from base_ptr into the block of memory pointed to
69 size_t index;
70 // This flag helps us preserve the null byte when performing compile-time
71 // concatenation on C strings.
6572 bool is_c_str;
6673};
6774
......@@ -71,15 +78,17 @@ struct ConstErrValue {
7178};
7279
7380enum ConstValSpecial {
74 ConstValSpecialOther,
81 ConstValSpecialRuntime,
82 ConstValSpecialStatic,
7583 ConstValSpecialUndef,
7684 ConstValSpecialZeroes,
7785};
7886
7987struct ConstExprValue {
80 bool ok;
81 bool depends_on_compile_var;
8288 ConstValSpecial special;
89 bool depends_on_compile_var;
90 LLVMValueRef llvm_value;
91 LLVMValueRef llvm_global;
8392
8493 // populated if val_type == ConstValTypeOk
8594 union {
......@@ -108,13 +117,9 @@ enum ReturnKnowledge {
108117};
109118
110119struct Expr {
111 TypeTableEntry *type_entry;
120 IrInstruction *instruction;
112121 ReturnKnowledge return_knowledge;
113122 VariableTableEntry *variable;
114
115 LLVMValueRef const_llvm_val;
116 ConstExprValue const_val;
117 bool has_global_const;
118123};
119124
120125struct StructValExprCodeGen {
......@@ -1289,7 +1294,6 @@ struct CodeGen {
12891294 // there will not be a corresponding fn_defs entry.
12901295 ZigList<FnTableEntry *> fn_protos;
12911296 ZigList<VariableTableEntry *> global_vars;
1292 ZigList<AstNode *> global_const_list;
12931297
12941298 OutType out_type;
12951299 FnTableEntry *cur_fn;
......@@ -1733,4 +1737,7 @@ enum LValPurpose {
17331737 LValPurposeConstAddressOf,
17341738};
17351739
1740static const size_t slice_ptr_index = 0;
1741static const size_t slice_len_index = 1;
1742
17361743#endif
src/analyze.cpp+21-20
......@@ -882,7 +882,7 @@ static TypeTableEntry *analyze_type_expr_pointer_only(CodeGen *g, ImportTableEnt
882882 if (result->type_entry->id == TypeTableEntryIdInvalid)
883883 return g->builtin_types.entry_invalid;
884884
885 assert(result->static_value.ok);
885 assert(result->static_value.special != ConstValSpecialRuntime);
886886 return result->static_value.data.x_type;
887887}
888888
......@@ -1963,9 +1963,8 @@ static void resolve_var_decl(CodeGen *g, ImportTableEntry *import, AstNode *node
19631963 }
19641964 if (implicit_type->id != TypeTableEntryIdInvalid) {
19651965 Expr *expr = get_resolved_expr(var_decl->expr);
1966 assert(result->static_value.ok);
1967 expr->const_val = result->static_value;
1968 expr->type_entry = result->type_entry;
1966 assert(result->static_value.special != ConstValSpecialRuntime);
1967 expr->instruction = result;
19691968 }
19701969 } else if (!is_extern) {
19711970 add_node_error(g, node, buf_sprintf("variables must be initialized"));
......@@ -2132,8 +2131,8 @@ static bool num_lit_fits_in_other_type(CodeGen *g, AstNode *literal_node, TypeTa
21322131 }
21332132
21342133 Expr *expr = get_resolved_expr(literal_node);
2135 ConstExprValue *const_val = &expr->const_val;
2136 assert(const_val->ok);
2134 ConstExprValue *const_val = &expr->instruction->static_value;
2135 assert(const_val->special != ConstValSpecialRuntime);
21372136 if (other_type_underlying->id == TypeTableEntryIdFloat) {
21382137 return true;
21392138 } else if (other_type_underlying->id == TypeTableEntryIdInt &&
......@@ -2600,15 +2599,15 @@ static void add_symbols_from_import(CodeGen *g, AstNode *src_use_node, AstNode *
26002599 AstNode *use_target_node = src_use_node->data.use.expr;
26012600 Expr *expr = get_resolved_expr(use_target_node);
26022601
2603 if (expr->type_entry->id == TypeTableEntryIdInvalid) {
2602 if (expr->instruction->type_entry->id == TypeTableEntryIdInvalid) {
26042603 tld->import->any_imports_failed = true;
26052604 return;
26062605 }
26072606
26082607 tld->resolution = TldResolutionOk;
26092608
2610 ConstExprValue *const_val = &expr->const_val;
2611 assert(const_val->ok);
2609 ConstExprValue *const_val = &expr->instruction->static_value;
2610 assert(const_val->special != ConstValSpecialRuntime);
26122611
26132612 ImportTableEntry *target_import = const_val->data.x_import;
26142613 assert(target_import);
......@@ -3031,10 +3030,11 @@ void find_libc_lib_path(CodeGen *g) {
30313030}
30323031
30333032static uint32_t hash_ptr(void *ptr) {
3034 uint64_t x = (uint64_t)(uintptr_t)(ptr);
3035 uint32_t a = x >> 32;
3036 uint32_t b = x & 0xffffffff;
3037 return a ^ b;
3033 return ((uintptr_t)ptr) % UINT32_MAX;
3034}
3035
3036static uint32_t hash_size(size_t x) {
3037 return x % UINT32_MAX;
30383038}
30393039
30403040uint32_t fn_type_id_hash(FnTypeId *id) {
......@@ -3090,7 +3090,7 @@ static uint32_t hash_const_val(TypeTableEntry *type, ConstExprValue *const_val)
30903090 case TypeTableEntryIdNumLitFloat:
30913091 return const_val->data.x_bignum.data.x_float * UINT32_MAX;
30923092 case TypeTableEntryIdPointer:
3093 return hash_ptr(const_val->data.x_ptr.ptr);
3093 return hash_ptr(const_val->data.x_ptr.base_ptr) + hash_size(const_val->data.x_ptr.index);
30943094 case TypeTableEntryIdUndefLit:
30953095 return 162837799;
30963096 case TypeTableEntryIdNullLit:
......@@ -3143,8 +3143,8 @@ uint32_t generic_fn_type_id_hash(GenericFnTypeId *id) {
31433143 for (size_t i = 0; i < id->generic_param_count; i += 1) {
31443144 GenericParamValue *generic_param = &id->generic_params[i];
31453145 if (generic_param->node) {
3146 ConstExprValue *const_val = &get_resolved_expr(generic_param->node)->const_val;
3147 assert(const_val->ok);
3146 ConstExprValue *const_val = &get_resolved_expr(generic_param->node)->instruction->static_value;
3147 assert(const_val->special != ConstValSpecialRuntime);
31483148 result += hash_const_val(generic_param->type, const_val);
31493149 }
31503150 result += hash_ptr(generic_param->type);
......@@ -3160,10 +3160,10 @@ bool generic_fn_type_id_eql(GenericFnTypeId *a, GenericFnTypeId *b) {
31603160 GenericParamValue *b_val = &b->generic_params[i];
31613161 if (a_val->type != b_val->type) return false;
31623162 if (a_val->node && b_val->node) {
3163 ConstExprValue *a_const_val = &get_resolved_expr(a_val->node)->const_val;
3164 ConstExprValue *b_const_val = &get_resolved_expr(b_val->node)->const_val;
3165 assert(a_const_val->ok);
3166 assert(b_const_val->ok);
3163 ConstExprValue *a_const_val = &get_resolved_expr(a_val->node)->instruction->static_value;
3164 ConstExprValue *b_const_val = &get_resolved_expr(b_val->node)->instruction->static_value;
3165 assert(a_const_val->special != ConstValSpecialRuntime);
3166 assert(b_const_val->special != ConstValSpecialRuntime);
31673167 if (!const_values_equal(a_const_val, b_const_val, a_val->type)) {
31683168 return false;
31693169 }
......@@ -3237,3 +3237,4 @@ uint64_t get_memcpy_align(CodeGen *g, TypeTableEntry *type_entry) {
32373237 return LLVMABISizeOfType(g->target_data_ref, first_type_in_mem->type_ref);
32383238}
32393239
3240
src/codegen.cpp+69-81
......@@ -226,7 +226,8 @@ void codegen_set_rdynamic(CodeGen *g, bool rdynamic) {
226226 g->linker_rdynamic = rdynamic;
227227}
228228
229static LLVMValueRef gen_const_val(CodeGen *g, TypeTableEntry *type_entry, ConstExprValue *const_val);
229static void render_const_val(CodeGen *g, TypeTableEntry *type_entry, ConstExprValue *const_val);
230static void render_const_val_global(CodeGen *g, TypeTableEntry *type_entry, ConstExprValue *const_val);
230231
231232static void set_debug_source_node(CodeGen *g, AstNode *node) {
232233 assert(node->block_context);
......@@ -862,11 +863,17 @@ static LLVMValueRef ir_llvm_value(CodeGen *g, IrInstruction *instruction) {
862863 if (!type_has_bits(instruction->type_entry))
863864 return nullptr;
864865 if (!instruction->llvm_value) {
865 assert(instruction->static_value.ok);
866 assert(instruction->static_value.special != ConstValSpecialRuntime);
866867 assert(instruction->type_entry);
867 instruction->llvm_value = gen_const_val(g, instruction->type_entry, &instruction->static_value);
868 render_const_val(g, instruction->type_entry, &instruction->static_value);
869 instruction->llvm_value = instruction->static_value.llvm_value;
868870 assert(instruction->llvm_value);
869871 }
872 if (instruction->static_value.special != ConstValSpecialRuntime) {
873 if (instruction->type_entry->id == TypeTableEntryIdPointer) {
874 return LLVMBuildLoad(g->builder, instruction->static_value.llvm_global, "");
875 }
876 }
870877 return instruction->llvm_value;
871878}
872879
......@@ -1401,9 +1408,9 @@ static LLVMValueRef ir_render_decl_var(CodeGen *g, IrExecutable *executable,
14011408 bool want_zeroes = false;
14021409
14031410 ConstExprValue *const_val = &init_value->static_value;
1404 if (!const_val->ok || const_val->special == ConstValSpecialOther)
1411 if (const_val->special == ConstValSpecialRuntime || const_val->special == ConstValSpecialStatic)
14051412 have_init_expr = true;
1406 if (const_val->ok && const_val->special == ConstValSpecialZeroes)
1413 if (const_val->special == ConstValSpecialZeroes)
14071414 want_zeroes = true;
14081415
14091416 if (have_init_expr) {
......@@ -1740,14 +1747,14 @@ static void ir_render(CodeGen *g, FnTableEntry *fn_entry) {
17401747}
17411748
17421749static LLVMValueRef gen_const_val(CodeGen *g, TypeTableEntry *type_entry, ConstExprValue *const_val) {
1743 assert(const_val->ok);
1744
17451750 switch (const_val->special) {
1751 case ConstValSpecialRuntime:
1752 zig_unreachable();
17461753 case ConstValSpecialUndef:
17471754 return LLVMGetUndef(type_entry->type_ref);
17481755 case ConstValSpecialZeroes:
17491756 return LLVMConstNull(type_entry->type_ref);
1750 case ConstValSpecialOther:
1757 case ConstValSpecialStatic:
17511758 break;
17521759
17531760 }
......@@ -1814,7 +1821,7 @@ static LLVMValueRef gen_const_val(CodeGen *g, TypeTableEntry *type_entry, ConstE
18141821 continue;
18151822 }
18161823 fields[type_struct_field->gen_index] = gen_const_val(g, type_struct_field->type_entry,
1817 const_val->data.x_struct.fields[i]);
1824 &const_val->data.x_struct.fields[i]);
18181825 }
18191826 return LLVMConstNamedStruct(type_entry->type_ref, fields,
18201827 type_entry->data.structure.gen_field_count);
......@@ -1829,8 +1836,8 @@ static LLVMValueRef gen_const_val(CodeGen *g, TypeTableEntry *type_entry, ConstE
18291836 uint64_t len = type_entry->data.array.len;
18301837 LLVMValueRef *values = allocate<LLVMValueRef>(len);
18311838 for (uint64_t i = 0; i < len; i += 1) {
1832 ConstExprValue *field_value = const_val->data.x_array.fields[i];
1833 values[i] = gen_const_val(g, child_type, field_value);
1839 ConstExprValue *elem_value = &const_val->data.x_array.elements[i];
1840 values[i] = gen_const_val(g, child_type, elem_value);
18341841 }
18351842 return LLVMConstArray(child_type->type_ref, values, len);
18361843 }
......@@ -1878,29 +1885,26 @@ static LLVMValueRef gen_const_val(CodeGen *g, TypeTableEntry *type_entry, ConstE
18781885 case TypeTableEntryIdPointer:
18791886 {
18801887 TypeTableEntry *child_type = type_entry->data.pointer.child_type;
1881 size_t len = const_val->data.x_ptr.len;
1882 LLVMValueRef target_val;
1883 if (len == 1) {
1884 target_val = gen_const_val(g, child_type, const_val->data.x_ptr.ptr[0]);
1885 } else if (len > 1) {
1886 LLVMValueRef *values = allocate<LLVMValueRef>(len);
1887 for (size_t i = 0; i < len; i += 1) {
1888 values[i] = gen_const_val(g, child_type, const_val->data.x_ptr.ptr[i]);
1889 }
1890 target_val = LLVMConstArray(child_type->type_ref, values, len);
1891 } else {
1892 return LLVMGetUndef(type_entry->type_ref);
1893 }
1894 LLVMValueRef global_value = LLVMAddGlobal(g->module, LLVMTypeOf(target_val), "");
1895 LLVMSetInitializer(global_value, target_val);
1896 LLVMSetLinkage(global_value, LLVMPrivateLinkage);
1897 LLVMSetGlobalConstant(global_value, type_entry->data.pointer.is_const);
1898 LLVMSetUnnamedAddr(global_value, true);
1899
1900 if (len > 1) {
1901 return LLVMConstBitCast(global_value, type_entry->type_ref);
1888
1889 render_const_val_global(g, type_entry, const_val);
1890 size_t index = const_val->data.x_ptr.index;
1891 if (index == SIZE_MAX) {
1892 render_const_val(g, child_type, const_val->data.x_ptr.base_ptr);
1893 render_const_val_global(g, child_type, const_val->data.x_ptr.base_ptr);
1894 return const_val->data.x_ptr.base_ptr->llvm_global;
19021895 } else {
1903 return global_value;
1896 ConstExprValue *array_const_val = const_val->data.x_ptr.base_ptr;
1897 TypeTableEntry *array_type = get_array_type(g, child_type,
1898 array_const_val->data.x_array.size);
1899 render_const_val(g, array_type, array_const_val);
1900 render_const_val_global(g, array_type, array_const_val);
1901 TypeTableEntry *usize = g->builtin_types.entry_usize;
1902 LLVMValueRef indices[] = {
1903 LLVMConstNull(usize->type_ref),
1904 LLVMConstInt(usize->type_ref, index, false),
1905 };
1906 LLVMValueRef ptr_val = LLVMConstInBoundsGEP(array_const_val->llvm_global, indices, 2);
1907 return ptr_val;
19041908 }
19051909 }
19061910 case TypeTableEntryIdErrorUnion:
......@@ -1945,27 +1949,26 @@ static LLVMValueRef gen_const_val(CodeGen *g, TypeTableEntry *type_entry, ConstE
19451949 zig_unreachable();
19461950}
19471951
1948static void gen_const_globals(CodeGen *g) {
1949 for (size_t i = 0; i < g->global_const_list.length; i += 1) {
1950 AstNode *expr_node = g->global_const_list.at(i);
1951 Expr *expr = get_resolved_expr(expr_node);
1952 ConstExprValue *const_val = &expr->const_val;
1953 assert(const_val->ok);
1954 TypeTableEntry *type_entry = expr->type_entry;
1955
1956 if (handle_is_ptr(type_entry)) {
1957 LLVMValueRef init_val = gen_const_val(g, type_entry, const_val);
1958 LLVMValueRef global_value = LLVMAddGlobal(g->module, LLVMTypeOf(init_val), "");
1959 LLVMSetInitializer(global_value, init_val);
1960 LLVMSetLinkage(global_value, LLVMPrivateLinkage);
1961 LLVMSetGlobalConstant(global_value, true);
1962 LLVMSetUnnamedAddr(global_value, true);
1963 expr->const_llvm_val = global_value;
1964 } else {
1965 expr->const_llvm_val = gen_const_val(g, type_entry, const_val);
1966 }
1967 assert(expr->const_llvm_val);
1952static void render_const_val(CodeGen *g, TypeTableEntry *type_entry, ConstExprValue *const_val) {
1953 if (!const_val->llvm_value)
1954 const_val->llvm_value = gen_const_val(g, type_entry, const_val);
1955
1956 if (const_val->llvm_global)
1957 LLVMSetInitializer(const_val->llvm_global, const_val->llvm_value);
1958}
1959
1960static void render_const_val_global(CodeGen *g, TypeTableEntry *type_entry, ConstExprValue *const_val) {
1961 if (!const_val->llvm_global) {
1962 LLVMValueRef global_value = LLVMAddGlobal(g->module, type_entry->type_ref, "");
1963 LLVMSetLinkage(global_value, LLVMInternalLinkage);
1964 LLVMSetGlobalConstant(global_value, true);
1965 LLVMSetUnnamedAddr(global_value, true);
1966
1967 const_val->llvm_global = global_value;
19681968 }
1969
1970 if (const_val->llvm_value)
1971 LLVMSetInitializer(const_val->llvm_global, const_val->llvm_value);
19691972}
19701973
19711974static void delete_unused_builtin_fns(CodeGen *g) {
......@@ -2096,9 +2099,6 @@ static void do_code_gen(CodeGen *g) {
20962099 assert(!g->errors.length);
20972100
20982101 delete_unused_builtin_fns(g);
2099
2100
2101 gen_const_globals(g);
21022102 generate_error_name_table(g);
21032103
21042104 // Generate module level variables
......@@ -2107,8 +2107,8 @@ static void do_code_gen(CodeGen *g) {
21072107
21082108 if (var->type->id == TypeTableEntryIdNumLitFloat) {
21092109 // Generate debug info for it but that's it.
2110 ConstExprValue *const_val = &get_resolved_expr(var->val_node)->const_val;
2111 assert(const_val->ok);
2110 ConstExprValue *const_val = &get_resolved_expr(var->val_node)->instruction->static_value;
2111 assert(const_val->special != ConstValSpecialRuntime);
21122112 TypeTableEntry *var_type = g->builtin_types.entry_f64;
21132113 LLVMValueRef init_val = LLVMConstReal(var_type->type_ref, const_val->data.x_bignum.data.x_float);
21142114 gen_global_var(g, var, init_val, var_type);
......@@ -2117,8 +2117,8 @@ static void do_code_gen(CodeGen *g) {
21172117
21182118 if (var->type->id == TypeTableEntryIdNumLitInt) {
21192119 // Generate debug info for it but that's it.
2120 ConstExprValue *const_val = &get_resolved_expr(var->val_node)->const_val;
2121 assert(const_val->ok);
2120 ConstExprValue *const_val = &get_resolved_expr(var->val_node)->instruction->static_value;
2121 assert(const_val->special != ConstValSpecialRuntime);
21222122 TypeTableEntry *var_type = const_val->data.x_bignum.is_negative ?
21232123 g->builtin_types.entry_isize : g->builtin_types.entry_usize;
21242124 LLVMValueRef init_val = LLVMConstInt(var_type->type_ref,
......@@ -2143,25 +2143,13 @@ static void do_code_gen(CodeGen *g) {
21432143 LLVMSetLinkage(global_value, LLVMExternalLinkage);
21442144 } else {
21452145 AstNode *expr_node = var->decl_node->data.variable_declaration.expr;
2146 LLVMValueRef init_val;
2147 if (expr_node) {
2148 Expr *expr = get_resolved_expr(expr_node);
2149 ConstExprValue *const_val = &expr->const_val;
2150 assert(const_val->ok);
2151 TypeTableEntry *type_entry = expr->type_entry;
2152 init_val = gen_const_val(g, type_entry, const_val);
2153 } else {
2154 init_val = LLVMConstNull(var->type->type_ref);
2155 }
2156
2157 global_value = LLVMAddGlobal(g->module, LLVMTypeOf(init_val), buf_ptr(&var->name));
2158 LLVMSetInitializer(global_value, init_val);
2159 LLVMSetLinkage(global_value, LLVMInternalLinkage);
2160 LLVMSetUnnamedAddr(global_value, true);
2161
2146 IrInstruction *instruction = get_resolved_expr(expr_node)->instruction;
2147 render_const_val(g, instruction->type_entry, &instruction->static_value);
2148 render_const_val_global(g, instruction->type_entry, &instruction->static_value);
2149 global_value = instruction->static_value.llvm_global;
21622150 // TODO debug info for function pointers
21632151 if (var->gen_is_const && var->type->id != TypeTableEntryIdFn) {
2164 gen_global_var(g, var, init_val, var->type);
2152 gen_global_var(g, var, instruction->static_value.llvm_value, var->type);
21652153 }
21662154 }
21672155
......@@ -3282,11 +3270,11 @@ static void get_c_type(CodeGen *g, TypeTableEntry *type_entry, Buf *out_buf) {
32823270
32833271static void get_c_type_node(CodeGen *g, AstNode *type_node, Buf *out_buf) {
32843272 Expr *expr = get_resolved_expr(type_node);
3285 assert(expr->type_entry);
3286 assert(expr->type_entry->id == TypeTableEntryIdMetaType);
3273 assert(expr->instruction->type_entry);
3274 assert(expr->instruction->type_entry->id == TypeTableEntryIdMetaType);
32873275
3288 ConstExprValue *const_val = &expr->const_val;
3289 assert(const_val->ok);
3276 ConstExprValue *const_val = &expr->instruction->static_value;
3277 assert(const_val->special != ConstValSpecialRuntime);
32903278
32913279 TypeTableEntry *type_entry = const_val->data.x_type;
32923280
src/eval.cpp+20-99
......@@ -147,7 +147,7 @@ static int eval_const_expr_bin_op_bignum(ConstExprValue *op1_val, ConstExprValue
147147 }
148148 }
149149
150 out_val->ok = true;
150 out_val->special = ConstValSpecialStatic;
151151 out_val->depends_on_compile_var = op1_val->depends_on_compile_var || op2_val->depends_on_compile_var;
152152 return 0;
153153}
......@@ -155,8 +155,8 @@ static int eval_const_expr_bin_op_bignum(ConstExprValue *op1_val, ConstExprValue
155155int eval_const_expr_bin_op(ConstExprValue *op1_val, TypeTableEntry *op1_type,
156156 BinOpType bin_op, ConstExprValue *op2_val, TypeTableEntry *op2_type, ConstExprValue *out_val)
157157{
158 assert(op1_val->ok);
159 assert(op2_val->ok);
158 assert(op1_val->special != ConstValSpecialRuntime);
159 assert(op2_val->special != ConstValSpecialRuntime);
160160 assert(op1_type->id != TypeTableEntryIdInvalid);
161161 assert(op2_type->id != TypeTableEntryIdInvalid);
162162
......@@ -171,7 +171,7 @@ int eval_const_expr_bin_op(ConstExprValue *op1_val, TypeTableEntry *op1_type,
171171 assert(op1_type->id == TypeTableEntryIdBool);
172172 assert(op2_type->id == TypeTableEntryIdBool);
173173 out_val->data.x_bool = eval_bool_bin_op_bool(op1_val->data.x_bool, bin_op, op2_val->data.x_bool);
174 out_val->ok = true;
174 out_val->special = ConstValSpecialStatic;
175175 out_val->depends_on_compile_var = op1_val->depends_on_compile_var || op2_val->depends_on_compile_var;
176176 return 0;
177177 case BinOpTypeCmpEq:
......@@ -219,7 +219,7 @@ int eval_const_expr_bin_op(ConstExprValue *op1_val, TypeTableEntry *op1_type,
219219 out_val->depends_on_compile_var =
220220 op1_val->depends_on_compile_var || op2_val->depends_on_compile_var;
221221 out_val->data.x_bool = answer;
222 out_val->ok = true;
222 out_val->special = ConstValSpecialStatic;
223223 return 0;
224224 }
225225 case BinOpTypeAdd:
......@@ -309,67 +309,7 @@ void eval_const_expr_implicit_cast(CastOp cast_op,
309309 *const_val = *other_val;
310310 break;
311311 case CastOpPointerReinterpret:
312 if (other_type->id == TypeTableEntryIdPointer &&
313 new_type->id == TypeTableEntryIdPointer)
314 {
315 TypeTableEntry *other_child_type = other_type->data.pointer.child_type;
316 TypeTableEntry *new_child_type = new_type->data.pointer.child_type;
317
318 if ((other_child_type->id == TypeTableEntryIdInt ||
319 other_child_type->id == TypeTableEntryIdFloat) &&
320 (new_child_type->id == TypeTableEntryIdInt ||
321 new_child_type->id == TypeTableEntryIdFloat))
322 {
323 ConstExprValue **ptr_val = allocate<ConstExprValue*>(1);
324 *ptr_val = other_val->data.x_ptr.ptr[0];
325 const_val->data.x_ptr.ptr = ptr_val;
326 const_val->data.x_ptr.len = 1;
327 const_val->ok = true;
328 const_val->special = other_val->special;
329 const_val->depends_on_compile_var = other_val->depends_on_compile_var;
330 } else {
331 zig_panic("TODO");
332 }
333 } else if (other_type->id == TypeTableEntryIdMaybe &&
334 new_type->id == TypeTableEntryIdMaybe)
335 {
336 if (!other_val->data.x_maybe) {
337 *const_val = *other_val;
338 break;
339 }
340
341 TypeTableEntry *other_ptr_type = other_type->data.maybe.child_type;
342 TypeTableEntry *new_ptr_type = new_type->data.maybe.child_type;
343
344 if (other_ptr_type->id == TypeTableEntryIdPointer &&
345 new_ptr_type->id == TypeTableEntryIdPointer)
346 {
347 TypeTableEntry *other_child_type = other_ptr_type->data.pointer.child_type;
348 TypeTableEntry *new_child_type = new_ptr_type->data.pointer.child_type;
349
350 if ((other_child_type->id == TypeTableEntryIdInt ||
351 other_child_type->id == TypeTableEntryIdFloat) &&
352 (new_child_type->id == TypeTableEntryIdInt ||
353 new_child_type->id == TypeTableEntryIdFloat))
354 {
355 ConstExprValue *ptr_parent = allocate<ConstExprValue>(1);
356 ConstExprValue **ptr_val = allocate<ConstExprValue*>(1);
357 *ptr_val = other_val->data.x_maybe->data.x_ptr.ptr[0];
358 ptr_parent->data.x_ptr.ptr = ptr_val;
359 ptr_parent->data.x_ptr.len = 1;
360 ptr_parent->ok = true;
361
362 const_val->data.x_maybe = ptr_parent;
363 const_val->ok = true;
364 const_val->special = other_val->special;
365 const_val->depends_on_compile_var = other_val->depends_on_compile_var;
366 } else {
367 zig_panic("TODO");
368 }
369 } else {
370 zig_panic("TODO");
371 }
372 }
312 zig_panic("TODO compile time pointer reinterpret");
373313 break;
374314 case CastOpPtrToInt:
375315 case CastOpIntToPtr:
......@@ -378,62 +318,43 @@ void eval_const_expr_implicit_cast(CastOp cast_op,
378318 // can't do it
379319 break;
380320 case CastOpToUnknownSizeArray:
381 {
382 assert(other_type->id == TypeTableEntryIdArray);
383
384 ConstExprValue *all_fields = allocate<ConstExprValue>(2);
385 ConstExprValue *ptr_field = &all_fields[0];
386 ConstExprValue *len_field = &all_fields[1];
387
388 const_val->data.x_struct.fields = allocate<ConstExprValue*>(2);
389 const_val->data.x_struct.fields[0] = ptr_field;
390 const_val->data.x_struct.fields[1] = len_field;
391
392 ptr_field->ok = true;
393 ptr_field->data.x_ptr.ptr = other_val->data.x_array.fields;
394 ptr_field->data.x_ptr.len = other_type->data.array.len;
395
396 len_field->ok = true;
397 bignum_init_unsigned(&len_field->data.x_bignum, other_type->data.array.len);
398
399 const_val->ok = true;
400 break;
401 }
321 zig_panic("TODO compile time implicit to unknown size array");
322 break;
402323 case CastOpMaybeWrap:
403324 const_val->data.x_maybe = other_val;
404 const_val->ok = true;
325 const_val->special = ConstValSpecialStatic;
405326 break;
406327 case CastOpNullToMaybe:
407328 const_val->data.x_maybe = nullptr;
408 const_val->ok = true;
329 const_val->special = ConstValSpecialStatic;
409330 break;
410331 case CastOpErrorWrap:
411332 const_val->data.x_err.err = nullptr;
412333 const_val->data.x_err.payload = other_val;
413 const_val->ok = true;
334 const_val->special = ConstValSpecialStatic;
414335 break;
415336 case CastOpPureErrorWrap:
416337 const_val->data.x_err.err = other_val->data.x_err.err;
417 const_val->ok = true;
338 const_val->special = ConstValSpecialStatic;
418339 break;
419340 case CastOpErrToInt:
420341 {
421342 uint64_t value = other_val->data.x_err.err ? other_val->data.x_err.err->value : 0;
422343 bignum_init_unsigned(&const_val->data.x_bignum, value);
423 const_val->ok = true;
344 const_val->special = ConstValSpecialStatic;
424345 break;
425346 }
426347 case CastOpIntToFloat:
427348 bignum_cast_to_float(&const_val->data.x_bignum, &other_val->data.x_bignum);
428 const_val->ok = true;
349 const_val->special = ConstValSpecialStatic;
429350 break;
430351 case CastOpFloatToInt:
431352 bignum_cast_to_int(&const_val->data.x_bignum, &other_val->data.x_bignum);
432 const_val->ok = true;
353 const_val->special = ConstValSpecialStatic;
433354 break;
434355 case CastOpBoolToInt:
435356 bignum_init_unsigned(&const_val->data.x_bignum, other_val->data.x_bool ? 1 : 0);
436 const_val->ok = true;
357 const_val->special = ConstValSpecialStatic;
437358 break;
438359 case CastOpIntToEnum:
439360 {
......@@ -442,12 +363,12 @@ void eval_const_expr_implicit_cast(CastOp cast_op,
442363 assert(value < new_type->data.enumeration.src_field_count);
443364 const_val->data.x_enum.tag = value;
444365 const_val->data.x_enum.payload = NULL;
445 const_val->ok = true;
366 const_val->special = ConstValSpecialStatic;
446367 break;
447368 }
448369 case CastOpEnumToInt:
449370 bignum_init_unsigned(&const_val->data.x_bignum, other_val->data.x_enum.tag);
450 const_val->ok = true;
371 const_val->special = ConstValSpecialStatic;
451372 break;
452373 }
453374}
......@@ -465,7 +386,7 @@ static bool int_type_depends_on_compile_var(CodeGen *g, TypeTableEntry *int_type
465386
466387void eval_min_max_value(CodeGen *g, TypeTableEntry *type_entry, ConstExprValue *const_val, bool is_max) {
467388 if (type_entry->id == TypeTableEntryIdInt) {
468 const_val->ok = true;
389 const_val->special = ConstValSpecialStatic;
469390 const_val->depends_on_compile_var = int_type_depends_on_compile_var(g, type_entry);
470391 if (is_max) {
471392 if (type_entry->data.integral.is_signed) {
......@@ -486,7 +407,7 @@ void eval_min_max_value(CodeGen *g, TypeTableEntry *type_entry, ConstExprValue *
486407 } else if (type_entry->id == TypeTableEntryIdFloat) {
487408 zig_panic("TODO analyze_min_max_value float");
488409 } else if (type_entry->id == TypeTableEntryIdBool) {
489 const_val->ok = true;
410 const_val->special = ConstValSpecialStatic;
490411 const_val->data.x_bool = is_max;
491412 } else {
492413 zig_unreachable();
src/ir.cpp+125-94
......@@ -35,6 +35,18 @@ static IrInstruction *ir_gen_node_extra(IrBuilder *irb, AstNode *node, BlockCont
3535 LValPurpose lval);
3636static TypeTableEntry *ir_analyze_instruction(IrAnalyze *ira, IrInstruction *instruction);
3737
38ConstExprValue *const_ptr_pointee(ConstExprValue *const_val) {
39 ConstExprValue *base_ptr = const_val->data.x_ptr.base_ptr;
40 size_t index = const_val->data.x_ptr.index;
41
42 if (index == SIZE_MAX) {
43 return base_ptr;
44 } else {
45 assert(index < base_ptr->data.x_array.size);
46 return &base_ptr->data.x_array.elements[index];
47 }
48}
49
3850static void ir_instruction_append(IrBasicBlock *basic_block, IrInstruction *instruction) {
3951 assert(basic_block);
4052 assert(instruction);
......@@ -237,7 +249,7 @@ static IrInstruction *ir_build_cond_br(IrBuilder *irb, AstNode *source_node, IrI
237249{
238250 IrInstructionCondBr *cond_br_instruction = ir_build_instruction<IrInstructionCondBr>(irb, source_node);
239251 cond_br_instruction->base.type_entry = irb->codegen->builtin_types.entry_unreachable;
240 cond_br_instruction->base.static_value.ok = true;
252 cond_br_instruction->base.static_value.special = ConstValSpecialStatic;
241253 cond_br_instruction->condition = condition;
242254 cond_br_instruction->then_block = then_block;
243255 cond_br_instruction->else_block = else_block;
......@@ -262,7 +274,7 @@ static IrInstruction *ir_build_cond_br_from(IrBuilder *irb, IrInstruction *old_i
262274static IrInstruction *ir_build_return(IrBuilder *irb, AstNode *source_node, IrInstruction *return_value) {
263275 IrInstructionReturn *return_instruction = ir_build_instruction<IrInstructionReturn>(irb, source_node);
264276 return_instruction->base.type_entry = irb->codegen->builtin_types.entry_unreachable;
265 return_instruction->base.static_value.ok = true;
277 return_instruction->base.static_value.special = ConstValSpecialStatic;
266278 return_instruction->value = return_value;
267279
268280 ir_ref_instruction(return_value);
......@@ -281,20 +293,19 @@ static IrInstruction *ir_build_return_from(IrBuilder *irb, IrInstruction *old_in
281293static IrInstruction *ir_create_const(IrBuilder *irb, AstNode *source_node, TypeTableEntry *type_entry) {
282294 IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(irb->exec, source_node);
283295 const_instruction->base.type_entry = type_entry;
284 const_instruction->base.static_value.ok = true;
296 const_instruction->base.static_value.special = ConstValSpecialStatic;
285297 return &const_instruction->base;
286298}
287299
288300static IrInstruction *ir_build_const_void(IrBuilder *irb, AstNode *source_node) {
289301 IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irb, source_node);
290302 const_instruction->base.type_entry = irb->codegen->builtin_types.entry_void;
291 const_instruction->base.static_value.ok = true;
303 const_instruction->base.static_value.special = ConstValSpecialStatic;
292304 return &const_instruction->base;
293305}
294306
295307static IrInstruction *ir_build_const_undefined(IrBuilder *irb, AstNode *source_node) {
296308 IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irb, source_node);
297 const_instruction->base.static_value.ok = true;
298309 const_instruction->base.static_value.special = ConstValSpecialUndef;
299310 const_instruction->base.type_entry = irb->codegen->builtin_types.entry_undef;
300311 return &const_instruction->base;
......@@ -304,7 +315,7 @@ static IrInstruction *ir_build_const_bignum(IrBuilder *irb, AstNode *source_node
304315 IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irb, source_node);
305316 const_instruction->base.type_entry = (bignum->kind == BigNumKindInt) ?
306317 irb->codegen->builtin_types.entry_num_lit_int : irb->codegen->builtin_types.entry_num_lit_float;
307 const_instruction->base.static_value.ok = true;
318 const_instruction->base.static_value.special = ConstValSpecialStatic;
308319 const_instruction->base.static_value.data.x_bignum = *bignum;
309320 return &const_instruction->base;
310321}
......@@ -312,7 +323,7 @@ static IrInstruction *ir_build_const_bignum(IrBuilder *irb, AstNode *source_node
312323static IrInstruction *ir_build_const_usize(IrBuilder *irb, AstNode *source_node, uint64_t value) {
313324 IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irb, source_node);
314325 const_instruction->base.type_entry = irb->codegen->builtin_types.entry_usize;
315 const_instruction->base.static_value.ok = true;
326 const_instruction->base.static_value.special = ConstValSpecialStatic;
316327 bignum_init_unsigned(&const_instruction->base.static_value.data.x_bignum, value);
317328 return &const_instruction->base;
318329}
......@@ -320,7 +331,7 @@ static IrInstruction *ir_build_const_usize(IrBuilder *irb, AstNode *source_node,
320331static IrInstruction *ir_create_const_type(IrBuilder *irb, AstNode *source_node, TypeTableEntry *type_entry) {
321332 IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(irb->exec, source_node);
322333 const_instruction->base.type_entry = irb->codegen->builtin_types.entry_type;
323 const_instruction->base.static_value.ok = true;
334 const_instruction->base.static_value.special = ConstValSpecialStatic;
324335 const_instruction->base.static_value.data.x_type = type_entry;
325336 return &const_instruction->base;
326337}
......@@ -334,7 +345,7 @@ static IrInstruction *ir_build_const_type(IrBuilder *irb, AstNode *source_node,
334345static IrInstruction *ir_build_const_fn(IrBuilder *irb, AstNode *source_node, FnTableEntry *fn_entry) {
335346 IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irb, source_node);
336347 const_instruction->base.type_entry = fn_entry->type_entry;
337 const_instruction->base.static_value.ok = true;
348 const_instruction->base.static_value.special = ConstValSpecialStatic;
338349 const_instruction->base.static_value.data.x_fn = fn_entry;
339350 return &const_instruction->base;
340351}
......@@ -342,7 +353,7 @@ static IrInstruction *ir_build_const_fn(IrBuilder *irb, AstNode *source_node, Fn
342353static IrInstruction *ir_build_const_generic_fn(IrBuilder *irb, AstNode *source_node, TypeTableEntry *fn_type) {
343354 IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irb, source_node);
344355 const_instruction->base.type_entry = fn_type;
345 const_instruction->base.static_value.ok = true;
356 const_instruction->base.static_value.special = ConstValSpecialStatic;
346357 const_instruction->base.static_value.data.x_type = fn_type;
347358 return &const_instruction->base;
348359}
......@@ -350,7 +361,7 @@ static IrInstruction *ir_build_const_generic_fn(IrBuilder *irb, AstNode *source_
350361static IrInstruction *ir_build_const_import(IrBuilder *irb, AstNode *source_node, ImportTableEntry *import) {
351362 IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irb, source_node);
352363 const_instruction->base.type_entry = irb->codegen->builtin_types.entry_namespace;
353 const_instruction->base.static_value.ok = true;
364 const_instruction->base.static_value.special = ConstValSpecialStatic;
354365 const_instruction->base.static_value.data.x_import = import;
355366 return &const_instruction->base;
356367}
......@@ -358,7 +369,7 @@ static IrInstruction *ir_build_const_import(IrBuilder *irb, AstNode *source_node
358369static IrInstruction *ir_build_const_scope(IrBuilder *irb, AstNode *source_node, BlockContext *scope) {
359370 IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irb, source_node);
360371 const_instruction->base.type_entry = irb->codegen->builtin_types.entry_block;
361 const_instruction->base.static_value.ok = true;
372 const_instruction->base.static_value.special = ConstValSpecialStatic;
362373 const_instruction->base.static_value.data.x_block = scope;
363374 return &const_instruction->base;
364375}
......@@ -366,7 +377,7 @@ static IrInstruction *ir_build_const_scope(IrBuilder *irb, AstNode *source_node,
366377static IrInstruction *ir_build_const_bool(IrBuilder *irb, AstNode *source_node, bool value) {
367378 IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irb, source_node);
368379 const_instruction->base.type_entry = irb->codegen->builtin_types.entry_bool;
369 const_instruction->base.static_value.ok = true;
380 const_instruction->base.static_value.special = ConstValSpecialStatic;
370381 const_instruction->base.static_value.data.x_bool = value;
371382 return &const_instruction->base;
372383}
......@@ -377,45 +388,45 @@ static IrInstruction *ir_build_const_str_lit(IrBuilder *irb, AstNode *source_nod
377388 TypeTableEntry *type_entry = get_array_type(irb->codegen, u8_type, buf_len(str));
378389 const_instruction->base.type_entry = type_entry;
379390 ConstExprValue *const_val = &const_instruction->base.static_value;
380 const_val->ok = true;
381 const_val->data.x_array.fields = allocate<ConstExprValue*>(buf_len(str));
391 const_val->special = ConstValSpecialStatic;
392 const_val->data.x_array.elements = allocate<ConstExprValue>(buf_len(str));
393 const_val->data.x_array.size = buf_len(str);
382394
383 ConstExprValue *all_chars = allocate<ConstExprValue>(buf_len(str));
384395 for (size_t i = 0; i < buf_len(str); i += 1) {
385 ConstExprValue *this_char = &all_chars[i];
386 this_char->ok = true;
396 ConstExprValue *this_char = &const_val->data.x_array.elements[i];
397 this_char->special = ConstValSpecialStatic;
387398 bignum_init_unsigned(&this_char->data.x_bignum, buf_ptr(str)[i]);
388 const_val->data.x_array.fields[i] = this_char;
389399 }
390400
391401 return &const_instruction->base;
392402}
393403
394404static IrInstruction *ir_build_const_c_str_lit(IrBuilder *irb, AstNode *source_node, Buf *str) {
395 IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irb, source_node);
396 TypeTableEntry *u8_type = irb->codegen->builtin_types.entry_u8;
397 TypeTableEntry *type_entry = get_pointer_to_type(irb->codegen, u8_type, true);
398 const_instruction->base.type_entry = type_entry;
399 ConstExprValue *const_val = &const_instruction->base.static_value;
400 const_val->ok = true;
401
405 // first we build the underlying array
402406 size_t len_with_null = buf_len(str) + 1;
403 const_val->data.x_ptr.ptr = allocate<ConstExprValue*>(len_with_null);
404 const_val->data.x_ptr.len = len_with_null;
405 const_val->data.x_ptr.is_c_str = true;
406
407 ConstExprValue *all_chars = allocate<ConstExprValue>(len_with_null);
407 ConstExprValue *array_val = allocate<ConstExprValue>(1);
408 array_val->special = ConstValSpecialStatic;
409 array_val->data.x_array.elements = allocate<ConstExprValue>(len_with_null);
410 array_val->data.x_array.size = len_with_null;
408411 for (size_t i = 0; i < buf_len(str); i += 1) {
409 ConstExprValue *this_char = &all_chars[i];
410 this_char->ok = true;
412 ConstExprValue *this_char = &array_val->data.x_array.elements[i];
413 this_char->special = ConstValSpecialStatic;
411414 bignum_init_unsigned(&this_char->data.x_bignum, buf_ptr(str)[i]);
412 const_val->data.x_ptr.ptr[i] = this_char;
413415 }
414
415 ConstExprValue *null_char = &all_chars[len_with_null - 1];
416 null_char->ok = true;
416 ConstExprValue *null_char = &array_val->data.x_array.elements[len_with_null - 1];
417 null_char->special = ConstValSpecialStatic;
417418 bignum_init_unsigned(&null_char->data.x_bignum, 0);
418 const_val->data.x_ptr.ptr[len_with_null - 1] = null_char;
419
420 // then make the pointer point to it
421 IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irb, source_node);
422 TypeTableEntry *u8_type = irb->codegen->builtin_types.entry_u8;
423 TypeTableEntry *type_entry = get_pointer_to_type(irb->codegen, u8_type, true);
424 const_instruction->base.type_entry = type_entry;
425 ConstExprValue *ptr_val = &const_instruction->base.static_value;
426 ptr_val->special = ConstValSpecialStatic;
427 ptr_val->data.x_ptr.base_ptr = array_val;
428 ptr_val->data.x_ptr.index = 0;
429 ptr_val->data.x_ptr.is_c_str = true;
419430
420431 return &const_instruction->base;
421432}
......@@ -591,7 +602,7 @@ static IrInstruction *ir_build_phi_from(IrBuilder *irb, IrInstruction *old_instr
591602static IrInstruction *ir_build_br(IrBuilder *irb, AstNode *source_node, IrBasicBlock *dest_block, bool is_inline) {
592603 IrInstructionBr *br_instruction = ir_build_instruction<IrInstructionBr>(irb, source_node);
593604 br_instruction->base.type_entry = irb->codegen->builtin_types.entry_unreachable;
594 br_instruction->base.static_value.ok = true;
605 br_instruction->base.static_value.special = ConstValSpecialStatic;
595606 br_instruction->dest_block = dest_block;
596607 br_instruction->is_inline = is_inline;
597608
......@@ -662,7 +673,7 @@ static IrInstruction *ir_build_container_init_fields(IrBuilder *irb, AstNode *so
662673static IrInstruction *ir_build_unreachable(IrBuilder *irb, AstNode *source_node) {
663674 IrInstructionUnreachable *unreachable_instruction =
664675 ir_build_instruction<IrInstructionUnreachable>(irb, source_node);
665 unreachable_instruction->base.static_value.ok = true;
676 unreachable_instruction->base.static_value.special = ConstValSpecialStatic;
666677 unreachable_instruction->base.type_entry = irb->codegen->builtin_types.entry_unreachable;
667678 return &unreachable_instruction->base;
668679}
......@@ -677,7 +688,7 @@ static IrInstruction *ir_build_store_ptr(IrBuilder *irb, AstNode *source_node,
677688 IrInstruction *ptr, IrInstruction *value)
678689{
679690 IrInstructionStorePtr *instruction = ir_build_instruction<IrInstructionStorePtr>(irb, source_node);
680 instruction->base.static_value.ok = true;
691 instruction->base.static_value.special = ConstValSpecialStatic;
681692 instruction->base.type_entry = irb->codegen->builtin_types.entry_void;
682693 instruction->ptr = ptr;
683694 instruction->value = value;
......@@ -700,7 +711,7 @@ static IrInstruction *ir_build_var_decl(IrBuilder *irb, AstNode *source_node,
700711 VariableTableEntry *var, IrInstruction *var_type, IrInstruction *init_value)
701712{
702713 IrInstructionDeclVar *decl_var_instruction = ir_build_instruction<IrInstructionDeclVar>(irb, source_node);
703 decl_var_instruction->base.static_value.ok = true;
714 decl_var_instruction->base.static_value.special = ConstValSpecialStatic;
704715 decl_var_instruction->base.type_entry = irb->codegen->builtin_types.entry_void;
705716 decl_var_instruction->var = var;
706717 decl_var_instruction->var_type = var_type;
......@@ -1900,7 +1911,7 @@ static bool ir_num_lit_fits_in_other_type(IrAnalyze *ira, IrInstruction *instruc
19001911 }
19011912
19021913 ConstExprValue *const_val = &instruction->static_value;
1903 assert(const_val->ok);
1914 assert(const_val->special != ConstValSpecialRuntime);
19041915 if (other_type_underlying->id == TypeTableEntryIdFloat) {
19051916 return true;
19061917 } else if (other_type_underlying->id == TypeTableEntryIdInt &&
......@@ -2110,10 +2121,10 @@ static IrInstruction *ir_resolve_cast(IrAnalyze *ira, IrInstruction *source_inst
21102121 IrInstruction *dest_type, CastOp cast_op, bool need_alloca)
21112122{
21122123 assert(dest_type->type_entry->id == TypeTableEntryIdMetaType);
2113 assert(dest_type->static_value.ok);
2124 assert(dest_type->static_value.special != ConstValSpecialRuntime);
21142125 TypeTableEntry *wanted_type = dest_type->static_value.data.x_type;
21152126
2116 if (value->static_value.ok) {
2127 if (value->static_value.special != ConstValSpecialRuntime) {
21172128 IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->source_node, wanted_type);
21182129 eval_const_expr_implicit_cast(cast_op, &value->static_value, value->type_entry,
21192130 &result->static_value, wanted_type);
......@@ -2194,7 +2205,7 @@ static ConstExprValue *ir_build_const_from(IrAnalyze *ira, IrInstruction *old_in
21942205 }
21952206 ir_link_new_instruction(new_instruction, old_instruction);
21962207 ConstExprValue *const_val = &new_instruction->static_value;
2197 const_val->ok = true;
2208 const_val->special = ConstValSpecialStatic;
21982209 const_val->depends_on_compile_var = depends_on_compile_var;
21992210 return const_val;
22002211}
......@@ -2226,7 +2237,7 @@ static TypeTableEntry *ir_resolve_type(IrAnalyze *ira, IrInstruction *type_value
22262237 }
22272238
22282239 ConstExprValue *const_val = &type_value->static_value;
2229 if (!const_val->ok) {
2240 if (const_val->special == ConstValSpecialRuntime) {
22302241 add_node_error(ira->codegen, type_value->source_node,
22312242 buf_sprintf("unable to evaluate constant expression"));
22322243 return ira->codegen->builtin_types.entry_invalid;
......@@ -2249,7 +2260,7 @@ static bool ir_resolve_bool(IrAnalyze *ira, IrInstruction *bool_value, bool *out
22492260 }
22502261
22512262 ConstExprValue *const_val = &bool_value->static_value;
2252 if (!const_val->ok) {
2263 if (const_val->special == ConstValSpecialRuntime) {
22532264 add_node_error(ira->codegen, bool_value->source_node,
22542265 buf_sprintf("unable to evaluate constant expression"));
22552266 return false;
......@@ -2273,7 +2284,7 @@ static FnTableEntry *ir_resolve_fn(IrAnalyze *ira, IrInstruction *fn_value) {
22732284 }
22742285
22752286 ConstExprValue *const_val = &fn_value->static_value;
2276 if (!const_val->ok) {
2287 if (const_val->special == ConstValSpecialRuntime) {
22772288 add_node_error(ira->codegen, fn_value->source_node,
22782289 buf_sprintf("unable to evaluate constant expression"));
22792290 return nullptr;
......@@ -2286,7 +2297,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
22862297 IrInstruction *dest_type, IrInstruction *value)
22872298{
22882299 assert(dest_type->type_entry->id == TypeTableEntryIdMetaType);
2289 assert(dest_type->static_value.ok);
2300 assert(dest_type->static_value.special != ConstValSpecialRuntime);
22902301
22912302 TypeTableEntry *wanted_type = dest_type->static_value.data.x_type;
22922303 TypeTableEntry *actual_type = value->type_entry;
......@@ -2618,7 +2629,7 @@ static TypeTableEntry *ir_analyze_bin_op_bool(IrAnalyze *ira, IrInstructionBinOp
26182629
26192630 ConstExprValue *op1_val = &casted_op1->static_value;
26202631 ConstExprValue *op2_val = &casted_op2->static_value;
2621 if (op1_val->ok && op2_val->ok) {
2632 if (op1_val->special != ConstValSpecialRuntime && op2_val->special != ConstValSpecialRuntime) {
26222633 bool depends_on_compile_var = op1_val->depends_on_compile_var || op2_val->depends_on_compile_var;
26232634 ConstExprValue *out_val = ir_build_const_from(ira, &bin_op_instruction->base, depends_on_compile_var);
26242635
......@@ -2710,7 +2721,7 @@ static TypeTableEntry *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp
27102721
27112722 ConstExprValue *op1_val = &casted_op1->static_value;
27122723 ConstExprValue *op2_val = &casted_op2->static_value;
2713 if (op1_val->ok && op2_val->ok) {
2724 if (op1_val->special != ConstValSpecialRuntime && op2_val->special != ConstValSpecialRuntime) {
27142725 bool type_can_gt_lt_cmp = (resolved_type->id == TypeTableEntryIdNumLitFloat ||
27152726 resolved_type->id == TypeTableEntryIdNumLitInt ||
27162727 resolved_type->id == TypeTableEntryIdFloat ||
......@@ -2799,7 +2810,7 @@ static int ir_eval_bignum(ConstExprValue *op1_val, ConstExprValue *op2_val,
27992810 }
28002811 }
28012812
2802 out_val->ok = true;
2813 out_val->special = ConstValSpecialStatic;
28032814 out_val->depends_on_compile_var = op1_val->depends_on_compile_var || op2_val->depends_on_compile_var;
28042815 return 0;
28052816}
......@@ -2892,7 +2903,7 @@ static TypeTableEntry *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp
28922903 return ira->codegen->builtin_types.entry_invalid;
28932904
28942905
2895 if (casted_op1->static_value.ok && casted_op2->static_value.ok) {
2906 if (casted_op1->static_value.special != ConstValSpecialRuntime && casted_op2->static_value.special != ConstValSpecialRuntime) {
28962907 ConstExprValue *op1_val = &casted_op1->static_value;
28972908 ConstExprValue *op2_val = &casted_op2->static_value;
28982909 ConstExprValue *out_val = &bin_op_instruction->base.static_value;
......@@ -2992,7 +3003,7 @@ static TypeTableEntry *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruc
29923003 break;
29933004 case TypeTableEntryIdNumLitFloat:
29943005 case TypeTableEntryIdNumLitInt:
2995 if (is_export || is_extern || !casted_init_value->static_value.ok) {
3006 if (is_export || is_extern || casted_init_value->static_value.special == ConstValSpecialRuntime) {
29963007 add_node_error(ira->codegen, var_type->source_node, buf_sprintf("unable to infer variable type"));
29973008 result_type = ira->codegen->builtin_types.entry_invalid;
29983009 }
......@@ -3006,7 +3017,7 @@ static TypeTableEntry *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruc
30063017 break;
30073018 case TypeTableEntryIdMetaType:
30083019 case TypeTableEntryIdNamespace:
3009 if (!casted_init_value->static_value.ok) {
3020 if (casted_init_value->static_value.special == ConstValSpecialRuntime) {
30103021 add_node_error(ira->codegen, var_type->source_node,
30113022 buf_sprintf("variable of type '%s' must be constant", buf_ptr(&result_type->name)));
30123023 result_type = ira->codegen->builtin_types.entry_invalid;
......@@ -3052,7 +3063,7 @@ static TypeTableEntry *ir_analyze_instruction_call(IrAnalyze *ira, IrInstruction
30523063 if (fn_ref->type_entry->id == TypeTableEntryIdInvalid)
30533064 return ira->codegen->builtin_types.entry_invalid;
30543065
3055 if (fn_ref->static_value.ok) {
3066 if (fn_ref->static_value.special != ConstValSpecialRuntime) {
30563067 if (fn_ref->type_entry->id == TypeTableEntryIdMetaType) {
30573068 size_t actual_param_count = call_instruction->arg_count;
30583069
......@@ -3106,9 +3117,9 @@ static TypeTableEntry *ir_analyze_unary_bool_not(IrAnalyze *ira, IrInstructionUn
31063117 return ira->codegen->builtin_types.entry_invalid;
31073118
31083119 ConstExprValue *operand_val = &casted_value->static_value;
3109 if (operand_val->ok) {
3120 if (operand_val->special != ConstValSpecialRuntime) {
31103121 ConstExprValue *result_val = &un_op_instruction->base.static_value;
3111 result_val->ok = true;
3122 result_val->special = ConstValSpecialStatic;
31123123 result_val->depends_on_compile_var = operand_val->depends_on_compile_var;
31133124 result_val->data.x_bool = !operand_val->data.x_bool;
31143125 return bool_type;
......@@ -3204,7 +3215,7 @@ static TypeTableEntry *ir_analyze_unary_address_of(IrAnalyze *ira, IrInstruction
32043215 {
32053216 ConstExprValue *out_val = ir_build_const_from(ira, &un_op_instruction->base,
32063217 value->static_value.depends_on_compile_var);
3207 assert(value->static_value.ok);
3218 assert(value->static_value.special != ConstValSpecialRuntime);
32083219 TypeTableEntry *child_type = value->static_value.data.x_type;
32093220 out_val->data.x_type = get_pointer_to_type(ira->codegen, child_type, is_const);
32103221 return ira->codegen->builtin_types.entry_type;
......@@ -3252,9 +3263,10 @@ static TypeTableEntry *ir_analyze_dereference(IrAnalyze *ira, IrInstructionUnOp
32523263 // this dereference is always an rvalue because in the IR gen we identify lvalue and emit
32533264 // one of the ptr instructions
32543265
3255 if (value->static_value.ok) {
3266 if (value->static_value.special != ConstValSpecialRuntime) {
32563267 ConstExprValue *out_val = ir_build_const_from(ira, &un_op_instruction->base, false);
3257 *out_val = *value->static_value.data.x_ptr.ptr[0];
3268 ConstExprValue *pointee = const_ptr_pointee(&value->static_value);
3269 *out_val = *pointee;
32583270 return child_type;
32593271 }
32603272
......@@ -3428,7 +3440,7 @@ static TypeTableEntry *ir_analyze_instruction_cond_br(IrAnalyze *ira, IrInstruct
34283440 return ir_finish_anal(ira, ira->codegen->builtin_types.entry_unreachable);
34293441
34303442 // TODO detect backward jumps
3431 if (condition->static_value.ok) {
3443 if (condition->static_value.special != ConstValSpecialRuntime) {
34323444 IrBasicBlock *old_dest_block = condition->static_value.data.x_bool ?
34333445 cond_br_instruction->then_block : cond_br_instruction->else_block;
34343446
......@@ -3463,7 +3475,7 @@ static TypeTableEntry *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionP
34633475 continue;
34643476 IrInstruction *value = phi_instruction->incoming_values[i]->other;
34653477 assert(value->type_entry);
3466 if (value->static_value.ok) {
3478 if (value->static_value.special != ConstValSpecialRuntime) {
34673479 ConstExprValue *out_val = ir_build_const_from(ira, &phi_instruction->base,
34683480 value->static_value.depends_on_compile_var);
34693481 *out_val = value->static_value;
......@@ -3523,17 +3535,16 @@ static TypeTableEntry *ir_analyze_instruction_var_ptr(IrAnalyze *ira, IrInstruct
35233535 } else if (var->src_is_const) {
35243536 AstNode *var_decl_node = var->decl_node;
35253537 assert(var_decl_node->type == NodeTypeVariableDeclaration);
3526 mem_slot = &get_resolved_expr(var_decl_node->data.variable_declaration.expr)->const_val;
3527 assert(mem_slot->ok);
3538 mem_slot = &get_resolved_expr(var_decl_node->data.variable_declaration.expr)->instruction->static_value;
3539 assert(mem_slot->special != ConstValSpecialRuntime);
35283540 }
35293541
3530 if (mem_slot && mem_slot->ok) {
3542 if (mem_slot && mem_slot->special != ConstValSpecialRuntime) {
35313543 ConstExprValue *out_val = ir_build_const_from(ira, &var_ptr_instruction->base,
35323544 mem_slot->depends_on_compile_var);
35333545
3534 out_val->data.x_ptr.len = 1;
3535 out_val->data.x_ptr.ptr = allocate<ConstExprValue *>(1);
3536 out_val->data.x_ptr.ptr[0] = mem_slot;
3546 out_val->data.x_ptr.base_ptr = mem_slot;
3547 out_val->data.x_ptr.index = SIZE_MAX;
35373548 return ptr_type;
35383549 } else {
35393550 ir_build_var_ptr_from(&ira->new_irb, &var_ptr_instruction->base, var);
......@@ -3577,7 +3588,7 @@ static TypeTableEntry *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruc
35773588 if (casted_elem_index == ira->codegen->invalid_instruction)
35783589 return ira->codegen->builtin_types.entry_invalid;
35793590
3580 if (casted_elem_index->static_value.ok) {
3591 if (casted_elem_index->static_value.special != ConstValSpecialRuntime) {
35813592 uint64_t index = casted_elem_index->static_value.data.x_bignum.data.x_uint;
35823593 if (array_type->id == TypeTableEntryIdArray) {
35833594 uint64_t array_len = array_type->data.array.len;
......@@ -3589,24 +3600,34 @@ static TypeTableEntry *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruc
35893600 }
35903601 }
35913602
3592 if (array_ptr->static_value.ok) {
3603 if (array_ptr->static_value.special != ConstValSpecialRuntime) {
35933604 bool depends_on_compile_var = array_ptr->static_value.depends_on_compile_var ||
35943605 casted_elem_index->static_value.depends_on_compile_var;
35953606 ConstExprValue *out_val = ir_build_const_from(ira, &elem_ptr_instruction->base, depends_on_compile_var);
3596 out_val->data.x_ptr.len = 1;
3597 out_val->data.x_ptr.ptr = allocate<ConstExprValue *>(1);
35983607 if (array_type->id == TypeTableEntryIdPointer) {
3599 uint64_t pointer_len = array_ptr->static_value.data.x_ptr.len;
3600 if (index >= pointer_len) {
3608 size_t offset = array_ptr->static_value.data.x_ptr.index;
3609 size_t new_index;
3610 size_t mem_size;
3611 size_t old_size;
3612 if (offset == SIZE_MAX) {
3613 new_index = SIZE_MAX;
3614 mem_size = 1;
3615 old_size = 1;
3616 } else {
3617 new_index = offset + index;
3618 mem_size = array_ptr->static_value.data.x_ptr.base_ptr->data.x_array.size;
3619 old_size = mem_size - offset;
3620 }
3621 if (new_index >= mem_size) {
36013622 add_node_error(ira->codegen, elem_ptr_instruction->base.source_node,
3602 buf_sprintf("index %" PRIu64 " outside pointer of size %" PRIu64,
3603 index, pointer_len));
3623 buf_sprintf("index %" PRIu64 " outside pointer of size %" PRIu64, index, old_size));
36043624 return ira->codegen->builtin_types.entry_invalid;
36053625 }
3606 out_val->data.x_ptr.ptr[0] = array_ptr->static_value.data.x_ptr.ptr[index];
3626 out_val->data.x_ptr.base_ptr = array_ptr->static_value.data.x_ptr.base_ptr;
3627 out_val->data.x_ptr.index = new_index;
36073628 } else if (is_slice(array_type)) {
3608 ConstExprValue *ptr_field = array_ptr->static_value.data.x_struct.fields[0];
3609 ConstExprValue *len_field = array_ptr->static_value.data.x_struct.fields[1];
3629 ConstExprValue *ptr_field = &array_ptr->static_value.data.x_struct.fields[slice_ptr_index];
3630 ConstExprValue *len_field = &array_ptr->static_value.data.x_struct.fields[slice_len_index];
36103631 uint64_t slice_len = len_field->data.x_bignum.data.x_uint;
36113632 if (index >= slice_len) {
36123633 add_node_error(ira->codegen, elem_ptr_instruction->base.source_node,
......@@ -3614,10 +3635,18 @@ static TypeTableEntry *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruc
36143635 index, slice_len));
36153636 return ira->codegen->builtin_types.entry_invalid;
36163637 }
3617 assert(index < ptr_field->data.x_ptr.len);
3618 out_val->data.x_ptr.ptr[0] = ptr_field->data.x_ptr.ptr[index];
3638 out_val->data.x_ptr.base_ptr = ptr_field->data.x_ptr.base_ptr;
3639 size_t offset = ptr_field->data.x_ptr.index;
3640 if (offset == SIZE_MAX) {
3641 out_val->data.x_ptr.index = SIZE_MAX;
3642 } else {
3643 uint64_t new_index = offset + index;
3644 assert(new_index < ptr_field->data.x_ptr.base_ptr->data.x_array.size);
3645 out_val->data.x_ptr.index = new_index;
3646 }
36193647 } else if (array_type->id == TypeTableEntryIdArray) {
3620 out_val->data.x_ptr.ptr[0] = array_ptr->static_value.data.x_array.fields[index];
3648 out_val->data.x_ptr.base_ptr = &array_ptr->static_value;
3649 out_val->data.x_ptr.index = index;
36213650 } else {
36223651 zig_unreachable();
36233652 }
......@@ -3790,9 +3819,9 @@ static TypeTableEntry *ir_analyze_instruction_load_ptr(IrAnalyze *ira, IrInstruc
37903819 return type_entry;
37913820 } else if (type_entry->id == TypeTableEntryIdPointer) {
37923821 TypeTableEntry *child_type = type_entry->data.pointer.child_type;
3793 if (ptr->static_value.ok) {
3794 ConstExprValue *pointee = ptr->static_value.data.x_ptr.ptr[0];
3795 if (pointee->ok) {
3822 if (ptr->static_value.special != ConstValSpecialRuntime) {
3823 ConstExprValue *pointee = const_ptr_pointee(&ptr->static_value);
3824 if (pointee->special != ConstValSpecialRuntime) {
37963825 ConstExprValue *out_val = ir_build_const_from(ira, &load_ptr_instruction->base,
37973826 pointee->depends_on_compile_var);
37983827 *out_val = *pointee;
......@@ -3823,18 +3852,20 @@ static TypeTableEntry *ir_analyze_instruction_store_ptr(IrAnalyze *ira, IrInstru
38233852 if (casted_value == ira->codegen->invalid_instruction)
38243853 return ira->codegen->builtin_types.entry_invalid;
38253854
3826 if (ptr->static_value.ok && casted_value->static_value.ok) {
3827 ConstExprValue *dest_val = ptr->static_value.data.x_ptr.ptr[0];
3828 if (dest_val->ok) {
3855 if (ptr->static_value.special != ConstValSpecialRuntime &&
3856 casted_value->static_value.special != ConstValSpecialRuntime)
3857 {
3858 ConstExprValue *dest_val = const_ptr_pointee(&ptr->static_value);
3859 if (dest_val->special != ConstValSpecialRuntime) {
38293860 *dest_val = casted_value->static_value;
38303861 return ir_analyze_void(ira, &store_ptr_instruction->base);
38313862 }
38323863 }
38333864
3834 if (ptr->static_value.ok) {
3865 if (ptr->static_value.special != ConstValSpecialRuntime) {
38353866 // This memory location is transforming from known at compile time to known at runtime.
38363867 // We must emit our own var ptr instruction.
3837 ptr->static_value.ok = false;
3868 ptr->static_value.special = ConstValSpecialRuntime;
38383869 IrInstruction *new_ptr_inst;
38393870 if (ptr->id == IrInstructionIdVarPtr) {
38403871 IrInstructionVarPtr *var_ptr_inst = (IrInstructionVarPtr *)ptr;
......@@ -3842,7 +3873,7 @@ static TypeTableEntry *ir_analyze_instruction_store_ptr(IrAnalyze *ira, IrInstru
38423873 new_ptr_inst = ir_build_var_ptr(&ira->new_irb, store_ptr_instruction->base.source_node, var);
38433874 assert(var->mem_slot_index != SIZE_MAX);
38443875 ConstExprValue *mem_slot = &ira->exec_context.mem_slot_list[var->mem_slot_index];
3845 mem_slot->ok = false;
3876 mem_slot->special = ConstValSpecialRuntime;
38463877 } else if (ptr->id == IrInstructionIdFieldPtr) {
38473878 zig_panic("TODO");
38483879 } else if (ptr->id == IrInstructionIdElemPtr) {
......@@ -4236,7 +4267,7 @@ IrInstruction *ir_exec_const_result(IrExecutable *exec) {
42364267
42374268 IrInstructionReturn *ret_inst = (IrInstructionReturn *)only_inst;
42384269 IrInstruction *value = ret_inst->value;
4239 assert(value->static_value.ok);
4270 assert(value->static_value.special != ConstValSpecialRuntime);
42404271 return value;
42414272}
42424273
src/ir.hpp+1
......@@ -19,5 +19,6 @@ TypeTableEntry *ir_analyze(CodeGen *g, IrExecutable *old_executable, IrExecutabl
1919IrInstruction *ir_exec_const_result(IrExecutable *exec);
2020
2121bool ir_has_side_effects(IrInstruction *instruction);
22ConstExprValue *const_ptr_pointee(ConstExprValue *const_val);
2223
2324#endif
src/ir_print.cpp+6-4
......@@ -23,13 +23,15 @@ static void ir_print_prefix(IrPrint *irp, IrInstruction *instruction) {
2323
2424static void ir_print_const_value(IrPrint *irp, TypeTableEntry *type_entry, ConstExprValue *const_val) {
2525 switch (const_val->special) {
26 case ConstValSpecialRuntime:
27 zig_unreachable();
2628 case ConstValSpecialUndef:
2729 fprintf(irp->f, "undefined");
2830 return;
2931 case ConstValSpecialZeroes:
3032 fprintf(irp->f, "zeroes");
3133 return;
32 case ConstValSpecialOther:
34 case ConstValSpecialStatic:
3335 break;
3436 }
3537 switch (type_entry->id) {
......@@ -70,7 +72,7 @@ static void ir_print_const_value(IrPrint *irp, TypeTableEntry *type_entry, Const
7072 }
7173 case TypeTableEntryIdPointer:
7274 fprintf(irp->f, "&");
73 ir_print_const_value(irp, type_entry->data.pointer.child_type, const_val->data.x_ptr.ptr[0]);
75 ir_print_const_value(irp, type_entry->data.pointer.child_type, const_ptr_pointee(const_val));
7476 break;
7577 case TypeTableEntryIdFn:
7678 {
......@@ -91,7 +93,7 @@ static void ir_print_const_value(IrPrint *irp, TypeTableEntry *type_entry, Const
9193 for (uint64_t i = 0; i < len; i += 1) {
9294 if (i != 0)
9395 fprintf(irp->f, ",");
94 ConstExprValue *child_value = const_val->data.x_array.fields[i];
96 ConstExprValue *child_value = &const_val->data.x_array.elements[i];
9597 TypeTableEntry *child_type = type_entry->data.array.child_type;
9698 ir_print_const_value(irp, child_type, child_value);
9799 }
......@@ -126,7 +128,7 @@ static void ir_print_var_instruction(IrPrint *irp, IrInstruction *instruction) {
126128}
127129
128130static void ir_print_other_instruction(IrPrint *irp, IrInstruction *instruction) {
129 if (instruction->static_value.ok) {
131 if (instruction->static_value.special != ConstValSpecialRuntime) {
130132 ir_print_const_instruction(irp, instruction);
131133 } else {
132134 ir_print_var_instruction(irp, instruction);
src/parser.cpp-1
......@@ -2763,7 +2763,6 @@ AstNode *ast_clone_subtree_special(AstNode *old_node, uint32_t *next_node_index,
27632763 old_node->data.prefix_op_expr.primary_expr, next_node_index);
27642764 break;
27652765 case NodeTypeFnCallExpr:
2766 assert(!old_node->data.fn_call_expr.resolved_expr.has_global_const);
27672766 clone_subtree_field(&new_node->data.fn_call_expr.fn_ref_expr,
27682767 old_node->data.fn_call_expr.fn_ref_expr, next_node_index);
27692768 clone_subtree_list(&new_node->data.fn_call_expr.params,