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 {...@@ -51,17 +51,24 @@ struct ConstEnumValue {
51};51};
5252
53struct ConstStructValue {53struct ConstStructValue {
54 ConstExprValue **fields;54 ConstExprValue *fields;
55};55};
5656
57struct ConstArrayValue {57struct 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;
59};62};
6063
61struct ConstPtrValue {64struct ConstPtrValue {
62 ConstExprValue **ptr;65 ConstExprValue *base_ptr;
63 // len should almost always be 1. exceptions include C strings66 // If index is SIZE_MAX, then base_ptr points directly to child type.
64 uint64_t len;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.
65 bool is_c_str;72 bool is_c_str;
66};73};
6774
...@@ -71,15 +78,17 @@ struct ConstErrValue {...@@ -71,15 +78,17 @@ struct ConstErrValue {
71};78};
7279
73enum ConstValSpecial {80enum ConstValSpecial {
74 ConstValSpecialOther,81 ConstValSpecialRuntime,
82 ConstValSpecialStatic,
75 ConstValSpecialUndef,83 ConstValSpecialUndef,
76 ConstValSpecialZeroes,84 ConstValSpecialZeroes,
77};85};
7886
79struct ConstExprValue {87struct ConstExprValue {
80 bool ok;
81 bool depends_on_compile_var;
82 ConstValSpecial special;88 ConstValSpecial special;
89 bool depends_on_compile_var;
90 LLVMValueRef llvm_value;
91 LLVMValueRef llvm_global;
8392
84 // populated if val_type == ConstValTypeOk93 // populated if val_type == ConstValTypeOk
85 union {94 union {
...@@ -108,13 +117,9 @@ enum ReturnKnowledge {...@@ -108,13 +117,9 @@ enum ReturnKnowledge {
108};117};
109118
110struct Expr {119struct Expr {
111 TypeTableEntry *type_entry;120 IrInstruction *instruction;
112 ReturnKnowledge return_knowledge;121 ReturnKnowledge return_knowledge;
113 VariableTableEntry *variable;122 VariableTableEntry *variable;
114
115 LLVMValueRef const_llvm_val;
116 ConstExprValue const_val;
117 bool has_global_const;
118};123};
119124
120struct StructValExprCodeGen {125struct StructValExprCodeGen {
...@@ -1289,7 +1294,6 @@ struct CodeGen {...@@ -1289,7 +1294,6 @@ struct CodeGen {
1289 // there will not be a corresponding fn_defs entry.1294 // there will not be a corresponding fn_defs entry.
1290 ZigList<FnTableEntry *> fn_protos;1295 ZigList<FnTableEntry *> fn_protos;
1291 ZigList<VariableTableEntry *> global_vars;1296 ZigList<VariableTableEntry *> global_vars;
1292 ZigList<AstNode *> global_const_list;
12931297
1294 OutType out_type;1298 OutType out_type;
1295 FnTableEntry *cur_fn;1299 FnTableEntry *cur_fn;
...@@ -1733,4 +1737,7 @@ enum LValPurpose {...@@ -1733,4 +1737,7 @@ enum LValPurpose {
1733 LValPurposeConstAddressOf,1737 LValPurposeConstAddressOf,
1734};1738};
17351739
1740static const size_t slice_ptr_index = 0;
1741static const size_t slice_len_index = 1;
1742
1736#endif1743#endif
src/analyze.cpp+21-20
...@@ -882,7 +882,7 @@ static TypeTableEntry *analyze_type_expr_pointer_only(CodeGen *g, ImportTableEnt...@@ -882,7 +882,7 @@ static TypeTableEntry *analyze_type_expr_pointer_only(CodeGen *g, ImportTableEnt
882 if (result->type_entry->id == TypeTableEntryIdInvalid)882 if (result->type_entry->id == TypeTableEntryIdInvalid)
883 return g->builtin_types.entry_invalid;883 return g->builtin_types.entry_invalid;
884884
885 assert(result->static_value.ok);885 assert(result->static_value.special != ConstValSpecialRuntime);
886 return result->static_value.data.x_type;886 return result->static_value.data.x_type;
887}887}
888888
...@@ -1963,9 +1963,8 @@ static void resolve_var_decl(CodeGen *g, ImportTableEntry *import, AstNode *node...@@ -1963,9 +1963,8 @@ static void resolve_var_decl(CodeGen *g, ImportTableEntry *import, AstNode *node
1963 }1963 }
1964 if (implicit_type->id != TypeTableEntryIdInvalid) {1964 if (implicit_type->id != TypeTableEntryIdInvalid) {
1965 Expr *expr = get_resolved_expr(var_decl->expr);1965 Expr *expr = get_resolved_expr(var_decl->expr);
1966 assert(result->static_value.ok);1966 assert(result->static_value.special != ConstValSpecialRuntime);
1967 expr->const_val = result->static_value;1967 expr->instruction = result;
1968 expr->type_entry = result->type_entry;
1969 }1968 }
1970 } else if (!is_extern) {1969 } else if (!is_extern) {
1971 add_node_error(g, node, buf_sprintf("variables must be initialized"));1970 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...@@ -2132,8 +2131,8 @@ static bool num_lit_fits_in_other_type(CodeGen *g, AstNode *literal_node, TypeTa
2132 }2131 }
21332132
2134 Expr *expr = get_resolved_expr(literal_node);2133 Expr *expr = get_resolved_expr(literal_node);
2135 ConstExprValue *const_val = &expr->const_val;2134 ConstExprValue *const_val = &expr->instruction->static_value;
2136 assert(const_val->ok);2135 assert(const_val->special != ConstValSpecialRuntime);
2137 if (other_type_underlying->id == TypeTableEntryIdFloat) {2136 if (other_type_underlying->id == TypeTableEntryIdFloat) {
2138 return true;2137 return true;
2139 } else if (other_type_underlying->id == TypeTableEntryIdInt &&2138 } else if (other_type_underlying->id == TypeTableEntryIdInt &&
...@@ -2600,15 +2599,15 @@ static void add_symbols_from_import(CodeGen *g, AstNode *src_use_node, AstNode *...@@ -2600,15 +2599,15 @@ static void add_symbols_from_import(CodeGen *g, AstNode *src_use_node, AstNode *
2600 AstNode *use_target_node = src_use_node->data.use.expr;2599 AstNode *use_target_node = src_use_node->data.use.expr;
2601 Expr *expr = get_resolved_expr(use_target_node);2600 Expr *expr = get_resolved_expr(use_target_node);
26022601
2603 if (expr->type_entry->id == TypeTableEntryIdInvalid) {2602 if (expr->instruction->type_entry->id == TypeTableEntryIdInvalid) {
2604 tld->import->any_imports_failed = true;2603 tld->import->any_imports_failed = true;
2605 return;2604 return;
2606 }2605 }
26072606
2608 tld->resolution = TldResolutionOk;2607 tld->resolution = TldResolutionOk;
26092608
2610 ConstExprValue *const_val = &expr->const_val;2609 ConstExprValue *const_val = &expr->instruction->static_value;
2611 assert(const_val->ok);2610 assert(const_val->special != ConstValSpecialRuntime);
26122611
2613 ImportTableEntry *target_import = const_val->data.x_import;2612 ImportTableEntry *target_import = const_val->data.x_import;
2614 assert(target_import);2613 assert(target_import);
...@@ -3031,10 +3030,11 @@ void find_libc_lib_path(CodeGen *g) {...@@ -3031,10 +3030,11 @@ void find_libc_lib_path(CodeGen *g) {
3031}3030}
30323031
3033static uint32_t hash_ptr(void *ptr) {3032static uint32_t hash_ptr(void *ptr) {
3034 uint64_t x = (uint64_t)(uintptr_t)(ptr);3033 return ((uintptr_t)ptr) % UINT32_MAX;
3035 uint32_t a = x >> 32;3034}
3036 uint32_t b = x & 0xffffffff;3035
3037 return a ^ b;3036static uint32_t hash_size(size_t x) {
3037 return x % UINT32_MAX;
3038}3038}
30393039
3040uint32_t fn_type_id_hash(FnTypeId *id) {3040uint32_t fn_type_id_hash(FnTypeId *id) {
...@@ -3090,7 +3090,7 @@ static uint32_t hash_const_val(TypeTableEntry *type, ConstExprValue *const_val)...@@ -3090,7 +3090,7 @@ static uint32_t hash_const_val(TypeTableEntry *type, ConstExprValue *const_val)
3090 case TypeTableEntryIdNumLitFloat:3090 case TypeTableEntryIdNumLitFloat:
3091 return const_val->data.x_bignum.data.x_float * UINT32_MAX;3091 return const_val->data.x_bignum.data.x_float * UINT32_MAX;
3092 case TypeTableEntryIdPointer:3092 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);
3094 case TypeTableEntryIdUndefLit:3094 case TypeTableEntryIdUndefLit:
3095 return 162837799;3095 return 162837799;
3096 case TypeTableEntryIdNullLit:3096 case TypeTableEntryIdNullLit:
...@@ -3143,8 +3143,8 @@ uint32_t generic_fn_type_id_hash(GenericFnTypeId *id) {...@@ -3143,8 +3143,8 @@ uint32_t generic_fn_type_id_hash(GenericFnTypeId *id) {
3143 for (size_t i = 0; i < id->generic_param_count; i += 1) {3143 for (size_t i = 0; i < id->generic_param_count; i += 1) {
3144 GenericParamValue *generic_param = &id->generic_params[i];3144 GenericParamValue *generic_param = &id->generic_params[i];
3145 if (generic_param->node) {3145 if (generic_param->node) {
3146 ConstExprValue *const_val = &get_resolved_expr(generic_param->node)->const_val;3146 ConstExprValue *const_val = &get_resolved_expr(generic_param->node)->instruction->static_value;
3147 assert(const_val->ok);3147 assert(const_val->special != ConstValSpecialRuntime);
3148 result += hash_const_val(generic_param->type, const_val);3148 result += hash_const_val(generic_param->type, const_val);
3149 }3149 }
3150 result += hash_ptr(generic_param->type);3150 result += hash_ptr(generic_param->type);
...@@ -3160,10 +3160,10 @@ bool generic_fn_type_id_eql(GenericFnTypeId *a, GenericFnTypeId *b) {...@@ -3160,10 +3160,10 @@ bool generic_fn_type_id_eql(GenericFnTypeId *a, GenericFnTypeId *b) {
3160 GenericParamValue *b_val = &b->generic_params[i];3160 GenericParamValue *b_val = &b->generic_params[i];
3161 if (a_val->type != b_val->type) return false;3161 if (a_val->type != b_val->type) return false;
3162 if (a_val->node && b_val->node) {3162 if (a_val->node && b_val->node) {
3163 ConstExprValue *a_const_val = &get_resolved_expr(a_val->node)->const_val;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)->const_val;3164 ConstExprValue *b_const_val = &get_resolved_expr(b_val->node)->instruction->static_value;
3165 assert(a_const_val->ok);3165 assert(a_const_val->special != ConstValSpecialRuntime);
3166 assert(b_const_val->ok);3166 assert(b_const_val->special != ConstValSpecialRuntime);
3167 if (!const_values_equal(a_const_val, b_const_val, a_val->type)) {3167 if (!const_values_equal(a_const_val, b_const_val, a_val->type)) {
3168 return false;3168 return false;
3169 }3169 }
...@@ -3237,3 +3237,4 @@ uint64_t get_memcpy_align(CodeGen *g, TypeTableEntry *type_entry) {...@@ -3237,3 +3237,4 @@ uint64_t get_memcpy_align(CodeGen *g, TypeTableEntry *type_entry) {
3237 return LLVMABISizeOfType(g->target_data_ref, first_type_in_mem->type_ref);3237 return LLVMABISizeOfType(g->target_data_ref, first_type_in_mem->type_ref);
3238}3238}
32393239
3240
src/codegen.cpp+69-81
...@@ -226,7 +226,8 @@ void codegen_set_rdynamic(CodeGen *g, bool rdynamic) {...@@ -226,7 +226,8 @@ void codegen_set_rdynamic(CodeGen *g, bool rdynamic) {
226 g->linker_rdynamic = rdynamic;226 g->linker_rdynamic = rdynamic;
227}227}
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
231static void set_debug_source_node(CodeGen *g, AstNode *node) {232static void set_debug_source_node(CodeGen *g, AstNode *node) {
232 assert(node->block_context);233 assert(node->block_context);
...@@ -862,11 +863,17 @@ static LLVMValueRef ir_llvm_value(CodeGen *g, IrInstruction *instruction) {...@@ -862,11 +863,17 @@ static LLVMValueRef ir_llvm_value(CodeGen *g, IrInstruction *instruction) {
862 if (!type_has_bits(instruction->type_entry))863 if (!type_has_bits(instruction->type_entry))
863 return nullptr;864 return nullptr;
864 if (!instruction->llvm_value) {865 if (!instruction->llvm_value) {
865 assert(instruction->static_value.ok);866 assert(instruction->static_value.special != ConstValSpecialRuntime);
866 assert(instruction->type_entry);867 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;
868 assert(instruction->llvm_value);870 assert(instruction->llvm_value);
869 }871 }
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 }
870 return instruction->llvm_value;877 return instruction->llvm_value;
871}878}
872879
...@@ -1401,9 +1408,9 @@ static LLVMValueRef ir_render_decl_var(CodeGen *g, IrExecutable *executable,...@@ -1401,9 +1408,9 @@ static LLVMValueRef ir_render_decl_var(CodeGen *g, IrExecutable *executable,
1401 bool want_zeroes = false;1408 bool want_zeroes = false;
14021409
1403 ConstExprValue *const_val = &init_value->static_value;1410 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)
1405 have_init_expr = true;1412 have_init_expr = true;
1406 if (const_val->ok && const_val->special == ConstValSpecialZeroes)1413 if (const_val->special == ConstValSpecialZeroes)
1407 want_zeroes = true;1414 want_zeroes = true;
14081415
1409 if (have_init_expr) {1416 if (have_init_expr) {
...@@ -1740,14 +1747,14 @@ static void ir_render(CodeGen *g, FnTableEntry *fn_entry) {...@@ -1740,14 +1747,14 @@ static void ir_render(CodeGen *g, FnTableEntry *fn_entry) {
1740}1747}
17411748
1742static LLVMValueRef gen_const_val(CodeGen *g, TypeTableEntry *type_entry, ConstExprValue *const_val) {1749static LLVMValueRef gen_const_val(CodeGen *g, TypeTableEntry *type_entry, ConstExprValue *const_val) {
1743 assert(const_val->ok);
1744
1745 switch (const_val->special) {1750 switch (const_val->special) {
1751 case ConstValSpecialRuntime:
1752 zig_unreachable();
1746 case ConstValSpecialUndef:1753 case ConstValSpecialUndef:
1747 return LLVMGetUndef(type_entry->type_ref);1754 return LLVMGetUndef(type_entry->type_ref);
1748 case ConstValSpecialZeroes:1755 case ConstValSpecialZeroes:
1749 return LLVMConstNull(type_entry->type_ref);1756 return LLVMConstNull(type_entry->type_ref);
1750 case ConstValSpecialOther:1757 case ConstValSpecialStatic:
1751 break;1758 break;
17521759
1753 }1760 }
...@@ -1814,7 +1821,7 @@ static LLVMValueRef gen_const_val(CodeGen *g, TypeTableEntry *type_entry, ConstE...@@ -1814,7 +1821,7 @@ static LLVMValueRef gen_const_val(CodeGen *g, TypeTableEntry *type_entry, ConstE
1814 continue;1821 continue;
1815 }1822 }
1816 fields[type_struct_field->gen_index] = gen_const_val(g, type_struct_field->type_entry,1823 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]);
1818 }1825 }
1819 return LLVMConstNamedStruct(type_entry->type_ref, fields,1826 return LLVMConstNamedStruct(type_entry->type_ref, fields,
1820 type_entry->data.structure.gen_field_count);1827 type_entry->data.structure.gen_field_count);
...@@ -1829,8 +1836,8 @@ static LLVMValueRef gen_const_val(CodeGen *g, TypeTableEntry *type_entry, ConstE...@@ -1829,8 +1836,8 @@ static LLVMValueRef gen_const_val(CodeGen *g, TypeTableEntry *type_entry, ConstE
1829 uint64_t len = type_entry->data.array.len;1836 uint64_t len = type_entry->data.array.len;
1830 LLVMValueRef *values = allocate<LLVMValueRef>(len);1837 LLVMValueRef *values = allocate<LLVMValueRef>(len);
1831 for (uint64_t i = 0; i < len; i += 1) {1838 for (uint64_t i = 0; i < len; i += 1) {
1832 ConstExprValue *field_value = const_val->data.x_array.fields[i];1839 ConstExprValue *elem_value = &const_val->data.x_array.elements[i];
1833 values[i] = gen_const_val(g, child_type, field_value);1840 values[i] = gen_const_val(g, child_type, elem_value);
1834 }1841 }
1835 return LLVMConstArray(child_type->type_ref, values, len);1842 return LLVMConstArray(child_type->type_ref, values, len);
1836 }1843 }
...@@ -1878,29 +1885,26 @@ static LLVMValueRef gen_const_val(CodeGen *g, TypeTableEntry *type_entry, ConstE...@@ -1878,29 +1885,26 @@ static LLVMValueRef gen_const_val(CodeGen *g, TypeTableEntry *type_entry, ConstE
1878 case TypeTableEntryIdPointer:1885 case TypeTableEntryIdPointer:
1879 {1886 {
1880 TypeTableEntry *child_type = type_entry->data.pointer.child_type;1887 TypeTableEntry *child_type = type_entry->data.pointer.child_type;
1881 size_t len = const_val->data.x_ptr.len;1888
1882 LLVMValueRef target_val;1889 render_const_val_global(g, type_entry, const_val);
1883 if (len == 1) {1890 size_t index = const_val->data.x_ptr.index;
1884 target_val = gen_const_val(g, child_type, const_val->data.x_ptr.ptr[0]);1891 if (index == SIZE_MAX) {
1885 } else if (len > 1) {1892 render_const_val(g, child_type, const_val->data.x_ptr.base_ptr);
1886 LLVMValueRef *values = allocate<LLVMValueRef>(len);1893 render_const_val_global(g, child_type, const_val->data.x_ptr.base_ptr);
1887 for (size_t i = 0; i < len; i += 1) {1894 return const_val->data.x_ptr.base_ptr->llvm_global;
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);
1902 } else {1895 } 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;
1904 }1908 }
1905 }1909 }
1906 case TypeTableEntryIdErrorUnion:1910 case TypeTableEntryIdErrorUnion:
...@@ -1945,27 +1949,26 @@ static LLVMValueRef gen_const_val(CodeGen *g, TypeTableEntry *type_entry, ConstE...@@ -1945,27 +1949,26 @@ static LLVMValueRef gen_const_val(CodeGen *g, TypeTableEntry *type_entry, ConstE
1945 zig_unreachable();1949 zig_unreachable();
1946}1950}
19471951
1948static void gen_const_globals(CodeGen *g) {1952static void render_const_val(CodeGen *g, TypeTableEntry *type_entry, ConstExprValue *const_val) {
1949 for (size_t i = 0; i < g->global_const_list.length; i += 1) {1953 if (!const_val->llvm_value)
1950 AstNode *expr_node = g->global_const_list.at(i);1954 const_val->llvm_value = gen_const_val(g, type_entry, const_val);
1951 Expr *expr = get_resolved_expr(expr_node);1955
1952 ConstExprValue *const_val = &expr->const_val;1956 if (const_val->llvm_global)
1953 assert(const_val->ok);1957 LLVMSetInitializer(const_val->llvm_global, const_val->llvm_value);
1954 TypeTableEntry *type_entry = expr->type_entry;1958}
19551959
1956 if (handle_is_ptr(type_entry)) {1960static void render_const_val_global(CodeGen *g, TypeTableEntry *type_entry, ConstExprValue *const_val) {
1957 LLVMValueRef init_val = gen_const_val(g, type_entry, const_val);1961 if (!const_val->llvm_global) {
1958 LLVMValueRef global_value = LLVMAddGlobal(g->module, LLVMTypeOf(init_val), "");1962 LLVMValueRef global_value = LLVMAddGlobal(g->module, type_entry->type_ref, "");
1959 LLVMSetInitializer(global_value, init_val);1963 LLVMSetLinkage(global_value, LLVMInternalLinkage);
1960 LLVMSetLinkage(global_value, LLVMPrivateLinkage);1964 LLVMSetGlobalConstant(global_value, true);
1961 LLVMSetGlobalConstant(global_value, true);1965 LLVMSetUnnamedAddr(global_value, true);
1962 LLVMSetUnnamedAddr(global_value, true);1966
1963 expr->const_llvm_val = global_value;1967 const_val->llvm_global = global_value;
1964 } else {
1965 expr->const_llvm_val = gen_const_val(g, type_entry, const_val);
1966 }
1967 assert(expr->const_llvm_val);
1968 }1968 }
1969
1970 if (const_val->llvm_value)
1971 LLVMSetInitializer(const_val->llvm_global, const_val->llvm_value);
1969}1972}
19701973
1971static void delete_unused_builtin_fns(CodeGen *g) {1974static void delete_unused_builtin_fns(CodeGen *g) {
...@@ -2096,9 +2099,6 @@ static void do_code_gen(CodeGen *g) {...@@ -2096,9 +2099,6 @@ static void do_code_gen(CodeGen *g) {
2096 assert(!g->errors.length);2099 assert(!g->errors.length);
20972100
2098 delete_unused_builtin_fns(g);2101 delete_unused_builtin_fns(g);
2099
2100
2101 gen_const_globals(g);
2102 generate_error_name_table(g);2102 generate_error_name_table(g);
21032103
2104 // Generate module level variables2104 // Generate module level variables
...@@ -2107,8 +2107,8 @@ static void do_code_gen(CodeGen *g) {...@@ -2107,8 +2107,8 @@ static void do_code_gen(CodeGen *g) {
21072107
2108 if (var->type->id == TypeTableEntryIdNumLitFloat) {2108 if (var->type->id == TypeTableEntryIdNumLitFloat) {
2109 // Generate debug info for it but that's it.2109 // Generate debug info for it but that's it.
2110 ConstExprValue *const_val = &get_resolved_expr(var->val_node)->const_val;2110 ConstExprValue *const_val = &get_resolved_expr(var->val_node)->instruction->static_value;
2111 assert(const_val->ok);2111 assert(const_val->special != ConstValSpecialRuntime);
2112 TypeTableEntry *var_type = g->builtin_types.entry_f64;2112 TypeTableEntry *var_type = g->builtin_types.entry_f64;
2113 LLVMValueRef init_val = LLVMConstReal(var_type->type_ref, const_val->data.x_bignum.data.x_float);2113 LLVMValueRef init_val = LLVMConstReal(var_type->type_ref, const_val->data.x_bignum.data.x_float);
2114 gen_global_var(g, var, init_val, var_type);2114 gen_global_var(g, var, init_val, var_type);
...@@ -2117,8 +2117,8 @@ static void do_code_gen(CodeGen *g) {...@@ -2117,8 +2117,8 @@ static void do_code_gen(CodeGen *g) {
21172117
2118 if (var->type->id == TypeTableEntryIdNumLitInt) {2118 if (var->type->id == TypeTableEntryIdNumLitInt) {
2119 // Generate debug info for it but that's it.2119 // Generate debug info for it but that's it.
2120 ConstExprValue *const_val = &get_resolved_expr(var->val_node)->const_val;2120 ConstExprValue *const_val = &get_resolved_expr(var->val_node)->instruction->static_value;
2121 assert(const_val->ok);2121 assert(const_val->special != ConstValSpecialRuntime);
2122 TypeTableEntry *var_type = const_val->data.x_bignum.is_negative ?2122 TypeTableEntry *var_type = const_val->data.x_bignum.is_negative ?
2123 g->builtin_types.entry_isize : g->builtin_types.entry_usize;2123 g->builtin_types.entry_isize : g->builtin_types.entry_usize;
2124 LLVMValueRef init_val = LLVMConstInt(var_type->type_ref,2124 LLVMValueRef init_val = LLVMConstInt(var_type->type_ref,
...@@ -2143,25 +2143,13 @@ static void do_code_gen(CodeGen *g) {...@@ -2143,25 +2143,13 @@ static void do_code_gen(CodeGen *g) {
2143 LLVMSetLinkage(global_value, LLVMExternalLinkage);2143 LLVMSetLinkage(global_value, LLVMExternalLinkage);
2144 } else {2144 } else {
2145 AstNode *expr_node = var->decl_node->data.variable_declaration.expr;2145 AstNode *expr_node = var->decl_node->data.variable_declaration.expr;
2146 LLVMValueRef init_val;2146 IrInstruction *instruction = get_resolved_expr(expr_node)->instruction;
2147 if (expr_node) {2147 render_const_val(g, instruction->type_entry, &instruction->static_value);
2148 Expr *expr = get_resolved_expr(expr_node);2148 render_const_val_global(g, instruction->type_entry, &instruction->static_value);
2149 ConstExprValue *const_val = &expr->const_val;2149 global_value = instruction->static_value.llvm_global;
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
2162 // TODO debug info for function pointers2150 // TODO debug info for function pointers
2163 if (var->gen_is_const && var->type->id != TypeTableEntryIdFn) {2151 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);
2165 }2153 }
2166 }2154 }
21672155
...@@ -3282,11 +3270,11 @@ static void get_c_type(CodeGen *g, TypeTableEntry *type_entry, Buf *out_buf) {...@@ -3282,11 +3270,11 @@ static void get_c_type(CodeGen *g, TypeTableEntry *type_entry, Buf *out_buf) {
32823270
3283static void get_c_type_node(CodeGen *g, AstNode *type_node, Buf *out_buf) {3271static void get_c_type_node(CodeGen *g, AstNode *type_node, Buf *out_buf) {
3284 Expr *expr = get_resolved_expr(type_node);3272 Expr *expr = get_resolved_expr(type_node);
3285 assert(expr->type_entry);3273 assert(expr->instruction->type_entry);
3286 assert(expr->type_entry->id == TypeTableEntryIdMetaType);3274 assert(expr->instruction->type_entry->id == TypeTableEntryIdMetaType);
32873275
3288 ConstExprValue *const_val = &expr->const_val;3276 ConstExprValue *const_val = &expr->instruction->static_value;
3289 assert(const_val->ok);3277 assert(const_val->special != ConstValSpecialRuntime);
32903278
3291 TypeTableEntry *type_entry = const_val->data.x_type;3279 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...@@ -147,7 +147,7 @@ static int eval_const_expr_bin_op_bignum(ConstExprValue *op1_val, ConstExprValue
147 }147 }
148 }148 }
149149
150 out_val->ok = true;150 out_val->special = ConstValSpecialStatic;
151 out_val->depends_on_compile_var = op1_val->depends_on_compile_var || op2_val->depends_on_compile_var;151 out_val->depends_on_compile_var = op1_val->depends_on_compile_var || op2_val->depends_on_compile_var;
152 return 0;152 return 0;
153}153}
...@@ -155,8 +155,8 @@ static int eval_const_expr_bin_op_bignum(ConstExprValue *op1_val, ConstExprValue...@@ -155,8 +155,8 @@ static int eval_const_expr_bin_op_bignum(ConstExprValue *op1_val, ConstExprValue
155int eval_const_expr_bin_op(ConstExprValue *op1_val, TypeTableEntry *op1_type,155int eval_const_expr_bin_op(ConstExprValue *op1_val, TypeTableEntry *op1_type,
156 BinOpType bin_op, ConstExprValue *op2_val, TypeTableEntry *op2_type, ConstExprValue *out_val)156 BinOpType bin_op, ConstExprValue *op2_val, TypeTableEntry *op2_type, ConstExprValue *out_val)
157{157{
158 assert(op1_val->ok);158 assert(op1_val->special != ConstValSpecialRuntime);
159 assert(op2_val->ok);159 assert(op2_val->special != ConstValSpecialRuntime);
160 assert(op1_type->id != TypeTableEntryIdInvalid);160 assert(op1_type->id != TypeTableEntryIdInvalid);
161 assert(op2_type->id != TypeTableEntryIdInvalid);161 assert(op2_type->id != TypeTableEntryIdInvalid);
162162
...@@ -171,7 +171,7 @@ int eval_const_expr_bin_op(ConstExprValue *op1_val, TypeTableEntry *op1_type,...@@ -171,7 +171,7 @@ int eval_const_expr_bin_op(ConstExprValue *op1_val, TypeTableEntry *op1_type,
171 assert(op1_type->id == TypeTableEntryIdBool);171 assert(op1_type->id == TypeTableEntryIdBool);
172 assert(op2_type->id == TypeTableEntryIdBool);172 assert(op2_type->id == TypeTableEntryIdBool);
173 out_val->data.x_bool = eval_bool_bin_op_bool(op1_val->data.x_bool, bin_op, op2_val->data.x_bool);173 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;
175 out_val->depends_on_compile_var = op1_val->depends_on_compile_var || op2_val->depends_on_compile_var;175 out_val->depends_on_compile_var = op1_val->depends_on_compile_var || op2_val->depends_on_compile_var;
176 return 0;176 return 0;
177 case BinOpTypeCmpEq:177 case BinOpTypeCmpEq:
...@@ -219,7 +219,7 @@ int eval_const_expr_bin_op(ConstExprValue *op1_val, TypeTableEntry *op1_type,...@@ -219,7 +219,7 @@ int eval_const_expr_bin_op(ConstExprValue *op1_val, TypeTableEntry *op1_type,
219 out_val->depends_on_compile_var =219 out_val->depends_on_compile_var =
220 op1_val->depends_on_compile_var || op2_val->depends_on_compile_var;220 op1_val->depends_on_compile_var || op2_val->depends_on_compile_var;
221 out_val->data.x_bool = answer;221 out_val->data.x_bool = answer;
222 out_val->ok = true;222 out_val->special = ConstValSpecialStatic;
223 return 0;223 return 0;
224 }224 }
225 case BinOpTypeAdd:225 case BinOpTypeAdd:
...@@ -309,67 +309,7 @@ void eval_const_expr_implicit_cast(CastOp cast_op,...@@ -309,67 +309,7 @@ void eval_const_expr_implicit_cast(CastOp cast_op,
309 *const_val = *other_val;309 *const_val = *other_val;
310 break;310 break;
311 case CastOpPointerReinterpret:311 case CastOpPointerReinterpret:
312 if (other_type->id == TypeTableEntryIdPointer &&312 zig_panic("TODO compile time pointer reinterpret");
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 }
373 break;313 break;
374 case CastOpPtrToInt:314 case CastOpPtrToInt:
375 case CastOpIntToPtr:315 case CastOpIntToPtr:
...@@ -378,62 +318,43 @@ void eval_const_expr_implicit_cast(CastOp cast_op,...@@ -378,62 +318,43 @@ void eval_const_expr_implicit_cast(CastOp cast_op,
378 // can't do it318 // can't do it
379 break;319 break;
380 case CastOpToUnknownSizeArray:320 case CastOpToUnknownSizeArray:
381 {321 zig_panic("TODO compile time implicit to unknown size array");
382 assert(other_type->id == TypeTableEntryIdArray);322 break;
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 }
402 case CastOpMaybeWrap:323 case CastOpMaybeWrap:
403 const_val->data.x_maybe = other_val;324 const_val->data.x_maybe = other_val;
404 const_val->ok = true;325 const_val->special = ConstValSpecialStatic;
405 break;326 break;
406 case CastOpNullToMaybe:327 case CastOpNullToMaybe:
407 const_val->data.x_maybe = nullptr;328 const_val->data.x_maybe = nullptr;
408 const_val->ok = true;329 const_val->special = ConstValSpecialStatic;
409 break;330 break;
410 case CastOpErrorWrap:331 case CastOpErrorWrap:
411 const_val->data.x_err.err = nullptr;332 const_val->data.x_err.err = nullptr;
412 const_val->data.x_err.payload = other_val;333 const_val->data.x_err.payload = other_val;
413 const_val->ok = true;334 const_val->special = ConstValSpecialStatic;
414 break;335 break;
415 case CastOpPureErrorWrap:336 case CastOpPureErrorWrap:
416 const_val->data.x_err.err = other_val->data.x_err.err;337 const_val->data.x_err.err = other_val->data.x_err.err;
417 const_val->ok = true;338 const_val->special = ConstValSpecialStatic;
418 break;339 break;
419 case CastOpErrToInt:340 case CastOpErrToInt:
420 {341 {
421 uint64_t value = other_val->data.x_err.err ? other_val->data.x_err.err->value : 0;342 uint64_t value = other_val->data.x_err.err ? other_val->data.x_err.err->value : 0;
422 bignum_init_unsigned(&const_val->data.x_bignum, value);343 bignum_init_unsigned(&const_val->data.x_bignum, value);
423 const_val->ok = true;344 const_val->special = ConstValSpecialStatic;
424 break;345 break;
425 }346 }
426 case CastOpIntToFloat:347 case CastOpIntToFloat:
427 bignum_cast_to_float(&const_val->data.x_bignum, &other_val->data.x_bignum);348 bignum_cast_to_float(&const_val->data.x_bignum, &other_val->data.x_bignum);
428 const_val->ok = true;349 const_val->special = ConstValSpecialStatic;
429 break;350 break;
430 case CastOpFloatToInt:351 case CastOpFloatToInt:
431 bignum_cast_to_int(&const_val->data.x_bignum, &other_val->data.x_bignum);352 bignum_cast_to_int(&const_val->data.x_bignum, &other_val->data.x_bignum);
432 const_val->ok = true;353 const_val->special = ConstValSpecialStatic;
433 break;354 break;
434 case CastOpBoolToInt:355 case CastOpBoolToInt:
435 bignum_init_unsigned(&const_val->data.x_bignum, other_val->data.x_bool ? 1 : 0);356 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;
437 break;358 break;
438 case CastOpIntToEnum:359 case CastOpIntToEnum:
439 {360 {
...@@ -442,12 +363,12 @@ void eval_const_expr_implicit_cast(CastOp cast_op,...@@ -442,12 +363,12 @@ void eval_const_expr_implicit_cast(CastOp cast_op,
442 assert(value < new_type->data.enumeration.src_field_count);363 assert(value < new_type->data.enumeration.src_field_count);
443 const_val->data.x_enum.tag = value;364 const_val->data.x_enum.tag = value;
444 const_val->data.x_enum.payload = NULL;365 const_val->data.x_enum.payload = NULL;
445 const_val->ok = true;366 const_val->special = ConstValSpecialStatic;
446 break;367 break;
447 }368 }
448 case CastOpEnumToInt:369 case CastOpEnumToInt:
449 bignum_init_unsigned(&const_val->data.x_bignum, other_val->data.x_enum.tag);370 bignum_init_unsigned(&const_val->data.x_bignum, other_val->data.x_enum.tag);
450 const_val->ok = true;371 const_val->special = ConstValSpecialStatic;
451 break;372 break;
452 }373 }
453}374}
...@@ -465,7 +386,7 @@ static bool int_type_depends_on_compile_var(CodeGen *g, TypeTableEntry *int_type...@@ -465,7 +386,7 @@ static bool int_type_depends_on_compile_var(CodeGen *g, TypeTableEntry *int_type
465386
466void eval_min_max_value(CodeGen *g, TypeTableEntry *type_entry, ConstExprValue *const_val, bool is_max) {387void eval_min_max_value(CodeGen *g, TypeTableEntry *type_entry, ConstExprValue *const_val, bool is_max) {
467 if (type_entry->id == TypeTableEntryIdInt) {388 if (type_entry->id == TypeTableEntryIdInt) {
468 const_val->ok = true;389 const_val->special = ConstValSpecialStatic;
469 const_val->depends_on_compile_var = int_type_depends_on_compile_var(g, type_entry);390 const_val->depends_on_compile_var = int_type_depends_on_compile_var(g, type_entry);
470 if (is_max) {391 if (is_max) {
471 if (type_entry->data.integral.is_signed) {392 if (type_entry->data.integral.is_signed) {
...@@ -486,7 +407,7 @@ void eval_min_max_value(CodeGen *g, TypeTableEntry *type_entry, ConstExprValue *...@@ -486,7 +407,7 @@ void eval_min_max_value(CodeGen *g, TypeTableEntry *type_entry, ConstExprValue *
486 } else if (type_entry->id == TypeTableEntryIdFloat) {407 } else if (type_entry->id == TypeTableEntryIdFloat) {
487 zig_panic("TODO analyze_min_max_value float");408 zig_panic("TODO analyze_min_max_value float");
488 } else if (type_entry->id == TypeTableEntryIdBool) {409 } else if (type_entry->id == TypeTableEntryIdBool) {
489 const_val->ok = true;410 const_val->special = ConstValSpecialStatic;
490 const_val->data.x_bool = is_max;411 const_val->data.x_bool = is_max;
491 } else {412 } else {
492 zig_unreachable();413 zig_unreachable();
src/ir.cpp+125-94
...@@ -35,6 +35,18 @@ static IrInstruction *ir_gen_node_extra(IrBuilder *irb, AstNode *node, BlockCont...@@ -35,6 +35,18 @@ static IrInstruction *ir_gen_node_extra(IrBuilder *irb, AstNode *node, BlockCont
35 LValPurpose lval);35 LValPurpose lval);
36static TypeTableEntry *ir_analyze_instruction(IrAnalyze *ira, IrInstruction *instruction);36static 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
38static void ir_instruction_append(IrBasicBlock *basic_block, IrInstruction *instruction) {50static void ir_instruction_append(IrBasicBlock *basic_block, IrInstruction *instruction) {
39 assert(basic_block);51 assert(basic_block);
40 assert(instruction);52 assert(instruction);
...@@ -237,7 +249,7 @@ static IrInstruction *ir_build_cond_br(IrBuilder *irb, AstNode *source_node, IrI...@@ -237,7 +249,7 @@ static IrInstruction *ir_build_cond_br(IrBuilder *irb, AstNode *source_node, IrI
237{249{
238 IrInstructionCondBr *cond_br_instruction = ir_build_instruction<IrInstructionCondBr>(irb, source_node);250 IrInstructionCondBr *cond_br_instruction = ir_build_instruction<IrInstructionCondBr>(irb, source_node);
239 cond_br_instruction->base.type_entry = irb->codegen->builtin_types.entry_unreachable;251 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;
241 cond_br_instruction->condition = condition;253 cond_br_instruction->condition = condition;
242 cond_br_instruction->then_block = then_block;254 cond_br_instruction->then_block = then_block;
243 cond_br_instruction->else_block = else_block;255 cond_br_instruction->else_block = else_block;
...@@ -262,7 +274,7 @@ static IrInstruction *ir_build_cond_br_from(IrBuilder *irb, IrInstruction *old_i...@@ -262,7 +274,7 @@ static IrInstruction *ir_build_cond_br_from(IrBuilder *irb, IrInstruction *old_i
262static IrInstruction *ir_build_return(IrBuilder *irb, AstNode *source_node, IrInstruction *return_value) {274static IrInstruction *ir_build_return(IrBuilder *irb, AstNode *source_node, IrInstruction *return_value) {
263 IrInstructionReturn *return_instruction = ir_build_instruction<IrInstructionReturn>(irb, source_node);275 IrInstructionReturn *return_instruction = ir_build_instruction<IrInstructionReturn>(irb, source_node);
264 return_instruction->base.type_entry = irb->codegen->builtin_types.entry_unreachable;276 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;
266 return_instruction->value = return_value;278 return_instruction->value = return_value;
267279
268 ir_ref_instruction(return_value);280 ir_ref_instruction(return_value);
...@@ -281,20 +293,19 @@ static IrInstruction *ir_build_return_from(IrBuilder *irb, IrInstruction *old_in...@@ -281,20 +293,19 @@ static IrInstruction *ir_build_return_from(IrBuilder *irb, IrInstruction *old_in
281static IrInstruction *ir_create_const(IrBuilder *irb, AstNode *source_node, TypeTableEntry *type_entry) {293static IrInstruction *ir_create_const(IrBuilder *irb, AstNode *source_node, TypeTableEntry *type_entry) {
282 IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(irb->exec, source_node);294 IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(irb->exec, source_node);
283 const_instruction->base.type_entry = type_entry;295 const_instruction->base.type_entry = type_entry;
284 const_instruction->base.static_value.ok = true;296 const_instruction->base.static_value.special = ConstValSpecialStatic;
285 return &const_instruction->base;297 return &const_instruction->base;
286}298}
287299
288static IrInstruction *ir_build_const_void(IrBuilder *irb, AstNode *source_node) {300static IrInstruction *ir_build_const_void(IrBuilder *irb, AstNode *source_node) {
289 IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irb, source_node);301 IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irb, source_node);
290 const_instruction->base.type_entry = irb->codegen->builtin_types.entry_void;302 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;
292 return &const_instruction->base;304 return &const_instruction->base;
293}305}
294306
295static IrInstruction *ir_build_const_undefined(IrBuilder *irb, AstNode *source_node) {307static IrInstruction *ir_build_const_undefined(IrBuilder *irb, AstNode *source_node) {
296 IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irb, source_node);308 IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irb, source_node);
297 const_instruction->base.static_value.ok = true;
298 const_instruction->base.static_value.special = ConstValSpecialUndef;309 const_instruction->base.static_value.special = ConstValSpecialUndef;
299 const_instruction->base.type_entry = irb->codegen->builtin_types.entry_undef;310 const_instruction->base.type_entry = irb->codegen->builtin_types.entry_undef;
300 return &const_instruction->base;311 return &const_instruction->base;
...@@ -304,7 +315,7 @@ static IrInstruction *ir_build_const_bignum(IrBuilder *irb, AstNode *source_node...@@ -304,7 +315,7 @@ static IrInstruction *ir_build_const_bignum(IrBuilder *irb, AstNode *source_node
304 IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irb, source_node);315 IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irb, source_node);
305 const_instruction->base.type_entry = (bignum->kind == BigNumKindInt) ?316 const_instruction->base.type_entry = (bignum->kind == BigNumKindInt) ?
306 irb->codegen->builtin_types.entry_num_lit_int : irb->codegen->builtin_types.entry_num_lit_float;317 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;
308 const_instruction->base.static_value.data.x_bignum = *bignum;319 const_instruction->base.static_value.data.x_bignum = *bignum;
309 return &const_instruction->base;320 return &const_instruction->base;
310}321}
...@@ -312,7 +323,7 @@ static IrInstruction *ir_build_const_bignum(IrBuilder *irb, AstNode *source_node...@@ -312,7 +323,7 @@ static IrInstruction *ir_build_const_bignum(IrBuilder *irb, AstNode *source_node
312static IrInstruction *ir_build_const_usize(IrBuilder *irb, AstNode *source_node, uint64_t value) {323static IrInstruction *ir_build_const_usize(IrBuilder *irb, AstNode *source_node, uint64_t value) {
313 IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irb, source_node);324 IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irb, source_node);
314 const_instruction->base.type_entry = irb->codegen->builtin_types.entry_usize;325 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;
316 bignum_init_unsigned(&const_instruction->base.static_value.data.x_bignum, value);327 bignum_init_unsigned(&const_instruction->base.static_value.data.x_bignum, value);
317 return &const_instruction->base;328 return &const_instruction->base;
318}329}
...@@ -320,7 +331,7 @@ static IrInstruction *ir_build_const_usize(IrBuilder *irb, AstNode *source_node,...@@ -320,7 +331,7 @@ static IrInstruction *ir_build_const_usize(IrBuilder *irb, AstNode *source_node,
320static IrInstruction *ir_create_const_type(IrBuilder *irb, AstNode *source_node, TypeTableEntry *type_entry) {331static IrInstruction *ir_create_const_type(IrBuilder *irb, AstNode *source_node, TypeTableEntry *type_entry) {
321 IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(irb->exec, source_node);332 IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(irb->exec, source_node);
322 const_instruction->base.type_entry = irb->codegen->builtin_types.entry_type;333 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;
324 const_instruction->base.static_value.data.x_type = type_entry;335 const_instruction->base.static_value.data.x_type = type_entry;
325 return &const_instruction->base;336 return &const_instruction->base;
326}337}
...@@ -334,7 +345,7 @@ static IrInstruction *ir_build_const_type(IrBuilder *irb, AstNode *source_node,...@@ -334,7 +345,7 @@ static IrInstruction *ir_build_const_type(IrBuilder *irb, AstNode *source_node,
334static IrInstruction *ir_build_const_fn(IrBuilder *irb, AstNode *source_node, FnTableEntry *fn_entry) {345static IrInstruction *ir_build_const_fn(IrBuilder *irb, AstNode *source_node, FnTableEntry *fn_entry) {
335 IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irb, source_node);346 IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irb, source_node);
336 const_instruction->base.type_entry = fn_entry->type_entry;347 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;
338 const_instruction->base.static_value.data.x_fn = fn_entry;349 const_instruction->base.static_value.data.x_fn = fn_entry;
339 return &const_instruction->base;350 return &const_instruction->base;
340}351}
...@@ -342,7 +353,7 @@ static IrInstruction *ir_build_const_fn(IrBuilder *irb, AstNode *source_node, Fn...@@ -342,7 +353,7 @@ static IrInstruction *ir_build_const_fn(IrBuilder *irb, AstNode *source_node, Fn
342static IrInstruction *ir_build_const_generic_fn(IrBuilder *irb, AstNode *source_node, TypeTableEntry *fn_type) {353static IrInstruction *ir_build_const_generic_fn(IrBuilder *irb, AstNode *source_node, TypeTableEntry *fn_type) {
343 IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irb, source_node);354 IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irb, source_node);
344 const_instruction->base.type_entry = fn_type;355 const_instruction->base.type_entry = fn_type;
345 const_instruction->base.static_value.ok = true;356 const_instruction->base.static_value.special = ConstValSpecialStatic;
346 const_instruction->base.static_value.data.x_type = fn_type;357 const_instruction->base.static_value.data.x_type = fn_type;
347 return &const_instruction->base;358 return &const_instruction->base;
348}359}
...@@ -350,7 +361,7 @@ static IrInstruction *ir_build_const_generic_fn(IrBuilder *irb, AstNode *source_...@@ -350,7 +361,7 @@ static IrInstruction *ir_build_const_generic_fn(IrBuilder *irb, AstNode *source_
350static IrInstruction *ir_build_const_import(IrBuilder *irb, AstNode *source_node, ImportTableEntry *import) {361static IrInstruction *ir_build_const_import(IrBuilder *irb, AstNode *source_node, ImportTableEntry *import) {
351 IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irb, source_node);362 IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irb, source_node);
352 const_instruction->base.type_entry = irb->codegen->builtin_types.entry_namespace;363 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;
354 const_instruction->base.static_value.data.x_import = import;365 const_instruction->base.static_value.data.x_import = import;
355 return &const_instruction->base;366 return &const_instruction->base;
356}367}
...@@ -358,7 +369,7 @@ static IrInstruction *ir_build_const_import(IrBuilder *irb, AstNode *source_node...@@ -358,7 +369,7 @@ static IrInstruction *ir_build_const_import(IrBuilder *irb, AstNode *source_node
358static IrInstruction *ir_build_const_scope(IrBuilder *irb, AstNode *source_node, BlockContext *scope) {369static IrInstruction *ir_build_const_scope(IrBuilder *irb, AstNode *source_node, BlockContext *scope) {
359 IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irb, source_node);370 IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irb, source_node);
360 const_instruction->base.type_entry = irb->codegen->builtin_types.entry_block;371 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;
362 const_instruction->base.static_value.data.x_block = scope;373 const_instruction->base.static_value.data.x_block = scope;
363 return &const_instruction->base;374 return &const_instruction->base;
364}375}
...@@ -366,7 +377,7 @@ static IrInstruction *ir_build_const_scope(IrBuilder *irb, AstNode *source_node,...@@ -366,7 +377,7 @@ static IrInstruction *ir_build_const_scope(IrBuilder *irb, AstNode *source_node,
366static IrInstruction *ir_build_const_bool(IrBuilder *irb, AstNode *source_node, bool value) {377static IrInstruction *ir_build_const_bool(IrBuilder *irb, AstNode *source_node, bool value) {
367 IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irb, source_node);378 IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irb, source_node);
368 const_instruction->base.type_entry = irb->codegen->builtin_types.entry_bool;379 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;
370 const_instruction->base.static_value.data.x_bool = value;381 const_instruction->base.static_value.data.x_bool = value;
371 return &const_instruction->base;382 return &const_instruction->base;
372}383}
...@@ -377,45 +388,45 @@ static IrInstruction *ir_build_const_str_lit(IrBuilder *irb, AstNode *source_nod...@@ -377,45 +388,45 @@ static IrInstruction *ir_build_const_str_lit(IrBuilder *irb, AstNode *source_nod
377 TypeTableEntry *type_entry = get_array_type(irb->codegen, u8_type, buf_len(str));388 TypeTableEntry *type_entry = get_array_type(irb->codegen, u8_type, buf_len(str));
378 const_instruction->base.type_entry = type_entry;389 const_instruction->base.type_entry = type_entry;
379 ConstExprValue *const_val = &const_instruction->base.static_value;390 ConstExprValue *const_val = &const_instruction->base.static_value;
380 const_val->ok = true;391 const_val->special = ConstValSpecialStatic;
381 const_val->data.x_array.fields = allocate<ConstExprValue*>(buf_len(str));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));
384 for (size_t i = 0; i < buf_len(str); i += 1) {395 for (size_t i = 0; i < buf_len(str); i += 1) {
385 ConstExprValue *this_char = &all_chars[i];396 ConstExprValue *this_char = &const_val->data.x_array.elements[i];
386 this_char->ok = true;397 this_char->special = ConstValSpecialStatic;
387 bignum_init_unsigned(&this_char->data.x_bignum, buf_ptr(str)[i]);398 bignum_init_unsigned(&this_char->data.x_bignum, buf_ptr(str)[i]);
388 const_val->data.x_array.fields[i] = this_char;
389 }399 }
390400
391 return &const_instruction->base;401 return &const_instruction->base;
392}402}
393403
394static IrInstruction *ir_build_const_c_str_lit(IrBuilder *irb, AstNode *source_node, Buf *str) {404static 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);405 // first we build the underlying array
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
402 size_t len_with_null = buf_len(str) + 1;406 size_t len_with_null = buf_len(str) + 1;
403 const_val->data.x_ptr.ptr = allocate<ConstExprValue*>(len_with_null);407 ConstExprValue *array_val = allocate<ConstExprValue>(1);
404 const_val->data.x_ptr.len = len_with_null;408 array_val->special = ConstValSpecialStatic;
405 const_val->data.x_ptr.is_c_str = true;409 array_val->data.x_array.elements = allocate<ConstExprValue>(len_with_null);
406410 array_val->data.x_array.size = len_with_null;
407 ConstExprValue *all_chars = allocate<ConstExprValue>(len_with_null);
408 for (size_t i = 0; i < buf_len(str); i += 1) {411 for (size_t i = 0; i < buf_len(str); i += 1) {
409 ConstExprValue *this_char = &all_chars[i];412 ConstExprValue *this_char = &array_val->data.x_array.elements[i];
410 this_char->ok = true;413 this_char->special = ConstValSpecialStatic;
411 bignum_init_unsigned(&this_char->data.x_bignum, buf_ptr(str)[i]);414 bignum_init_unsigned(&this_char->data.x_bignum, buf_ptr(str)[i]);
412 const_val->data.x_ptr.ptr[i] = this_char;
413 }415 }
414416 ConstExprValue *null_char = &array_val->data.x_array.elements[len_with_null - 1];
415 ConstExprValue *null_char = &all_chars[len_with_null - 1];417 null_char->special = ConstValSpecialStatic;
416 null_char->ok = true;
417 bignum_init_unsigned(&null_char->data.x_bignum, 0);418 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
420 return &const_instruction->base;431 return &const_instruction->base;
421}432}
...@@ -591,7 +602,7 @@ static IrInstruction *ir_build_phi_from(IrBuilder *irb, IrInstruction *old_instr...@@ -591,7 +602,7 @@ static IrInstruction *ir_build_phi_from(IrBuilder *irb, IrInstruction *old_instr
591static IrInstruction *ir_build_br(IrBuilder *irb, AstNode *source_node, IrBasicBlock *dest_block, bool is_inline) {602static IrInstruction *ir_build_br(IrBuilder *irb, AstNode *source_node, IrBasicBlock *dest_block, bool is_inline) {
592 IrInstructionBr *br_instruction = ir_build_instruction<IrInstructionBr>(irb, source_node);603 IrInstructionBr *br_instruction = ir_build_instruction<IrInstructionBr>(irb, source_node);
593 br_instruction->base.type_entry = irb->codegen->builtin_types.entry_unreachable;604 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;
595 br_instruction->dest_block = dest_block;606 br_instruction->dest_block = dest_block;
596 br_instruction->is_inline = is_inline;607 br_instruction->is_inline = is_inline;
597608
...@@ -662,7 +673,7 @@ static IrInstruction *ir_build_container_init_fields(IrBuilder *irb, AstNode *so...@@ -662,7 +673,7 @@ static IrInstruction *ir_build_container_init_fields(IrBuilder *irb, AstNode *so
662static IrInstruction *ir_build_unreachable(IrBuilder *irb, AstNode *source_node) {673static IrInstruction *ir_build_unreachable(IrBuilder *irb, AstNode *source_node) {
663 IrInstructionUnreachable *unreachable_instruction =674 IrInstructionUnreachable *unreachable_instruction =
664 ir_build_instruction<IrInstructionUnreachable>(irb, source_node);675 ir_build_instruction<IrInstructionUnreachable>(irb, source_node);
665 unreachable_instruction->base.static_value.ok = true;676 unreachable_instruction->base.static_value.special = ConstValSpecialStatic;
666 unreachable_instruction->base.type_entry = irb->codegen->builtin_types.entry_unreachable;677 unreachable_instruction->base.type_entry = irb->codegen->builtin_types.entry_unreachable;
667 return &unreachable_instruction->base;678 return &unreachable_instruction->base;
668}679}
...@@ -677,7 +688,7 @@ static IrInstruction *ir_build_store_ptr(IrBuilder *irb, AstNode *source_node,...@@ -677,7 +688,7 @@ static IrInstruction *ir_build_store_ptr(IrBuilder *irb, AstNode *source_node,
677 IrInstruction *ptr, IrInstruction *value)688 IrInstruction *ptr, IrInstruction *value)
678{689{
679 IrInstructionStorePtr *instruction = ir_build_instruction<IrInstructionStorePtr>(irb, source_node);690 IrInstructionStorePtr *instruction = ir_build_instruction<IrInstructionStorePtr>(irb, source_node);
680 instruction->base.static_value.ok = true;691 instruction->base.static_value.special = ConstValSpecialStatic;
681 instruction->base.type_entry = irb->codegen->builtin_types.entry_void;692 instruction->base.type_entry = irb->codegen->builtin_types.entry_void;
682 instruction->ptr = ptr;693 instruction->ptr = ptr;
683 instruction->value = value;694 instruction->value = value;
...@@ -700,7 +711,7 @@ static IrInstruction *ir_build_var_decl(IrBuilder *irb, AstNode *source_node,...@@ -700,7 +711,7 @@ static IrInstruction *ir_build_var_decl(IrBuilder *irb, AstNode *source_node,
700 VariableTableEntry *var, IrInstruction *var_type, IrInstruction *init_value)711 VariableTableEntry *var, IrInstruction *var_type, IrInstruction *init_value)
701{712{
702 IrInstructionDeclVar *decl_var_instruction = ir_build_instruction<IrInstructionDeclVar>(irb, source_node);713 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;
704 decl_var_instruction->base.type_entry = irb->codegen->builtin_types.entry_void;715 decl_var_instruction->base.type_entry = irb->codegen->builtin_types.entry_void;
705 decl_var_instruction->var = var;716 decl_var_instruction->var = var;
706 decl_var_instruction->var_type = var_type;717 decl_var_instruction->var_type = var_type;
...@@ -1900,7 +1911,7 @@ static bool ir_num_lit_fits_in_other_type(IrAnalyze *ira, IrInstruction *instruc...@@ -1900,7 +1911,7 @@ static bool ir_num_lit_fits_in_other_type(IrAnalyze *ira, IrInstruction *instruc
1900 }1911 }
19011912
1902 ConstExprValue *const_val = &instruction->static_value;1913 ConstExprValue *const_val = &instruction->static_value;
1903 assert(const_val->ok);1914 assert(const_val->special != ConstValSpecialRuntime);
1904 if (other_type_underlying->id == TypeTableEntryIdFloat) {1915 if (other_type_underlying->id == TypeTableEntryIdFloat) {
1905 return true;1916 return true;
1906 } else if (other_type_underlying->id == TypeTableEntryIdInt &&1917 } else if (other_type_underlying->id == TypeTableEntryIdInt &&
...@@ -2110,10 +2121,10 @@ static IrInstruction *ir_resolve_cast(IrAnalyze *ira, IrInstruction *source_inst...@@ -2110,10 +2121,10 @@ static IrInstruction *ir_resolve_cast(IrAnalyze *ira, IrInstruction *source_inst
2110 IrInstruction *dest_type, CastOp cast_op, bool need_alloca)2121 IrInstruction *dest_type, CastOp cast_op, bool need_alloca)
2111{2122{
2112 assert(dest_type->type_entry->id == TypeTableEntryIdMetaType);2123 assert(dest_type->type_entry->id == TypeTableEntryIdMetaType);
2113 assert(dest_type->static_value.ok);2124 assert(dest_type->static_value.special != ConstValSpecialRuntime);
2114 TypeTableEntry *wanted_type = dest_type->static_value.data.x_type;2125 TypeTableEntry *wanted_type = dest_type->static_value.data.x_type;
21152126
2116 if (value->static_value.ok) {2127 if (value->static_value.special != ConstValSpecialRuntime) {
2117 IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->source_node, wanted_type);2128 IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->source_node, wanted_type);
2118 eval_const_expr_implicit_cast(cast_op, &value->static_value, value->type_entry,2129 eval_const_expr_implicit_cast(cast_op, &value->static_value, value->type_entry,
2119 &result->static_value, wanted_type);2130 &result->static_value, wanted_type);
...@@ -2194,7 +2205,7 @@ static ConstExprValue *ir_build_const_from(IrAnalyze *ira, IrInstruction *old_in...@@ -2194,7 +2205,7 @@ static ConstExprValue *ir_build_const_from(IrAnalyze *ira, IrInstruction *old_in
2194 }2205 }
2195 ir_link_new_instruction(new_instruction, old_instruction);2206 ir_link_new_instruction(new_instruction, old_instruction);
2196 ConstExprValue *const_val = &new_instruction->static_value;2207 ConstExprValue *const_val = &new_instruction->static_value;
2197 const_val->ok = true;2208 const_val->special = ConstValSpecialStatic;
2198 const_val->depends_on_compile_var = depends_on_compile_var;2209 const_val->depends_on_compile_var = depends_on_compile_var;
2199 return const_val;2210 return const_val;
2200}2211}
...@@ -2226,7 +2237,7 @@ static TypeTableEntry *ir_resolve_type(IrAnalyze *ira, IrInstruction *type_value...@@ -2226,7 +2237,7 @@ static TypeTableEntry *ir_resolve_type(IrAnalyze *ira, IrInstruction *type_value
2226 }2237 }
22272238
2228 ConstExprValue *const_val = &type_value->static_value;2239 ConstExprValue *const_val = &type_value->static_value;
2229 if (!const_val->ok) {2240 if (const_val->special == ConstValSpecialRuntime) {
2230 add_node_error(ira->codegen, type_value->source_node,2241 add_node_error(ira->codegen, type_value->source_node,
2231 buf_sprintf("unable to evaluate constant expression"));2242 buf_sprintf("unable to evaluate constant expression"));
2232 return ira->codegen->builtin_types.entry_invalid;2243 return ira->codegen->builtin_types.entry_invalid;
...@@ -2249,7 +2260,7 @@ static bool ir_resolve_bool(IrAnalyze *ira, IrInstruction *bool_value, bool *out...@@ -2249,7 +2260,7 @@ static bool ir_resolve_bool(IrAnalyze *ira, IrInstruction *bool_value, bool *out
2249 }2260 }
22502261
2251 ConstExprValue *const_val = &bool_value->static_value;2262 ConstExprValue *const_val = &bool_value->static_value;
2252 if (!const_val->ok) {2263 if (const_val->special == ConstValSpecialRuntime) {
2253 add_node_error(ira->codegen, bool_value->source_node,2264 add_node_error(ira->codegen, bool_value->source_node,
2254 buf_sprintf("unable to evaluate constant expression"));2265 buf_sprintf("unable to evaluate constant expression"));
2255 return false;2266 return false;
...@@ -2273,7 +2284,7 @@ static FnTableEntry *ir_resolve_fn(IrAnalyze *ira, IrInstruction *fn_value) {...@@ -2273,7 +2284,7 @@ static FnTableEntry *ir_resolve_fn(IrAnalyze *ira, IrInstruction *fn_value) {
2273 }2284 }
22742285
2275 ConstExprValue *const_val = &fn_value->static_value;2286 ConstExprValue *const_val = &fn_value->static_value;
2276 if (!const_val->ok) {2287 if (const_val->special == ConstValSpecialRuntime) {
2277 add_node_error(ira->codegen, fn_value->source_node,2288 add_node_error(ira->codegen, fn_value->source_node,
2278 buf_sprintf("unable to evaluate constant expression"));2289 buf_sprintf("unable to evaluate constant expression"));
2279 return nullptr;2290 return nullptr;
...@@ -2286,7 +2297,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst...@@ -2286,7 +2297,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
2286 IrInstruction *dest_type, IrInstruction *value)2297 IrInstruction *dest_type, IrInstruction *value)
2287{2298{
2288 assert(dest_type->type_entry->id == TypeTableEntryIdMetaType);2299 assert(dest_type->type_entry->id == TypeTableEntryIdMetaType);
2289 assert(dest_type->static_value.ok);2300 assert(dest_type->static_value.special != ConstValSpecialRuntime);
22902301
2291 TypeTableEntry *wanted_type = dest_type->static_value.data.x_type;2302 TypeTableEntry *wanted_type = dest_type->static_value.data.x_type;
2292 TypeTableEntry *actual_type = value->type_entry;2303 TypeTableEntry *actual_type = value->type_entry;
...@@ -2618,7 +2629,7 @@ static TypeTableEntry *ir_analyze_bin_op_bool(IrAnalyze *ira, IrInstructionBinOp...@@ -2618,7 +2629,7 @@ static TypeTableEntry *ir_analyze_bin_op_bool(IrAnalyze *ira, IrInstructionBinOp
26182629
2619 ConstExprValue *op1_val = &casted_op1->static_value;2630 ConstExprValue *op1_val = &casted_op1->static_value;
2620 ConstExprValue *op2_val = &casted_op2->static_value;2631 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) {
2622 bool depends_on_compile_var = op1_val->depends_on_compile_var || op2_val->depends_on_compile_var;2633 bool depends_on_compile_var = op1_val->depends_on_compile_var || op2_val->depends_on_compile_var;
2623 ConstExprValue *out_val = ir_build_const_from(ira, &bin_op_instruction->base, depends_on_compile_var);2634 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...@@ -2710,7 +2721,7 @@ static TypeTableEntry *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp
27102721
2711 ConstExprValue *op1_val = &casted_op1->static_value;2722 ConstExprValue *op1_val = &casted_op1->static_value;
2712 ConstExprValue *op2_val = &casted_op2->static_value;2723 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) {
2714 bool type_can_gt_lt_cmp = (resolved_type->id == TypeTableEntryIdNumLitFloat ||2725 bool type_can_gt_lt_cmp = (resolved_type->id == TypeTableEntryIdNumLitFloat ||
2715 resolved_type->id == TypeTableEntryIdNumLitInt ||2726 resolved_type->id == TypeTableEntryIdNumLitInt ||
2716 resolved_type->id == TypeTableEntryIdFloat ||2727 resolved_type->id == TypeTableEntryIdFloat ||
...@@ -2799,7 +2810,7 @@ static int ir_eval_bignum(ConstExprValue *op1_val, ConstExprValue *op2_val,...@@ -2799,7 +2810,7 @@ static int ir_eval_bignum(ConstExprValue *op1_val, ConstExprValue *op2_val,
2799 }2810 }
2800 }2811 }
28012812
2802 out_val->ok = true;2813 out_val->special = ConstValSpecialStatic;
2803 out_val->depends_on_compile_var = op1_val->depends_on_compile_var || op2_val->depends_on_compile_var;2814 out_val->depends_on_compile_var = op1_val->depends_on_compile_var || op2_val->depends_on_compile_var;
2804 return 0;2815 return 0;
2805}2816}
...@@ -2892,7 +2903,7 @@ static TypeTableEntry *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp...@@ -2892,7 +2903,7 @@ static TypeTableEntry *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp
2892 return ira->codegen->builtin_types.entry_invalid;2903 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) {
2896 ConstExprValue *op1_val = &casted_op1->static_value;2907 ConstExprValue *op1_val = &casted_op1->static_value;
2897 ConstExprValue *op2_val = &casted_op2->static_value;2908 ConstExprValue *op2_val = &casted_op2->static_value;
2898 ConstExprValue *out_val = &bin_op_instruction->base.static_value;2909 ConstExprValue *out_val = &bin_op_instruction->base.static_value;
...@@ -2992,7 +3003,7 @@ static TypeTableEntry *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruc...@@ -2992,7 +3003,7 @@ static TypeTableEntry *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruc
2992 break;3003 break;
2993 case TypeTableEntryIdNumLitFloat:3004 case TypeTableEntryIdNumLitFloat:
2994 case TypeTableEntryIdNumLitInt:3005 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) {
2996 add_node_error(ira->codegen, var_type->source_node, buf_sprintf("unable to infer variable type"));3007 add_node_error(ira->codegen, var_type->source_node, buf_sprintf("unable to infer variable type"));
2997 result_type = ira->codegen->builtin_types.entry_invalid;3008 result_type = ira->codegen->builtin_types.entry_invalid;
2998 }3009 }
...@@ -3006,7 +3017,7 @@ static TypeTableEntry *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruc...@@ -3006,7 +3017,7 @@ static TypeTableEntry *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruc
3006 break;3017 break;
3007 case TypeTableEntryIdMetaType:3018 case TypeTableEntryIdMetaType:
3008 case TypeTableEntryIdNamespace:3019 case TypeTableEntryIdNamespace:
3009 if (!casted_init_value->static_value.ok) {3020 if (casted_init_value->static_value.special == ConstValSpecialRuntime) {
3010 add_node_error(ira->codegen, var_type->source_node,3021 add_node_error(ira->codegen, var_type->source_node,
3011 buf_sprintf("variable of type '%s' must be constant", buf_ptr(&result_type->name)));3022 buf_sprintf("variable of type '%s' must be constant", buf_ptr(&result_type->name)));
3012 result_type = ira->codegen->builtin_types.entry_invalid;3023 result_type = ira->codegen->builtin_types.entry_invalid;
...@@ -3052,7 +3063,7 @@ static TypeTableEntry *ir_analyze_instruction_call(IrAnalyze *ira, IrInstruction...@@ -3052,7 +3063,7 @@ static TypeTableEntry *ir_analyze_instruction_call(IrAnalyze *ira, IrInstruction
3052 if (fn_ref->type_entry->id == TypeTableEntryIdInvalid)3063 if (fn_ref->type_entry->id == TypeTableEntryIdInvalid)
3053 return ira->codegen->builtin_types.entry_invalid;3064 return ira->codegen->builtin_types.entry_invalid;
30543065
3055 if (fn_ref->static_value.ok) {3066 if (fn_ref->static_value.special != ConstValSpecialRuntime) {
3056 if (fn_ref->type_entry->id == TypeTableEntryIdMetaType) {3067 if (fn_ref->type_entry->id == TypeTableEntryIdMetaType) {
3057 size_t actual_param_count = call_instruction->arg_count;3068 size_t actual_param_count = call_instruction->arg_count;
30583069
...@@ -3106,9 +3117,9 @@ static TypeTableEntry *ir_analyze_unary_bool_not(IrAnalyze *ira, IrInstructionUn...@@ -3106,9 +3117,9 @@ static TypeTableEntry *ir_analyze_unary_bool_not(IrAnalyze *ira, IrInstructionUn
3106 return ira->codegen->builtin_types.entry_invalid;3117 return ira->codegen->builtin_types.entry_invalid;
31073118
3108 ConstExprValue *operand_val = &casted_value->static_value;3119 ConstExprValue *operand_val = &casted_value->static_value;
3109 if (operand_val->ok) {3120 if (operand_val->special != ConstValSpecialRuntime) {
3110 ConstExprValue *result_val = &un_op_instruction->base.static_value;3121 ConstExprValue *result_val = &un_op_instruction->base.static_value;
3111 result_val->ok = true;3122 result_val->special = ConstValSpecialStatic;
3112 result_val->depends_on_compile_var = operand_val->depends_on_compile_var;3123 result_val->depends_on_compile_var = operand_val->depends_on_compile_var;
3113 result_val->data.x_bool = !operand_val->data.x_bool;3124 result_val->data.x_bool = !operand_val->data.x_bool;
3114 return bool_type;3125 return bool_type;
...@@ -3204,7 +3215,7 @@ static TypeTableEntry *ir_analyze_unary_address_of(IrAnalyze *ira, IrInstruction...@@ -3204,7 +3215,7 @@ static TypeTableEntry *ir_analyze_unary_address_of(IrAnalyze *ira, IrInstruction
3204 {3215 {
3205 ConstExprValue *out_val = ir_build_const_from(ira, &un_op_instruction->base,3216 ConstExprValue *out_val = ir_build_const_from(ira, &un_op_instruction->base,
3206 value->static_value.depends_on_compile_var);3217 value->static_value.depends_on_compile_var);
3207 assert(value->static_value.ok);3218 assert(value->static_value.special != ConstValSpecialRuntime);
3208 TypeTableEntry *child_type = value->static_value.data.x_type;3219 TypeTableEntry *child_type = value->static_value.data.x_type;
3209 out_val->data.x_type = get_pointer_to_type(ira->codegen, child_type, is_const);3220 out_val->data.x_type = get_pointer_to_type(ira->codegen, child_type, is_const);
3210 return ira->codegen->builtin_types.entry_type;3221 return ira->codegen->builtin_types.entry_type;
...@@ -3252,9 +3263,10 @@ static TypeTableEntry *ir_analyze_dereference(IrAnalyze *ira, IrInstructionUnOp...@@ -3252,9 +3263,10 @@ static TypeTableEntry *ir_analyze_dereference(IrAnalyze *ira, IrInstructionUnOp
3252 // this dereference is always an rvalue because in the IR gen we identify lvalue and emit3263 // this dereference is always an rvalue because in the IR gen we identify lvalue and emit
3253 // one of the ptr instructions3264 // one of the ptr instructions
32543265
3255 if (value->static_value.ok) {3266 if (value->static_value.special != ConstValSpecialRuntime) {
3256 ConstExprValue *out_val = ir_build_const_from(ira, &un_op_instruction->base, false);3267 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;
3258 return child_type;3270 return child_type;
3259 }3271 }
32603272
...@@ -3428,7 +3440,7 @@ static TypeTableEntry *ir_analyze_instruction_cond_br(IrAnalyze *ira, IrInstruct...@@ -3428,7 +3440,7 @@ static TypeTableEntry *ir_analyze_instruction_cond_br(IrAnalyze *ira, IrInstruct
3428 return ir_finish_anal(ira, ira->codegen->builtin_types.entry_unreachable);3440 return ir_finish_anal(ira, ira->codegen->builtin_types.entry_unreachable);
34293441
3430 // TODO detect backward jumps3442 // TODO detect backward jumps
3431 if (condition->static_value.ok) {3443 if (condition->static_value.special != ConstValSpecialRuntime) {
3432 IrBasicBlock *old_dest_block = condition->static_value.data.x_bool ?3444 IrBasicBlock *old_dest_block = condition->static_value.data.x_bool ?
3433 cond_br_instruction->then_block : cond_br_instruction->else_block;3445 cond_br_instruction->then_block : cond_br_instruction->else_block;
34343446
...@@ -3463,7 +3475,7 @@ static TypeTableEntry *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionP...@@ -3463,7 +3475,7 @@ static TypeTableEntry *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionP
3463 continue;3475 continue;
3464 IrInstruction *value = phi_instruction->incoming_values[i]->other;3476 IrInstruction *value = phi_instruction->incoming_values[i]->other;
3465 assert(value->type_entry);3477 assert(value->type_entry);
3466 if (value->static_value.ok) {3478 if (value->static_value.special != ConstValSpecialRuntime) {
3467 ConstExprValue *out_val = ir_build_const_from(ira, &phi_instruction->base,3479 ConstExprValue *out_val = ir_build_const_from(ira, &phi_instruction->base,
3468 value->static_value.depends_on_compile_var);3480 value->static_value.depends_on_compile_var);
3469 *out_val = value->static_value;3481 *out_val = value->static_value;
...@@ -3523,17 +3535,16 @@ static TypeTableEntry *ir_analyze_instruction_var_ptr(IrAnalyze *ira, IrInstruct...@@ -3523,17 +3535,16 @@ static TypeTableEntry *ir_analyze_instruction_var_ptr(IrAnalyze *ira, IrInstruct
3523 } else if (var->src_is_const) {3535 } else if (var->src_is_const) {
3524 AstNode *var_decl_node = var->decl_node;3536 AstNode *var_decl_node = var->decl_node;
3525 assert(var_decl_node->type == NodeTypeVariableDeclaration);3537 assert(var_decl_node->type == NodeTypeVariableDeclaration);
3526 mem_slot = &get_resolved_expr(var_decl_node->data.variable_declaration.expr)->const_val;3538 mem_slot = &get_resolved_expr(var_decl_node->data.variable_declaration.expr)->instruction->static_value;
3527 assert(mem_slot->ok);3539 assert(mem_slot->special != ConstValSpecialRuntime);
3528 }3540 }
35293541
3530 if (mem_slot && mem_slot->ok) {3542 if (mem_slot && mem_slot->special != ConstValSpecialRuntime) {
3531 ConstExprValue *out_val = ir_build_const_from(ira, &var_ptr_instruction->base,3543 ConstExprValue *out_val = ir_build_const_from(ira, &var_ptr_instruction->base,
3532 mem_slot->depends_on_compile_var);3544 mem_slot->depends_on_compile_var);
35333545
3534 out_val->data.x_ptr.len = 1;3546 out_val->data.x_ptr.base_ptr = mem_slot;
3535 out_val->data.x_ptr.ptr = allocate<ConstExprValue *>(1);3547 out_val->data.x_ptr.index = SIZE_MAX;
3536 out_val->data.x_ptr.ptr[0] = mem_slot;
3537 return ptr_type;3548 return ptr_type;
3538 } else {3549 } else {
3539 ir_build_var_ptr_from(&ira->new_irb, &var_ptr_instruction->base, var);3550 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...@@ -3577,7 +3588,7 @@ static TypeTableEntry *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruc
3577 if (casted_elem_index == ira->codegen->invalid_instruction)3588 if (casted_elem_index == ira->codegen->invalid_instruction)
3578 return ira->codegen->builtin_types.entry_invalid;3589 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) {
3581 uint64_t index = casted_elem_index->static_value.data.x_bignum.data.x_uint;3592 uint64_t index = casted_elem_index->static_value.data.x_bignum.data.x_uint;
3582 if (array_type->id == TypeTableEntryIdArray) {3593 if (array_type->id == TypeTableEntryIdArray) {
3583 uint64_t array_len = array_type->data.array.len;3594 uint64_t array_len = array_type->data.array.len;
...@@ -3589,24 +3600,34 @@ static TypeTableEntry *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruc...@@ -3589,24 +3600,34 @@ static TypeTableEntry *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruc
3589 }3600 }
3590 }3601 }
35913602
3592 if (array_ptr->static_value.ok) {3603 if (array_ptr->static_value.special != ConstValSpecialRuntime) {
3593 bool depends_on_compile_var = array_ptr->static_value.depends_on_compile_var ||3604 bool depends_on_compile_var = array_ptr->static_value.depends_on_compile_var ||
3594 casted_elem_index->static_value.depends_on_compile_var;3605 casted_elem_index->static_value.depends_on_compile_var;
3595 ConstExprValue *out_val = ir_build_const_from(ira, &elem_ptr_instruction->base, depends_on_compile_var);3606 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);
3598 if (array_type->id == TypeTableEntryIdPointer) {3607 if (array_type->id == TypeTableEntryIdPointer) {
3599 uint64_t pointer_len = array_ptr->static_value.data.x_ptr.len;3608 size_t offset = array_ptr->static_value.data.x_ptr.index;
3600 if (index >= pointer_len) {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) {
3601 add_node_error(ira->codegen, elem_ptr_instruction->base.source_node,3622 add_node_error(ira->codegen, elem_ptr_instruction->base.source_node,
3602 buf_sprintf("index %" PRIu64 " outside pointer of size %" PRIu64,3623 buf_sprintf("index %" PRIu64 " outside pointer of size %" PRIu64, index, old_size));
3603 index, pointer_len));
3604 return ira->codegen->builtin_types.entry_invalid;3624 return ira->codegen->builtin_types.entry_invalid;
3605 }3625 }
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;
3607 } else if (is_slice(array_type)) {3628 } else if (is_slice(array_type)) {
3608 ConstExprValue *ptr_field = array_ptr->static_value.data.x_struct.fields[0];3629 ConstExprValue *ptr_field = &array_ptr->static_value.data.x_struct.fields[slice_ptr_index];
3609 ConstExprValue *len_field = array_ptr->static_value.data.x_struct.fields[1];3630 ConstExprValue *len_field = &array_ptr->static_value.data.x_struct.fields[slice_len_index];
3610 uint64_t slice_len = len_field->data.x_bignum.data.x_uint;3631 uint64_t slice_len = len_field->data.x_bignum.data.x_uint;
3611 if (index >= slice_len) {3632 if (index >= slice_len) {
3612 add_node_error(ira->codegen, elem_ptr_instruction->base.source_node,3633 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...@@ -3614,10 +3635,18 @@ static TypeTableEntry *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruc
3614 index, slice_len));3635 index, slice_len));
3615 return ira->codegen->builtin_types.entry_invalid;3636 return ira->codegen->builtin_types.entry_invalid;
3616 }3637 }
3617 assert(index < ptr_field->data.x_ptr.len);3638 out_val->data.x_ptr.base_ptr = ptr_field->data.x_ptr.base_ptr;
3618 out_val->data.x_ptr.ptr[0] = ptr_field->data.x_ptr.ptr[index];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 }
3619 } else if (array_type->id == TypeTableEntryIdArray) {3647 } 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;
3621 } else {3650 } else {
3622 zig_unreachable();3651 zig_unreachable();
3623 }3652 }
...@@ -3790,9 +3819,9 @@ static TypeTableEntry *ir_analyze_instruction_load_ptr(IrAnalyze *ira, IrInstruc...@@ -3790,9 +3819,9 @@ static TypeTableEntry *ir_analyze_instruction_load_ptr(IrAnalyze *ira, IrInstruc
3790 return type_entry;3819 return type_entry;
3791 } else if (type_entry->id == TypeTableEntryIdPointer) {3820 } else if (type_entry->id == TypeTableEntryIdPointer) {
3792 TypeTableEntry *child_type = type_entry->data.pointer.child_type;3821 TypeTableEntry *child_type = type_entry->data.pointer.child_type;
3793 if (ptr->static_value.ok) {3822 if (ptr->static_value.special != ConstValSpecialRuntime) {
3794 ConstExprValue *pointee = ptr->static_value.data.x_ptr.ptr[0];3823 ConstExprValue *pointee = const_ptr_pointee(&ptr->static_value);
3795 if (pointee->ok) {3824 if (pointee->special != ConstValSpecialRuntime) {
3796 ConstExprValue *out_val = ir_build_const_from(ira, &load_ptr_instruction->base,3825 ConstExprValue *out_val = ir_build_const_from(ira, &load_ptr_instruction->base,
3797 pointee->depends_on_compile_var);3826 pointee->depends_on_compile_var);
3798 *out_val = *pointee;3827 *out_val = *pointee;
...@@ -3823,18 +3852,20 @@ static TypeTableEntry *ir_analyze_instruction_store_ptr(IrAnalyze *ira, IrInstru...@@ -3823,18 +3852,20 @@ static TypeTableEntry *ir_analyze_instruction_store_ptr(IrAnalyze *ira, IrInstru
3823 if (casted_value == ira->codegen->invalid_instruction)3852 if (casted_value == ira->codegen->invalid_instruction)
3824 return ira->codegen->builtin_types.entry_invalid;3853 return ira->codegen->builtin_types.entry_invalid;
38253854
3826 if (ptr->static_value.ok && casted_value->static_value.ok) {3855 if (ptr->static_value.special != ConstValSpecialRuntime &&
3827 ConstExprValue *dest_val = ptr->static_value.data.x_ptr.ptr[0];3856 casted_value->static_value.special != ConstValSpecialRuntime)
3828 if (dest_val->ok) {3857 {
3858 ConstExprValue *dest_val = const_ptr_pointee(&ptr->static_value);
3859 if (dest_val->special != ConstValSpecialRuntime) {
3829 *dest_val = casted_value->static_value;3860 *dest_val = casted_value->static_value;
3830 return ir_analyze_void(ira, &store_ptr_instruction->base);3861 return ir_analyze_void(ira, &store_ptr_instruction->base);
3831 }3862 }
3832 }3863 }
38333864
3834 if (ptr->static_value.ok) {3865 if (ptr->static_value.special != ConstValSpecialRuntime) {
3835 // This memory location is transforming from known at compile time to known at runtime.3866 // This memory location is transforming from known at compile time to known at runtime.
3836 // We must emit our own var ptr instruction.3867 // We must emit our own var ptr instruction.
3837 ptr->static_value.ok = false;3868 ptr->static_value.special = ConstValSpecialRuntime;
3838 IrInstruction *new_ptr_inst;3869 IrInstruction *new_ptr_inst;
3839 if (ptr->id == IrInstructionIdVarPtr) {3870 if (ptr->id == IrInstructionIdVarPtr) {
3840 IrInstructionVarPtr *var_ptr_inst = (IrInstructionVarPtr *)ptr;3871 IrInstructionVarPtr *var_ptr_inst = (IrInstructionVarPtr *)ptr;
...@@ -3842,7 +3873,7 @@ static TypeTableEntry *ir_analyze_instruction_store_ptr(IrAnalyze *ira, IrInstru...@@ -3842,7 +3873,7 @@ static TypeTableEntry *ir_analyze_instruction_store_ptr(IrAnalyze *ira, IrInstru
3842 new_ptr_inst = ir_build_var_ptr(&ira->new_irb, store_ptr_instruction->base.source_node, var);3873 new_ptr_inst = ir_build_var_ptr(&ira->new_irb, store_ptr_instruction->base.source_node, var);
3843 assert(var->mem_slot_index != SIZE_MAX);3874 assert(var->mem_slot_index != SIZE_MAX);
3844 ConstExprValue *mem_slot = &ira->exec_context.mem_slot_list[var->mem_slot_index];3875 ConstExprValue *mem_slot = &ira->exec_context.mem_slot_list[var->mem_slot_index];
3845 mem_slot->ok = false;3876 mem_slot->special = ConstValSpecialRuntime;
3846 } else if (ptr->id == IrInstructionIdFieldPtr) {3877 } else if (ptr->id == IrInstructionIdFieldPtr) {
3847 zig_panic("TODO");3878 zig_panic("TODO");
3848 } else if (ptr->id == IrInstructionIdElemPtr) {3879 } else if (ptr->id == IrInstructionIdElemPtr) {
...@@ -4236,7 +4267,7 @@ IrInstruction *ir_exec_const_result(IrExecutable *exec) {...@@ -4236,7 +4267,7 @@ IrInstruction *ir_exec_const_result(IrExecutable *exec) {
42364267
4237 IrInstructionReturn *ret_inst = (IrInstructionReturn *)only_inst;4268 IrInstructionReturn *ret_inst = (IrInstructionReturn *)only_inst;
4238 IrInstruction *value = ret_inst->value;4269 IrInstruction *value = ret_inst->value;
4239 assert(value->static_value.ok);4270 assert(value->static_value.special != ConstValSpecialRuntime);
4240 return value;4271 return value;
4241}4272}
42424273
src/ir.hpp+1
...@@ -19,5 +19,6 @@ TypeTableEntry *ir_analyze(CodeGen *g, IrExecutable *old_executable, IrExecutabl...@@ -19,5 +19,6 @@ TypeTableEntry *ir_analyze(CodeGen *g, IrExecutable *old_executable, IrExecutabl
19IrInstruction *ir_exec_const_result(IrExecutable *exec);19IrInstruction *ir_exec_const_result(IrExecutable *exec);
2020
21bool ir_has_side_effects(IrInstruction *instruction);21bool ir_has_side_effects(IrInstruction *instruction);
22ConstExprValue *const_ptr_pointee(ConstExprValue *const_val);
2223
23#endif24#endif
src/ir_print.cpp+6-4
...@@ -23,13 +23,15 @@ static void ir_print_prefix(IrPrint *irp, IrInstruction *instruction) {...@@ -23,13 +23,15 @@ static void ir_print_prefix(IrPrint *irp, IrInstruction *instruction) {
2323
24static void ir_print_const_value(IrPrint *irp, TypeTableEntry *type_entry, ConstExprValue *const_val) {24static void ir_print_const_value(IrPrint *irp, TypeTableEntry *type_entry, ConstExprValue *const_val) {
25 switch (const_val->special) {25 switch (const_val->special) {
26 case ConstValSpecialRuntime:
27 zig_unreachable();
26 case ConstValSpecialUndef:28 case ConstValSpecialUndef:
27 fprintf(irp->f, "undefined");29 fprintf(irp->f, "undefined");
28 return;30 return;
29 case ConstValSpecialZeroes:31 case ConstValSpecialZeroes:
30 fprintf(irp->f, "zeroes");32 fprintf(irp->f, "zeroes");
31 return;33 return;
32 case ConstValSpecialOther:34 case ConstValSpecialStatic:
33 break;35 break;
34 }36 }
35 switch (type_entry->id) {37 switch (type_entry->id) {
...@@ -70,7 +72,7 @@ static void ir_print_const_value(IrPrint *irp, TypeTableEntry *type_entry, Const...@@ -70,7 +72,7 @@ static void ir_print_const_value(IrPrint *irp, TypeTableEntry *type_entry, Const
70 }72 }
71 case TypeTableEntryIdPointer:73 case TypeTableEntryIdPointer:
72 fprintf(irp->f, "&");74 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));
74 break;76 break;
75 case TypeTableEntryIdFn:77 case TypeTableEntryIdFn:
76 {78 {
...@@ -91,7 +93,7 @@ static void ir_print_const_value(IrPrint *irp, TypeTableEntry *type_entry, Const...@@ -91,7 +93,7 @@ static void ir_print_const_value(IrPrint *irp, TypeTableEntry *type_entry, Const
91 for (uint64_t i = 0; i < len; i += 1) {93 for (uint64_t i = 0; i < len; i += 1) {
92 if (i != 0)94 if (i != 0)
93 fprintf(irp->f, ",");95 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];
95 TypeTableEntry *child_type = type_entry->data.array.child_type;97 TypeTableEntry *child_type = type_entry->data.array.child_type;
96 ir_print_const_value(irp, child_type, child_value);98 ir_print_const_value(irp, child_type, child_value);
97 }99 }
...@@ -126,7 +128,7 @@ static void ir_print_var_instruction(IrPrint *irp, IrInstruction *instruction) {...@@ -126,7 +128,7 @@ static void ir_print_var_instruction(IrPrint *irp, IrInstruction *instruction) {
126}128}
127129
128static void ir_print_other_instruction(IrPrint *irp, IrInstruction *instruction) {130static void ir_print_other_instruction(IrPrint *irp, IrInstruction *instruction) {
129 if (instruction->static_value.ok) {131 if (instruction->static_value.special != ConstValSpecialRuntime) {
130 ir_print_const_instruction(irp, instruction);132 ir_print_const_instruction(irp, instruction);
131 } else {133 } else {
132 ir_print_var_instruction(irp, instruction);134 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,...@@ -2763,7 +2763,6 @@ AstNode *ast_clone_subtree_special(AstNode *old_node, uint32_t *next_node_index,
2763 old_node->data.prefix_op_expr.primary_expr, next_node_index);2763 old_node->data.prefix_op_expr.primary_expr, next_node_index);
2764 break;2764 break;
2765 case NodeTypeFnCallExpr:2765 case NodeTypeFnCallExpr:
2766 assert(!old_node->data.fn_call_expr.resolved_expr.has_global_const);
2767 clone_subtree_field(&new_node->data.fn_call_expr.fn_ref_expr,2766 clone_subtree_field(&new_node->data.fn_call_expr.fn_ref_expr,
2768 old_node->data.fn_call_expr.fn_ref_expr, next_node_index);2767 old_node->data.fn_call_expr.fn_ref_expr, next_node_index);
2769 clone_subtree_list(&new_node->data.fn_call_expr.params,2768 clone_subtree_list(&new_node->data.fn_call_expr.params,