authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-02-04 20:30:00-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-02-04 20:30:00-05:00
log8c6fa982cd0a02775264b616c37da9907cc603bb
treebf8101fa59d6909ea4e3364d0b31e63fbdf3c69e
parent2828a9695f088f5454f445fdd0544d805a33837b
signaturelock-open Commit is signed but in an unrecognized format.

SIMD: array to vector, vector to array, wrapping int add

also vectors and arrays now use the same ConstExprVal representation See #903

8 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};
254254
255struct ConstVector {
256 ConstExprValue *elements;
257};
258
259enum ConstValSpecial {255enum 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;
326321
327 // populated if special == ConstValSpecialRuntime322 // 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};
22432240
2244struct IrInstruction {2241struct IrInstruction {
...@@ -3368,6 +3365,19 @@ struct IrInstructionBitReverse {...@@ -3368,6 +3365,19 @@ struct IrInstructionBitReverse {
3368 IrInstruction *op;3365 IrInstruction *op;
3369};3366};
33703367
3368struct IrInstructionArrayToVector {
3369 IrInstruction base;
3370
3371 IrInstruction *array;
3372};
3373
3374struct IrInstructionVectorToArray {
3375 IrInstruction base;
3376
3377 IrInstruction *vector;
3378 LLVMValueRef tmp_ptr;
3379};
3380
3371static const size_t slice_ptr_index = 0;3381static const size_t slice_ptr_index = 0;
3372static const size_t slice_len_index = 1;3382static const size_t slice_len_index = 1;
33733383
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}
44594459
4460bool 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
4460ZigType *get_vector_type(CodeGen *g, uint32_t len, ZigType *elem_type) {4466ZigType *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}
57515759
5760static 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
5752bool const_values_equal(CodeGen *g, ConstExprValue *a, ConstExprValue *b) {5782bool 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}
59875987
5988static 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
5988void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) {6022void 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) {
63796372
6380// Canonicalize the array value as ConstArraySpecialNone6373// Canonicalize the array value as ConstArraySpecialNone
6381void expand_undef_array(CodeGen *g, ConstExprValue *const_val) {6374void 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);
64126411
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}
64286429
6430// Deprecated. Reference the parent field directly.
6429ConstParent *get_const_val_parent(CodeGen *g, ConstExprValue *value) {6431ConstParent *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);
74bool is_ref(ZigType *type_entry);74bool is_ref(ZigType *type_entry);
75bool is_array_ref(ZigType *type_entry);75bool is_array_ref(ZigType *type_entry);
76bool is_container_ref(ZigType *type_entry);76bool is_container_ref(ZigType *type_entry);
77bool is_valid_vector_elem_type(ZigType *elem_type);
77void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node);78void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node);
78void scan_import(CodeGen *g, ImportTableEntry *import);79void scan_import(CodeGen *g, ImportTableEntry *import);
79void preview_use_decl(CodeGen *g, AstNode *node);80void 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}
19221922
1923static LLVMValueRef build_alloca(CodeGen *g, ZigType *type_entry, const char *name, uint32_t alignment) {1923static 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}
19291928
...@@ -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}
32483247
3248static 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
3249static bool value_is_all_undef(ConstExprValue *const_val) {3264static 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}
51965201
5202static 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
5216static 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
5197static void set_debug_location(CodeGen *g, IrInstruction *instruction) {5228static 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 }
65106568
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_
168static ConstExprValue *ir_resolve_const(IrAnalyze *ira, IrInstruction *value, UndefAllowed undef_allowed);168static ConstExprValue *ir_resolve_const(IrAnalyze *ira, IrInstruction *value, UndefAllowed undef_allowed);
169static void copy_const_val(ConstExprValue *dest, ConstExprValue *src, bool same_global_refs);169static void copy_const_val(ConstExprValue *dest, ConstExprValue *src, bool same_global_refs);
170static Error resolve_ptr_align(IrAnalyze *ira, ZigType *ty, uint32_t *result_align);170static Error resolve_ptr_align(IrAnalyze *ira, ZigType *ty, uint32_t *result_align);
171static void ir_add_alloca(IrAnalyze *ira, IrInstruction *instruction, ZigType *type_entry);
171172
172static ConstExprValue *const_ptr_pointee_unchecked(CodeGen *g, ConstExprValue *const_val) {173static 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}
901902
903static constexpr IrInstructionId ir_instruction_id(IrInstructionVectorToArray *) {
904 return IrInstructionIdVectorToArray;
905}
906
907static constexpr IrInstructionId ir_instruction_id(IrInstructionArrayToVector *) {
908 return IrInstructionIdArrayToVector;
909}
910
902template<typename T>911template<typename T>
903static T *ir_create_instruction(IrBuilder *irb, Scope *scope, AstNode *source_node) {912static 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}
28232832
2833static 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
2848static 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
2824static void ir_count_defers(IrBuilder *irb, Scope *inner_scope, Scope *outer_scope, size_t *results) {2861static 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
82708307
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);
82738311
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}
1071610754
10755static 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
10768static 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
10717static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_instr,10781static 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 }
1110411168
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 }
1110511186
11106 // cast from undefined to anything11187 // 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}
1178211863
11783static int ir_eval_math_op(ZigType *type_entry, ConstExprValue *op1_val,11864static 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 }
1181111892
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 }
1195712038
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.
12045static 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}
1196212081
11963static IrInstruction *ir_analyze_bit_shift(IrAnalyze *ira, IrInstructionBinOp *bin_op_instruction) {12082static 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;
1203112150
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;
1229412396
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 }
1232012399
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;
1874718826
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}
2034720423
20424static 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
20348static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue *val) {20435static 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 case20482 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}
2042820498
20499static 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
20429static Error buf_read_value_bytes(IrAnalyze *ira, CodeGen *codegen, AstNode *source_node, uint8_t *buf, ConstExprValue *val) {20524static 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);
2047020565 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();
2163821705
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;
2213322202
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}
974974
975static 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
981static 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
975static void ir_print_int_to_err(IrPrint *irp, IrInstructionIntToErr *instruction) {987static 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 @@
1const std = @import("std");
2const assertOrPanic = std.debug.assertOrPanic;
3
4test "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