| author | |
| committer | |
| log | 8c6fa982cd0a02775264b616c37da9907cc603bb |
| tree | bf8101fa59d6909ea4e3364d0b31e63fbdf3c69e |
| parent | 2828a9695f088f5454f445fdd0544d805a33837b |
| signature |
also vectors and arrays now use the same ConstExprVal representation
See #9038 files changed, 403 insertions(+), 224 deletions(-)
src/all_types.hpp+15-5| ... | @@ -252,10 +252,6 @@ struct ConstArgTuple { | ... | @@ -252,10 +252,6 @@ struct ConstArgTuple { |
| 252 | size_t end_index; | 252 | size_t end_index; |
| 253 | }; | 253 | }; |
| 254 | 254 | ||
| 255 | struct ConstVector { | ||
| 256 | ConstExprValue *elements; | ||
| 257 | }; | ||
| 258 | |||
| 259 | enum ConstValSpecial { | 255 | enum ConstValSpecial { |
| 260 | ConstValSpecialRuntime, | 256 | ConstValSpecialRuntime, |
| 261 | ConstValSpecialStatic, | 257 | ConstValSpecialStatic, |
| ... | @@ -322,7 +318,6 @@ struct ConstExprValue { | ... | @@ -322,7 +318,6 @@ struct ConstExprValue { |
| 322 | ConstPtrValue x_ptr; | 318 | ConstPtrValue x_ptr; |
| 323 | ImportTableEntry *x_import; | 319 | ImportTableEntry *x_import; |
| 324 | ConstArgTuple x_arg_tuple; | 320 | ConstArgTuple x_arg_tuple; |
| 325 | ConstVector x_vector; | ||
| 326 | 321 | ||
| 327 | // populated if special == ConstValSpecialRuntime | 322 | // populated if special == ConstValSpecialRuntime |
| 328 | RuntimeHintErrorUnion rh_error_union; | 323 | RuntimeHintErrorUnion rh_error_union; |
| ... | @@ -2239,6 +2234,8 @@ enum IrInstructionId { | ... | @@ -2239,6 +2234,8 @@ enum IrInstructionId { |
| 2239 | IrInstructionIdToBytes, | 2234 | IrInstructionIdToBytes, |
| 2240 | IrInstructionIdFromBytes, | 2235 | IrInstructionIdFromBytes, |
| 2241 | IrInstructionIdCheckRuntimeScope, | 2236 | IrInstructionIdCheckRuntimeScope, |
| 2237 | IrInstructionIdVectorToArray, | ||
| 2238 | IrInstructionIdArrayToVector, | ||
| 2242 | }; | 2239 | }; |
| 2243 | 2240 | ||
| 2244 | struct IrInstruction { | 2241 | struct IrInstruction { |
| ... | @@ -3368,6 +3365,19 @@ struct IrInstructionBitReverse { | ... | @@ -3368,6 +3365,19 @@ struct IrInstructionBitReverse { |
| 3368 | IrInstruction *op; | 3365 | IrInstruction *op; |
| 3369 | }; | 3366 | }; |
| 3370 | 3367 | ||
| 3368 | struct IrInstructionArrayToVector { | ||
| 3369 | IrInstruction base; | ||
| 3370 | |||
| 3371 | IrInstruction *array; | ||
| 3372 | }; | ||
| 3373 | |||
| 3374 | struct IrInstructionVectorToArray { | ||
| 3375 | IrInstruction base; | ||
| 3376 | |||
| 3377 | IrInstruction *vector; | ||
| 3378 | LLVMValueRef tmp_ptr; | ||
| 3379 | }; | ||
| 3380 | |||
| 3371 | static const size_t slice_ptr_index = 0; | 3381 | static const size_t slice_ptr_index = 0; |
| 3372 | static const size_t slice_len_index = 1; | 3382 | static const size_t slice_len_index = 1; |
| 3373 | 3383 |
src/analyze.cpp+90-88| ... | @@ -4457,7 +4457,15 @@ ZigType *get_int_type(CodeGen *g, bool is_signed, uint32_t size_in_bits) { | ... | @@ -4457,7 +4457,15 @@ ZigType *get_int_type(CodeGen *g, bool is_signed, uint32_t size_in_bits) { |
| 4457 | return new_entry; | 4457 | return new_entry; |
| 4458 | } | 4458 | } |
| 4459 | 4459 | ||
| 4460 | bool is_valid_vector_elem_type(ZigType *elem_type) { | ||
| 4461 | return elem_type->id == ZigTypeIdInt || | ||
| 4462 | elem_type->id == ZigTypeIdFloat || | ||
| 4463 | get_codegen_ptr_type(elem_type) != nullptr; | ||
| 4464 | } | ||
| 4465 | |||
| 4460 | ZigType *get_vector_type(CodeGen *g, uint32_t len, ZigType *elem_type) { | 4466 | ZigType *get_vector_type(CodeGen *g, uint32_t len, ZigType *elem_type) { |
| 4467 | assert(is_valid_vector_elem_type(elem_type)); | ||
| 4468 | |||
| 4461 | TypeId type_id = {}; | 4469 | TypeId type_id = {}; |
| 4462 | type_id.id = ZigTypeIdVector; | 4470 | type_id.id = ZigTypeIdVector; |
| 4463 | type_id.data.vector.len = len; | 4471 | type_id.data.vector.len = len; |
| ... | @@ -5749,6 +5757,28 @@ bool const_values_equal_ptr(ConstExprValue *a, ConstExprValue *b) { | ... | @@ -5749,6 +5757,28 @@ bool const_values_equal_ptr(ConstExprValue *a, ConstExprValue *b) { |
| 5749 | zig_unreachable(); | 5757 | zig_unreachable(); |
| 5750 | } | 5758 | } |
| 5751 | 5759 | ||
| 5760 | static bool const_values_equal_array(CodeGen *g, ConstExprValue *a, ConstExprValue *b, size_t len) { | ||
| 5761 | assert(a->data.x_array.special != ConstArraySpecialUndef); | ||
| 5762 | assert(b->data.x_array.special != ConstArraySpecialUndef); | ||
| 5763 | if (a->data.x_array.special == ConstArraySpecialBuf && | ||
| 5764 | b->data.x_array.special == ConstArraySpecialBuf) | ||
| 5765 | { | ||
| 5766 | return buf_eql_buf(a->data.x_array.data.s_buf, b->data.x_array.data.s_buf); | ||
| 5767 | } | ||
| 5768 | expand_undef_array(g, a); | ||
| 5769 | expand_undef_array(g, b); | ||
| 5770 | |||
| 5771 | ConstExprValue *a_elems = a->data.x_array.data.s_none.elements; | ||
| 5772 | ConstExprValue *b_elems = b->data.x_array.data.s_none.elements; | ||
| 5773 | |||
| 5774 | for (size_t i = 0; i < len; i += 1) { | ||
| 5775 | if (!const_values_equal(g, &a_elems[i], &b_elems[i])) | ||
| 5776 | return false; | ||
| 5777 | } | ||
| 5778 | |||
| 5779 | return true; | ||
| 5780 | } | ||
| 5781 | |||
| 5752 | bool const_values_equal(CodeGen *g, ConstExprValue *a, ConstExprValue *b) { | 5782 | bool const_values_equal(CodeGen *g, ConstExprValue *a, ConstExprValue *b) { |
| 5753 | assert(a->type->id == b->type->id); | 5783 | assert(a->type->id == b->type->id); |
| 5754 | assert(a->special == ConstValSpecialStatic); | 5784 | assert(a->special == ConstValSpecialStatic); |
| ... | @@ -5803,28 +5833,12 @@ bool const_values_equal(CodeGen *g, ConstExprValue *a, ConstExprValue *b) { | ... | @@ -5803,28 +5833,12 @@ bool const_values_equal(CodeGen *g, ConstExprValue *a, ConstExprValue *b) { |
| 5803 | case ZigTypeIdPointer: | 5833 | case ZigTypeIdPointer: |
| 5804 | case ZigTypeIdFn: | 5834 | case ZigTypeIdFn: |
| 5805 | return const_values_equal_ptr(a, b); | 5835 | return const_values_equal_ptr(a, b); |
| 5836 | case ZigTypeIdVector: | ||
| 5837 | assert(a->type->data.vector.len == b->type->data.vector.len); | ||
| 5838 | return const_values_equal_array(g, a, b, a->type->data.vector.len); | ||
| 5806 | case ZigTypeIdArray: { | 5839 | case ZigTypeIdArray: { |
| 5807 | assert(a->type->data.array.len == b->type->data.array.len); | 5840 | assert(a->type->data.array.len == b->type->data.array.len); |
| 5808 | assert(a->data.x_array.special != ConstArraySpecialUndef); | 5841 | return const_values_equal_array(g, a, b, a->type->data.array.len); |
| 5809 | assert(b->data.x_array.special != ConstArraySpecialUndef); | ||
| 5810 | if (a->data.x_array.special == ConstArraySpecialBuf && | ||
| 5811 | b->data.x_array.special == ConstArraySpecialBuf) | ||
| 5812 | { | ||
| 5813 | return buf_eql_buf(a->data.x_array.data.s_buf, b->data.x_array.data.s_buf); | ||
| 5814 | } | ||
| 5815 | expand_undef_array(g, a); | ||
| 5816 | expand_undef_array(g, b); | ||
| 5817 | |||
| 5818 | size_t len = a->type->data.array.len; | ||
| 5819 | ConstExprValue *a_elems = a->data.x_array.data.s_none.elements; | ||
| 5820 | ConstExprValue *b_elems = b->data.x_array.data.s_none.elements; | ||
| 5821 | |||
| 5822 | for (size_t i = 0; i < len; i += 1) { | ||
| 5823 | if (!const_values_equal(g, &a_elems[i], &b_elems[i])) | ||
| 5824 | return false; | ||
| 5825 | } | ||
| 5826 | |||
| 5827 | return true; | ||
| 5828 | } | 5842 | } |
| 5829 | case ZigTypeIdStruct: | 5843 | case ZigTypeIdStruct: |
| 5830 | for (size_t i = 0; i < a->type->data.structure.src_field_count; i += 1) { | 5844 | for (size_t i = 0; i < a->type->data.structure.src_field_count; i += 1) { |
| ... | @@ -5853,20 +5867,6 @@ bool const_values_equal(CodeGen *g, ConstExprValue *a, ConstExprValue *b) { | ... | @@ -5853,20 +5867,6 @@ bool const_values_equal(CodeGen *g, ConstExprValue *a, ConstExprValue *b) { |
| 5853 | case ZigTypeIdArgTuple: | 5867 | case ZigTypeIdArgTuple: |
| 5854 | return a->data.x_arg_tuple.start_index == b->data.x_arg_tuple.start_index && | 5868 | return a->data.x_arg_tuple.start_index == b->data.x_arg_tuple.start_index && |
| 5855 | a->data.x_arg_tuple.end_index == b->data.x_arg_tuple.end_index; | 5869 | a->data.x_arg_tuple.end_index == b->data.x_arg_tuple.end_index; |
| 5856 | case ZigTypeIdVector: { | ||
| 5857 | assert(a->type->data.vector.len == b->type->data.vector.len); | ||
| 5858 | |||
| 5859 | size_t len = a->type->data.vector.len; | ||
| 5860 | ConstExprValue *a_elems = a->data.x_vector.elements; | ||
| 5861 | ConstExprValue *b_elems = b->data.x_vector.elements; | ||
| 5862 | |||
| 5863 | for (size_t i = 0; i < len; i += 1) { | ||
| 5864 | if (!const_values_equal(g, &a_elems[i], &b_elems[i])) | ||
| 5865 | return false; | ||
| 5866 | } | ||
| 5867 | |||
| 5868 | return true; | ||
| 5869 | } | ||
| 5870 | case ZigTypeIdBoundFn: | 5870 | case ZigTypeIdBoundFn: |
| 5871 | case ZigTypeIdInvalid: | 5871 | case ZigTypeIdInvalid: |
| 5872 | case ZigTypeIdUnreachable: | 5872 | case ZigTypeIdUnreachable: |
| ... | @@ -5985,6 +5985,40 @@ static void render_const_val_err_set(CodeGen *g, Buf *buf, ConstExprValue *const | ... | @@ -5985,6 +5985,40 @@ static void render_const_val_err_set(CodeGen *g, Buf *buf, ConstExprValue *const |
| 5985 | } | 5985 | } |
| 5986 | } | 5986 | } |
| 5987 | 5987 | ||
| 5988 | static void render_const_val_array(CodeGen *g, Buf *buf, ConstExprValue *const_val, size_t len) { | ||
| 5989 | switch (const_val->data.x_array.special) { | ||
| 5990 | case ConstArraySpecialUndef: | ||
| 5991 | buf_append_str(buf, "undefined"); | ||
| 5992 | return; | ||
| 5993 | case ConstArraySpecialBuf: { | ||
| 5994 | Buf *array_buf = const_val->data.x_array.data.s_buf; | ||
| 5995 | buf_append_char(buf, '"'); | ||
| 5996 | for (size_t i = 0; i < buf_len(array_buf); i += 1) { | ||
| 5997 | uint8_t c = buf_ptr(array_buf)[i]; | ||
| 5998 | if (c == '"') { | ||
| 5999 | buf_append_str(buf, "\\\""); | ||
| 6000 | } else { | ||
| 6001 | buf_append_char(buf, c); | ||
| 6002 | } | ||
| 6003 | } | ||
| 6004 | buf_append_char(buf, '"'); | ||
| 6005 | return; | ||
| 6006 | } | ||
| 6007 | case ConstArraySpecialNone: { | ||
| 6008 | buf_appendf(buf, "%s{", buf_ptr(&const_val->type->name)); | ||
| 6009 | for (uint64_t i = 0; i < len; i += 1) { | ||
| 6010 | if (i != 0) | ||
| 6011 | buf_appendf(buf, ","); | ||
| 6012 | ConstExprValue *child_value = &const_val->data.x_array.data.s_none.elements[i]; | ||
| 6013 | render_const_value(g, buf, child_value); | ||
| 6014 | } | ||
| 6015 | buf_appendf(buf, "}"); | ||
| 6016 | return; | ||
| 6017 | } | ||
| 6018 | } | ||
| 6019 | zig_unreachable(); | ||
| 6020 | } | ||
| 6021 | |||
| 5988 | void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) { | 6022 | void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) { |
| 5989 | switch (const_val->special) { | 6023 | switch (const_val->special) { |
| 5990 | case ConstValSpecialRuntime: | 6024 | case ConstValSpecialRuntime: |
| ... | @@ -6065,51 +6099,10 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) { | ... | @@ -6065,51 +6099,10 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) { |
| 6065 | } | 6099 | } |
| 6066 | case ZigTypeIdPointer: | 6100 | case ZigTypeIdPointer: |
| 6067 | return render_const_val_ptr(g, buf, const_val, type_entry); | 6101 | return render_const_val_ptr(g, buf, const_val, type_entry); |
| 6102 | case ZigTypeIdVector: | ||
| 6103 | return render_const_val_array(g, buf, const_val, type_entry->data.vector.len); | ||
| 6068 | case ZigTypeIdArray: | 6104 | case ZigTypeIdArray: |
| 6069 | switch (const_val->data.x_array.special) { | 6105 | return render_const_val_array(g, buf, const_val, type_entry->data.array.len); |
| 6070 | case ConstArraySpecialUndef: | ||
| 6071 | buf_append_str(buf, "undefined"); | ||
| 6072 | return; | ||
| 6073 | case ConstArraySpecialBuf: { | ||
| 6074 | Buf *array_buf = const_val->data.x_array.data.s_buf; | ||
| 6075 | buf_append_char(buf, '"'); | ||
| 6076 | for (size_t i = 0; i < buf_len(array_buf); i += 1) { | ||
| 6077 | uint8_t c = buf_ptr(array_buf)[i]; | ||
| 6078 | if (c == '"') { | ||
| 6079 | buf_append_str(buf, "\\\""); | ||
| 6080 | } else { | ||
| 6081 | buf_append_char(buf, c); | ||
| 6082 | } | ||
| 6083 | } | ||
| 6084 | buf_append_char(buf, '"'); | ||
| 6085 | return; | ||
| 6086 | } | ||
| 6087 | case ConstArraySpecialNone: { | ||
| 6088 | buf_appendf(buf, "%s{", buf_ptr(&type_entry->name)); | ||
| 6089 | uint64_t len = type_entry->data.array.len; | ||
| 6090 | for (uint64_t i = 0; i < len; i += 1) { | ||
| 6091 | if (i != 0) | ||
| 6092 | buf_appendf(buf, ","); | ||
| 6093 | ConstExprValue *child_value = &const_val->data.x_array.data.s_none.elements[i]; | ||
| 6094 | render_const_value(g, buf, child_value); | ||
| 6095 | } | ||
| 6096 | buf_appendf(buf, "}"); | ||
| 6097 | return; | ||
| 6098 | } | ||
| 6099 | } | ||
| 6100 | zig_unreachable(); | ||
| 6101 | case ZigTypeIdVector: { | ||
| 6102 | buf_appendf(buf, "%s{", buf_ptr(&type_entry->name)); | ||
| 6103 | uint64_t len = type_entry->data.vector.len; | ||
| 6104 | for (uint32_t i = 0; i < len; i += 1) { | ||
| 6105 | if (i != 0) | ||
| 6106 | buf_appendf(buf, ","); | ||
| 6107 | ConstExprValue *child_value = &const_val->data.x_vector.elements[i]; | ||
| 6108 | render_const_value(g, buf, child_value); | ||
| 6109 | } | ||
| 6110 | buf_appendf(buf, "}"); | ||
| 6111 | return; | ||
| 6112 | } | ||
| 6113 | case ZigTypeIdNull: | 6106 | case ZigTypeIdNull: |
| 6114 | { | 6107 | { |
| 6115 | buf_appendf(buf, "null"); | 6108 | buf_appendf(buf, "null"); |
| ... | @@ -6379,7 +6372,17 @@ bool zig_llvm_fn_key_eql(ZigLLVMFnKey a, ZigLLVMFnKey b) { | ... | @@ -6379,7 +6372,17 @@ bool zig_llvm_fn_key_eql(ZigLLVMFnKey a, ZigLLVMFnKey b) { |
| 6379 | 6372 | ||
| 6380 | // Canonicalize the array value as ConstArraySpecialNone | 6373 | // Canonicalize the array value as ConstArraySpecialNone |
| 6381 | void expand_undef_array(CodeGen *g, ConstExprValue *const_val) { | 6374 | void expand_undef_array(CodeGen *g, ConstExprValue *const_val) { |
| 6382 | assert(const_val->type->id == ZigTypeIdArray); | 6375 | size_t elem_count; |
| 6376 | ZigType *elem_type; | ||
| 6377 | if (const_val->type->id == ZigTypeIdArray) { | ||
| 6378 | elem_count = const_val->type->data.array.len; | ||
| 6379 | elem_type = const_val->type->data.array.child_type; | ||
| 6380 | } else if (const_val->type->id == ZigTypeIdVector) { | ||
| 6381 | elem_count = const_val->type->data.vector.len; | ||
| 6382 | elem_type = const_val->type->data.vector.elem_type; | ||
| 6383 | } else { | ||
| 6384 | zig_unreachable(); | ||
| 6385 | } | ||
| 6383 | if (const_val->special == ConstValSpecialUndef) { | 6386 | if (const_val->special == ConstValSpecialUndef) { |
| 6384 | const_val->special = ConstValSpecialStatic; | 6387 | const_val->special = ConstValSpecialStatic; |
| 6385 | const_val->data.x_array.special = ConstArraySpecialUndef; | 6388 | const_val->data.x_array.special = ConstArraySpecialUndef; |
| ... | @@ -6389,18 +6392,14 @@ void expand_undef_array(CodeGen *g, ConstExprValue *const_val) { | ... | @@ -6389,18 +6392,14 @@ void expand_undef_array(CodeGen *g, ConstExprValue *const_val) { |
| 6389 | return; | 6392 | return; |
| 6390 | case ConstArraySpecialUndef: { | 6393 | case ConstArraySpecialUndef: { |
| 6391 | const_val->data.x_array.special = ConstArraySpecialNone; | 6394 | const_val->data.x_array.special = ConstArraySpecialNone; |
| 6392 | size_t elem_count = const_val->type->data.array.len; | ||
| 6393 | const_val->data.x_array.data.s_none.elements = create_const_vals(elem_count); | 6395 | const_val->data.x_array.data.s_none.elements = create_const_vals(elem_count); |
| 6394 | for (size_t i = 0; i < elem_count; i += 1) { | 6396 | for (size_t i = 0; i < elem_count; i += 1) { |
| 6395 | ConstExprValue *element_val = &const_val->data.x_array.data.s_none.elements[i]; | 6397 | ConstExprValue *element_val = &const_val->data.x_array.data.s_none.elements[i]; |
| 6396 | element_val->type = const_val->type->data.array.child_type; | 6398 | element_val->type = elem_type; |
| 6397 | init_const_undefined(g, element_val); | 6399 | init_const_undefined(g, element_val); |
| 6398 | ConstParent *parent = get_const_val_parent(g, element_val); | 6400 | element_val->parent.id = ConstParentIdArray; |
| 6399 | if (parent != nullptr) { | 6401 | element_val->parent.data.p_array.array_val = const_val; |
| 6400 | parent->id = ConstParentIdArray; | 6402 | element_val->parent.data.p_array.elem_index = i; |
| 6401 | parent->data.p_array.array_val = const_val; | ||
| 6402 | parent->data.p_array.elem_index = i; | ||
| 6403 | } | ||
| 6404 | } | 6403 | } |
| 6405 | return; | 6404 | return; |
| 6406 | } | 6405 | } |
| ... | @@ -6411,7 +6410,6 @@ void expand_undef_array(CodeGen *g, ConstExprValue *const_val) { | ... | @@ -6411,7 +6410,6 @@ void expand_undef_array(CodeGen *g, ConstExprValue *const_val) { |
| 6411 | g->string_literals_table.maybe_remove(buf); | 6410 | g->string_literals_table.maybe_remove(buf); |
| 6412 | 6411 | ||
| 6413 | const_val->data.x_array.special = ConstArraySpecialNone; | 6412 | const_val->data.x_array.special = ConstArraySpecialNone; |
| 6414 | size_t elem_count = const_val->type->data.array.len; | ||
| 6415 | assert(elem_count == buf_len(buf)); | 6413 | assert(elem_count == buf_len(buf)); |
| 6416 | const_val->data.x_array.data.s_none.elements = create_const_vals(elem_count); | 6414 | const_val->data.x_array.data.s_none.elements = create_const_vals(elem_count); |
| 6417 | for (size_t i = 0; i < elem_count; i += 1) { | 6415 | for (size_t i = 0; i < elem_count; i += 1) { |
| ... | @@ -6419,6 +6417,9 @@ void expand_undef_array(CodeGen *g, ConstExprValue *const_val) { | ... | @@ -6419,6 +6417,9 @@ void expand_undef_array(CodeGen *g, ConstExprValue *const_val) { |
| 6419 | this_char->special = ConstValSpecialStatic; | 6417 | this_char->special = ConstValSpecialStatic; |
| 6420 | this_char->type = g->builtin_types.entry_u8; | 6418 | this_char->type = g->builtin_types.entry_u8; |
| 6421 | bigint_init_unsigned(&this_char->data.x_bigint, (uint8_t)buf_ptr(buf)[i]); | 6419 | bigint_init_unsigned(&this_char->data.x_bigint, (uint8_t)buf_ptr(buf)[i]); |
| 6420 | this_char->parent.id = ConstParentIdArray; | ||
| 6421 | this_char->parent.data.p_array.array_val = const_val; | ||
| 6422 | this_char->parent.data.p_array.elem_index = i; | ||
| 6422 | } | 6423 | } |
| 6423 | return; | 6424 | return; |
| 6424 | } | 6425 | } |
| ... | @@ -6426,6 +6427,7 @@ void expand_undef_array(CodeGen *g, ConstExprValue *const_val) { | ... | @@ -6426,6 +6427,7 @@ void expand_undef_array(CodeGen *g, ConstExprValue *const_val) { |
| 6426 | zig_unreachable(); | 6427 | zig_unreachable(); |
| 6427 | } | 6428 | } |
| 6428 | 6429 | ||
| 6430 | // Deprecated. Reference the parent field directly. | ||
| 6429 | ConstParent *get_const_val_parent(CodeGen *g, ConstExprValue *value) { | 6431 | ConstParent *get_const_val_parent(CodeGen *g, ConstExprValue *value) { |
| 6430 | return &value->parent; | 6432 | return &value->parent; |
| 6431 | } | 6433 | } |
src/analyze.hpp+1| ... | @@ -74,6 +74,7 @@ TypeUnionField *find_union_field_by_tag(ZigType *type_entry, const BigInt *tag); | ... | @@ -74,6 +74,7 @@ TypeUnionField *find_union_field_by_tag(ZigType *type_entry, const BigInt *tag); |
| 74 | bool is_ref(ZigType *type_entry); | 74 | bool is_ref(ZigType *type_entry); |
| 75 | bool is_array_ref(ZigType *type_entry); | 75 | bool is_array_ref(ZigType *type_entry); |
| 76 | bool is_container_ref(ZigType *type_entry); | 76 | bool is_container_ref(ZigType *type_entry); |
| 77 | bool is_valid_vector_elem_type(ZigType *elem_type); | ||
| 77 | void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node); | 78 | void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node); |
| 78 | void scan_import(CodeGen *g, ImportTableEntry *import); | 79 | void scan_import(CodeGen *g, ImportTableEntry *import); |
| 79 | void preview_use_decl(CodeGen *g, AstNode *node); | 80 | void preview_use_decl(CodeGen *g, AstNode *node); |
src/codegen.cpp+78-20| ... | @@ -1921,9 +1921,8 @@ static void give_up_with_c_abi_error(CodeGen *g, AstNode *source_node) { | ... | @@ -1921,9 +1921,8 @@ static void give_up_with_c_abi_error(CodeGen *g, AstNode *source_node) { |
| 1921 | } | 1921 | } |
| 1922 | 1922 | ||
| 1923 | static LLVMValueRef build_alloca(CodeGen *g, ZigType *type_entry, const char *name, uint32_t alignment) { | 1923 | static LLVMValueRef build_alloca(CodeGen *g, ZigType *type_entry, const char *name, uint32_t alignment) { |
| 1924 | assert(alignment > 0); | ||
| 1925 | LLVMValueRef result = LLVMBuildAlloca(g->builder, type_entry->type_ref, name); | 1924 | LLVMValueRef result = LLVMBuildAlloca(g->builder, type_entry->type_ref, name); |
| 1926 | LLVMSetAlignment(result, alignment); | 1925 | LLVMSetAlignment(result, (alignment == 0) ? get_abi_alignment(g, type_entry) : alignment); |
| 1927 | return result; | 1926 | return result; |
| 1928 | } | 1927 | } |
| 1929 | 1928 | ||
| ... | @@ -3246,6 +3245,22 @@ static LLVMValueRef ir_render_load_ptr(CodeGen *g, IrExecutable *executable, IrI | ... | @@ -3246,6 +3245,22 @@ static LLVMValueRef ir_render_load_ptr(CodeGen *g, IrExecutable *executable, IrI |
| 3246 | return LLVMBuildTrunc(g->builder, shifted_value, child_type->type_ref, ""); | 3245 | return LLVMBuildTrunc(g->builder, shifted_value, child_type->type_ref, ""); |
| 3247 | } | 3246 | } |
| 3248 | 3247 | ||
| 3248 | static bool value_is_all_undef_array(ConstExprValue *const_val, size_t len) { | ||
| 3249 | switch (const_val->data.x_array.special) { | ||
| 3250 | case ConstArraySpecialUndef: | ||
| 3251 | return true; | ||
| 3252 | case ConstArraySpecialBuf: | ||
| 3253 | return false; | ||
| 3254 | case ConstArraySpecialNone: | ||
| 3255 | for (size_t i = 0; i < len; i += 1) { | ||
| 3256 | if (!value_is_all_undef(&const_val->data.x_array.data.s_none.elements[i])) | ||
| 3257 | return false; | ||
| 3258 | } | ||
| 3259 | return true; | ||
| 3260 | } | ||
| 3261 | zig_unreachable(); | ||
| 3262 | } | ||
| 3263 | |||
| 3249 | static bool value_is_all_undef(ConstExprValue *const_val) { | 3264 | static bool value_is_all_undef(ConstExprValue *const_val) { |
| 3250 | switch (const_val->special) { | 3265 | switch (const_val->special) { |
| 3251 | case ConstValSpecialRuntime: | 3266 | case ConstValSpecialRuntime: |
| ... | @@ -3260,19 +3275,9 @@ static bool value_is_all_undef(ConstExprValue *const_val) { | ... | @@ -3260,19 +3275,9 @@ static bool value_is_all_undef(ConstExprValue *const_val) { |
| 3260 | } | 3275 | } |
| 3261 | return true; | 3276 | return true; |
| 3262 | } else if (const_val->type->id == ZigTypeIdArray) { | 3277 | } else if (const_val->type->id == ZigTypeIdArray) { |
| 3263 | switch (const_val->data.x_array.special) { | 3278 | return value_is_all_undef_array(const_val, const_val->type->data.array.len); |
| 3264 | case ConstArraySpecialUndef: | 3279 | } else if (const_val->type->id == ZigTypeIdVector) { |
| 3265 | return true; | 3280 | return value_is_all_undef_array(const_val, const_val->type->data.vector.len); |
| 3266 | case ConstArraySpecialBuf: | ||
| 3267 | return false; | ||
| 3268 | case ConstArraySpecialNone: | ||
| 3269 | for (size_t i = 0; i < const_val->type->data.array.len; i += 1) { | ||
| 3270 | if (!value_is_all_undef(&const_val->data.x_array.data.s_none.elements[i])) | ||
| 3271 | return false; | ||
| 3272 | } | ||
| 3273 | return true; | ||
| 3274 | } | ||
| 3275 | zig_unreachable(); | ||
| 3276 | } else { | 3281 | } else { |
| 3277 | return false; | 3282 | return false; |
| 3278 | } | 3283 | } |
| ... | @@ -5194,6 +5199,32 @@ static LLVMValueRef ir_render_bit_reverse(CodeGen *g, IrExecutable *executable, | ... | @@ -5194,6 +5199,32 @@ static LLVMValueRef ir_render_bit_reverse(CodeGen *g, IrExecutable *executable, |
| 5194 | return LLVMBuildCall(g->builder, fn_val, &op, 1, ""); | 5199 | return LLVMBuildCall(g->builder, fn_val, &op, 1, ""); |
| 5195 | } | 5200 | } |
| 5196 | 5201 | ||
| 5202 | static LLVMValueRef ir_render_vector_to_array(CodeGen *g, IrExecutable *executable, | ||
| 5203 | IrInstructionVectorToArray *instruction) | ||
| 5204 | { | ||
| 5205 | ZigType *array_type = instruction->base.value.type; | ||
| 5206 | assert(array_type->id == ZigTypeIdArray); | ||
| 5207 | assert(handle_is_ptr(array_type)); | ||
| 5208 | assert(instruction->tmp_ptr); | ||
| 5209 | LLVMValueRef vector = ir_llvm_value(g, instruction->vector); | ||
| 5210 | LLVMValueRef casted_ptr = LLVMBuildBitCast(g->builder, instruction->tmp_ptr, | ||
| 5211 | LLVMPointerType(instruction->vector->value.type->type_ref, 0), ""); | ||
| 5212 | gen_store_untyped(g, vector, casted_ptr, 0, false); | ||
| 5213 | return instruction->tmp_ptr; | ||
| 5214 | } | ||
| 5215 | |||
| 5216 | static LLVMValueRef ir_render_array_to_vector(CodeGen *g, IrExecutable *executable, | ||
| 5217 | IrInstructionArrayToVector *instruction) | ||
| 5218 | { | ||
| 5219 | ZigType *vector_type = instruction->base.value.type; | ||
| 5220 | assert(vector_type->id == ZigTypeIdVector); | ||
| 5221 | assert(!handle_is_ptr(vector_type)); | ||
| 5222 | LLVMValueRef array_ptr = ir_llvm_value(g, instruction->array); | ||
| 5223 | LLVMValueRef casted_ptr = LLVMBuildBitCast(g->builder, array_ptr, | ||
| 5224 | LLVMPointerType(vector_type->type_ref, 0), ""); | ||
| 5225 | return gen_load_untyped(g, casted_ptr, 0, false, ""); | ||
| 5226 | } | ||
| 5227 | |||
| 5197 | static void set_debug_location(CodeGen *g, IrInstruction *instruction) { | 5228 | static void set_debug_location(CodeGen *g, IrInstruction *instruction) { |
| 5198 | AstNode *source_node = instruction->source_node; | 5229 | AstNode *source_node = instruction->source_node; |
| 5199 | Scope *scope = instruction->scope; | 5230 | Scope *scope = instruction->scope; |
| ... | @@ -5439,6 +5470,10 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, | ... | @@ -5439,6 +5470,10 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, |
| 5439 | return ir_render_bswap(g, executable, (IrInstructionBswap *)instruction); | 5470 | return ir_render_bswap(g, executable, (IrInstructionBswap *)instruction); |
| 5440 | case IrInstructionIdBitReverse: | 5471 | case IrInstructionIdBitReverse: |
| 5441 | return ir_render_bit_reverse(g, executable, (IrInstructionBitReverse *)instruction); | 5472 | return ir_render_bit_reverse(g, executable, (IrInstructionBitReverse *)instruction); |
| 5473 | case IrInstructionIdArrayToVector: | ||
| 5474 | return ir_render_array_to_vector(g, executable, (IrInstructionArrayToVector *)instruction); | ||
| 5475 | case IrInstructionIdVectorToArray: | ||
| 5476 | return ir_render_vector_to_array(g, executable, (IrInstructionVectorToArray *)instruction); | ||
| 5442 | } | 5477 | } |
| 5443 | zig_unreachable(); | 5478 | zig_unreachable(); |
| 5444 | } | 5479 | } |
| ... | @@ -6016,14 +6051,32 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c | ... | @@ -6016,14 +6051,32 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c |
| 6016 | return LLVMConstString(buf_ptr(buf), (unsigned)buf_len(buf), true); | 6051 | return LLVMConstString(buf_ptr(buf), (unsigned)buf_len(buf), true); |
| 6017 | } | 6052 | } |
| 6018 | } | 6053 | } |
| 6054 | zig_unreachable(); | ||
| 6019 | } | 6055 | } |
| 6020 | case ZigTypeIdVector: { | 6056 | case ZigTypeIdVector: { |
| 6021 | uint32_t len = type_entry->data.vector.len; | 6057 | uint32_t len = type_entry->data.vector.len; |
| 6022 | LLVMValueRef *values = allocate<LLVMValueRef>(len); | 6058 | switch (const_val->data.x_array.special) { |
| 6023 | for (uint32_t i = 0; i < len; i += 1) { | 6059 | case ConstArraySpecialUndef: |
| 6024 | values[i] = gen_const_val(g, &const_val->data.x_vector.elements[i], ""); | 6060 | return LLVMGetUndef(type_entry->type_ref); |
| 6061 | case ConstArraySpecialNone: { | ||
| 6062 | LLVMValueRef *values = allocate<LLVMValueRef>(len); | ||
| 6063 | for (uint64_t i = 0; i < len; i += 1) { | ||
| 6064 | ConstExprValue *elem_value = &const_val->data.x_array.data.s_none.elements[i]; | ||
| 6065 | values[i] = gen_const_val(g, elem_value, ""); | ||
| 6066 | } | ||
| 6067 | return LLVMConstVector(values, len); | ||
| 6068 | } | ||
| 6069 | case ConstArraySpecialBuf: { | ||
| 6070 | Buf *buf = const_val->data.x_array.data.s_buf; | ||
| 6071 | assert(buf_len(buf) == len); | ||
| 6072 | LLVMValueRef *values = allocate<LLVMValueRef>(len); | ||
| 6073 | for (uint64_t i = 0; i < len; i += 1) { | ||
| 6074 | values[i] = LLVMConstInt(g->builtin_types.entry_u8->type_ref, buf_ptr(buf)[i], false); | ||
| 6075 | } | ||
| 6076 | return LLVMConstVector(values, len); | ||
| 6077 | } | ||
| 6025 | } | 6078 | } |
| 6026 | return LLVMConstVector(values, len); | 6079 | zig_unreachable(); |
| 6027 | } | 6080 | } |
| 6028 | case ZigTypeIdUnion: | 6081 | case ZigTypeIdUnion: |
| 6029 | { | 6082 | { |
| ... | @@ -6467,6 +6520,7 @@ static void do_code_gen(CodeGen *g) { | ... | @@ -6467,6 +6520,7 @@ static void do_code_gen(CodeGen *g) { |
| 6467 | IrInstruction *instruction = fn_table_entry->alloca_list.at(alloca_i); | 6520 | IrInstruction *instruction = fn_table_entry->alloca_list.at(alloca_i); |
| 6468 | LLVMValueRef *slot; | 6521 | LLVMValueRef *slot; |
| 6469 | ZigType *slot_type = instruction->value.type; | 6522 | ZigType *slot_type = instruction->value.type; |
| 6523 | uint32_t alignment_bytes = 0; | ||
| 6470 | if (instruction->id == IrInstructionIdCast) { | 6524 | if (instruction->id == IrInstructionIdCast) { |
| 6471 | IrInstructionCast *cast_instruction = (IrInstructionCast *)instruction; | 6525 | IrInstructionCast *cast_instruction = (IrInstructionCast *)instruction; |
| 6472 | slot = &cast_instruction->tmp_ptr; | 6526 | slot = &cast_instruction->tmp_ptr; |
| ... | @@ -6502,10 +6556,14 @@ static void do_code_gen(CodeGen *g) { | ... | @@ -6502,10 +6556,14 @@ static void do_code_gen(CodeGen *g) { |
| 6502 | } else if (instruction->id == IrInstructionIdCmpxchgGen) { | 6556 | } else if (instruction->id == IrInstructionIdCmpxchgGen) { |
| 6503 | IrInstructionCmpxchgGen *cmpxchg_instruction = (IrInstructionCmpxchgGen *)instruction; | 6557 | IrInstructionCmpxchgGen *cmpxchg_instruction = (IrInstructionCmpxchgGen *)instruction; |
| 6504 | slot = &cmpxchg_instruction->tmp_ptr; | 6558 | slot = &cmpxchg_instruction->tmp_ptr; |
| 6559 | } else if (instruction->id == IrInstructionIdVectorToArray) { | ||
| 6560 | IrInstructionVectorToArray *vector_to_array_instruction = (IrInstructionVectorToArray *)instruction; | ||
| 6561 | alignment_bytes = get_abi_alignment(g, vector_to_array_instruction->vector->value.type); | ||
| 6562 | slot = &vector_to_array_instruction->tmp_ptr; | ||
| 6505 | } else { | 6563 | } else { |
| 6506 | zig_unreachable(); | 6564 | zig_unreachable(); |
| 6507 | } | 6565 | } |
| 6508 | *slot = build_alloca(g, slot_type, "", get_abi_alignment(g, slot_type)); | 6566 | *slot = build_alloca(g, slot_type, "", alignment_bytes); |
| 6509 | } | 6567 | } |
| 6510 | 6568 | ||
| 6511 | ImportTableEntry *import = get_scope_import(&fn_table_entry->fndef_scope->base); | 6569 | ImportTableEntry *import = get_scope_import(&fn_table_entry->fndef_scope->base); |
src/ir.cpp+180-111| ... | @@ -168,6 +168,7 @@ static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_ | ... | @@ -168,6 +168,7 @@ static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_ |
| 168 | static ConstExprValue *ir_resolve_const(IrAnalyze *ira, IrInstruction *value, UndefAllowed undef_allowed); | 168 | static ConstExprValue *ir_resolve_const(IrAnalyze *ira, IrInstruction *value, UndefAllowed undef_allowed); |
| 169 | static void copy_const_val(ConstExprValue *dest, ConstExprValue *src, bool same_global_refs); | 169 | static void copy_const_val(ConstExprValue *dest, ConstExprValue *src, bool same_global_refs); |
| 170 | static Error resolve_ptr_align(IrAnalyze *ira, ZigType *ty, uint32_t *result_align); | 170 | static Error resolve_ptr_align(IrAnalyze *ira, ZigType *ty, uint32_t *result_align); |
| 171 | static void ir_add_alloca(IrAnalyze *ira, IrInstruction *instruction, ZigType *type_entry); | ||
| 171 | 172 | ||
| 172 | static ConstExprValue *const_ptr_pointee_unchecked(CodeGen *g, ConstExprValue *const_val) { | 173 | static ConstExprValue *const_ptr_pointee_unchecked(CodeGen *g, ConstExprValue *const_val) { |
| 173 | assert(get_src_ptr_type(const_val->type) != nullptr); | 174 | assert(get_src_ptr_type(const_val->type) != nullptr); |
| ... | @@ -899,6 +900,14 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionCheckRuntimeScop | ... | @@ -899,6 +900,14 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionCheckRuntimeScop |
| 899 | return IrInstructionIdCheckRuntimeScope; | 900 | return IrInstructionIdCheckRuntimeScope; |
| 900 | } | 901 | } |
| 901 | 902 | ||
| 903 | static constexpr IrInstructionId ir_instruction_id(IrInstructionVectorToArray *) { | ||
| 904 | return IrInstructionIdVectorToArray; | ||
| 905 | } | ||
| 906 | |||
| 907 | static constexpr IrInstructionId ir_instruction_id(IrInstructionArrayToVector *) { | ||
| 908 | return IrInstructionIdArrayToVector; | ||
| 909 | } | ||
| 910 | |||
| 902 | template<typename T> | 911 | template<typename T> |
| 903 | static T *ir_create_instruction(IrBuilder *irb, Scope *scope, AstNode *source_node) { | 912 | static T *ir_create_instruction(IrBuilder *irb, Scope *scope, AstNode *source_node) { |
| 904 | T *special_instruction = allocate<T>(1); | 913 | T *special_instruction = allocate<T>(1); |
| ... | @@ -2821,6 +2830,34 @@ static IrInstruction *ir_build_check_runtime_scope(IrBuilder *irb, Scope *scope, | ... | @@ -2821,6 +2830,34 @@ static IrInstruction *ir_build_check_runtime_scope(IrBuilder *irb, Scope *scope, |
| 2821 | return &instruction->base; | 2830 | return &instruction->base; |
| 2822 | } | 2831 | } |
| 2823 | 2832 | ||
| 2833 | static IrInstruction *ir_build_vector_to_array(IrAnalyze *ira, IrInstruction *source_instruction, | ||
| 2834 | IrInstruction *vector, ZigType *result_type) | ||
| 2835 | { | ||
| 2836 | IrInstructionVectorToArray *instruction = ir_build_instruction<IrInstructionVectorToArray>(&ira->new_irb, | ||
| 2837 | source_instruction->scope, source_instruction->source_node); | ||
| 2838 | instruction->base.value.type = result_type; | ||
| 2839 | instruction->vector = vector; | ||
| 2840 | |||
| 2841 | ir_ref_instruction(vector, ira->new_irb.current_basic_block); | ||
| 2842 | |||
| 2843 | ir_add_alloca(ira, &instruction->base, result_type); | ||
| 2844 | |||
| 2845 | return &instruction->base; | ||
| 2846 | } | ||
| 2847 | |||
| 2848 | static IrInstruction *ir_build_array_to_vector(IrAnalyze *ira, IrInstruction *source_instruction, | ||
| 2849 | IrInstruction *array, ZigType *result_type) | ||
| 2850 | { | ||
| 2851 | IrInstructionArrayToVector *instruction = ir_build_instruction<IrInstructionArrayToVector>(&ira->new_irb, | ||
| 2852 | source_instruction->scope, source_instruction->source_node); | ||
| 2853 | instruction->base.value.type = result_type; | ||
| 2854 | instruction->array = array; | ||
| 2855 | |||
| 2856 | ir_ref_instruction(array, ira->new_irb.current_basic_block); | ||
| 2857 | |||
| 2858 | return &instruction->base; | ||
| 2859 | } | ||
| 2860 | |||
| 2824 | static void ir_count_defers(IrBuilder *irb, Scope *inner_scope, Scope *outer_scope, size_t *results) { | 2861 | static void ir_count_defers(IrBuilder *irb, Scope *inner_scope, Scope *outer_scope, size_t *results) { |
| 2825 | results[ReturnKindUnconditional] = 0; | 2862 | results[ReturnKindUnconditional] = 0; |
| 2826 | results[ReturnKindError] = 0; | 2863 | results[ReturnKindError] = 0; |
| ... | @@ -8270,6 +8307,7 @@ static bool ir_num_lit_fits_in_other_type(IrAnalyze *ira, IrInstruction *instruc | ... | @@ -8270,6 +8307,7 @@ static bool ir_num_lit_fits_in_other_type(IrAnalyze *ira, IrInstruction *instruc |
| 8270 | 8307 | ||
| 8271 | bool const_val_is_int = (const_val->type->id == ZigTypeIdInt || const_val->type->id == ZigTypeIdComptimeInt); | 8308 | bool const_val_is_int = (const_val->type->id == ZigTypeIdInt || const_val->type->id == ZigTypeIdComptimeInt); |
| 8272 | bool const_val_is_float = (const_val->type->id == ZigTypeIdFloat || const_val->type->id == ZigTypeIdComptimeFloat); | 8309 | bool const_val_is_float = (const_val->type->id == ZigTypeIdFloat || const_val->type->id == ZigTypeIdComptimeFloat); |
| 8310 | assert(const_val_is_int || const_val_is_float); | ||
| 8273 | 8311 | ||
| 8274 | if (other_type->id == ZigTypeIdFloat) { | 8312 | if (other_type->id == ZigTypeIdFloat) { |
| 8275 | if (const_val->type->id == ZigTypeIdComptimeInt || const_val->type->id == ZigTypeIdComptimeFloat) { | 8313 | if (const_val->type->id == ZigTypeIdComptimeInt || const_val->type->id == ZigTypeIdComptimeFloat) { |
| ... | @@ -10714,6 +10752,32 @@ static void report_recursive_error(IrAnalyze *ira, AstNode *source_node, ConstCa | ... | @@ -10714,6 +10752,32 @@ static void report_recursive_error(IrAnalyze *ira, AstNode *source_node, ConstCa |
| 10714 | } | 10752 | } |
| 10715 | } | 10753 | } |
| 10716 | 10754 | ||
| 10755 | static IrInstruction *ir_analyze_array_to_vector(IrAnalyze *ira, IrInstruction *source_instr, | ||
| 10756 | IrInstruction *array, ZigType *vector_type) | ||
| 10757 | { | ||
| 10758 | if (instr_is_comptime(array)) { | ||
| 10759 | // arrays and vectors have the same ConstExprValue representation | ||
| 10760 | IrInstruction *result = ir_const(ira, source_instr, vector_type); | ||
| 10761 | copy_const_val(&result->value, &array->value, false); | ||
| 10762 | result->value.type = vector_type; | ||
| 10763 | return result; | ||
| 10764 | } | ||
| 10765 | return ir_build_array_to_vector(ira, source_instr, array, vector_type); | ||
| 10766 | } | ||
| 10767 | |||
| 10768 | static IrInstruction *ir_analyze_vector_to_array(IrAnalyze *ira, IrInstruction *source_instr, | ||
| 10769 | IrInstruction *vector, ZigType *array_type) | ||
| 10770 | { | ||
| 10771 | if (instr_is_comptime(vector)) { | ||
| 10772 | // arrays and vectors have the same ConstExprValue representation | ||
| 10773 | IrInstruction *result = ir_const(ira, source_instr, array_type); | ||
| 10774 | copy_const_val(&result->value, &vector->value, false); | ||
| 10775 | result->value.type = array_type; | ||
| 10776 | return result; | ||
| 10777 | } | ||
| 10778 | return ir_build_vector_to_array(ira, source_instr, vector, array_type); | ||
| 10779 | } | ||
| 10780 | |||
| 10717 | static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_instr, | 10781 | static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_instr, |
| 10718 | ZigType *wanted_type, IrInstruction *value) | 10782 | ZigType *wanted_type, IrInstruction *value) |
| 10719 | { | 10783 | { |
| ... | @@ -11102,6 +11166,23 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst | ... | @@ -11102,6 +11166,23 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst |
| 11102 | } | 11166 | } |
| 11103 | } | 11167 | } |
| 11104 | 11168 | ||
| 11169 | // cast from @Vector(N, T) to [N]T | ||
| 11170 | if (wanted_type->id == ZigTypeIdArray && actual_type->id == ZigTypeIdVector && | ||
| 11171 | wanted_type->data.array.len == actual_type->data.vector.len && | ||
| 11172 | types_match_const_cast_only(ira, wanted_type->data.array.child_type, | ||
| 11173 | actual_type->data.vector.elem_type, source_node, false).id == ConstCastResultIdOk) | ||
| 11174 | { | ||
| 11175 | return ir_analyze_vector_to_array(ira, source_instr, value, wanted_type); | ||
| 11176 | } | ||
| 11177 | |||
| 11178 | // cast from [N]T to @Vector(N, T) | ||
| 11179 | if (actual_type->id == ZigTypeIdArray && wanted_type->id == ZigTypeIdVector && | ||
| 11180 | actual_type->data.array.len == wanted_type->data.vector.len && | ||
| 11181 | types_match_const_cast_only(ira, actual_type->data.array.child_type, | ||
| 11182 | wanted_type->data.vector.elem_type, source_node, false).id == ConstCastResultIdOk) | ||
| 11183 | { | ||
| 11184 | return ir_analyze_array_to_vector(ira, source_instr, value, wanted_type); | ||
| 11185 | } | ||
| 11105 | 11186 | ||
| 11106 | // cast from undefined to anything | 11187 | // cast from undefined to anything |
| 11107 | if (actual_type->id == ZigTypeIdUndefined) { | 11188 | if (actual_type->id == ZigTypeIdUndefined) { |
| ... | @@ -11780,8 +11861,8 @@ static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp * | ... | @@ -11780,8 +11861,8 @@ static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp * |
| 11780 | return result; | 11861 | return result; |
| 11781 | } | 11862 | } |
| 11782 | 11863 | ||
| 11783 | static int ir_eval_math_op(ZigType *type_entry, ConstExprValue *op1_val, | 11864 | static ErrorMsg *ir_eval_math_op_scalar(IrAnalyze *ira, IrInstruction *source_instr, ZigType *type_entry, |
| 11784 | IrBinOp op_id, ConstExprValue *op2_val, ConstExprValue *out_val) | 11865 | ConstExprValue *op1_val, IrBinOp op_id, ConstExprValue *op2_val, ConstExprValue *out_val) |
| 11785 | { | 11866 | { |
| 11786 | bool is_int; | 11867 | bool is_int; |
| 11787 | bool is_float; | 11868 | bool is_float; |
| ... | @@ -11803,10 +11884,10 @@ static int ir_eval_math_op(ZigType *type_entry, ConstExprValue *op1_val, | ... | @@ -11803,10 +11884,10 @@ static int ir_eval_math_op(ZigType *type_entry, ConstExprValue *op1_val, |
| 11803 | if ((op_id == IrBinOpDivUnspecified || op_id == IrBinOpRemRem || op_id == IrBinOpRemMod || | 11884 | if ((op_id == IrBinOpDivUnspecified || op_id == IrBinOpRemRem || op_id == IrBinOpRemMod || |
| 11804 | op_id == IrBinOpDivTrunc || op_id == IrBinOpDivFloor) && op2_zcmp == CmpEQ) | 11885 | op_id == IrBinOpDivTrunc || op_id == IrBinOpDivFloor) && op2_zcmp == CmpEQ) |
| 11805 | { | 11886 | { |
| 11806 | return ErrorDivByZero; | 11887 | return ir_add_error(ira, source_instr, buf_sprintf("division by zero")); |
| 11807 | } | 11888 | } |
| 11808 | if ((op_id == IrBinOpRemRem || op_id == IrBinOpRemMod) && op2_zcmp == CmpLT) { | 11889 | if ((op_id == IrBinOpRemRem || op_id == IrBinOpRemMod) && op2_zcmp == CmpLT) { |
| 11809 | return ErrorNegativeDenominator; | 11890 | return ir_add_error(ira, source_instr, buf_sprintf("negative denominator")); |
| 11810 | } | 11891 | } |
| 11811 | 11892 | ||
| 11812 | switch (op_id) { | 11893 | switch (op_id) { |
| ... | @@ -11852,7 +11933,7 @@ static int ir_eval_math_op(ZigType *type_entry, ConstExprValue *op1_val, | ... | @@ -11852,7 +11933,7 @@ static int ir_eval_math_op(ZigType *type_entry, ConstExprValue *op1_val, |
| 11852 | BigInt orig_bigint; | 11933 | BigInt orig_bigint; |
| 11853 | bigint_shl(&orig_bigint, &out_val->data.x_bigint, &op2_val->data.x_bigint); | 11934 | bigint_shl(&orig_bigint, &out_val->data.x_bigint, &op2_val->data.x_bigint); |
| 11854 | if (bigint_cmp(&op1_val->data.x_bigint, &orig_bigint) != CmpEQ) { | 11935 | if (bigint_cmp(&op1_val->data.x_bigint, &orig_bigint) != CmpEQ) { |
| 11855 | return ErrorShiftedOutOneBits; | 11936 | return ir_add_error(ira, source_instr, buf_sprintf("exact shift shifted out 1 bits")); |
| 11856 | } | 11937 | } |
| 11857 | break; | 11938 | break; |
| 11858 | } | 11939 | } |
| ... | @@ -11920,14 +12001,14 @@ static int ir_eval_math_op(ZigType *type_entry, ConstExprValue *op1_val, | ... | @@ -11920,14 +12001,14 @@ static int ir_eval_math_op(ZigType *type_entry, ConstExprValue *op1_val, |
| 11920 | BigInt remainder; | 12001 | BigInt remainder; |
| 11921 | bigint_rem(&remainder, &op1_val->data.x_bigint, &op2_val->data.x_bigint); | 12002 | bigint_rem(&remainder, &op1_val->data.x_bigint, &op2_val->data.x_bigint); |
| 11922 | if (bigint_cmp_zero(&remainder) != CmpEQ) { | 12003 | if (bigint_cmp_zero(&remainder) != CmpEQ) { |
| 11923 | return ErrorExactDivRemainder; | 12004 | return ir_add_error(ira, source_instr, buf_sprintf("exact division had a remainder")); |
| 11924 | } | 12005 | } |
| 11925 | } else { | 12006 | } else { |
| 11926 | float_div_trunc(out_val, op1_val, op2_val); | 12007 | float_div_trunc(out_val, op1_val, op2_val); |
| 11927 | ConstExprValue remainder; | 12008 | ConstExprValue remainder; |
| 11928 | float_rem(&remainder, op1_val, op2_val); | 12009 | float_rem(&remainder, op1_val, op2_val); |
| 11929 | if (float_cmp_zero(&remainder) != CmpEQ) { | 12010 | if (float_cmp_zero(&remainder) != CmpEQ) { |
| 11930 | return ErrorExactDivRemainder; | 12011 | return ir_add_error(ira, source_instr, buf_sprintf("exact division had a remainder")); |
| 11931 | } | 12012 | } |
| 11932 | } | 12013 | } |
| 11933 | break; | 12014 | break; |
| ... | @@ -11951,13 +12032,51 @@ static int ir_eval_math_op(ZigType *type_entry, ConstExprValue *op1_val, | ... | @@ -11951,13 +12032,51 @@ static int ir_eval_math_op(ZigType *type_entry, ConstExprValue *op1_val, |
| 11951 | if (!bigint_fits_in_bits(&out_val->data.x_bigint, type_entry->data.integral.bit_count, | 12032 | if (!bigint_fits_in_bits(&out_val->data.x_bigint, type_entry->data.integral.bit_count, |
| 11952 | type_entry->data.integral.is_signed)) | 12033 | type_entry->data.integral.is_signed)) |
| 11953 | { | 12034 | { |
| 11954 | return ErrorOverflow; | 12035 | return ir_add_error(ira, source_instr, buf_sprintf("operation caused overflow")); |
| 11955 | } | 12036 | } |
| 11956 | } | 12037 | } |
| 11957 | 12038 | ||
| 11958 | out_val->type = type_entry; | 12039 | out_val->type = type_entry; |
| 11959 | out_val->special = ConstValSpecialStatic; | 12040 | out_val->special = ConstValSpecialStatic; |
| 11960 | return 0; | 12041 | return nullptr; |
| 12042 | } | ||
| 12043 | |||
| 12044 | // This works on operands that have already been checked to be comptime known. | ||
| 12045 | static IrInstruction *ir_analyze_math_op(IrAnalyze *ira, IrInstruction *source_instr, | ||
| 12046 | ZigType *type_entry, ConstExprValue *op1_val, IrBinOp op_id, ConstExprValue *op2_val) | ||
| 12047 | { | ||
| 12048 | IrInstruction *result_instruction = ir_const(ira, source_instr, type_entry); | ||
| 12049 | ConstExprValue *out_val = &result_instruction->value; | ||
| 12050 | if (type_entry->id == ZigTypeIdVector) { | ||
| 12051 | expand_undef_array(ira->codegen, op1_val); | ||
| 12052 | expand_undef_array(ira->codegen, op2_val); | ||
| 12053 | out_val->special = ConstValSpecialUndef; | ||
| 12054 | expand_undef_array(ira->codegen, out_val); | ||
| 12055 | size_t len = type_entry->data.vector.len; | ||
| 12056 | ZigType *scalar_type = type_entry->data.vector.elem_type; | ||
| 12057 | for (size_t i = 0; i < len; i += 1) { | ||
| 12058 | ConstExprValue *scalar_op1_val = &op1_val->data.x_array.data.s_none.elements[i]; | ||
| 12059 | ConstExprValue *scalar_op2_val = &op2_val->data.x_array.data.s_none.elements[i]; | ||
| 12060 | ConstExprValue *scalar_out_val = &out_val->data.x_array.data.s_none.elements[i]; | ||
| 12061 | assert(scalar_op1_val->type == scalar_type); | ||
| 12062 | assert(scalar_op2_val->type == scalar_type); | ||
| 12063 | assert(scalar_out_val->type == scalar_type); | ||
| 12064 | ErrorMsg *msg = ir_eval_math_op_scalar(ira, source_instr, scalar_type, | ||
| 12065 | scalar_op1_val, op_id, scalar_op2_val, scalar_out_val); | ||
| 12066 | if (msg != nullptr) { | ||
| 12067 | add_error_note(ira->codegen, msg, source_instr->source_node, | ||
| 12068 | buf_sprintf("when computing vector element at index %" ZIG_PRI_usize, i)); | ||
| 12069 | return ira->codegen->invalid_instruction; | ||
| 12070 | } | ||
| 12071 | } | ||
| 12072 | out_val->type = type_entry; | ||
| 12073 | out_val->special = ConstValSpecialStatic; | ||
| 12074 | } else { | ||
| 12075 | if (ir_eval_math_op_scalar(ira, source_instr, type_entry, op1_val, op_id, op2_val, out_val) != nullptr) { | ||
| 12076 | return ira->codegen->invalid_instruction; | ||
| 12077 | } | ||
| 12078 | } | ||
| 12079 | return ir_implicit_cast(ira, result_instruction, type_entry); | ||
| 11961 | } | 12080 | } |
| 11962 | 12081 | ||
| 11963 | static IrInstruction *ir_analyze_bit_shift(IrAnalyze *ira, IrInstructionBinOp *bin_op_instruction) { | 12082 | static IrInstruction *ir_analyze_bit_shift(IrAnalyze *ira, IrInstructionBinOp *bin_op_instruction) { |
| ... | @@ -12029,24 +12148,7 @@ static IrInstruction *ir_analyze_bit_shift(IrAnalyze *ira, IrInstructionBinOp *b | ... | @@ -12029,24 +12148,7 @@ static IrInstruction *ir_analyze_bit_shift(IrAnalyze *ira, IrInstructionBinOp *b |
| 12029 | if (op2_val == nullptr) | 12148 | if (op2_val == nullptr) |
| 12030 | return ira->codegen->invalid_instruction; | 12149 | return ira->codegen->invalid_instruction; |
| 12031 | 12150 | ||
| 12032 | IrInstruction *result_instruction = ir_const(ira, &bin_op_instruction->base, op1->value.type); | 12151 | return ir_analyze_math_op(ira, &bin_op_instruction->base, op1->value.type, op1_val, op_id, op2_val); |
| 12033 | |||
| 12034 | int err; | ||
| 12035 | if ((err = ir_eval_math_op(op1->value.type, op1_val, op_id, op2_val, &result_instruction->value))) { | ||
| 12036 | if (err == ErrorOverflow) { | ||
| 12037 | ir_add_error(ira, &bin_op_instruction->base, buf_sprintf("operation caused overflow")); | ||
| 12038 | return ira->codegen->invalid_instruction; | ||
| 12039 | } else if (err == ErrorShiftedOutOneBits) { | ||
| 12040 | ir_add_error(ira, &bin_op_instruction->base, buf_sprintf("exact shift shifted out 1 bits")); | ||
| 12041 | return ira->codegen->invalid_instruction; | ||
| 12042 | } else { | ||
| 12043 | zig_unreachable(); | ||
| 12044 | } | ||
| 12045 | return ira->codegen->invalid_instruction; | ||
| 12046 | } | ||
| 12047 | |||
| 12048 | ir_num_lit_fits_in_other_type(ira, result_instruction, op1->value.type, false); | ||
| 12049 | return result_instruction; | ||
| 12050 | } else if (op1->value.type->id == ZigTypeIdComptimeInt) { | 12152 | } else if (op1->value.type->id == ZigTypeIdComptimeInt) { |
| 12051 | ir_add_error(ira, &bin_op_instruction->base, | 12153 | ir_add_error(ira, &bin_op_instruction->base, |
| 12052 | buf_sprintf("LHS of shift must be an integer type, or RHS must be compile-time known")); | 12154 | buf_sprintf("LHS of shift must be an integer type, or RHS must be compile-time known")); |
| ... | @@ -12292,30 +12394,7 @@ static IrInstruction *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp | ... | @@ -12292,30 +12394,7 @@ static IrInstruction *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp |
| 12292 | if (op2_val == nullptr) | 12394 | if (op2_val == nullptr) |
| 12293 | return ira->codegen->invalid_instruction; | 12395 | return ira->codegen->invalid_instruction; |
| 12294 | 12396 | ||
| 12295 | IrInstruction *result_instruction = ir_const(ira, &instruction->base, resolved_type); | 12397 | return ir_analyze_math_op(ira, &instruction->base, resolved_type, op1_val, op_id, op2_val); |
| 12296 | |||
| 12297 | int err; | ||
| 12298 | if ((err = ir_eval_math_op(resolved_type, op1_val, op_id, op2_val, &result_instruction->value))) { | ||
| 12299 | if (err == ErrorDivByZero) { | ||
| 12300 | ir_add_error(ira, &instruction->base, buf_sprintf("division by zero")); | ||
| 12301 | return ira->codegen->invalid_instruction; | ||
| 12302 | } else if (err == ErrorOverflow) { | ||
| 12303 | ir_add_error(ira, &instruction->base, buf_sprintf("operation caused overflow")); | ||
| 12304 | return ira->codegen->invalid_instruction; | ||
| 12305 | } else if (err == ErrorExactDivRemainder) { | ||
| 12306 | ir_add_error(ira, &instruction->base, buf_sprintf("exact division had a remainder")); | ||
| 12307 | return ira->codegen->invalid_instruction; | ||
| 12308 | } else if (err == ErrorNegativeDenominator) { | ||
| 12309 | ir_add_error(ira, &instruction->base, buf_sprintf("negative denominator")); | ||
| 12310 | return ira->codegen->invalid_instruction; | ||
| 12311 | } else { | ||
| 12312 | zig_unreachable(); | ||
| 12313 | } | ||
| 12314 | return ira->codegen->invalid_instruction; | ||
| 12315 | } | ||
| 12316 | |||
| 12317 | ir_num_lit_fits_in_other_type(ira, result_instruction, resolved_type, false); | ||
| 12318 | return result_instruction; | ||
| 12319 | } | 12398 | } |
| 12320 | 12399 | ||
| 12321 | IrInstruction *result = ir_build_bin_op(&ira->new_irb, instruction->base.scope, | 12400 | IrInstruction *result = ir_build_bin_op(&ira->new_irb, instruction->base.scope, |
| ... | @@ -18745,10 +18824,7 @@ static IrInstruction *ir_analyze_instruction_vector_type(IrAnalyze *ira, IrInstr | ... | @@ -18745,10 +18824,7 @@ static IrInstruction *ir_analyze_instruction_vector_type(IrAnalyze *ira, IrInstr |
| 18745 | if (type_is_invalid(elem_type)) | 18824 | if (type_is_invalid(elem_type)) |
| 18746 | return ira->codegen->invalid_instruction; | 18825 | return ira->codegen->invalid_instruction; |
| 18747 | 18826 | ||
| 18748 | if (elem_type->id != ZigTypeIdInt && | 18827 | if (!is_valid_vector_elem_type(elem_type)) { |
| 18749 | elem_type->id != ZigTypeIdFloat && | ||
| 18750 | get_codegen_ptr_type(elem_type) == nullptr) | ||
| 18751 | { | ||
| 18752 | ir_add_error(ira, instruction->elem_type, | 18828 | ir_add_error(ira, instruction->elem_type, |
| 18753 | buf_sprintf("vector element type must be integer, float, or pointer; '%s' is invalid", | 18829 | buf_sprintf("vector element type must be integer, float, or pointer; '%s' is invalid", |
| 18754 | buf_ptr(&elem_type->name))); | 18830 | buf_ptr(&elem_type->name))); |
| ... | @@ -20345,6 +20421,17 @@ static IrInstruction *ir_analyze_instruction_ptr_cast(IrAnalyze *ira, IrInstruct | ... | @@ -20345,6 +20421,17 @@ static IrInstruction *ir_analyze_instruction_ptr_cast(IrAnalyze *ira, IrInstruct |
| 20345 | return ir_analyze_ptr_cast(ira, &instruction->base, ptr, dest_type, dest_type_value); | 20421 | return ir_analyze_ptr_cast(ira, &instruction->base, ptr, dest_type, dest_type_value); |
| 20346 | } | 20422 | } |
| 20347 | 20423 | ||
| 20424 | static void buf_write_value_bytes_array(CodeGen *codegen, uint8_t *buf, ConstExprValue *val, size_t len) { | ||
| 20425 | size_t buf_i = 0; | ||
| 20426 | // TODO optimize the buf case | ||
| 20427 | expand_undef_array(codegen, val); | ||
| 20428 | for (size_t elem_i = 0; elem_i < val->type->data.array.len; elem_i += 1) { | ||
| 20429 | ConstExprValue *elem = &val->data.x_array.data.s_none.elements[elem_i]; | ||
| 20430 | buf_write_value_bytes(codegen, &buf[buf_i], elem); | ||
| 20431 | buf_i += type_size(codegen, elem->type); | ||
| 20432 | } | ||
| 20433 | } | ||
| 20434 | |||
| 20348 | static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue *val) { | 20435 | static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue *val) { |
| 20349 | if (val->special == ConstValSpecialUndef) | 20436 | if (val->special == ConstValSpecialUndef) |
| 20350 | val->special = ConstValSpecialStatic; | 20437 | val->special = ConstValSpecialStatic; |
| ... | @@ -20390,26 +20477,9 @@ static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue | ... | @@ -20390,26 +20477,9 @@ static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue |
| 20390 | zig_unreachable(); | 20477 | zig_unreachable(); |
| 20391 | } | 20478 | } |
| 20392 | case ZigTypeIdArray: | 20479 | case ZigTypeIdArray: |
| 20393 | { | 20480 | return buf_write_value_bytes_array(codegen, buf, val, val->type->data.array.len); |
| 20394 | size_t buf_i = 0; | 20481 | case ZigTypeIdVector: |
| 20395 | // TODO optimize the buf case | 20482 | return buf_write_value_bytes_array(codegen, buf, val, val->type->data.vector.len); |
| 20396 | expand_undef_array(codegen, val); | ||
| 20397 | for (size_t elem_i = 0; elem_i < val->type->data.array.len; elem_i += 1) { | ||
| 20398 | ConstExprValue *elem = &val->data.x_array.data.s_none.elements[elem_i]; | ||
| 20399 | buf_write_value_bytes(codegen, &buf[buf_i], elem); | ||
| 20400 | buf_i += type_size(codegen, elem->type); | ||
| 20401 | } | ||
| 20402 | } | ||
| 20403 | return; | ||
| 20404 | case ZigTypeIdVector: { | ||
| 20405 | size_t buf_i = 0; | ||
| 20406 | for (uint32_t elem_i = 0; elem_i < val->type->data.vector.len; elem_i += 1) { | ||
| 20407 | ConstExprValue *elem = &val->data.x_vector.elements[elem_i]; | ||
| 20408 | buf_write_value_bytes(codegen, &buf[buf_i], elem); | ||
| 20409 | buf_i += type_size(codegen, elem->type); | ||
| 20410 | } | ||
| 20411 | return; | ||
| 20412 | } | ||
| 20413 | case ZigTypeIdStruct: | 20483 | case ZigTypeIdStruct: |
| 20414 | zig_panic("TODO buf_write_value_bytes struct type"); | 20484 | zig_panic("TODO buf_write_value_bytes struct type"); |
| 20415 | case ZigTypeIdOptional: | 20485 | case ZigTypeIdOptional: |
| ... | @@ -20426,6 +20496,31 @@ static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue | ... | @@ -20426,6 +20496,31 @@ static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue |
| 20426 | zig_unreachable(); | 20496 | zig_unreachable(); |
| 20427 | } | 20497 | } |
| 20428 | 20498 | ||
| 20499 | static Error buf_read_value_bytes_array(IrAnalyze *ira, CodeGen *codegen, AstNode *source_node, uint8_t *buf, | ||
| 20500 | ConstExprValue *val, ZigType *elem_type, size_t len) | ||
| 20501 | { | ||
| 20502 | Error err; | ||
| 20503 | uint64_t elem_size = type_size(codegen, elem_type); | ||
| 20504 | |||
| 20505 | switch (val->data.x_array.special) { | ||
| 20506 | case ConstArraySpecialNone: | ||
| 20507 | val->data.x_array.data.s_none.elements = create_const_vals(len); | ||
| 20508 | for (size_t i = 0; i < len; i++) { | ||
| 20509 | ConstExprValue *elem = &val->data.x_array.data.s_none.elements[i]; | ||
| 20510 | elem->special = ConstValSpecialStatic; | ||
| 20511 | elem->type = elem_type; | ||
| 20512 | if ((err = buf_read_value_bytes(ira, codegen, source_node, buf + (elem_size * i), elem))) | ||
| 20513 | return err; | ||
| 20514 | } | ||
| 20515 | return ErrorNone; | ||
| 20516 | case ConstArraySpecialUndef: | ||
| 20517 | zig_panic("TODO buf_read_value_bytes ConstArraySpecialUndef array type"); | ||
| 20518 | case ConstArraySpecialBuf: | ||
| 20519 | zig_panic("TODO buf_read_value_bytes ConstArraySpecialBuf array type"); | ||
| 20520 | } | ||
| 20521 | zig_unreachable(); | ||
| 20522 | } | ||
| 20523 | |||
| 20429 | static Error buf_read_value_bytes(IrAnalyze *ira, CodeGen *codegen, AstNode *source_node, uint8_t *buf, ConstExprValue *val) { | 20524 | static Error buf_read_value_bytes(IrAnalyze *ira, CodeGen *codegen, AstNode *source_node, uint8_t *buf, ConstExprValue *val) { |
| 20430 | Error err; | 20525 | Error err; |
| 20431 | assert(val->special == ConstValSpecialStatic); | 20526 | assert(val->special == ConstValSpecialStatic); |
| ... | @@ -20464,42 +20559,12 @@ static Error buf_read_value_bytes(IrAnalyze *ira, CodeGen *codegen, AstNode *sou | ... | @@ -20464,42 +20559,12 @@ static Error buf_read_value_bytes(IrAnalyze *ira, CodeGen *codegen, AstNode *sou |
| 20464 | val->data.x_ptr.data.hard_coded_addr.addr = bigint_as_unsigned(&bn); | 20559 | val->data.x_ptr.data.hard_coded_addr.addr = bigint_as_unsigned(&bn); |
| 20465 | return ErrorNone; | 20560 | return ErrorNone; |
| 20466 | } | 20561 | } |
| 20467 | case ZigTypeIdArray: { | 20562 | case ZigTypeIdArray: |
| 20468 | uint64_t elem_size = type_size(codegen, val->type->data.array.child_type); | 20563 | return buf_read_value_bytes_array(ira, codegen, source_node, buf, val, val->type->data.array.child_type, |
| 20469 | size_t len = val->type->data.array.len; | 20564 | val->type->data.array.len); |
| 20470 | 20565 | case ZigTypeIdVector: | |
| 20471 | switch (val->data.x_array.special) { | 20566 | return buf_read_value_bytes_array(ira, codegen, source_node, buf, val, val->type->data.vector.elem_type, |
| 20472 | case ConstArraySpecialNone: | 20567 | val->type->data.vector.len); |
| 20473 | val->data.x_array.data.s_none.elements = create_const_vals(len); | ||
| 20474 | for (size_t i = 0; i < len; i++) { | ||
| 20475 | ConstExprValue *elem = &val->data.x_array.data.s_none.elements[i]; | ||
| 20476 | elem->special = ConstValSpecialStatic; | ||
| 20477 | elem->type = val->type->data.array.child_type; | ||
| 20478 | if ((err = buf_read_value_bytes(ira, codegen, source_node, buf + (elem_size * i), elem))) | ||
| 20479 | return err; | ||
| 20480 | } | ||
| 20481 | return ErrorNone; | ||
| 20482 | case ConstArraySpecialUndef: | ||
| 20483 | zig_panic("TODO buf_read_value_bytes ConstArraySpecialUndef array type"); | ||
| 20484 | case ConstArraySpecialBuf: | ||
| 20485 | zig_panic("TODO buf_read_value_bytes ConstArraySpecialBuf array type"); | ||
| 20486 | } | ||
| 20487 | zig_unreachable(); | ||
| 20488 | } | ||
| 20489 | case ZigTypeIdVector: { | ||
| 20490 | uint64_t elem_size = type_size(codegen, val->type->data.vector.elem_type); | ||
| 20491 | uint32_t len = val->type->data.vector.len; | ||
| 20492 | |||
| 20493 | val->data.x_vector.elements = create_const_vals(len); | ||
| 20494 | for (uint32_t i = 0; i < len; i += 1) { | ||
| 20495 | ConstExprValue *elem = &val->data.x_vector.elements[i]; | ||
| 20496 | elem->special = ConstValSpecialStatic; | ||
| 20497 | elem->type = val->type->data.vector.elem_type; | ||
| 20498 | if ((err = buf_read_value_bytes(ira, codegen, source_node, buf + (elem_size * i), elem))) | ||
| 20499 | return err; | ||
| 20500 | } | ||
| 20501 | return ErrorNone; | ||
| 20502 | } | ||
| 20503 | case ZigTypeIdEnum: | 20568 | case ZigTypeIdEnum: |
| 20504 | switch (val->type->data.enumeration.layout) { | 20569 | switch (val->type->data.enumeration.layout) { |
| 20505 | case ContainerLayoutAuto: | 20570 | case ContainerLayoutAuto: |
| ... | @@ -21634,6 +21699,8 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio | ... | @@ -21634,6 +21699,8 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio |
| 21634 | case IrInstructionIdDeclVarGen: | 21699 | case IrInstructionIdDeclVarGen: |
| 21635 | case IrInstructionIdPtrCastGen: | 21700 | case IrInstructionIdPtrCastGen: |
| 21636 | case IrInstructionIdCmpxchgGen: | 21701 | case IrInstructionIdCmpxchgGen: |
| 21702 | case IrInstructionIdArrayToVector: | ||
| 21703 | case IrInstructionIdVectorToArray: | ||
| 21637 | zig_unreachable(); | 21704 | zig_unreachable(); |
| 21638 | 21705 | ||
| 21639 | case IrInstructionIdReturn: | 21706 | case IrInstructionIdReturn: |
| ... | @@ -22129,6 +22196,8 @@ bool ir_has_side_effects(IrInstruction *instruction) { | ... | @@ -22129,6 +22196,8 @@ bool ir_has_side_effects(IrInstruction *instruction) { |
| 22129 | case IrInstructionIdFromBytes: | 22196 | case IrInstructionIdFromBytes: |
| 22130 | case IrInstructionIdToBytes: | 22197 | case IrInstructionIdToBytes: |
| 22131 | case IrInstructionIdEnumToInt: | 22198 | case IrInstructionIdEnumToInt: |
| 22199 | case IrInstructionIdVectorToArray: | ||
| 22200 | case IrInstructionIdArrayToVector: | ||
| 22132 | return false; | 22201 | return false; |
| 22133 | 22202 | ||
| 22134 | case IrInstructionIdAsm: | 22203 | case IrInstructionIdAsm: |
src/ir_print.cpp+18| ... | @@ -972,6 +972,18 @@ static void ir_print_check_runtime_scope(IrPrint *irp, IrInstructionCheckRuntime | ... | @@ -972,6 +972,18 @@ static void ir_print_check_runtime_scope(IrPrint *irp, IrInstructionCheckRuntime |
| 972 | fprintf(irp->f, ")"); | 972 | fprintf(irp->f, ")"); |
| 973 | } | 973 | } |
| 974 | 974 | ||
| 975 | static void ir_print_array_to_vector(IrPrint *irp, IrInstructionArrayToVector *instruction) { | ||
| 976 | fprintf(irp->f, "ArrayToVector("); | ||
| 977 | ir_print_other_instruction(irp, instruction->array); | ||
| 978 | fprintf(irp->f, ")"); | ||
| 979 | } | ||
| 980 | |||
| 981 | static void ir_print_vector_to_array(IrPrint *irp, IrInstructionVectorToArray *instruction) { | ||
| 982 | fprintf(irp->f, "VectorToArray("); | ||
| 983 | ir_print_other_instruction(irp, instruction->vector); | ||
| 984 | fprintf(irp->f, ")"); | ||
| 985 | } | ||
| 986 | |||
| 975 | static void ir_print_int_to_err(IrPrint *irp, IrInstructionIntToErr *instruction) { | 987 | static void ir_print_int_to_err(IrPrint *irp, IrInstructionIntToErr *instruction) { |
| 976 | fprintf(irp->f, "inttoerr "); | 988 | fprintf(irp->f, "inttoerr "); |
| 977 | ir_print_other_instruction(irp, instruction->target); | 989 | ir_print_other_instruction(irp, instruction->target); |
| ... | @@ -1825,6 +1837,12 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) { | ... | @@ -1825,6 +1837,12 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) { |
| 1825 | case IrInstructionIdDeclVarGen: | 1837 | case IrInstructionIdDeclVarGen: |
| 1826 | ir_print_decl_var_gen(irp, (IrInstructionDeclVarGen *)instruction); | 1838 | ir_print_decl_var_gen(irp, (IrInstructionDeclVarGen *)instruction); |
| 1827 | break; | 1839 | break; |
| 1840 | case IrInstructionIdArrayToVector: | ||
| 1841 | ir_print_array_to_vector(irp, (IrInstructionArrayToVector *)instruction); | ||
| 1842 | break; | ||
| 1843 | case IrInstructionIdVectorToArray: | ||
| 1844 | ir_print_vector_to_array(irp, (IrInstructionVectorToArray *)instruction); | ||
| 1845 | break; | ||
| 1828 | } | 1846 | } |
| 1829 | fprintf(irp->f, "\n"); | 1847 | fprintf(irp->f, "\n"); |
| 1830 | } | 1848 | } |
test/stage1/behavior.zig+1| ... | @@ -74,6 +74,7 @@ comptime { | ... | @@ -74,6 +74,7 @@ comptime { |
| 74 | _ = @import("behavior/underscore.zig"); | 74 | _ = @import("behavior/underscore.zig"); |
| 75 | _ = @import("behavior/union.zig"); | 75 | _ = @import("behavior/union.zig"); |
| 76 | _ = @import("behavior/var_args.zig"); | 76 | _ = @import("behavior/var_args.zig"); |
| 77 | _ = @import("behavior/vector.zig"); | ||
| 77 | _ = @import("behavior/void.zig"); | 78 | _ = @import("behavior/void.zig"); |
| 78 | _ = @import("behavior/while.zig"); | 79 | _ = @import("behavior/while.zig"); |
| 79 | _ = @import("behavior/widening.zig"); | 80 | _ = @import("behavior/widening.zig"); |
test/stage1/behavior/vector.zig created+20| ... | @@ -0,0 +1,20 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | const assertOrPanic = std.debug.assertOrPanic; | ||
| 3 | |||
| 4 | test "implicit array to vector and vector to array" { | ||
| 5 | const S = struct { | ||
| 6 | fn doTheTest() void { | ||
| 7 | var v: @Vector(4, i32) = [4]i32{10, 20, 30, 40}; | ||
| 8 | const x: @Vector(4, i32) = [4]i32{1, 2, 3, 4}; | ||
| 9 | v +%= x; | ||
| 10 | const result: [4]i32 = v; | ||
| 11 | assertOrPanic(result[0] == 11); | ||
| 12 | assertOrPanic(result[1] == 22); | ||
| 13 | assertOrPanic(result[2] == 33); | ||
| 14 | assertOrPanic(result[3] == 44); | ||
| 15 | } | ||
| 16 | }; | ||
| 17 | S.doTheTest(); | ||
| 18 | comptime S.doTheTest(); | ||
| 19 | } | ||
| 20 | |||