authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-06-17 13:31:19-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-06-17 13:31:19-04:00
logb025193de5b951734e5108e4762e5dc40359431b
tree4b29d27c03bbf6604964276ad01d35aab010540e
parent9564c05cd5641095d48baf982a372f00bdf02659
signaturelock-open Commit is signed but in an unrecognized format.

inferred comptime values rather than elided scopes

because of this example: ```zig export fn entry(b: bool) usize { var runtime = [1]i32{3}; comptime var i: usize = 0; inline while (i < 2) : (i += 1) { const result = if (i == 0) [1]i32{2} else runtime; } comptime { return i; } } ``` The problem is that the concept of "resetting" a result location, introduced in the previous commit, cannot handle elision scopes. This concept is inherently broken with inline loops.

5 files changed, 208 insertions(+), 235 deletions(-)

src/all_types.hpp+4-10
...@@ -203,6 +203,9 @@ enum ConstPtrMut {...@@ -203,6 +203,9 @@ enum ConstPtrMut {
203 // The pointer points to memory that is known only at runtime.203 // The pointer points to memory that is known only at runtime.
204 // For example it may point to the initializer value of a variable.204 // For example it may point to the initializer value of a variable.
205 ConstPtrMutRuntimeVar,205 ConstPtrMutRuntimeVar,
206 // The pointer points to memory for which it must be inferred whether the
207 // value is comptime known or not.
208 ConstPtrMutInfer,
206};209};
207210
208struct ConstPtrValue {211struct ConstPtrValue {
...@@ -1957,7 +1960,6 @@ enum ScopeId {...@@ -1957,7 +1960,6 @@ enum ScopeId {
1957 ScopeIdCompTime,1960 ScopeIdCompTime,
1958 ScopeIdCoroPrelude,1961 ScopeIdCoroPrelude,
1959 ScopeIdRuntime,1962 ScopeIdRuntime,
1960 ScopeIdElide,
1961};1963};
19621964
1963struct Scope {1965struct Scope {
...@@ -1971,14 +1973,6 @@ struct Scope {...@@ -1971,14 +1973,6 @@ struct Scope {
1971 ScopeId id;1973 ScopeId id;
1972};1974};
19731975
1974// This scope, when activated, causes all the instructions in the scope to be omitted
1975// from the generated code.
1976struct ScopeElide {
1977 Scope base;
1978
1979 bool activated;
1980};
1981
1982// This scope comes from global declarations or from1976// This scope comes from global declarations or from
1983// declarations in a container declaration1977// declarations in a container declaration
1984// NodeTypeContainerDecl1978// NodeTypeContainerDecl
...@@ -2655,6 +2649,7 @@ struct IrInstructionContainerInitFieldsField {...@@ -2655,6 +2649,7 @@ struct IrInstructionContainerInitFieldsField {
2655 IrInstruction *value;2649 IrInstruction *value;
2656 AstNode *source_node;2650 AstNode *source_node;
2657 TypeStructField *type_struct_field;2651 TypeStructField *type_struct_field;
2652 IrInstruction *result_loc;
2658};2653};
26592654
2660struct IrInstructionContainerInitFields {2655struct IrInstructionContainerInitFields {
...@@ -3655,7 +3650,6 @@ struct ResultLoc {...@@ -3655,7 +3650,6 @@ struct ResultLoc {
3655 IrInstruction *source_instruction;3650 IrInstruction *source_instruction;
3656 IrInstruction *gen_instruction; // value to store to the result loc3651 IrInstruction *gen_instruction; // value to store to the result loc
3657 ZigType *implicit_elem_type;3652 ZigType *implicit_elem_type;
3658 ScopeElide *scope_elide;
3659};3653};
36603654
3661struct ResultLocNone {3655struct ResultLocNone {
src/analyze.cpp+1-34
...@@ -166,12 +166,6 @@ Scope *create_runtime_scope(CodeGen *g, AstNode *node, Scope *parent, IrInstruct...@@ -166,12 +166,6 @@ Scope *create_runtime_scope(CodeGen *g, AstNode *node, Scope *parent, IrInstruct
166 return &scope->base;166 return &scope->base;
167}167}
168168
169ScopeElide *create_elide_scope(CodeGen *g, AstNode *node, Scope *parent) {
170 ScopeElide *scope = allocate<ScopeElide>(1);
171 init_scope(g, &scope->base, ScopeIdElide, node, parent);
172 return scope;
173}
174
175ScopeSuspend *create_suspend_scope(CodeGen *g, AstNode *node, Scope *parent) {169ScopeSuspend *create_suspend_scope(CodeGen *g, AstNode *node, Scope *parent) {
176 assert(node->type == NodeTypeSuspend);170 assert(node->type == NodeTypeSuspend);
177 ScopeSuspend *scope = allocate<ScopeSuspend>(1);171 ScopeSuspend *scope = allocate<ScopeSuspend>(1);
...@@ -4187,6 +4181,7 @@ static uint32_t hash_const_val_ptr(ConstExprValue *const_val) {...@@ -4187,6 +4181,7 @@ static uint32_t hash_const_val_ptr(ConstExprValue *const_val) {
4187 case ConstPtrMutComptimeConst:4181 case ConstPtrMutComptimeConst:
4188 hash_val += (uint32_t)4214318515;4182 hash_val += (uint32_t)4214318515;
4189 break;4183 break;
4184 case ConstPtrMutInfer:
4190 case ConstPtrMutComptimeVar:4185 case ConstPtrMutComptimeVar:
4191 hash_val += (uint32_t)1103195694;4186 hash_val += (uint32_t)1103195694;
4192 break;4187 break;
...@@ -7286,31 +7281,3 @@ void src_assert(bool ok, AstNode *source_node) {...@@ -7286,31 +7281,3 @@ void src_assert(bool ok, AstNode *source_node) {
7286 const char *msg = "assertion failed. This is a bug in the Zig compiler.";7281 const char *msg = "assertion failed. This is a bug in the Zig compiler.";
7287 stage2_panic(msg, strlen(msg));7282 stage2_panic(msg, strlen(msg));
7288}7283}
7289
7290bool scope_is_elided(Scope *scope) {
7291 for (;;) {
7292 switch (scope->id) {
7293 case ScopeIdElide:
7294 if (reinterpret_cast<ScopeElide *>(scope)->activated)
7295 return true;
7296 // fallthrough
7297 case ScopeIdBlock:
7298 case ScopeIdDefer:
7299 case ScopeIdDeferExpr:
7300 case ScopeIdVarDecl:
7301 case ScopeIdLoop:
7302 case ScopeIdSuspend:
7303 case ScopeIdCoroPrelude:
7304 case ScopeIdRuntime:
7305 scope = scope->parent;
7306 continue;
7307 case ScopeIdFnDef:
7308 case ScopeIdCompTime:
7309 case ScopeIdDecls:
7310 case ScopeIdCImport:
7311 return false;
7312 }
7313 zig_unreachable();
7314 }
7315}
7316
src/analyze.hpp-2
...@@ -121,7 +121,6 @@ ScopeFnDef *create_fndef_scope(CodeGen *g, AstNode *node, Scope *parent, ZigFn *...@@ -121,7 +121,6 @@ ScopeFnDef *create_fndef_scope(CodeGen *g, AstNode *node, Scope *parent, ZigFn *
121Scope *create_comptime_scope(CodeGen *g, AstNode *node, Scope *parent);121Scope *create_comptime_scope(CodeGen *g, AstNode *node, Scope *parent);
122Scope *create_coro_prelude_scope(CodeGen *g, AstNode *node, Scope *parent);122Scope *create_coro_prelude_scope(CodeGen *g, AstNode *node, Scope *parent);
123Scope *create_runtime_scope(CodeGen *g, AstNode *node, Scope *parent, IrInstruction *is_comptime);123Scope *create_runtime_scope(CodeGen *g, AstNode *node, Scope *parent, IrInstruction *is_comptime);
124ScopeElide *create_elide_scope(CodeGen *g, AstNode *node, Scope *parent);
125124
126void init_const_str_lit(CodeGen *g, ConstExprValue *const_val, Buf *str);125void init_const_str_lit(CodeGen *g, ConstExprValue *const_val, Buf *str);
127ConstExprValue *create_const_str_lit(CodeGen *g, Buf *str);126ConstExprValue *create_const_str_lit(CodeGen *g, Buf *str);
...@@ -254,6 +253,5 @@ void add_cc_args(CodeGen *g, ZigList<const char *> &args, const char *out_dep_pa...@@ -254,6 +253,5 @@ void add_cc_args(CodeGen *g, ZigList<const char *> &args, const char *out_dep_pa
254void src_assert(bool ok, AstNode *source_node);253void src_assert(bool ok, AstNode *source_node);
255bool is_container(ZigType *type_entry);254bool is_container(ZigType *type_entry);
256ConstExprValue *analyze_const_value(CodeGen *g, Scope *scope, AstNode *node, ZigType *type_entry, Buf *type_name);255ConstExprValue *analyze_const_value(CodeGen *g, Scope *scope, AstNode *node, ZigType *type_entry, Buf *type_name);
257bool scope_is_elided(Scope *scope);
258256
259#endif257#endif
src/codegen.cpp+3-6
...@@ -722,7 +722,6 @@ static ZigLLVMDIScope *get_di_scope(CodeGen *g, Scope *scope) {...@@ -722,7 +722,6 @@ static ZigLLVMDIScope *get_di_scope(CodeGen *g, Scope *scope) {
722 case ScopeIdCompTime:722 case ScopeIdCompTime:
723 case ScopeIdCoroPrelude:723 case ScopeIdCoroPrelude:
724 case ScopeIdRuntime:724 case ScopeIdRuntime:
725 case ScopeIdElide:
726 return get_di_scope(g, scope->parent);725 return get_di_scope(g, scope->parent);
727 }726 }
728 zig_unreachable();727 zig_unreachable();
...@@ -5761,12 +5760,10 @@ static void ir_render(CodeGen *g, ZigFn *fn_entry) {...@@ -5761,12 +5760,10 @@ static void ir_render(CodeGen *g, ZigFn *fn_entry) {
5761 if (instruction->ref_count == 0 && !ir_has_side_effects(instruction))5760 if (instruction->ref_count == 0 && !ir_has_side_effects(instruction))
5762 continue;5761 continue;
57635762
5764 if (!scope_is_elided(instruction->scope)) {5763 if (!g->strip_debug_symbols) {
5765 if (!g->strip_debug_symbols) {5764 set_debug_location(g, instruction);
5766 set_debug_location(g, instruction);
5767 }
5768 instruction->llvm_value = ir_render_instruction(g, executable, instruction);
5769 }5765 }
5766 instruction->llvm_value = ir_render_instruction(g, executable, instruction);
5770 }5767 }
5771 current_block->llvm_exit_block = LLVMGetInsertBlock(g->builder);5768 current_block->llvm_exit_block = LLVMGetInsertBlock(g->builder);
5772 }5769 }
src/ir.cpp+200-183
...@@ -196,6 +196,8 @@ static IrInstruction *ir_analyze_unwrap_error_payload(IrAnalyze *ira, IrInstruct...@@ -196,6 +196,8 @@ static IrInstruction *ir_analyze_unwrap_error_payload(IrAnalyze *ira, IrInstruct
196 IrInstruction *base_ptr, bool safety_check_on, bool initializing);196 IrInstruction *base_ptr, bool safety_check_on, bool initializing);
197static IrInstruction *ir_analyze_unwrap_err_code(IrAnalyze *ira, IrInstruction *source_instr,197static IrInstruction *ir_analyze_unwrap_err_code(IrAnalyze *ira, IrInstruction *source_instr,
198 IrInstruction *base_ptr, bool initializing);198 IrInstruction *base_ptr, bool initializing);
199static IrInstruction *ir_analyze_store_ptr(IrAnalyze *ira, IrInstruction *source_instr,
200 IrInstruction *ptr, IrInstruction *uncasted_value);
199201
200static ConstExprValue *const_ptr_pointee_unchecked(CodeGen *g, ConstExprValue *const_val) {202static ConstExprValue *const_ptr_pointee_unchecked(CodeGen *g, ConstExprValue *const_val) {
201 assert(get_src_ptr_type(const_val->type) != nullptr);203 assert(get_src_ptr_type(const_val->type) != nullptr);
...@@ -3363,7 +3365,6 @@ static void ir_count_defers(IrBuilder *irb, Scope *inner_scope, Scope *outer_sco...@@ -3363,7 +3365,6 @@ static void ir_count_defers(IrBuilder *irb, Scope *inner_scope, Scope *outer_sco
3363 case ScopeIdSuspend:3365 case ScopeIdSuspend:
3364 case ScopeIdCompTime:3366 case ScopeIdCompTime:
3365 case ScopeIdRuntime:3367 case ScopeIdRuntime:
3366 case ScopeIdElide:
3367 scope = scope->parent;3368 scope = scope->parent;
3368 continue;3369 continue;
3369 case ScopeIdDeferExpr:3370 case ScopeIdDeferExpr:
...@@ -3420,7 +3421,6 @@ static bool ir_gen_defers_for_block(IrBuilder *irb, Scope *inner_scope, Scope *o...@@ -3420,7 +3421,6 @@ static bool ir_gen_defers_for_block(IrBuilder *irb, Scope *inner_scope, Scope *o
3420 case ScopeIdSuspend:3421 case ScopeIdSuspend:
3421 case ScopeIdCompTime:3422 case ScopeIdCompTime:
3422 case ScopeIdRuntime:3423 case ScopeIdRuntime:
3423 case ScopeIdElide:
3424 scope = scope->parent;3424 scope = scope->parent;
3425 continue;3425 continue;
3426 case ScopeIdDeferExpr:3426 case ScopeIdDeferExpr:
...@@ -5758,15 +5758,8 @@ static IrInstruction *ir_gen_container_init_expr(IrBuilder *irb, Scope *scope, A...@@ -5758,15 +5758,8 @@ static IrInstruction *ir_gen_container_init_expr(IrBuilder *irb, Scope *scope, A
5758 return irb->codegen->invalid_instruction;5758 return irb->codegen->invalid_instruction;
5759 }5759 }
57605760
5761 IrInstruction *container_ptr = nullptr;5761 IrInstruction *container_ptr = ir_build_resolve_result(irb, scope, node, parent_result_loc,
5762 if (!ir_should_inline(irb->exec, scope)) {5762 container_type);
5763 src_assert(parent_result_loc->scope_elide == nullptr, node);
5764 parent_result_loc->scope_elide = create_elide_scope(irb->codegen, node, scope);
5765
5766 src_assert(parent_result_loc != nullptr, node);
5767 container_ptr = ir_build_resolve_result(irb, &parent_result_loc->scope_elide->base,
5768 node, parent_result_loc, container_type);
5769 }
57705763
5771 size_t field_count = container_init_expr->entries.length;5764 size_t field_count = container_init_expr->entries.length;
5772 IrInstructionContainerInitFieldsField *fields = allocate<IrInstructionContainerInitFieldsField>(field_count);5765 IrInstructionContainerInitFieldsField *fields = allocate<IrInstructionContainerInitFieldsField>(field_count);
...@@ -5777,27 +5770,22 @@ static IrInstruction *ir_gen_container_init_expr(IrBuilder *irb, Scope *scope, A...@@ -5777,27 +5770,22 @@ static IrInstruction *ir_gen_container_init_expr(IrBuilder *irb, Scope *scope, A
5777 Buf *name = entry_node->data.struct_val_field.name;5770 Buf *name = entry_node->data.struct_val_field.name;
5778 AstNode *expr_node = entry_node->data.struct_val_field.expr;5771 AstNode *expr_node = entry_node->data.struct_val_field.expr;
57795772
5780 Scope *val_scope = scope;5773 IrInstruction *field_ptr = ir_build_field_ptr(irb, scope, expr_node, container_ptr, name, true);
5781 ResultLoc *child_result_loc = nullptr;5774 ResultLocInstruction *result_loc_inst = allocate<ResultLocInstruction>(1);
5782 if (container_ptr != nullptr) {5775 result_loc_inst->base.id = ResultLocIdInstruction;
5783 IrInstruction *field_ptr = ir_build_field_ptr(irb, &parent_result_loc->scope_elide->base,5776 result_loc_inst->base.source_instruction = field_ptr;
5784 expr_node, container_ptr, name, true);5777 ir_ref_instruction(field_ptr, irb->current_basic_block);
5785 ResultLocInstruction *result_loc_inst = allocate<ResultLocInstruction>(1);5778 ir_build_reset_result(irb, scope, expr_node, &result_loc_inst->base);
5786 result_loc_inst->base.id = ResultLocIdInstruction;
5787 result_loc_inst->base.source_instruction = field_ptr;
5788 ir_ref_instruction(field_ptr, irb->current_basic_block);
5789 child_result_loc = &result_loc_inst->base;
5790 val_scope = &parent_result_loc->scope_elide->base;
5791 }
57925779
5793 IrInstruction *expr_value = ir_gen_node_extra(irb, expr_node, val_scope, LValNone,5780 IrInstruction *expr_value = ir_gen_node_extra(irb, expr_node, scope, LValNone,
5794 child_result_loc);5781 &result_loc_inst->base);
5795 if (expr_value == irb->codegen->invalid_instruction)5782 if (expr_value == irb->codegen->invalid_instruction)
5796 return expr_value;5783 return expr_value;
57975784
5798 fields[i].name = name;5785 fields[i].name = name;
5799 fields[i].value = expr_value;5786 fields[i].value = expr_value;
5800 fields[i].source_node = entry_node;5787 fields[i].source_node = entry_node;
5788 fields[i].result_loc = field_ptr;
5801 }5789 }
5802 IrInstruction *init_fields = ir_build_container_init_fields(irb, scope, node, container_type,5790 IrInstruction *init_fields = ir_build_container_init_fields(irb, scope, node, container_type,
5803 field_count, fields, container_ptr);5791 field_count, fields, container_ptr);
...@@ -5812,36 +5800,23 @@ static IrInstruction *ir_gen_container_init_expr(IrBuilder *irb, Scope *scope, A...@@ -5812,36 +5800,23 @@ static IrInstruction *ir_gen_container_init_expr(IrBuilder *irb, Scope *scope, A
5812 container_type = ir_build_array_type(irb, scope, node, item_count_inst, elem_type);5800 container_type = ir_build_array_type(irb, scope, node, item_count_inst, elem_type);
5813 }5801 }
58145802
5815 IrInstruction *container_ptr = nullptr;5803 IrInstruction *container_ptr = ir_build_resolve_result(irb, scope, node, parent_result_loc,
5816 if (!ir_should_inline(irb->exec, scope)) {5804 container_type);
5817 src_assert(parent_result_loc->scope_elide == nullptr, node);
5818 parent_result_loc->scope_elide = create_elide_scope(irb->codegen, node, scope);
5819
5820 container_ptr = ir_build_resolve_result(irb, &parent_result_loc->scope_elide->base,
5821 node, parent_result_loc, container_type);
5822 }
58235805
5824 IrInstruction **values = allocate<IrInstruction *>(item_count);5806 IrInstruction **values = allocate<IrInstruction *>(item_count);
5825 for (size_t i = 0; i < item_count; i += 1) {5807 for (size_t i = 0; i < item_count; i += 1) {
5826 AstNode *expr_node = container_init_expr->entries.at(i);5808 AstNode *expr_node = container_init_expr->entries.at(i);
58275809
5828 ResultLoc *child_result_loc = nullptr;5810 IrInstruction *elem_index = ir_build_const_usize(irb, scope, expr_node, i);
5829 Scope *val_scope = scope;5811 IrInstruction *elem_ptr = ir_build_elem_ptr(irb, scope, expr_node, container_ptr, elem_index,
5830 if (container_ptr != nullptr) {5812 false, PtrLenSingle, true);
5831 IrInstruction *elem_index = ir_build_const_usize(irb, &parent_result_loc->scope_elide->base,5813 ResultLocInstruction *result_loc_inst = allocate<ResultLocInstruction>(1);
5832 expr_node, i);5814 result_loc_inst->base.id = ResultLocIdInstruction;
5833 IrInstruction *elem_ptr = ir_build_elem_ptr(irb, &parent_result_loc->scope_elide->base,5815 result_loc_inst->base.source_instruction = elem_ptr;
5834 expr_node, container_ptr, elem_index, false, PtrLenSingle, true);5816 ir_ref_instruction(elem_ptr, irb->current_basic_block);
5835 ResultLocInstruction *result_loc_inst = allocate<ResultLocInstruction>(1);
5836 result_loc_inst->base.id = ResultLocIdInstruction;
5837 result_loc_inst->base.source_instruction = elem_ptr;
5838 ir_ref_instruction(elem_ptr, irb->current_basic_block);
5839 child_result_loc = &result_loc_inst->base;
5840 val_scope = &parent_result_loc->scope_elide->base;
5841 }
58425817
5843 IrInstruction *expr_value = ir_gen_node_extra(irb, expr_node, val_scope, LValNone,5818 IrInstruction *expr_value = ir_gen_node_extra(irb, expr_node, scope, LValNone,
5844 child_result_loc);5819 &result_loc_inst->base);
5845 if (expr_value == irb->codegen->invalid_instruction)5820 if (expr_value == irb->codegen->invalid_instruction)
5846 return expr_value;5821 return expr_value;
58475822
...@@ -8651,8 +8626,6 @@ static ConstExprValue *ir_exec_const_result(CodeGen *codegen, IrExecutable *exec...@@ -8651,8 +8626,6 @@ static ConstExprValue *ir_exec_const_result(CodeGen *codegen, IrExecutable *exec
8651 IrBasicBlock *bb = exec->basic_block_list.at(0);8626 IrBasicBlock *bb = exec->basic_block_list.at(0);
8652 for (size_t i = 0; i < bb->instruction_list.length; i += 1) {8627 for (size_t i = 0; i < bb->instruction_list.length; i += 1) {
8653 IrInstruction *instruction = bb->instruction_list.at(i);8628 IrInstruction *instruction = bb->instruction_list.at(i);
8654 if (scope_is_elided(instruction->scope))
8655 continue;
8656 if (instruction->id == IrInstructionIdReturn) {8629 if (instruction->id == IrInstructionIdReturn) {
8657 IrInstructionReturn *ret_inst = (IrInstructionReturn *)instruction;8630 IrInstructionReturn *ret_inst = (IrInstructionReturn *)instruction;
8658 IrInstruction *value = ret_inst->value;8631 IrInstruction *value = ret_inst->value;
...@@ -12745,9 +12718,7 @@ static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruc...@@ -12745,9 +12718,7 @@ static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruc
12745 ir_add_error(ira, ptr, buf_sprintf("attempt to dereference undefined value"));12718 ir_add_error(ira, ptr, buf_sprintf("attempt to dereference undefined value"));
12746 return ira->codegen->invalid_instruction;12719 return ira->codegen->invalid_instruction;
12747 }12720 }
12748 if (ptr->value.data.x_ptr.mut == ConstPtrMutComptimeConst ||12721 if (ptr->value.data.x_ptr.mut != ConstPtrMutRuntimeVar) {
12749 ptr->value.data.x_ptr.mut == ConstPtrMutComptimeVar)
12750 {
12751 ConstExprValue *pointee = const_ptr_pointee_unchecked(ira->codegen, &ptr->value);12722 ConstExprValue *pointee = const_ptr_pointee_unchecked(ira->codegen, &ptr->value);
12752 if (pointee->special != ConstValSpecialRuntime) {12723 if (pointee->special != ConstValSpecialRuntime) {
12753 IrInstruction *result = ir_const(ira, source_instruction, child_type);12724 IrInstruction *result = ir_const(ira, source_instruction, child_type);
...@@ -14487,7 +14458,25 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira,...@@ -14487,7 +14458,25 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira,
14487 }14458 }
1448814459
14489 if (init_val != nullptr && init_val->special != ConstValSpecialRuntime) {14460 if (init_val != nullptr && init_val->special != ConstValSpecialRuntime) {
14490 if (var->mem_slot_index != SIZE_MAX) {14461 // Resolve ConstPtrMutInfer
14462 if (var->gen_is_const) {
14463 var_ptr->value.data.x_ptr.mut = ConstPtrMutComptimeConst;
14464 } else if (is_comptime_var) {
14465 var_ptr->value.data.x_ptr.mut = ConstPtrMutComptimeVar;
14466 } else {
14467 // we need a runtime ptr but we have a comptime val.
14468 // since it's a comptime val there are no instructions for it.
14469 // we memcpy the init value here
14470 IrInstruction *deref = ir_get_deref(ira, var_ptr, var_ptr, nullptr);
14471 // If this assertion trips, something is wrong with the IR instructions, because
14472 // we expected the above deref to return a constant value, but it created a runtime
14473 // instruction.
14474 assert(deref->value.special != ConstValSpecialRuntime);
14475 var_ptr->value.special = ConstValSpecialRuntime;
14476 ir_analyze_store_ptr(ira, var_ptr, var_ptr, deref);
14477 }
14478
14479 if (var_ptr->value.special == ConstValSpecialStatic && var->mem_slot_index != SIZE_MAX) {
14491 assert(var->mem_slot_index < ira->exec_context.mem_slot_list.length);14480 assert(var->mem_slot_index < ira->exec_context.mem_slot_list.length);
14492 ConstExprValue *mem_slot = ira->exec_context.mem_slot_list.at(var->mem_slot_index);14481 ConstExprValue *mem_slot = ira->exec_context.mem_slot_list.at(var->mem_slot_index);
14493 copy_const_val(mem_slot, init_val, !is_comptime_var || var->gen_is_const);14482 copy_const_val(mem_slot, init_val, !is_comptime_var || var->gen_is_const);
...@@ -14818,9 +14807,9 @@ static IrInstruction *ir_analyze_alloca(IrAnalyze *ira, IrInstruction *source_in...@@ -14818,9 +14807,9 @@ static IrInstruction *ir_analyze_alloca(IrAnalyze *ira, IrInstruction *source_in
14818 pointee->special = ConstValSpecialUndef;14807 pointee->special = ConstValSpecialUndef;
1481914808
14820 IrInstructionAllocaGen *result = ir_create_alloca_gen(ira, source_inst, align, name_hint);14809 IrInstructionAllocaGen *result = ir_create_alloca_gen(ira, source_inst, align, name_hint);
14821 result->base.value.special = force_comptime ? ConstValSpecialStatic : ConstValSpecialRuntime;14810 result->base.value.special = ConstValSpecialStatic;
14822 result->base.value.data.x_ptr.special = ConstPtrSpecialRef;14811 result->base.value.data.x_ptr.special = ConstPtrSpecialRef;
14823 result->base.value.data.x_ptr.mut = force_comptime ? ConstPtrMutComptimeVar : ConstPtrMutRuntimeVar;14812 result->base.value.data.x_ptr.mut = force_comptime ? ConstPtrMutComptimeVar : ConstPtrMutInfer;
14824 result->base.value.data.x_ptr.data.ref.pointee = pointee;14813 result->base.value.data.x_ptr.data.ref.pointee = pointee;
1482514814
14826 if ((err = type_resolve(ira->codegen, var_type, ResolveStatusZeroBitsKnown)))14815 if ((err = type_resolve(ira->codegen, var_type, ResolveStatusZeroBitsKnown)))
...@@ -15109,7 +15098,10 @@ static IrInstruction *ir_analyze_instruction_resolve_result(IrAnalyze *ira, IrIn...@@ -15109,7 +15098,10 @@ static IrInstruction *ir_analyze_instruction_resolve_result(IrAnalyze *ira, IrIn
15109 ZigType *implicit_elem_type = ir_resolve_type(ira, instruction->ty->child);15098 ZigType *implicit_elem_type = ir_resolve_type(ira, instruction->ty->child);
15110 if (type_is_invalid(implicit_elem_type))15099 if (type_is_invalid(implicit_elem_type))
15111 return ira->codegen->invalid_instruction;15100 return ira->codegen->invalid_instruction;
15112 return ir_resolve_result(ira, &instruction->base, instruction->result_loc, implicit_elem_type, nullptr);15101 IrInstruction *result_loc = ir_resolve_result(ira, &instruction->base, instruction->result_loc, implicit_elem_type, nullptr);
15102 if (result_loc != nullptr)
15103 return result_loc;
15104 zig_panic("TODO");
15113}15105}
1511415106
15115static void ir_reset_result(ResultLoc *result_loc) {15107static void ir_reset_result(ResultLoc *result_loc) {
...@@ -15431,7 +15423,9 @@ static IrInstruction *ir_analyze_store_ptr(IrAnalyze *ira, IrInstruction *source...@@ -15431,7 +15423,9 @@ static IrInstruction *ir_analyze_store_ptr(IrAnalyze *ira, IrInstruction *source
15431 ir_add_error(ira, source_instr, buf_sprintf("cannot assign to constant"));15423 ir_add_error(ira, source_instr, buf_sprintf("cannot assign to constant"));
15432 return ira->codegen->invalid_instruction;15424 return ira->codegen->invalid_instruction;
15433 }15425 }
15434 if (ptr->value.data.x_ptr.mut == ConstPtrMutComptimeVar) {15426 if (ptr->value.data.x_ptr.mut == ConstPtrMutComptimeVar ||
15427 ptr->value.data.x_ptr.mut == ConstPtrMutInfer)
15428 {
15435 if (instr_is_comptime(value)) {15429 if (instr_is_comptime(value)) {
15436 ConstExprValue *dest_val = const_ptr_pointee(ira, ira->codegen, &ptr->value, source_instr->source_node);15430 ConstExprValue *dest_val = const_ptr_pointee(ira, ira->codegen, &ptr->value, source_instr->source_node);
15437 if (dest_val == nullptr)15431 if (dest_val == nullptr)
...@@ -15451,12 +15445,16 @@ static IrInstruction *ir_analyze_store_ptr(IrAnalyze *ira, IrInstruction *source...@@ -15451,12 +15445,16 @@ static IrInstruction *ir_analyze_store_ptr(IrAnalyze *ira, IrInstruction *source
15451 return ir_const_void(ira, source_instr);15445 return ir_const_void(ira, source_instr);
15452 }15446 }
15453 }15447 }
15454 ir_add_error(ira, source_instr,15448 if (ptr->value.data.x_ptr.mut == ConstPtrMutInfer) {
15455 buf_sprintf("cannot store runtime value in compile time variable"));15449 ptr->value.special = ConstValSpecialRuntime;
15456 ConstExprValue *dest_val = const_ptr_pointee_unchecked(ira->codegen, &ptr->value);15450 } else {
15457 dest_val->type = ira->codegen->builtin_types.entry_invalid;15451 ir_add_error(ira, source_instr,
15452 buf_sprintf("cannot store runtime value in compile time variable"));
15453 ConstExprValue *dest_val = const_ptr_pointee_unchecked(ira->codegen, &ptr->value);
15454 dest_val->type = ira->codegen->builtin_types.entry_invalid;
1545815455
15459 return ira->codegen->invalid_instruction;15456 return ira->codegen->invalid_instruction;
15457 }
15460 }15458 }
15461 }15459 }
1546215460
...@@ -17091,6 +17089,81 @@ static IrInstruction *ir_analyze_container_member_access_inner(IrAnalyze *ira,...@@ -17091,6 +17089,81 @@ static IrInstruction *ir_analyze_container_member_access_inner(IrAnalyze *ira,
17091 return ira->codegen->invalid_instruction;17089 return ira->codegen->invalid_instruction;
17092}17090}
1709317091
17092static IrInstruction *ir_analyze_struct_field_ptr(IrAnalyze *ira, IrInstruction *source_instr,
17093 TypeStructField *field, IrInstruction *struct_ptr, ZigType *struct_type, bool initializing)
17094{
17095 switch (type_has_one_possible_value(ira->codegen, field->type_entry)) {
17096 case OnePossibleValueInvalid:
17097 return ira->codegen->invalid_instruction;
17098 case OnePossibleValueYes: {
17099 IrInstruction *elem = ir_const(ira, source_instr, field->type_entry);
17100 return ir_get_ref(ira, source_instr, elem, false, false);
17101 }
17102 case OnePossibleValueNo:
17103 break;
17104 }
17105 assert(struct_ptr->value.type->id == ZigTypeIdPointer);
17106 bool is_packed = (struct_type->data.structure.layout == ContainerLayoutPacked);
17107 uint32_t align_bytes = is_packed ? 1 : get_abi_alignment(ira->codegen, field->type_entry);
17108 uint32_t ptr_bit_offset = struct_ptr->value.type->data.pointer.bit_offset_in_host;
17109 uint32_t ptr_host_int_bytes = struct_ptr->value.type->data.pointer.host_int_bytes;
17110 uint32_t host_int_bytes_for_result_type = (ptr_host_int_bytes == 0) ?
17111 get_host_int_bytes(ira->codegen, struct_type, field) : ptr_host_int_bytes;
17112 bool is_const = struct_ptr->value.type->data.pointer.is_const;
17113 bool is_volatile = struct_ptr->value.type->data.pointer.is_volatile;
17114 ZigType *ptr_type = get_pointer_to_type_extra(ira->codegen, field->type_entry,
17115 is_const, is_volatile, PtrLenSingle, align_bytes,
17116 (uint32_t)(ptr_bit_offset + field->bit_offset_in_host),
17117 (uint32_t)host_int_bytes_for_result_type, false);
17118 if (instr_is_comptime(struct_ptr)) {
17119 ConstExprValue *ptr_val = ir_resolve_const(ira, struct_ptr, UndefBad);
17120 if (!ptr_val)
17121 return ira->codegen->invalid_instruction;
17122
17123 if (ptr_val->data.x_ptr.special != ConstPtrSpecialHardCodedAddr) {
17124 ConstExprValue *struct_val = const_ptr_pointee(ira, ira->codegen, ptr_val, source_instr->source_node);
17125 if (struct_val == nullptr)
17126 return ira->codegen->invalid_instruction;
17127 if (type_is_invalid(struct_val->type))
17128 return ira->codegen->invalid_instruction;
17129 if (struct_val->special == ConstValSpecialUndef && initializing) {
17130 struct_val->data.x_struct.fields = create_const_vals(struct_type->data.structure.src_field_count);
17131 struct_val->special = ConstValSpecialStatic;
17132 for (size_t i = 0; i < struct_type->data.structure.src_field_count; i += 1) {
17133 ConstExprValue *field_val = &struct_val->data.x_struct.fields[i];
17134 field_val->special = ConstValSpecialUndef;
17135 field_val->type = struct_type->data.structure.fields[i].type_entry;
17136 ConstParent *parent = get_const_val_parent(ira->codegen, field_val);
17137 if (parent != nullptr) {
17138 parent->id = ConstParentIdStruct;
17139 parent->data.p_struct.struct_val = struct_val;
17140 parent->data.p_struct.field_index = i;
17141 }
17142 }
17143 }
17144 IrInstruction *result;
17145 if (ptr_val->data.x_ptr.mut == ConstPtrMutInfer) {
17146 result = ir_build_struct_field_ptr(&ira->new_irb, source_instr->scope,
17147 source_instr->source_node, struct_ptr, field);
17148 result->value.type = ptr_type;
17149 result->value.special = ConstValSpecialStatic;
17150 } else {
17151 result = ir_const(ira, source_instr, ptr_type);
17152 }
17153 ConstExprValue *const_val = &result->value;
17154 const_val->data.x_ptr.special = ConstPtrSpecialBaseStruct;
17155 const_val->data.x_ptr.mut = struct_ptr->value.data.x_ptr.mut;
17156 const_val->data.x_ptr.data.base_struct.struct_val = struct_val;
17157 const_val->data.x_ptr.data.base_struct.field_index = field->src_index;
17158 return result;
17159 }
17160 }
17161 IrInstruction *result = ir_build_struct_field_ptr(&ira->new_irb, source_instr->scope, source_instr->source_node,
17162 struct_ptr, field);
17163 result->value.type = ptr_type;
17164 return result;
17165}
17166
17094static IrInstruction *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_name,17167static IrInstruction *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_name,
17095 IrInstruction *source_instr, IrInstruction *container_ptr, ZigType *container_type, bool initializing)17168 IrInstruction *source_instr, IrInstruction *container_ptr, ZigType *container_type, bool initializing)
17096{17169{
...@@ -17101,59 +17174,10 @@ static IrInstruction *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_...@@ -17101,59 +17174,10 @@ static IrInstruction *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_
17101 return ira->codegen->invalid_instruction;17174 return ira->codegen->invalid_instruction;
1710217175
17103 assert(container_ptr->value.type->id == ZigTypeIdPointer);17176 assert(container_ptr->value.type->id == ZigTypeIdPointer);
17104 bool is_const = container_ptr->value.type->data.pointer.is_const;
17105 bool is_volatile = container_ptr->value.type->data.pointer.is_volatile;
17106 if (bare_type->id == ZigTypeIdStruct) {17177 if (bare_type->id == ZigTypeIdStruct) {
17107 TypeStructField *field = find_struct_type_field(bare_type, field_name);17178 TypeStructField *field = find_struct_type_field(bare_type, field_name);
17108 if (field) {17179 if (field != nullptr) {
17109 switch (type_has_one_possible_value(ira->codegen, field->type_entry)) {17180 return ir_analyze_struct_field_ptr(ira, source_instr, field, container_ptr, bare_type, initializing);
17110 case OnePossibleValueInvalid:
17111 return ira->codegen->invalid_instruction;
17112 case OnePossibleValueYes: {
17113 IrInstruction *elem = ir_const(ira, source_instr, field->type_entry);
17114 return ir_get_ref(ira, source_instr, elem, false, false);
17115 }
17116 case OnePossibleValueNo:
17117 break;
17118 }
17119 bool is_packed = (bare_type->data.structure.layout == ContainerLayoutPacked);
17120 uint32_t align_bytes = is_packed ? 1 : get_abi_alignment(ira->codegen, field->type_entry);
17121 uint32_t ptr_bit_offset = container_ptr->value.type->data.pointer.bit_offset_in_host;
17122 uint32_t ptr_host_int_bytes = container_ptr->value.type->data.pointer.host_int_bytes;
17123 uint32_t host_int_bytes_for_result_type = (ptr_host_int_bytes == 0) ?
17124 get_host_int_bytes(ira->codegen, bare_type, field) : ptr_host_int_bytes;
17125 if (instr_is_comptime(container_ptr)) {
17126 ConstExprValue *ptr_val = ir_resolve_const(ira, container_ptr, UndefBad);
17127 if (!ptr_val)
17128 return ira->codegen->invalid_instruction;
17129
17130 if (ptr_val->data.x_ptr.special != ConstPtrSpecialHardCodedAddr) {
17131 ConstExprValue *struct_val = const_ptr_pointee(ira, ira->codegen, ptr_val, source_instr->source_node);
17132 if (struct_val == nullptr)
17133 return ira->codegen->invalid_instruction;
17134 if (type_is_invalid(struct_val->type))
17135 return ira->codegen->invalid_instruction;
17136 ZigType *ptr_type = get_pointer_to_type_extra(ira->codegen, field->type_entry,
17137 is_const, is_volatile, PtrLenSingle, align_bytes,
17138 (uint32_t)(ptr_bit_offset + field->bit_offset_in_host),
17139 (uint32_t)host_int_bytes_for_result_type, false);
17140 IrInstruction *result = ir_const(ira, source_instr, ptr_type);
17141 ConstExprValue *const_val = &result->value;
17142 const_val->data.x_ptr.special = ConstPtrSpecialBaseStruct;
17143 const_val->data.x_ptr.mut = container_ptr->value.data.x_ptr.mut;
17144 const_val->data.x_ptr.data.base_struct.struct_val = struct_val;
17145 const_val->data.x_ptr.data.base_struct.field_index = field->src_index;
17146 return result;
17147 }
17148 }
17149 IrInstruction *result = ir_build_struct_field_ptr(&ira->new_irb, source_instr->scope, source_instr->source_node,
17150 container_ptr, field);
17151 result->value.type = get_pointer_to_type_extra(ira->codegen, field->type_entry, is_const, is_volatile,
17152 PtrLenSingle,
17153 align_bytes,
17154 (uint32_t)(ptr_bit_offset + field->bit_offset_in_host),
17155 host_int_bytes_for_result_type, false);
17156 return result;
17157 } else {17181 } else {
17158 return ir_analyze_container_member_access_inner(ira, bare_type, field_name,17182 return ir_analyze_container_member_access_inner(ira, bare_type, field_name,
17159 source_instr, container_ptr, container_type);17183 source_instr, container_ptr, container_type);
...@@ -17162,6 +17186,9 @@ static IrInstruction *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_...@@ -17162,6 +17186,9 @@ static IrInstruction *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_
17162 return ir_analyze_container_member_access_inner(ira, bare_type, field_name,17186 return ir_analyze_container_member_access_inner(ira, bare_type, field_name,
17163 source_instr, container_ptr, container_type);17187 source_instr, container_ptr, container_type);
17164 } else if (bare_type->id == ZigTypeIdUnion) {17188 } else if (bare_type->id == ZigTypeIdUnion) {
17189 bool is_const = container_ptr->value.type->data.pointer.is_const;
17190 bool is_volatile = container_ptr->value.type->data.pointer.is_volatile;
17191
17165 TypeUnionField *field = find_union_type_field(bare_type, field_name);17192 TypeUnionField *field = find_union_type_field(bare_type, field_name);
17166 if (field) {17193 if (field) {
17167 if (instr_is_comptime(container_ptr)) {17194 if (instr_is_comptime(container_ptr)) {
...@@ -18849,7 +18876,7 @@ static IrInstruction *ir_analyze_instruction_ref(IrAnalyze *ira, IrInstructionRe...@@ -18849,7 +18876,7 @@ static IrInstruction *ir_analyze_instruction_ref(IrAnalyze *ira, IrInstructionRe
1884918876
18850static IrInstruction *ir_analyze_container_init_fields_union(IrAnalyze *ira, IrInstruction *instruction,18877static IrInstruction *ir_analyze_container_init_fields_union(IrAnalyze *ira, IrInstruction *instruction,
18851 ZigType *container_type, size_t instr_field_count, IrInstructionContainerInitFieldsField *fields,18878 ZigType *container_type, size_t instr_field_count, IrInstructionContainerInitFieldsField *fields,
18852 IrInstruction *old_result_loc)18879 IrInstruction *result_loc)
18853{18880{
18854 Error err;18881 Error err;
18855 assert(container_type->id == ZigTypeIdUnion);18882 assert(container_type->id == ZigTypeIdUnion);
...@@ -18905,21 +18932,17 @@ static IrInstruction *ir_analyze_container_init_fields_union(IrAnalyze *ira, IrI...@@ -18905,21 +18932,17 @@ static IrInstruction *ir_analyze_container_init_fields_union(IrAnalyze *ira, IrI
18905 return result;18932 return result;
18906 }18933 }
1890718934
18908 ir_assert(old_result_loc != nullptr, instruction);
18909 IrInstruction *result_loc = old_result_loc->child;
18910 if (type_is_invalid(result_loc->value.type))
18911 return result_loc;
18912 return ir_get_deref(ira, instruction, result_loc, nullptr);18935 return ir_get_deref(ira, instruction, result_loc, nullptr);
18913}18936}
1891418937
18915static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruction *instruction,18938static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruction *instruction,
18916 ZigType *container_type, size_t instr_field_count, IrInstructionContainerInitFieldsField *fields,18939 ZigType *container_type, size_t instr_field_count, IrInstructionContainerInitFieldsField *fields,
18917 IrInstruction *old_result_loc)18940 IrInstruction *result_loc)
18918{18941{
18919 Error err;18942 Error err;
18920 if (container_type->id == ZigTypeIdUnion) {18943 if (container_type->id == ZigTypeIdUnion) {
18921 return ir_analyze_container_init_fields_union(ira, instruction, container_type, instr_field_count,18944 return ir_analyze_container_init_fields_union(ira, instruction, container_type, instr_field_count,
18922 fields, old_result_loc);18945 fields, result_loc);
18923 }18946 }
18924 if (container_type->id != ZigTypeIdStruct || is_slice(container_type)) {18947 if (container_type->id != ZigTypeIdStruct || is_slice(container_type)) {
18925 ir_add_error(ira, instruction,18948 ir_add_error(ira, instruction,
...@@ -18936,20 +18959,28 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc...@@ -18936,20 +18959,28 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc
18936 IrInstruction *first_non_const_instruction = nullptr;18959 IrInstruction *first_non_const_instruction = nullptr;
1893718960
18938 AstNode **field_assign_nodes = allocate<AstNode *>(actual_field_count);18961 AstNode **field_assign_nodes = allocate<AstNode *>(actual_field_count);
18962 ZigList<IrInstruction *> const_ptrs = {};
1893918963
18940 bool is_comptime = ir_should_inline(ira->new_irb.exec, instruction->scope)18964 bool is_comptime = ir_should_inline(ira->new_irb.exec, instruction->scope)
18941 || type_requires_comptime(ira->codegen, container_type) == ReqCompTimeYes;18965 || type_requires_comptime(ira->codegen, container_type) == ReqCompTimeYes;
1894218966
18943 ConstExprValue const_val = {};18967
18944 const_val.special = ConstValSpecialStatic;18968 // Here we iterate over the fields that have been initialized, and emit
18945 const_val.type = container_type;18969 // compile errors for missing fields and duplicate fields.
18946 // const_val.global_refs = allocate<ConstGlobalRefs>(1);18970 // It is only now that we find out whether the struct initialization can be a comptime
18947 const_val.data.x_struct.fields = create_const_vals(actual_field_count);18971 // value, but we have already emitted runtime instructions for the fields that
18972 // were initialized with runtime values, and have omitted instructions that would have
18973 // initialized fields with comptime values.
18974 // So now we must clean up this situation. If it turns out the struct initialization can
18975 // be a comptime value, overwrite ConstPtrMutInfer with ConstPtrMutComptimeConst.
18976 // Otherwise, we must emit instructions to runtime-initialize the fields that have
18977 // comptime-known values.
18978
18948 for (size_t i = 0; i < instr_field_count; i += 1) {18979 for (size_t i = 0; i < instr_field_count; i += 1) {
18949 IrInstructionContainerInitFieldsField *field = &fields[i];18980 IrInstructionContainerInitFieldsField *field = &fields[i];
1895018981
18951 IrInstruction *field_value = field->value->child;18982 IrInstruction *field_result_loc = field->result_loc->child;
18952 if (type_is_invalid(field_value->value.type))18983 if (type_is_invalid(field_result_loc->value.type))
18953 return ira->codegen->invalid_instruction;18984 return ira->codegen->invalid_instruction;
1895418985
18955 TypeStructField *type_field = find_struct_type_field(container_type, field->name);18986 TypeStructField *type_field = find_struct_type_field(container_type, field->name);
...@@ -18963,10 +18994,6 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc...@@ -18963,10 +18994,6 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc
18963 if (type_is_invalid(type_field->type_entry))18994 if (type_is_invalid(type_field->type_entry))
18964 return ira->codegen->invalid_instruction;18995 return ira->codegen->invalid_instruction;
1896518996
18966 IrInstruction *casted_field_value = ir_implicit_cast(ira, field_value, type_field->type_entry);
18967 if (casted_field_value == ira->codegen->invalid_instruction)
18968 return ira->codegen->invalid_instruction;
18969
18970 size_t field_index = type_field->src_index;18997 size_t field_index = type_field->src_index;
18971 AstNode *existing_assign_node = field_assign_nodes[field_index];18998 AstNode *existing_assign_node = field_assign_nodes[field_index];
18972 if (existing_assign_node) {18999 if (existing_assign_node) {
...@@ -18976,23 +19003,18 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc...@@ -18976,23 +19003,18 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc
18976 }19003 }
18977 field_assign_nodes[field_index] = field->source_node;19004 field_assign_nodes[field_index] = field->source_node;
1897819005
18979 if (const_val.special == ConstValSpecialStatic) {19006 if (instr_is_comptime(field_result_loc) &&
18980 if (is_comptime || casted_field_value->value.special != ConstValSpecialRuntime) {19007 field_result_loc->value.data.x_ptr.mut != ConstPtrMutRuntimeVar)
18981 ConstExprValue *field_val = ir_resolve_const(ira, casted_field_value, UndefOk);19008 {
18982 if (!field_val)19009 const_ptrs.append(field_result_loc);
18983 return ira->codegen->invalid_instruction;19010 } else {
1898419011 first_non_const_instruction = field_result_loc;
18985 copy_const_val(&const_val.data.x_struct.fields[field_index], field_val, true);
18986 } else {
18987 first_non_const_instruction = casted_field_value;
18988 const_val.special = ConstValSpecialRuntime;
18989 }
18990 }19012 }
18991 }19013 }
1899219014
18993 bool any_missing = false;19015 bool any_missing = false;
18994 for (size_t i = 0; i < actual_field_count; i += 1) {19016 for (size_t i = 0; i < actual_field_count; i += 1) {
18995 if (field_assign_nodes[i]) continue;19017 if (field_assign_nodes[i] != nullptr) continue;
1899619018
18997 // look for a default field value19019 // look for a default field value
18998 TypeStructField *field = &container_type->data.structure.fields[i];19020 TypeStructField *field = &container_type->data.structure.fields[i];
...@@ -19018,44 +19040,41 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc...@@ -19018,44 +19040,41 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc
19018 IrInstruction *runtime_inst = ir_const(ira, instruction, field->init_val->type);19040 IrInstruction *runtime_inst = ir_const(ira, instruction, field->init_val->type);
19019 copy_const_val(&runtime_inst->value, field->init_val, true);19041 copy_const_val(&runtime_inst->value, field->init_val, true);
1902019042
19021 if (const_val.special == ConstValSpecialStatic) {19043 IrInstruction *field_ptr = ir_analyze_struct_field_ptr(ira, instruction, field, result_loc,
19022 copy_const_val(&const_val.data.x_struct.fields[i], field->init_val, true);19044 container_type, true);
19045 ir_analyze_store_ptr(ira, instruction, field_ptr, runtime_inst);
19046 if (instr_is_comptime(field_ptr) && field_ptr->value.data.x_ptr.mut != ConstPtrMutRuntimeVar) {
19047 const_ptrs.append(field_ptr);
19048 } else {
19049 first_non_const_instruction = result_loc;
19023 }19050 }
19024 }19051 }
19025 if (any_missing)19052 if (any_missing)
19026 return ira->codegen->invalid_instruction;19053 return ira->codegen->invalid_instruction;
1902719054
19028 if (const_val.special == ConstValSpecialStatic) {19055 if (result_loc->value.data.x_ptr.mut == ConstPtrMutInfer) {
19029 IrInstruction *result = ir_const(ira, instruction, nullptr);19056 if (const_ptrs.length == actual_field_count) {
19030 ConstExprValue *out_val = &result->value;19057 result_loc->value.data.x_ptr.mut = ConstPtrMutComptimeConst;
19031 copy_const_val(out_val, &const_val, false);19058 } else {
19032 out_val->type = container_type;19059 result_loc->value.special = ConstValSpecialRuntime;
1903319060 for (size_t i = 0; i < const_ptrs.length; i += 1) {
19034 for (size_t i = 0; i < instr_field_count; i += 1) {19061 IrInstruction *field_result_loc = const_ptrs.at(i);
19035 ConstExprValue *field_val = &out_val->data.x_struct.fields[i];19062 IrInstruction *deref = ir_get_deref(ira, field_result_loc, field_result_loc, nullptr);
19036 ConstParent *parent = get_const_val_parent(ira->codegen, field_val);19063 field_result_loc->value.special = ConstValSpecialRuntime;
19037 if (parent != nullptr) {19064 ir_analyze_store_ptr(ira, field_result_loc, field_result_loc, deref);
19038 parent->id = ConstParentIdStruct;
19039 parent->data.p_struct.field_index = i;
19040 parent->data.p_struct.struct_val = out_val;
19041 }19065 }
19042 }19066 }
19043
19044 return result;
19045 }19067 }
1904619068
19047 if (is_comptime) {19069 IrInstruction *result = ir_get_deref(ira, instruction, result_loc, nullptr);
19070
19071 if (is_comptime && !instr_is_comptime(result)) {
19048 ir_add_error_node(ira, first_non_const_instruction->source_node,19072 ir_add_error_node(ira, first_non_const_instruction->source_node,
19049 buf_sprintf("unable to evaluate constant expression"));19073 buf_sprintf("unable to evaluate constant expression"));
19050 return ira->codegen->invalid_instruction;19074 return ira->codegen->invalid_instruction;
19051 }19075 }
1905219076
1905319077 return result;
19054 ir_assert(old_result_loc != nullptr, instruction);
19055 IrInstruction *result_loc = old_result_loc->child;
19056 if (type_is_invalid(result_loc->value.type))
19057 return result_loc;
19058 return ir_get_deref(ira, instruction, result_loc, nullptr);
19059}19078}
1906019079
19061static IrInstruction *ir_analyze_instruction_container_init_list(IrAnalyze *ira,19080static IrInstruction *ir_analyze_instruction_container_init_list(IrAnalyze *ira,
...@@ -19074,8 +19093,11 @@ static IrInstruction *ir_analyze_instruction_container_init_list(IrAnalyze *ira,...@@ -19074,8 +19093,11 @@ static IrInstruction *ir_analyze_instruction_container_init_list(IrAnalyze *ira,
19074 buf_sprintf("expected array type or [_], found slice"));19093 buf_sprintf("expected array type or [_], found slice"));
19075 return ira->codegen->invalid_instruction;19094 return ira->codegen->invalid_instruction;
19076 } else if (container_type->id == ZigTypeIdStruct && !is_slice(container_type) && elem_count == 0) {19095 } else if (container_type->id == ZigTypeIdStruct && !is_slice(container_type) && elem_count == 0) {
19077 return ir_analyze_container_init_fields(ira, &instruction->base, container_type, 0, nullptr,19096 ir_assert(instruction->result_loc != nullptr, &instruction->base);
19078 instruction->result_loc);19097 IrInstruction *result_loc = instruction->result_loc->child;
19098 if (type_is_invalid(result_loc->value.type))
19099 return result_loc;
19100 return ir_analyze_container_init_fields(ira, &instruction->base, container_type, 0, nullptr, result_loc);
19079 } else if (container_type->id == ZigTypeIdArray) {19101 } else if (container_type->id == ZigTypeIdArray) {
19080 // array is same as slice init but we make a compile error if the length is wrong19102 // array is same as slice init but we make a compile error if the length is wrong
19081 ZigType *child_type;19103 ZigType *child_type;
...@@ -19199,8 +19221,13 @@ static IrInstruction *ir_analyze_instruction_container_init_fields(IrAnalyze *ir...@@ -19199,8 +19221,13 @@ static IrInstruction *ir_analyze_instruction_container_init_fields(IrAnalyze *ir
19199 if (type_is_invalid(container_type))19221 if (type_is_invalid(container_type))
19200 return ira->codegen->invalid_instruction;19222 return ira->codegen->invalid_instruction;
1920119223
19224 ir_assert(instruction->result_loc != nullptr, &instruction->base);
19225 IrInstruction *result_loc = instruction->result_loc->child;
19226 if (type_is_invalid(result_loc->value.type))
19227 return result_loc;
19228
19202 return ir_analyze_container_init_fields(ira, &instruction->base, container_type,19229 return ir_analyze_container_init_fields(ira, &instruction->base, container_type,
19203 instruction->field_count, instruction->fields, instruction->result_loc);19230 instruction->field_count, instruction->fields, result_loc);
19204}19231}
1920519232
19206static IrInstruction *ir_analyze_instruction_compile_err(IrAnalyze *ira,19233static IrInstruction *ir_analyze_instruction_compile_err(IrAnalyze *ira,
...@@ -24390,17 +24417,7 @@ static IrInstruction *ir_analyze_instruction_end_expr(IrAnalyze *ira, IrInstruct...@@ -24390,17 +24417,7 @@ static IrInstruction *ir_analyze_instruction_end_expr(IrAnalyze *ira, IrInstruct
24390 if (type_is_invalid(value->value.type))24417 if (type_is_invalid(value->value.type))
24391 return ira->codegen->invalid_instruction;24418 return ira->codegen->invalid_instruction;
2439224419
24393 bool want_resolve_result;24420 bool want_resolve_result = !instruction->result_loc->written;
24394 if (instruction->result_loc->written) {
24395 if (instruction->result_loc->scope_elide != nullptr && instr_is_comptime(value)) {
24396 want_resolve_result = true;
24397 instruction->result_loc->scope_elide->activated = true;
24398 } else {
24399 want_resolve_result = false;
24400 }
24401 } else {
24402 want_resolve_result = true;
24403 }
24404 if (want_resolve_result) {24421 if (want_resolve_result) {
24405 IrInstruction *result_loc = ir_resolve_result(ira, &instruction->base, instruction->result_loc,24422 IrInstruction *result_loc = ir_resolve_result(ira, &instruction->base, instruction->result_loc,
24406 value->value.type, value);24423 value->value.type, value);