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
signature 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 {
203203 // The pointer points to memory that is known only at runtime.
204204 // For example it may point to the initializer value of a variable.
205205 ConstPtrMutRuntimeVar,
206 // The pointer points to memory for which it must be inferred whether the
207 // value is comptime known or not.
208 ConstPtrMutInfer,
206209};
207210
208211struct ConstPtrValue {
......@@ -1957,7 +1960,6 @@ enum ScopeId {
19571960 ScopeIdCompTime,
19581961 ScopeIdCoroPrelude,
19591962 ScopeIdRuntime,
1960 ScopeIdElide,
19611963};
19621964
19631965struct Scope {
......@@ -1971,14 +1973,6 @@ struct Scope {
19711973 ScopeId id;
19721974};
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
19821976// This scope comes from global declarations or from
19831977// declarations in a container declaration
19841978// NodeTypeContainerDecl
......@@ -2655,6 +2649,7 @@ struct IrInstructionContainerInitFieldsField {
26552649 IrInstruction *value;
26562650 AstNode *source_node;
26572651 TypeStructField *type_struct_field;
2652 IrInstruction *result_loc;
26582653};
26592654
26602655struct IrInstructionContainerInitFields {
......@@ -3655,7 +3650,6 @@ struct ResultLoc {
36553650 IrInstruction *source_instruction;
36563651 IrInstruction *gen_instruction; // value to store to the result loc
36573652 ZigType *implicit_elem_type;
3658 ScopeElide *scope_elide;
36593653};
36603654
36613655struct ResultLocNone {
src/analyze.cpp+1-34
......@@ -166,12 +166,6 @@ Scope *create_runtime_scope(CodeGen *g, AstNode *node, Scope *parent, IrInstruct
166166 return &scope->base;
167167}
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
175169ScopeSuspend *create_suspend_scope(CodeGen *g, AstNode *node, Scope *parent) {
176170 assert(node->type == NodeTypeSuspend);
177171 ScopeSuspend *scope = allocate<ScopeSuspend>(1);
......@@ -4187,6 +4181,7 @@ static uint32_t hash_const_val_ptr(ConstExprValue *const_val) {
41874181 case ConstPtrMutComptimeConst:
41884182 hash_val += (uint32_t)4214318515;
41894183 break;
4184 case ConstPtrMutInfer:
41904185 case ConstPtrMutComptimeVar:
41914186 hash_val += (uint32_t)1103195694;
41924187 break;
......@@ -7286,31 +7281,3 @@ void src_assert(bool ok, AstNode *source_node) {
72867281 const char *msg = "assertion failed. This is a bug in the Zig compiler.";
72877282 stage2_panic(msg, strlen(msg));
72887283}
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 *
121121Scope *create_comptime_scope(CodeGen *g, AstNode *node, Scope *parent);
122122Scope *create_coro_prelude_scope(CodeGen *g, AstNode *node, Scope *parent);
123123Scope *create_runtime_scope(CodeGen *g, AstNode *node, Scope *parent, IrInstruction *is_comptime);
124ScopeElide *create_elide_scope(CodeGen *g, AstNode *node, Scope *parent);
125124
126125void init_const_str_lit(CodeGen *g, ConstExprValue *const_val, Buf *str);
127126ConstExprValue *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
254253void src_assert(bool ok, AstNode *source_node);
255254bool is_container(ZigType *type_entry);
256255ConstExprValue *analyze_const_value(CodeGen *g, Scope *scope, AstNode *node, ZigType *type_entry, Buf *type_name);
257bool scope_is_elided(Scope *scope);
258256
259257#endif
src/codegen.cpp+3-6
......@@ -722,7 +722,6 @@ static ZigLLVMDIScope *get_di_scope(CodeGen *g, Scope *scope) {
722722 case ScopeIdCompTime:
723723 case ScopeIdCoroPrelude:
724724 case ScopeIdRuntime:
725 case ScopeIdElide:
726725 return get_di_scope(g, scope->parent);
727726 }
728727 zig_unreachable();
......@@ -5761,12 +5760,10 @@ static void ir_render(CodeGen *g, ZigFn *fn_entry) {
57615760 if (instruction->ref_count == 0 && !ir_has_side_effects(instruction))
57625761 continue;
57635762
5764 if (!scope_is_elided(instruction->scope)) {
5765 if (!g->strip_debug_symbols) {
5766 set_debug_location(g, instruction);
5767 }
5768 instruction->llvm_value = ir_render_instruction(g, executable, instruction);
5763 if (!g->strip_debug_symbols) {
5764 set_debug_location(g, instruction);
57695765 }
5766 instruction->llvm_value = ir_render_instruction(g, executable, instruction);
57705767 }
57715768 current_block->llvm_exit_block = LLVMGetInsertBlock(g->builder);
57725769 }
src/ir.cpp+200-183
......@@ -196,6 +196,8 @@ static IrInstruction *ir_analyze_unwrap_error_payload(IrAnalyze *ira, IrInstruct
196196 IrInstruction *base_ptr, bool safety_check_on, bool initializing);
197197static IrInstruction *ir_analyze_unwrap_err_code(IrAnalyze *ira, IrInstruction *source_instr,
198198 IrInstruction *base_ptr, bool initializing);
199static IrInstruction *ir_analyze_store_ptr(IrAnalyze *ira, IrInstruction *source_instr,
200 IrInstruction *ptr, IrInstruction *uncasted_value);
199201
200202static ConstExprValue *const_ptr_pointee_unchecked(CodeGen *g, ConstExprValue *const_val) {
201203 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
33633365 case ScopeIdSuspend:
33643366 case ScopeIdCompTime:
33653367 case ScopeIdRuntime:
3366 case ScopeIdElide:
33673368 scope = scope->parent;
33683369 continue;
33693370 case ScopeIdDeferExpr:
......@@ -3420,7 +3421,6 @@ static bool ir_gen_defers_for_block(IrBuilder *irb, Scope *inner_scope, Scope *o
34203421 case ScopeIdSuspend:
34213422 case ScopeIdCompTime:
34223423 case ScopeIdRuntime:
3423 case ScopeIdElide:
34243424 scope = scope->parent;
34253425 continue;
34263426 case ScopeIdDeferExpr:
......@@ -5758,15 +5758,8 @@ static IrInstruction *ir_gen_container_init_expr(IrBuilder *irb, Scope *scope, A
57585758 return irb->codegen->invalid_instruction;
57595759 }
57605760
5761 IrInstruction *container_ptr = nullptr;
5762 if (!ir_should_inline(irb->exec, scope)) {
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 }
5761 IrInstruction *container_ptr = ir_build_resolve_result(irb, scope, node, parent_result_loc,
5762 container_type);
57705763
57715764 size_t field_count = container_init_expr->entries.length;
57725765 IrInstructionContainerInitFieldsField *fields = allocate<IrInstructionContainerInitFieldsField>(field_count);
......@@ -5777,27 +5770,22 @@ static IrInstruction *ir_gen_container_init_expr(IrBuilder *irb, Scope *scope, A
57775770 Buf *name = entry_node->data.struct_val_field.name;
57785771 AstNode *expr_node = entry_node->data.struct_val_field.expr;
57795772
5780 Scope *val_scope = scope;
5781 ResultLoc *child_result_loc = nullptr;
5782 if (container_ptr != nullptr) {
5783 IrInstruction *field_ptr = ir_build_field_ptr(irb, &parent_result_loc->scope_elide->base,
5784 expr_node, container_ptr, name, true);
5785 ResultLocInstruction *result_loc_inst = allocate<ResultLocInstruction>(1);
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 }
5773 IrInstruction *field_ptr = ir_build_field_ptr(irb, scope, expr_node, container_ptr, name, true);
5774 ResultLocInstruction *result_loc_inst = allocate<ResultLocInstruction>(1);
5775 result_loc_inst->base.id = ResultLocIdInstruction;
5776 result_loc_inst->base.source_instruction = field_ptr;
5777 ir_ref_instruction(field_ptr, irb->current_basic_block);
5778 ir_build_reset_result(irb, scope, expr_node, &result_loc_inst->base);
57925779
5793 IrInstruction *expr_value = ir_gen_node_extra(irb, expr_node, val_scope, LValNone,
5794 child_result_loc);
5780 IrInstruction *expr_value = ir_gen_node_extra(irb, expr_node, scope, LValNone,
5781 &result_loc_inst->base);
57955782 if (expr_value == irb->codegen->invalid_instruction)
57965783 return expr_value;
57975784
57985785 fields[i].name = name;
57995786 fields[i].value = expr_value;
58005787 fields[i].source_node = entry_node;
5788 fields[i].result_loc = field_ptr;
58015789 }
58025790 IrInstruction *init_fields = ir_build_container_init_fields(irb, scope, node, container_type,
58035791 field_count, fields, container_ptr);
......@@ -5812,36 +5800,23 @@ static IrInstruction *ir_gen_container_init_expr(IrBuilder *irb, Scope *scope, A
58125800 container_type = ir_build_array_type(irb, scope, node, item_count_inst, elem_type);
58135801 }
58145802
5815 IrInstruction *container_ptr = nullptr;
5816 if (!ir_should_inline(irb->exec, scope)) {
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 }
5803 IrInstruction *container_ptr = ir_build_resolve_result(irb, scope, node, parent_result_loc,
5804 container_type);
58235805
58245806 IrInstruction **values = allocate<IrInstruction *>(item_count);
58255807 for (size_t i = 0; i < item_count; i += 1) {
58265808 AstNode *expr_node = container_init_expr->entries.at(i);
58275809
5828 ResultLoc *child_result_loc = nullptr;
5829 Scope *val_scope = scope;
5830 if (container_ptr != nullptr) {
5831 IrInstruction *elem_index = ir_build_const_usize(irb, &parent_result_loc->scope_elide->base,
5832 expr_node, i);
5833 IrInstruction *elem_ptr = ir_build_elem_ptr(irb, &parent_result_loc->scope_elide->base,
5834 expr_node, container_ptr, elem_index, false, PtrLenSingle, true);
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 }
5810 IrInstruction *elem_index = ir_build_const_usize(irb, scope, expr_node, i);
5811 IrInstruction *elem_ptr = ir_build_elem_ptr(irb, scope, expr_node, container_ptr, elem_index,
5812 false, PtrLenSingle, true);
5813 ResultLocInstruction *result_loc_inst = allocate<ResultLocInstruction>(1);
5814 result_loc_inst->base.id = ResultLocIdInstruction;
5815 result_loc_inst->base.source_instruction = elem_ptr;
5816 ir_ref_instruction(elem_ptr, irb->current_basic_block);
58425817
5843 IrInstruction *expr_value = ir_gen_node_extra(irb, expr_node, val_scope, LValNone,
5844 child_result_loc);
5818 IrInstruction *expr_value = ir_gen_node_extra(irb, expr_node, scope, LValNone,
5819 &result_loc_inst->base);
58455820 if (expr_value == irb->codegen->invalid_instruction)
58465821 return expr_value;
58475822
......@@ -8651,8 +8626,6 @@ static ConstExprValue *ir_exec_const_result(CodeGen *codegen, IrExecutable *exec
86518626 IrBasicBlock *bb = exec->basic_block_list.at(0);
86528627 for (size_t i = 0; i < bb->instruction_list.length; i += 1) {
86538628 IrInstruction *instruction = bb->instruction_list.at(i);
8654 if (scope_is_elided(instruction->scope))
8655 continue;
86568629 if (instruction->id == IrInstructionIdReturn) {
86578630 IrInstructionReturn *ret_inst = (IrInstructionReturn *)instruction;
86588631 IrInstruction *value = ret_inst->value;
......@@ -12745,9 +12718,7 @@ static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruc
1274512718 ir_add_error(ira, ptr, buf_sprintf("attempt to dereference undefined value"));
1274612719 return ira->codegen->invalid_instruction;
1274712720 }
12748 if (ptr->value.data.x_ptr.mut == ConstPtrMutComptimeConst ||
12749 ptr->value.data.x_ptr.mut == ConstPtrMutComptimeVar)
12750 {
12721 if (ptr->value.data.x_ptr.mut != ConstPtrMutRuntimeVar) {
1275112722 ConstExprValue *pointee = const_ptr_pointee_unchecked(ira->codegen, &ptr->value);
1275212723 if (pointee->special != ConstValSpecialRuntime) {
1275312724 IrInstruction *result = ir_const(ira, source_instruction, child_type);
......@@ -14487,7 +14458,25 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira,
1448714458 }
1448814459
1448914460 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) {
1449114480 assert(var->mem_slot_index < ira->exec_context.mem_slot_list.length);
1449214481 ConstExprValue *mem_slot = ira->exec_context.mem_slot_list.at(var->mem_slot_index);
1449314482 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
1481814807 pointee->special = ConstValSpecialUndef;
1481914808
1482014809 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;
1482214811 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;
1482414813 result->base.value.data.x_ptr.data.ref.pointee = pointee;
1482514814
1482614815 if ((err = type_resolve(ira->codegen, var_type, ResolveStatusZeroBitsKnown)))
......@@ -15109,7 +15098,10 @@ static IrInstruction *ir_analyze_instruction_resolve_result(IrAnalyze *ira, IrIn
1510915098 ZigType *implicit_elem_type = ir_resolve_type(ira, instruction->ty->child);
1511015099 if (type_is_invalid(implicit_elem_type))
1511115100 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");
1511315105}
1511415106
1511515107static void ir_reset_result(ResultLoc *result_loc) {
......@@ -15431,7 +15423,9 @@ static IrInstruction *ir_analyze_store_ptr(IrAnalyze *ira, IrInstruction *source
1543115423 ir_add_error(ira, source_instr, buf_sprintf("cannot assign to constant"));
1543215424 return ira->codegen->invalid_instruction;
1543315425 }
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 {
1543515429 if (instr_is_comptime(value)) {
1543615430 ConstExprValue *dest_val = const_ptr_pointee(ira, ira->codegen, &ptr->value, source_instr->source_node);
1543715431 if (dest_val == nullptr)
......@@ -15451,12 +15445,16 @@ static IrInstruction *ir_analyze_store_ptr(IrAnalyze *ira, IrInstruction *source
1545115445 return ir_const_void(ira, source_instr);
1545215446 }
1545315447 }
15454 ir_add_error(ira, source_instr,
15455 buf_sprintf("cannot store runtime value in compile time variable"));
15456 ConstExprValue *dest_val = const_ptr_pointee_unchecked(ira->codegen, &ptr->value);
15457 dest_val->type = ira->codegen->builtin_types.entry_invalid;
15448 if (ptr->value.data.x_ptr.mut == ConstPtrMutInfer) {
15449 ptr->value.special = ConstValSpecialRuntime;
15450 } else {
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 }
1546015458 }
1546115459 }
1546215460
......@@ -17091,6 +17089,81 @@ static IrInstruction *ir_analyze_container_member_access_inner(IrAnalyze *ira,
1709117089 return ira->codegen->invalid_instruction;
1709217090}
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
1709417167static IrInstruction *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_name,
1709517168 IrInstruction *source_instr, IrInstruction *container_ptr, ZigType *container_type, bool initializing)
1709617169{
......@@ -17101,59 +17174,10 @@ static IrInstruction *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_
1710117174 return ira->codegen->invalid_instruction;
1710217175
1710317176 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;
1710617177 if (bare_type->id == ZigTypeIdStruct) {
1710717178 TypeStructField *field = find_struct_type_field(bare_type, field_name);
17108 if (field) {
17109 switch (type_has_one_possible_value(ira->codegen, field->type_entry)) {
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;
17179 if (field != nullptr) {
17180 return ir_analyze_struct_field_ptr(ira, source_instr, field, container_ptr, bare_type, initializing);
1715717181 } else {
1715817182 return ir_analyze_container_member_access_inner(ira, bare_type, field_name,
1715917183 source_instr, container_ptr, container_type);
......@@ -17162,6 +17186,9 @@ static IrInstruction *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_
1716217186 return ir_analyze_container_member_access_inner(ira, bare_type, field_name,
1716317187 source_instr, container_ptr, container_type);
1716417188 } 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
1716517192 TypeUnionField *field = find_union_type_field(bare_type, field_name);
1716617193 if (field) {
1716717194 if (instr_is_comptime(container_ptr)) {
......@@ -18849,7 +18876,7 @@ static IrInstruction *ir_analyze_instruction_ref(IrAnalyze *ira, IrInstructionRe
1884918876
1885018877static IrInstruction *ir_analyze_container_init_fields_union(IrAnalyze *ira, IrInstruction *instruction,
1885118878 ZigType *container_type, size_t instr_field_count, IrInstructionContainerInitFieldsField *fields,
18852 IrInstruction *old_result_loc)
18879 IrInstruction *result_loc)
1885318880{
1885418881 Error err;
1885518882 assert(container_type->id == ZigTypeIdUnion);
......@@ -18905,21 +18932,17 @@ static IrInstruction *ir_analyze_container_init_fields_union(IrAnalyze *ira, IrI
1890518932 return result;
1890618933 }
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;
1891218935 return ir_get_deref(ira, instruction, result_loc, nullptr);
1891318936}
1891418937
1891518938static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruction *instruction,
1891618939 ZigType *container_type, size_t instr_field_count, IrInstructionContainerInitFieldsField *fields,
18917 IrInstruction *old_result_loc)
18940 IrInstruction *result_loc)
1891818941{
1891918942 Error err;
1892018943 if (container_type->id == ZigTypeIdUnion) {
1892118944 return ir_analyze_container_init_fields_union(ira, instruction, container_type, instr_field_count,
18922 fields, old_result_loc);
18945 fields, result_loc);
1892318946 }
1892418947 if (container_type->id != ZigTypeIdStruct || is_slice(container_type)) {
1892518948 ir_add_error(ira, instruction,
......@@ -18936,20 +18959,28 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc
1893618959 IrInstruction *first_non_const_instruction = nullptr;
1893718960
1893818961 AstNode **field_assign_nodes = allocate<AstNode *>(actual_field_count);
18962 ZigList<IrInstruction *> const_ptrs = {};
1893918963
1894018964 bool is_comptime = ir_should_inline(ira->new_irb.exec, instruction->scope)
1894118965 || type_requires_comptime(ira->codegen, container_type) == ReqCompTimeYes;
1894218966
18943 ConstExprValue const_val = {};
18944 const_val.special = ConstValSpecialStatic;
18945 const_val.type = container_type;
18946 // const_val.global_refs = allocate<ConstGlobalRefs>(1);
18947 const_val.data.x_struct.fields = create_const_vals(actual_field_count);
18967
18968 // Here we iterate over the fields that have been initialized, and emit
18969 // compile errors for missing fields and duplicate fields.
18970 // It is only now that we find out whether the struct initialization can be a comptime
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
1894818979 for (size_t i = 0; i < instr_field_count; i += 1) {
1894918980 IrInstructionContainerInitFieldsField *field = &fields[i];
1895018981
18951 IrInstruction *field_value = field->value->child;
18952 if (type_is_invalid(field_value->value.type))
18982 IrInstruction *field_result_loc = field->result_loc->child;
18983 if (type_is_invalid(field_result_loc->value.type))
1895318984 return ira->codegen->invalid_instruction;
1895418985
1895518986 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
1896318994 if (type_is_invalid(type_field->type_entry))
1896418995 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
1897018997 size_t field_index = type_field->src_index;
1897118998 AstNode *existing_assign_node = field_assign_nodes[field_index];
1897218999 if (existing_assign_node) {
......@@ -18976,23 +19003,18 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc
1897619003 }
1897719004 field_assign_nodes[field_index] = field->source_node;
1897819005
18979 if (const_val.special == ConstValSpecialStatic) {
18980 if (is_comptime || casted_field_value->value.special != ConstValSpecialRuntime) {
18981 ConstExprValue *field_val = ir_resolve_const(ira, casted_field_value, UndefOk);
18982 if (!field_val)
18983 return ira->codegen->invalid_instruction;
18984
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 }
19006 if (instr_is_comptime(field_result_loc) &&
19007 field_result_loc->value.data.x_ptr.mut != ConstPtrMutRuntimeVar)
19008 {
19009 const_ptrs.append(field_result_loc);
19010 } else {
19011 first_non_const_instruction = field_result_loc;
1899019012 }
1899119013 }
1899219014
1899319015 bool any_missing = false;
1899419016 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
1899719019 // look for a default field value
1899819020 TypeStructField *field = &container_type->data.structure.fields[i];
......@@ -19018,44 +19040,41 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc
1901819040 IrInstruction *runtime_inst = ir_const(ira, instruction, field->init_val->type);
1901919041 copy_const_val(&runtime_inst->value, field->init_val, true);
1902019042
19021 if (const_val.special == ConstValSpecialStatic) {
19022 copy_const_val(&const_val.data.x_struct.fields[i], field->init_val, true);
19043 IrInstruction *field_ptr = ir_analyze_struct_field_ptr(ira, instruction, field, result_loc,
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;
1902319050 }
1902419051 }
1902519052 if (any_missing)
1902619053 return ira->codegen->invalid_instruction;
1902719054
19028 if (const_val.special == ConstValSpecialStatic) {
19029 IrInstruction *result = ir_const(ira, instruction, nullptr);
19030 ConstExprValue *out_val = &result->value;
19031 copy_const_val(out_val, &const_val, false);
19032 out_val->type = container_type;
19033
19034 for (size_t i = 0; i < instr_field_count; i += 1) {
19035 ConstExprValue *field_val = &out_val->data.x_struct.fields[i];
19036 ConstParent *parent = get_const_val_parent(ira->codegen, field_val);
19037 if (parent != nullptr) {
19038 parent->id = ConstParentIdStruct;
19039 parent->data.p_struct.field_index = i;
19040 parent->data.p_struct.struct_val = out_val;
19055 if (result_loc->value.data.x_ptr.mut == ConstPtrMutInfer) {
19056 if (const_ptrs.length == actual_field_count) {
19057 result_loc->value.data.x_ptr.mut = ConstPtrMutComptimeConst;
19058 } else {
19059 result_loc->value.special = ConstValSpecialRuntime;
19060 for (size_t i = 0; i < const_ptrs.length; i += 1) {
19061 IrInstruction *field_result_loc = const_ptrs.at(i);
19062 IrInstruction *deref = ir_get_deref(ira, field_result_loc, field_result_loc, nullptr);
19063 field_result_loc->value.special = ConstValSpecialRuntime;
19064 ir_analyze_store_ptr(ira, field_result_loc, field_result_loc, deref);
1904119065 }
1904219066 }
19043
19044 return result;
1904519067 }
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)) {
1904819072 ir_add_error_node(ira, first_non_const_instruction->source_node,
1904919073 buf_sprintf("unable to evaluate constant expression"));
1905019074 return ira->codegen->invalid_instruction;
1905119075 }
1905219076
19053
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);
19077 return result;
1905919078}
1906019079
1906119080static IrInstruction *ir_analyze_instruction_container_init_list(IrAnalyze *ira,
......@@ -19074,8 +19093,11 @@ static IrInstruction *ir_analyze_instruction_container_init_list(IrAnalyze *ira,
1907419093 buf_sprintf("expected array type or [_], found slice"));
1907519094 return ira->codegen->invalid_instruction;
1907619095 } 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,
19078 instruction->result_loc);
19096 ir_assert(instruction->result_loc != nullptr, &instruction->base);
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);
1907919101 } else if (container_type->id == ZigTypeIdArray) {
1908019102 // array is same as slice init but we make a compile error if the length is wrong
1908119103 ZigType *child_type;
......@@ -19199,8 +19221,13 @@ static IrInstruction *ir_analyze_instruction_container_init_fields(IrAnalyze *ir
1919919221 if (type_is_invalid(container_type))
1920019222 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
1920219229 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);
1920419231}
1920519232
1920619233static IrInstruction *ir_analyze_instruction_compile_err(IrAnalyze *ira,
......@@ -24390,17 +24417,7 @@ static IrInstruction *ir_analyze_instruction_end_expr(IrAnalyze *ira, IrInstruct
2439024417 if (type_is_invalid(value->value.type))
2439124418 return ira->codegen->invalid_instruction;
2439224419
24393 bool want_resolve_result;
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 }
24420 bool want_resolve_result = !instruction->result_loc->written;
2440424421 if (want_resolve_result) {
2440524422 IrInstruction *result_loc = ir_resolve_result(ira, &instruction->base, instruction->result_loc,
2440624423 value->value.type, value);