authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-06-17 17:46:03-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-06-17 17:46:03-04:00
log4e182c7e9e44a97fe925344057b7b30c3ff2cae4
treed17f9f54040013805f810a870b9bcee6388e55db
parent05680008445564d3b43fd720723c86b526ff97c3
signaturelock-open Commit is signed but in an unrecognized format.

inferred comptime array inits


3 files changed, 130 insertions(+), 108 deletions(-)

src/all_types.hpp+1-1
......@@ -2640,7 +2640,7 @@ struct IrInstructionContainerInitList {
26402640 IrInstruction *container_type;
26412641 IrInstruction *elem_type;
26422642 size_t item_count;
2643 IrInstruction **items;
2643 IrInstruction **elem_result_loc_list;
26442644 IrInstruction *result_loc;
26452645};
26462646
src/ir.cpp+127-105
......@@ -1524,18 +1524,19 @@ static IrInstruction *ir_build_un_op(IrBuilder *irb, Scope *scope, AstNode *sour
15241524}
15251525
15261526static IrInstruction *ir_build_container_init_list(IrBuilder *irb, Scope *scope, AstNode *source_node,
1527 IrInstruction *container_type, size_t item_count, IrInstruction **items, IrInstruction *result_loc)
1527 IrInstruction *container_type, size_t item_count, IrInstruction **elem_result_loc_list,
1528 IrInstruction *result_loc)
15281529{
15291530 IrInstructionContainerInitList *container_init_list_instruction =
15301531 ir_build_instruction<IrInstructionContainerInitList>(irb, scope, source_node);
15311532 container_init_list_instruction->container_type = container_type;
15321533 container_init_list_instruction->item_count = item_count;
1533 container_init_list_instruction->items = items;
1534 container_init_list_instruction->elem_result_loc_list = elem_result_loc_list;
15341535 container_init_list_instruction->result_loc = result_loc;
15351536
15361537 ir_ref_instruction(container_type, irb->current_basic_block);
15371538 for (size_t i = 0; i < item_count; i += 1) {
1538 ir_ref_instruction(items[i], irb->current_basic_block);
1539 ir_ref_instruction(elem_result_loc_list[i], irb->current_basic_block);
15391540 }
15401541 if (result_loc != nullptr) ir_ref_instruction(result_loc, irb->current_basic_block);
15411542
......@@ -5802,7 +5803,7 @@ static IrInstruction *ir_gen_container_init_expr(IrBuilder *irb, Scope *scope, A
58025803 IrInstruction *container_ptr = ir_build_resolve_result(irb, scope, node, parent_result_loc,
58035804 container_type);
58045805
5805 IrInstruction **values = allocate<IrInstruction *>(item_count);
5806 IrInstruction **result_locs = allocate<IrInstruction *>(item_count);
58065807 for (size_t i = 0; i < item_count; i += 1) {
58075808 AstNode *expr_node = container_init_expr->entries.at(i);
58085809
......@@ -5813,16 +5814,17 @@ static IrInstruction *ir_gen_container_init_expr(IrBuilder *irb, Scope *scope, A
58135814 result_loc_inst->base.id = ResultLocIdInstruction;
58145815 result_loc_inst->base.source_instruction = elem_ptr;
58155816 ir_ref_instruction(elem_ptr, irb->current_basic_block);
5817 ir_build_reset_result(irb, scope, expr_node, &result_loc_inst->base);
58165818
58175819 IrInstruction *expr_value = ir_gen_node_extra(irb, expr_node, scope, LValNone,
58185820 &result_loc_inst->base);
58195821 if (expr_value == irb->codegen->invalid_instruction)
58205822 return expr_value;
58215823
5822 values[i] = expr_value;
5824 result_locs[i] = elem_ptr;
58235825 }
58245826 IrInstruction *init_list = ir_build_container_init_list(irb, scope, node, container_type,
5825 item_count, values, container_ptr);
5827 item_count, result_locs, container_ptr);
58265828 return ir_lval_wrap(irb, scope, init_list, lval, parent_result_loc);
58275829 }
58285830 }
......@@ -16891,6 +16893,22 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct
1689116893 if (array_ptr_val == nullptr)
1689216894 return ira->codegen->invalid_instruction;
1689316895
16896 if (array_ptr_val->special == ConstValSpecialUndef && array_type->id == ZigTypeIdArray &&
16897 elem_ptr_instruction->initializing)
16898 {
16899 array_ptr_val->data.x_array.special = ConstArraySpecialNone;
16900 array_ptr_val->data.x_array.data.s_none.elements = create_const_vals(array_type->data.array.len);
16901 array_ptr_val->special = ConstValSpecialStatic;
16902 for (size_t i = 0; i < array_type->data.array.len; i += 1) {
16903 ConstExprValue *elem_val = &array_ptr_val->data.x_array.data.s_none.elements[i];
16904 elem_val->special = ConstValSpecialUndef;
16905 elem_val->type = array_type->data.array.child_type;
16906 elem_val->parent.id = ConstParentIdArray;
16907 elem_val->parent.data.p_array.array_val = array_ptr_val;
16908 elem_val->parent.data.p_array.elem_index = i;
16909 }
16910 }
16911
1689416912 if (array_ptr_val->special != ConstValSpecialRuntime &&
1689516913 (array_type->id != ZigTypeIdPointer ||
1689616914 array_ptr_val->data.x_ptr.special != ConstPtrSpecialHardCodedAddr))
......@@ -17011,7 +17029,16 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct
1701117029 }
1701217030 return result;
1701317031 } else if (array_type->id == ZigTypeIdArray) {
17014 IrInstruction *result = ir_const(ira, &elem_ptr_instruction->base, return_type);
17032 IrInstruction *result;
17033 if (orig_array_ptr_val->data.x_ptr.mut == ConstPtrMutInfer) {
17034 result = ir_build_elem_ptr(&ira->new_irb, elem_ptr_instruction->base.scope,
17035 elem_ptr_instruction->base.source_node, array_ptr, casted_elem_index,
17036 false, elem_ptr_instruction->ptr_len, elem_ptr_instruction->initializing);
17037 result->value.type = return_type;
17038 result->value.special = ConstValSpecialStatic;
17039 } else {
17040 result = ir_const(ira, &elem_ptr_instruction->base, return_type);
17041 }
1701517042 ConstExprValue *out_val = &result->value;
1701617043 out_val->data.x_ptr.special = ConstPtrSpecialBaseArray;
1701717044 out_val->data.x_ptr.mut = orig_array_ptr_val->data.x_ptr.mut;
......@@ -19099,8 +19126,6 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc
1909919126static IrInstruction *ir_analyze_instruction_container_init_list(IrAnalyze *ira,
1910019127 IrInstructionContainerInitList *instruction)
1910119128{
19102 Error err;
19103
1910419129 ZigType *container_type = ir_resolve_type(ira, instruction->container_type->child);
1910519130 if (type_is_invalid(container_type))
1910619131 return ira->codegen->invalid_instruction;
......@@ -19111,125 +19136,122 @@ static IrInstruction *ir_analyze_instruction_container_init_list(IrAnalyze *ira,
1911119136 ir_add_error(ira, &instruction->base,
1911219137 buf_sprintf("expected array type or [_], found slice"));
1911319138 return ira->codegen->invalid_instruction;
19114 } else if (container_type->id == ZigTypeIdStruct && !is_slice(container_type) && elem_count == 0) {
19139 }
19140
19141 if (container_type->id == ZigTypeIdVoid) {
19142 if (elem_count != 0) {
19143 ir_add_error_node(ira, instruction->base.source_node,
19144 buf_sprintf("void expression expects no arguments"));
19145 return ira->codegen->invalid_instruction;
19146 }
19147 return ir_const_void(ira, &instruction->base);
19148 }
19149
19150 if (container_type->id == ZigTypeIdStruct && elem_count == 0) {
1911519151 ir_assert(instruction->result_loc != nullptr, &instruction->base);
1911619152 IrInstruction *result_loc = instruction->result_loc->child;
1911719153 if (type_is_invalid(result_loc->value.type))
1911819154 return result_loc;
1911919155 return ir_analyze_container_init_fields(ira, &instruction->base, container_type, 0, nullptr, result_loc);
19120 } else if (container_type->id == ZigTypeIdArray) {
19121 // array is same as slice init but we make a compile error if the length is wrong
19122 ZigType *child_type;
19123 if (container_type->id == ZigTypeIdArray) {
19124 child_type = container_type->data.array.child_type;
19125 if (container_type->data.array.len != elem_count) {
19126 ZigType *literal_type = get_array_type(ira->codegen, child_type, elem_count);
19127
19128 ir_add_error(ira, &instruction->base,
19129 buf_sprintf("expected %s literal, found %s literal",
19130 buf_ptr(&container_type->name), buf_ptr(&literal_type->name)));
19131 return ira->codegen->invalid_instruction;
19132 }
19133 } else {
19134 ZigType *pointer_type = container_type->data.structure.fields[slice_ptr_index].type_entry;
19135 assert(pointer_type->id == ZigTypeIdPointer);
19136 child_type = pointer_type->data.pointer.child_type;
19137 }
19138
19139 if ((err = type_resolve(ira->codegen, child_type, ResolveStatusSizeKnown))) {
19140 return ira->codegen->invalid_instruction;
19141 }
19156 }
1914219157
19143 ZigType *fixed_size_array_type = get_array_type(ira->codegen, child_type, elem_count);
19158 if (container_type->id != ZigTypeIdArray) {
19159 ir_add_error_node(ira, instruction->base.source_node,
19160 buf_sprintf("type '%s' does not support array initialization",
19161 buf_ptr(&container_type->name)));
19162 return ira->codegen->invalid_instruction;
19163 }
1914419164
19145 ConstExprValue const_val = {};
19146 const_val.special = ConstValSpecialStatic;
19147 const_val.type = fixed_size_array_type;
19148 // const_val.global_refs = allocate<ConstGlobalRefs>(1);
19149 const_val.data.x_array.data.s_none.elements = create_const_vals(elem_count);
19165 ir_assert(instruction->result_loc != nullptr, &instruction->base);
19166 IrInstruction *result_loc = instruction->result_loc->child;
19167 if (type_is_invalid(result_loc->value.type))
19168 return result_loc;
19169 ir_assert(result_loc->value.type->id == ZigTypeIdPointer, &instruction->base);
1915019170
19151 bool is_comptime = ir_should_inline(ira->new_irb.exec, instruction->base.scope);
19171 ZigType *child_type = container_type->data.array.child_type;
19172 if (container_type->data.array.len != elem_count) {
19173 ZigType *literal_type = get_array_type(ira->codegen, child_type, elem_count);
1915219174
19153 IrInstruction **new_items = allocate<IrInstruction *>(elem_count);
19175 ir_add_error(ira, &instruction->base,
19176 buf_sprintf("expected %s literal, found %s literal",
19177 buf_ptr(&container_type->name), buf_ptr(&literal_type->name)));
19178 return ira->codegen->invalid_instruction;
19179 }
1915419180
19155 IrInstruction *first_non_const_instruction = nullptr;
19181 bool is_comptime;
19182 switch (type_requires_comptime(ira->codegen, container_type)) {
19183 case ReqCompTimeInvalid:
19184 return ira->codegen->invalid_instruction;
19185 case ReqCompTimeNo:
19186 is_comptime = ir_should_inline(ira->new_irb.exec, instruction->base.scope);
19187 break;
19188 case ReqCompTimeYes:
19189 is_comptime = true;
19190 break;
19191 }
1915619192
19157 for (size_t i = 0; i < elem_count; i += 1) {
19158 IrInstruction *arg_value = instruction->items[i]->child;
19159 if (type_is_invalid(arg_value->value.type))
19160 return ira->codegen->invalid_instruction;
19193 IrInstruction *first_non_const_instruction = nullptr;
1916119194
19162 IrInstruction *casted_arg = ir_implicit_cast(ira, arg_value, child_type);
19163 if (casted_arg == ira->codegen->invalid_instruction)
19164 return ira->codegen->invalid_instruction;
19195 // The Result Location Mechanism has already emitted runtime instructions to
19196 // initialize runtime elements and has omitted instructions for the comptime
19197 // elements. However it is only now that we find out whether the array initialization
19198 // can be a comptime value. So we must clean up the situation. If it turns out
19199 // array initialization can be a comptime value, overwrite ConstPtrMutInfer with
19200 // ConstPtrMutComptimeConst. Otherwise, emit instructions to runtime-initialize the
19201 // elements that have comptime-known values.
19202 ZigList<IrInstruction *> const_ptrs = {};
1916519203
19166 new_items[i] = casted_arg;
19204 for (size_t i = 0; i < elem_count; i += 1) {
19205 IrInstruction *elem_result_loc = instruction->elem_result_loc_list[i]->child;
19206 if (type_is_invalid(elem_result_loc->value.type))
19207 return ira->codegen->invalid_instruction;
1916719208
19168 if (const_val.special == ConstValSpecialStatic) {
19169 if (is_comptime || casted_arg->value.special != ConstValSpecialRuntime) {
19170 ConstExprValue *elem_val = ir_resolve_const(ira, casted_arg, UndefBad);
19171 if (!elem_val)
19172 return ira->codegen->invalid_instruction;
19209 assert(elem_result_loc->value.type->id == ZigTypeIdPointer);
1917319210
19174 copy_const_val(&const_val.data.x_array.data.s_none.elements[i], elem_val, true);
19175 } else {
19176 first_non_const_instruction = casted_arg;
19177 const_val.special = ConstValSpecialRuntime;
19178 }
19179 }
19211 if (instr_is_comptime(elem_result_loc) &&
19212 elem_result_loc->value.data.x_ptr.mut != ConstPtrMutRuntimeVar)
19213 {
19214 const_ptrs.append(elem_result_loc);
19215 } else {
19216 first_non_const_instruction = elem_result_loc;
1918019217 }
19218 }
1918119219
19182 if (const_val.special == ConstValSpecialStatic) {
19183 IrInstruction *result = ir_const(ira, &instruction->base, nullptr);
19184 ConstExprValue *out_val = &result->value;
19185 copy_const_val(out_val, &const_val, false);
19186 result->value.type = fixed_size_array_type;
19187 for (size_t i = 0; i < elem_count; i += 1) {
19188 ConstExprValue *elem_val = &out_val->data.x_array.data.s_none.elements[i];
19189 ConstParent *parent = get_const_val_parent(ira->codegen, elem_val);
19190 if (parent != nullptr) {
19191 parent->id = ConstParentIdArray;
19192 parent->data.p_array.array_val = out_val;
19193 parent->data.p_array.elem_index = i;
19194 }
19220 if (result_loc->value.data.x_ptr.mut == ConstPtrMutInfer) {
19221 if (const_ptrs.length == elem_count) {
19222 result_loc->value.data.x_ptr.mut = ConstPtrMutComptimeConst;
19223 } else {
19224 result_loc->value.special = ConstValSpecialRuntime;
19225 for (size_t i = 0; i < const_ptrs.length; i += 1) {
19226 IrInstruction *elem_result_loc = const_ptrs.at(i);
19227 assert(elem_result_loc->value.special == ConstValSpecialStatic);
19228 IrInstruction *deref = ir_get_deref(ira, elem_result_loc, elem_result_loc, nullptr);
19229 elem_result_loc->value.special = ConstValSpecialRuntime;
19230 ir_analyze_store_ptr(ira, elem_result_loc, elem_result_loc, deref);
1919519231 }
19196 return result;
1919719232 }
19233 }
1919819234
19199 if (is_comptime) {
19200 ir_add_error_node(ira, first_non_const_instruction->source_node,
19201 buf_sprintf("unable to evaluate constant expression"));
19202 return ira->codegen->invalid_instruction;
19203 }
19235 IrInstruction *result = ir_get_deref(ira, &instruction->base, result_loc, nullptr);
19236 if (instr_is_comptime(result))
19237 return result;
1920419238
19205 ir_assert(instruction->result_loc != nullptr, &instruction->base);
19206 IrInstruction *result_loc = instruction->result_loc->child;
19207 if (type_is_invalid(result_loc->value.type))
19208 return result_loc;
19209 ir_assert(result_loc->value.type->id == ZigTypeIdPointer, &instruction->base);
19210 ZigType *result_elem_type = result_loc->value.type->data.pointer.child_type;
19211 if (is_slice(result_elem_type)) {
19212 ErrorMsg *msg = ir_add_error(ira, &instruction->base,
19213 buf_sprintf("runtime-initialized array cannot be casted to slice type '%s'",
19214 buf_ptr(&result_elem_type->name)));
19215 add_error_note(ira->codegen, msg, first_non_const_instruction->source_node,
19216 buf_sprintf("this value is not comptime-known"));
19217 return ira->codegen->invalid_instruction;
19218 }
19219 return ir_get_deref(ira, &instruction->base, result_loc, nullptr);
19220 } else if (container_type->id == ZigTypeIdVoid) {
19221 if (elem_count != 0) {
19222 ir_add_error_node(ira, instruction->base.source_node,
19223 buf_sprintf("void expression expects no arguments"));
19224 return ira->codegen->invalid_instruction;
19225 }
19226 return ir_const_void(ira, &instruction->base);
19227 } else {
19228 ir_add_error_node(ira, instruction->base.source_node,
19229 buf_sprintf("type '%s' does not support array initialization",
19230 buf_ptr(&container_type->name)));
19239 if (is_comptime) {
19240 ir_add_error_node(ira, first_non_const_instruction->source_node,
19241 buf_sprintf("unable to evaluate constant expression"));
19242 return ira->codegen->invalid_instruction;
19243 }
19244
19245 ZigType *result_elem_type = result_loc->value.type->data.pointer.child_type;
19246 if (is_slice(result_elem_type)) {
19247 ErrorMsg *msg = ir_add_error(ira, &instruction->base,
19248 buf_sprintf("runtime-initialized array cannot be casted to slice type '%s'",
19249 buf_ptr(&result_elem_type->name)));
19250 add_error_note(ira->codegen, msg, first_non_const_instruction->source_node,
19251 buf_sprintf("this value is not comptime-known"));
1923119252 return ira->codegen->invalid_instruction;
1923219253 }
19254 return result;
1923319255}
1923419256
1923519257static IrInstruction *ir_analyze_instruction_container_init_fields(IrAnalyze *ira,
src/ir_print.cpp+2-2
......@@ -348,10 +348,10 @@ static void ir_print_container_init_list(IrPrint *irp, IrInstructionContainerIni
348348 fprintf(irp->f, "...(%" ZIG_PRI_usize " items)...", instruction->item_count);
349349 } else {
350350 for (size_t i = 0; i < instruction->item_count; i += 1) {
351 IrInstruction *item = instruction->items[i];
351 IrInstruction *result_loc = instruction->elem_result_loc_list[i];
352352 if (i != 0)
353353 fprintf(irp->f, ", ");
354 ir_print_other_instruction(irp, item);
354 ir_print_other_instruction(irp, result_loc);
355355 }
356356 }
357357 fprintf(irp->f, "}");