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
signature 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 {...@@ -2640,7 +2640,7 @@ struct IrInstructionContainerInitList {
2640 IrInstruction *container_type;2640 IrInstruction *container_type;
2641 IrInstruction *elem_type;2641 IrInstruction *elem_type;
2642 size_t item_count;2642 size_t item_count;
2643 IrInstruction **items;2643 IrInstruction **elem_result_loc_list;
2644 IrInstruction *result_loc;2644 IrInstruction *result_loc;
2645};2645};
26462646
src/ir.cpp+127-105
...@@ -1524,18 +1524,19 @@ static IrInstruction *ir_build_un_op(IrBuilder *irb, Scope *scope, AstNode *sour...@@ -1524,18 +1524,19 @@ static IrInstruction *ir_build_un_op(IrBuilder *irb, Scope *scope, AstNode *sour
1524}1524}
15251525
1526static IrInstruction *ir_build_container_init_list(IrBuilder *irb, Scope *scope, AstNode *source_node,1526static 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)
1528{1529{
1529 IrInstructionContainerInitList *container_init_list_instruction =1530 IrInstructionContainerInitList *container_init_list_instruction =
1530 ir_build_instruction<IrInstructionContainerInitList>(irb, scope, source_node);1531 ir_build_instruction<IrInstructionContainerInitList>(irb, scope, source_node);
1531 container_init_list_instruction->container_type = container_type;1532 container_init_list_instruction->container_type = container_type;
1532 container_init_list_instruction->item_count = item_count;1533 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;
1534 container_init_list_instruction->result_loc = result_loc;1535 container_init_list_instruction->result_loc = result_loc;
15351536
1536 ir_ref_instruction(container_type, irb->current_basic_block);1537 ir_ref_instruction(container_type, irb->current_basic_block);
1537 for (size_t i = 0; i < item_count; i += 1) {1538 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);
1539 }1540 }
1540 if (result_loc != nullptr) ir_ref_instruction(result_loc, irb->current_basic_block);1541 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...@@ -5802,7 +5803,7 @@ static IrInstruction *ir_gen_container_init_expr(IrBuilder *irb, Scope *scope, A
5802 IrInstruction *container_ptr = ir_build_resolve_result(irb, scope, node, parent_result_loc,5803 IrInstruction *container_ptr = ir_build_resolve_result(irb, scope, node, parent_result_loc,
5803 container_type);5804 container_type);
58045805
5805 IrInstruction **values = allocate<IrInstruction *>(item_count);5806 IrInstruction **result_locs = allocate<IrInstruction *>(item_count);
5806 for (size_t i = 0; i < item_count; i += 1) {5807 for (size_t i = 0; i < item_count; i += 1) {
5807 AstNode *expr_node = container_init_expr->entries.at(i);5808 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...@@ -5813,16 +5814,17 @@ static IrInstruction *ir_gen_container_init_expr(IrBuilder *irb, Scope *scope, A
5813 result_loc_inst->base.id = ResultLocIdInstruction;5814 result_loc_inst->base.id = ResultLocIdInstruction;
5814 result_loc_inst->base.source_instruction = elem_ptr;5815 result_loc_inst->base.source_instruction = elem_ptr;
5815 ir_ref_instruction(elem_ptr, irb->current_basic_block);5816 ir_ref_instruction(elem_ptr, irb->current_basic_block);
5817 ir_build_reset_result(irb, scope, expr_node, &result_loc_inst->base);
58165818
5817 IrInstruction *expr_value = ir_gen_node_extra(irb, expr_node, scope, LValNone,5819 IrInstruction *expr_value = ir_gen_node_extra(irb, expr_node, scope, LValNone,
5818 &result_loc_inst->base);5820 &result_loc_inst->base);
5819 if (expr_value == irb->codegen->invalid_instruction)5821 if (expr_value == irb->codegen->invalid_instruction)
5820 return expr_value;5822 return expr_value;
58215823
5822 values[i] = expr_value;5824 result_locs[i] = elem_ptr;
5823 }5825 }
5824 IrInstruction *init_list = ir_build_container_init_list(irb, scope, node, container_type,5826 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);
5826 return ir_lval_wrap(irb, scope, init_list, lval, parent_result_loc);5828 return ir_lval_wrap(irb, scope, init_list, lval, parent_result_loc);
5827 }5829 }
5828 }5830 }
...@@ -16891,6 +16893,22 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct...@@ -16891,6 +16893,22 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct
16891 if (array_ptr_val == nullptr)16893 if (array_ptr_val == nullptr)
16892 return ira->codegen->invalid_instruction;16894 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
16894 if (array_ptr_val->special != ConstValSpecialRuntime &&16912 if (array_ptr_val->special != ConstValSpecialRuntime &&
16895 (array_type->id != ZigTypeIdPointer ||16913 (array_type->id != ZigTypeIdPointer ||
16896 array_ptr_val->data.x_ptr.special != ConstPtrSpecialHardCodedAddr))16914 array_ptr_val->data.x_ptr.special != ConstPtrSpecialHardCodedAddr))
...@@ -17011,7 +17029,16 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct...@@ -17011,7 +17029,16 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct
17011 }17029 }
17012 return result;17030 return result;
17013 } else if (array_type->id == ZigTypeIdArray) {17031 } 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 }
17015 ConstExprValue *out_val = &result->value;17042 ConstExprValue *out_val = &result->value;
17016 out_val->data.x_ptr.special = ConstPtrSpecialBaseArray;17043 out_val->data.x_ptr.special = ConstPtrSpecialBaseArray;
17017 out_val->data.x_ptr.mut = orig_array_ptr_val->data.x_ptr.mut;17044 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...@@ -19099,8 +19126,6 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc
19099static IrInstruction *ir_analyze_instruction_container_init_list(IrAnalyze *ira,19126static IrInstruction *ir_analyze_instruction_container_init_list(IrAnalyze *ira,
19100 IrInstructionContainerInitList *instruction)19127 IrInstructionContainerInitList *instruction)
19101{19128{
19102 Error err;
19103
19104 ZigType *container_type = ir_resolve_type(ira, instruction->container_type->child);19129 ZigType *container_type = ir_resolve_type(ira, instruction->container_type->child);
19105 if (type_is_invalid(container_type))19130 if (type_is_invalid(container_type))
19106 return ira->codegen->invalid_instruction;19131 return ira->codegen->invalid_instruction;
...@@ -19111,125 +19136,122 @@ static IrInstruction *ir_analyze_instruction_container_init_list(IrAnalyze *ira,...@@ -19111,125 +19136,122 @@ static IrInstruction *ir_analyze_instruction_container_init_list(IrAnalyze *ira,
19111 ir_add_error(ira, &instruction->base,19136 ir_add_error(ira, &instruction->base,
19112 buf_sprintf("expected array type or [_], found slice"));19137 buf_sprintf("expected array type or [_], found slice"));
19113 return ira->codegen->invalid_instruction;19138 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) {
19115 ir_assert(instruction->result_loc != nullptr, &instruction->base);19151 ir_assert(instruction->result_loc != nullptr, &instruction->base);
19116 IrInstruction *result_loc = instruction->result_loc->child;19152 IrInstruction *result_loc = instruction->result_loc->child;
19117 if (type_is_invalid(result_loc->value.type))19153 if (type_is_invalid(result_loc->value.type))
19118 return result_loc;19154 return result_loc;
19119 return ir_analyze_container_init_fields(ira, &instruction->base, container_type, 0, nullptr, result_loc);19155 return ir_analyze_container_init_fields(ira, &instruction->base, container_type, 0, nullptr, result_loc);
19120 } else if (container_type->id == ZigTypeIdArray) {19156 }
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 }
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 = {};19165 ir_assert(instruction->result_loc != nullptr, &instruction->base);
19146 const_val.special = ConstValSpecialStatic;19166 IrInstruction *result_loc = instruction->result_loc->child;
19147 const_val.type = fixed_size_array_type;19167 if (type_is_invalid(result_loc->value.type))
19148 // const_val.global_refs = allocate<ConstGlobalRefs>(1);19168 return result_loc;
19149 const_val.data.x_array.data.s_none.elements = create_const_vals(elem_count);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) {19193 IrInstruction *first_non_const_instruction = nullptr;
19158 IrInstruction *arg_value = instruction->items[i]->child;
19159 if (type_is_invalid(arg_value->value.type))
19160 return ira->codegen->invalid_instruction;
1916119194
19162 IrInstruction *casted_arg = ir_implicit_cast(ira, arg_value, child_type);19195 // The Result Location Mechanism has already emitted runtime instructions to
19163 if (casted_arg == ira->codegen->invalid_instruction)19196 // initialize runtime elements and has omitted instructions for the comptime
19164 return ira->codegen->invalid_instruction;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) {19209 assert(elem_result_loc->value.type->id == ZigTypeIdPointer);
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;
1917319210
19174 copy_const_val(&const_val.data.x_array.data.s_none.elements[i], elem_val, true);19211 if (instr_is_comptime(elem_result_loc) &&
19175 } else {19212 elem_result_loc->value.data.x_ptr.mut != ConstPtrMutRuntimeVar)
19176 first_non_const_instruction = casted_arg;19213 {
19177 const_val.special = ConstValSpecialRuntime;19214 const_ptrs.append(elem_result_loc);
19178 }19215 } else {
19179 }19216 first_non_const_instruction = elem_result_loc;
19180 }19217 }
19218 }
1918119219
19182 if (const_val.special == ConstValSpecialStatic) {19220 if (result_loc->value.data.x_ptr.mut == ConstPtrMutInfer) {
19183 IrInstruction *result = ir_const(ira, &instruction->base, nullptr);19221 if (const_ptrs.length == elem_count) {
19184 ConstExprValue *out_val = &result->value;19222 result_loc->value.data.x_ptr.mut = ConstPtrMutComptimeConst;
19185 copy_const_val(out_val, &const_val, false);19223 } else {
19186 result->value.type = fixed_size_array_type;19224 result_loc->value.special = ConstValSpecialRuntime;
19187 for (size_t i = 0; i < elem_count; i += 1) {19225 for (size_t i = 0; i < const_ptrs.length; i += 1) {
19188 ConstExprValue *elem_val = &out_val->data.x_array.data.s_none.elements[i];19226 IrInstruction *elem_result_loc = const_ptrs.at(i);
19189 ConstParent *parent = get_const_val_parent(ira->codegen, elem_val);19227 assert(elem_result_loc->value.special == ConstValSpecialStatic);
19190 if (parent != nullptr) {19228 IrInstruction *deref = ir_get_deref(ira, elem_result_loc, elem_result_loc, nullptr);
19191 parent->id = ConstParentIdArray;19229 elem_result_loc->value.special = ConstValSpecialRuntime;
19192 parent->data.p_array.array_val = out_val;19230 ir_analyze_store_ptr(ira, elem_result_loc, elem_result_loc, deref);
19193 parent->data.p_array.elem_index = i;
19194 }
19195 }19231 }
19196 return result;
19197 }19232 }
19233 }
1919819234
19199 if (is_comptime) {19235 IrInstruction *result = ir_get_deref(ira, &instruction->base, result_loc, nullptr);
19200 ir_add_error_node(ira, first_non_const_instruction->source_node,19236 if (instr_is_comptime(result))
19201 buf_sprintf("unable to evaluate constant expression"));19237 return result;
19202 return ira->codegen->invalid_instruction;
19203 }
1920419238
19205 ir_assert(instruction->result_loc != nullptr, &instruction->base);19239 if (is_comptime) {
19206 IrInstruction *result_loc = instruction->result_loc->child;19240 ir_add_error_node(ira, first_non_const_instruction->source_node,
19207 if (type_is_invalid(result_loc->value.type))19241 buf_sprintf("unable to evaluate constant expression"));
19208 return result_loc;19242 return ira->codegen->invalid_instruction;
19209 ir_assert(result_loc->value.type->id == ZigTypeIdPointer, &instruction->base);19243 }
19210 ZigType *result_elem_type = result_loc->value.type->data.pointer.child_type;19244
19211 if (is_slice(result_elem_type)) {19245 ZigType *result_elem_type = result_loc->value.type->data.pointer.child_type;
19212 ErrorMsg *msg = ir_add_error(ira, &instruction->base,19246 if (is_slice(result_elem_type)) {
19213 buf_sprintf("runtime-initialized array cannot be casted to slice type '%s'",19247 ErrorMsg *msg = ir_add_error(ira, &instruction->base,
19214 buf_ptr(&result_elem_type->name)));19248 buf_sprintf("runtime-initialized array cannot be casted to slice type '%s'",
19215 add_error_note(ira->codegen, msg, first_non_const_instruction->source_node,19249 buf_ptr(&result_elem_type->name)));
19216 buf_sprintf("this value is not comptime-known"));19250 add_error_note(ira->codegen, msg, first_non_const_instruction->source_node,
19217 return ira->codegen->invalid_instruction;19251 buf_sprintf("this value is not comptime-known"));
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)));
19231 return ira->codegen->invalid_instruction;19252 return ira->codegen->invalid_instruction;
19232 }19253 }
19254 return result;
19233}19255}
1923419256
19235static IrInstruction *ir_analyze_instruction_container_init_fields(IrAnalyze *ira,19257static 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...@@ -348,10 +348,10 @@ static void ir_print_container_init_list(IrPrint *irp, IrInstructionContainerIni
348 fprintf(irp->f, "...(%" ZIG_PRI_usize " items)...", instruction->item_count);348 fprintf(irp->f, "...(%" ZIG_PRI_usize " items)...", instruction->item_count);
349 } else {349 } else {
350 for (size_t i = 0; i < instruction->item_count; i += 1) {350 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];
352 if (i != 0)352 if (i != 0)
353 fprintf(irp->f, ", ");353 fprintf(irp->f, ", ");
354 ir_print_other_instruction(irp, item);354 ir_print_other_instruction(irp, result_loc);
355 }355 }
356 }356 }
357 fprintf(irp->f, "}");357 fprintf(irp->f, "}");