authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-11-05 13:39:56-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-11-05 13:40:57-05:00
logcb8af1c6d48d5fdb26484a070b8af069c4152049
tree0c3baee6423b40eda3ba57e9d41041f6c9fbd3b8
parenta26e9fa7238e972301f761db80434fa0205d1016
parent9a08de93b64a332af9f581ef15b208e153fa19f0
signaturelock-open Commit is signed but in an unrecognized format.

Merge branch 'vector-element-access'

This introduces the concept of vector index being part of a pointer type. This avoids vectors having well-defined in-memory layout, and allows vectors of any integer bit width to work the same way. When a vector is indexed with a scalar, this is vector element access, which this branch implements. When a vector is indexed with a vector, this is gather/scatter, which is not implemented in this branch. closes #3575 closes #3580

8 files changed, 422 insertions(+), 41 deletions(-)

src/all_types.hpp+30-1
...@@ -1183,13 +1183,22 @@ struct FnTypeId {...@@ -1183,13 +1183,22 @@ struct FnTypeId {
1183uint32_t fn_type_id_hash(FnTypeId*);1183uint32_t fn_type_id_hash(FnTypeId*);
1184bool fn_type_id_eql(FnTypeId *a, FnTypeId *b);1184bool fn_type_id_eql(FnTypeId *a, FnTypeId *b);
11851185
1186static const uint32_t VECTOR_INDEX_NONE = UINT32_MAX;
1187static const uint32_t VECTOR_INDEX_RUNTIME = UINT32_MAX - 1;
1188
1186struct ZigTypePointer {1189struct ZigTypePointer {
1187 ZigType *child_type;1190 ZigType *child_type;
1188 ZigType *slice_parent;1191 ZigType *slice_parent;
1192
1189 PtrLen ptr_len;1193 PtrLen ptr_len;
1190 uint32_t explicit_alignment; // 0 means use ABI alignment1194 uint32_t explicit_alignment; // 0 means use ABI alignment
1195
1191 uint32_t bit_offset_in_host;1196 uint32_t bit_offset_in_host;
1192 uint32_t host_int_bytes; // size of host integer. 0 means no host integer; this field is aligned1197 // size of host integer. 0 means no host integer; this field is aligned
1198 // when vector_index != VECTOR_INDEX_NONE this is the len of the containing vector
1199 uint32_t host_int_bytes;
1200
1201 uint32_t vector_index; // see the VECTOR_INDEX_* constants
1193 bool is_const;1202 bool is_const;
1194 bool is_volatile;1203 bool is_volatile;
1195 bool allow_zero;1204 bool allow_zero;
...@@ -1732,8 +1741,11 @@ struct TypeId {...@@ -1732,8 +1741,11 @@ struct TypeId {
1732 ZigType *child_type;1741 ZigType *child_type;
1733 PtrLen ptr_len;1742 PtrLen ptr_len;
1734 uint32_t alignment;1743 uint32_t alignment;
1744
1735 uint32_t bit_offset_in_host;1745 uint32_t bit_offset_in_host;
1736 uint32_t host_int_bytes;1746 uint32_t host_int_bytes;
1747
1748 uint32_t vector_index;
1737 bool is_const;1749 bool is_const;
1738 bool is_volatile;1750 bool is_volatile;
1739 bool allow_zero;1751 bool allow_zero;
...@@ -2414,6 +2426,7 @@ enum IrInstructionId {...@@ -2414,6 +2426,7 @@ enum IrInstructionId {
2414 IrInstructionIdLoadPtr,2426 IrInstructionIdLoadPtr,
2415 IrInstructionIdLoadPtrGen,2427 IrInstructionIdLoadPtrGen,
2416 IrInstructionIdStorePtr,2428 IrInstructionIdStorePtr,
2429 IrInstructionIdVectorStoreElem,
2417 IrInstructionIdFieldPtr,2430 IrInstructionIdFieldPtr,
2418 IrInstructionIdStructFieldPtr,2431 IrInstructionIdStructFieldPtr,
2419 IrInstructionIdUnionFieldPtr,2432 IrInstructionIdUnionFieldPtr,
...@@ -2563,6 +2576,7 @@ enum IrInstructionId {...@@ -2563,6 +2576,7 @@ enum IrInstructionId {
2563 IrInstructionIdResume,2576 IrInstructionIdResume,
2564 IrInstructionIdSpillBegin,2577 IrInstructionIdSpillBegin,
2565 IrInstructionIdSpillEnd,2578 IrInstructionIdSpillEnd,
2579 IrInstructionIdVectorExtractElem,
2566};2580};
25672581
2568struct IrInstruction {2582struct IrInstruction {
...@@ -2757,6 +2771,14 @@ struct IrInstructionStorePtr {...@@ -2757,6 +2771,14 @@ struct IrInstructionStorePtr {
2757 IrInstruction *value;2771 IrInstruction *value;
2758};2772};
27592773
2774struct IrInstructionVectorStoreElem {
2775 IrInstruction base;
2776
2777 IrInstruction *vector_ptr;
2778 IrInstruction *index;
2779 IrInstruction *value;
2780};
2781
2760struct IrInstructionFieldPtr {2782struct IrInstructionFieldPtr {
2761 IrInstruction base;2783 IrInstruction base;
27622784
...@@ -3890,6 +3912,13 @@ struct IrInstructionSpillEnd {...@@ -3890,6 +3912,13 @@ struct IrInstructionSpillEnd {
3890 IrInstructionSpillBegin *begin;3912 IrInstructionSpillBegin *begin;
3891};3913};
38923914
3915struct IrInstructionVectorExtractElem {
3916 IrInstruction base;
3917
3918 IrInstruction *vector;
3919 IrInstruction *index;
3920};
3921
3893enum ResultLocId {3922enum ResultLocId {
3894 ResultLocIdInvalid,3923 ResultLocIdInvalid,
3895 ResultLocIdNone,3924 ResultLocIdNone,
src/analyze.cpp+57-14
...@@ -480,9 +480,10 @@ ZigType *get_fn_frame_type(CodeGen *g, ZigFn *fn) {...@@ -480,9 +480,10 @@ ZigType *get_fn_frame_type(CodeGen *g, ZigFn *fn) {
480 return entry;480 return entry;
481}481}
482482
483ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_const,483ZigType *get_pointer_to_type_extra2(CodeGen *g, ZigType *child_type, bool is_const,
484 bool is_volatile, PtrLen ptr_len, uint32_t byte_alignment,484 bool is_volatile, PtrLen ptr_len, uint32_t byte_alignment,
485 uint32_t bit_offset_in_host, uint32_t host_int_bytes, bool allow_zero)485 uint32_t bit_offset_in_host, uint32_t host_int_bytes, bool allow_zero,
486 uint32_t vector_index)
486{487{
487 assert(ptr_len != PtrLenC || allow_zero);488 assert(ptr_len != PtrLenC || allow_zero);
488 assert(!type_is_invalid(child_type));489 assert(!type_is_invalid(child_type));
...@@ -494,7 +495,7 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons...@@ -494,7 +495,7 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons
494 byte_alignment = 0;495 byte_alignment = 0;
495 }496 }
496497
497 if (host_int_bytes != 0) {498 if (host_int_bytes != 0 && vector_index == VECTOR_INDEX_NONE) {
498 uint32_t child_type_bits = type_size_bits(g, child_type);499 uint32_t child_type_bits = type_size_bits(g, child_type);
499 if (host_int_bytes * 8 == child_type_bits) {500 if (host_int_bytes * 8 == child_type_bits) {
500 assert(bit_offset_in_host == 0);501 assert(bit_offset_in_host == 0);
...@@ -504,7 +505,9 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons...@@ -504,7 +505,9 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons
504505
505 TypeId type_id = {};506 TypeId type_id = {};
506 ZigType **parent_pointer = nullptr;507 ZigType **parent_pointer = nullptr;
507 if (host_int_bytes != 0 || is_volatile || byte_alignment != 0 || ptr_len != PtrLenSingle || allow_zero) {508 if (host_int_bytes != 0 || is_volatile || byte_alignment != 0 || ptr_len != PtrLenSingle ||
509 allow_zero || vector_index != VECTOR_INDEX_NONE)
510 {
508 type_id.id = ZigTypeIdPointer;511 type_id.id = ZigTypeIdPointer;
509 type_id.data.pointer.child_type = child_type;512 type_id.data.pointer.child_type = child_type;
510 type_id.data.pointer.is_const = is_const;513 type_id.data.pointer.is_const = is_const;
...@@ -514,6 +517,7 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons...@@ -514,6 +517,7 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons
514 type_id.data.pointer.host_int_bytes = host_int_bytes;517 type_id.data.pointer.host_int_bytes = host_int_bytes;
515 type_id.data.pointer.ptr_len = ptr_len;518 type_id.data.pointer.ptr_len = ptr_len;
516 type_id.data.pointer.allow_zero = allow_zero;519 type_id.data.pointer.allow_zero = allow_zero;
520 type_id.data.pointer.vector_index = vector_index;
517521
518 auto existing_entry = g->type_table.maybe_get(type_id);522 auto existing_entry = g->type_table.maybe_get(type_id);
519 if (existing_entry)523 if (existing_entry)
...@@ -540,19 +544,36 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons...@@ -540,19 +544,36 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons
540 allow_zero_str = allow_zero ? "allowzero " : "";544 allow_zero_str = allow_zero ? "allowzero " : "";
541 }545 }
542 buf_resize(&entry->name, 0);546 buf_resize(&entry->name, 0);
543 if (host_int_bytes == 0 && byte_alignment == 0) {547 if (host_int_bytes == 0 && byte_alignment == 0 && vector_index == VECTOR_INDEX_NONE) {
544 buf_appendf(&entry->name, "%s%s%s%s%s",548 buf_appendf(&entry->name, "%s%s%s%s%s",
545 star_str, const_str, volatile_str, allow_zero_str, buf_ptr(&child_type->name));549 star_str, const_str, volatile_str, allow_zero_str, buf_ptr(&child_type->name));
546 } else if (host_int_bytes == 0) {550 } else if (host_int_bytes == 0 && vector_index == VECTOR_INDEX_NONE) {
547 buf_appendf(&entry->name, "%salign(%" PRIu32 ") %s%s%s%s", star_str, byte_alignment,551 buf_appendf(&entry->name, "%salign(%" PRIu32 ") %s%s%s%s", star_str, byte_alignment,
548 const_str, volatile_str, allow_zero_str, buf_ptr(&child_type->name));552 const_str, volatile_str, allow_zero_str, buf_ptr(&child_type->name));
549 } else if (byte_alignment == 0) {553 } else if (byte_alignment == 0) {
550 buf_appendf(&entry->name, "%salign(:%" PRIu32 ":%" PRIu32 ") %s%s%s%s", star_str,554 assert(vector_index == VECTOR_INDEX_NONE);
551 bit_offset_in_host, host_int_bytes, const_str, volatile_str, allow_zero_str,555 buf_appendf(&entry->name, "%salign(:%" PRIu32 ":%" PRIu32 ") %s%s%s%s",
556 star_str,
557 bit_offset_in_host, host_int_bytes,
558 const_str, volatile_str, allow_zero_str,
559 buf_ptr(&child_type->name));
560 } else if (vector_index == VECTOR_INDEX_NONE) {
561 buf_appendf(&entry->name, "%salign(%" PRIu32 ":%" PRIu32 ":%" PRIu32 ") %s%s%s%s",
562 star_str, byte_alignment,
563 bit_offset_in_host, host_int_bytes,
564 const_str, volatile_str, allow_zero_str,
565 buf_ptr(&child_type->name));
566 } else if (vector_index == VECTOR_INDEX_RUNTIME) {
567 buf_appendf(&entry->name, "%salign(%" PRIu32 ":%" PRIu32 ":%" PRIu32 ":?) %s%s%s%s",
568 star_str, byte_alignment,
569 bit_offset_in_host, host_int_bytes,
570 const_str, volatile_str, allow_zero_str,
552 buf_ptr(&child_type->name));571 buf_ptr(&child_type->name));
553 } else {572 } else {
554 buf_appendf(&entry->name, "%salign(%" PRIu32 ":%" PRIu32 ":%" PRIu32 ") %s%s%s%s", star_str, byte_alignment,573 buf_appendf(&entry->name, "%salign(%" PRIu32 ":%" PRIu32 ":%" PRIu32 ":%" PRIu32 ") %s%s%s%s",
555 bit_offset_in_host, host_int_bytes, const_str, volatile_str, allow_zero_str,574 star_str, byte_alignment,
575 bit_offset_in_host, host_int_bytes, vector_index,
576 const_str, volatile_str, allow_zero_str,
556 buf_ptr(&child_type->name));577 buf_ptr(&child_type->name));
557 }578 }
558579
...@@ -581,6 +602,7 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons...@@ -581,6 +602,7 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons
581 entry->data.pointer.bit_offset_in_host = bit_offset_in_host;602 entry->data.pointer.bit_offset_in_host = bit_offset_in_host;
582 entry->data.pointer.host_int_bytes = host_int_bytes;603 entry->data.pointer.host_int_bytes = host_int_bytes;
583 entry->data.pointer.allow_zero = allow_zero;604 entry->data.pointer.allow_zero = allow_zero;
605 entry->data.pointer.vector_index = vector_index;
584606
585 if (parent_pointer) {607 if (parent_pointer) {
586 *parent_pointer = entry;608 *parent_pointer = entry;
...@@ -590,8 +612,17 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons...@@ -590,8 +612,17 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons
590 return entry;612 return entry;
591}613}
592614
615ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_const,
616 bool is_volatile, PtrLen ptr_len, uint32_t byte_alignment,
617 uint32_t bit_offset_in_host, uint32_t host_int_bytes, bool allow_zero)
618{
619 return get_pointer_to_type_extra2(g, child_type, is_const, is_volatile, ptr_len,
620 byte_alignment, bit_offset_in_host, host_int_bytes, allow_zero, VECTOR_INDEX_NONE);
621}
622
593ZigType *get_pointer_to_type(CodeGen *g, ZigType *child_type, bool is_const) {623ZigType *get_pointer_to_type(CodeGen *g, ZigType *child_type, bool is_const) {
594 return get_pointer_to_type_extra(g, child_type, is_const, false, PtrLenSingle, 0, 0, 0, false);624 return get_pointer_to_type_extra2(g, child_type, is_const, false, PtrLenSingle, 0, 0, 0, false,
625 VECTOR_INDEX_NONE);
595}626}
596627
597ZigType *get_optional_type(CodeGen *g, ZigType *child_type) {628ZigType *get_optional_type(CodeGen *g, ZigType *child_type) {
...@@ -6910,6 +6941,7 @@ uint32_t type_id_hash(TypeId x) {...@@ -6910,6 +6941,7 @@ uint32_t type_id_hash(TypeId x) {
6910 (x.data.pointer.allow_zero ? (uint32_t)3324284834 : (uint32_t)3584904923) +6941 (x.data.pointer.allow_zero ? (uint32_t)3324284834 : (uint32_t)3584904923) +
6911 (((uint32_t)x.data.pointer.alignment) ^ (uint32_t)0x777fbe0e) +6942 (((uint32_t)x.data.pointer.alignment) ^ (uint32_t)0x777fbe0e) +
6912 (((uint32_t)x.data.pointer.bit_offset_in_host) ^ (uint32_t)2639019452) +6943 (((uint32_t)x.data.pointer.bit_offset_in_host) ^ (uint32_t)2639019452) +
6944 (((uint32_t)x.data.pointer.vector_index) ^ (uint32_t)0x19199716) +
6913 (((uint32_t)x.data.pointer.host_int_bytes) ^ (uint32_t)529908881);6945 (((uint32_t)x.data.pointer.host_int_bytes) ^ (uint32_t)529908881);
6914 case ZigTypeIdArray:6946 case ZigTypeIdArray:
6915 return hash_ptr(x.data.array.child_type) +6947 return hash_ptr(x.data.array.child_type) +
...@@ -6962,6 +6994,7 @@ bool type_id_eql(TypeId a, TypeId b) {...@@ -6962,6 +6994,7 @@ bool type_id_eql(TypeId a, TypeId b) {
6962 a.data.pointer.allow_zero == b.data.pointer.allow_zero &&6994 a.data.pointer.allow_zero == b.data.pointer.allow_zero &&
6963 a.data.pointer.alignment == b.data.pointer.alignment &&6995 a.data.pointer.alignment == b.data.pointer.alignment &&
6964 a.data.pointer.bit_offset_in_host == b.data.pointer.bit_offset_in_host &&6996 a.data.pointer.bit_offset_in_host == b.data.pointer.bit_offset_in_host &&
6997 a.data.pointer.vector_index == b.data.pointer.vector_index &&
6965 a.data.pointer.host_int_bytes == b.data.pointer.host_int_bytes;6998 a.data.pointer.host_int_bytes == b.data.pointer.host_int_bytes;
6966 case ZigTypeIdArray:6999 case ZigTypeIdArray:
6967 return a.data.array.child_type == b.data.array.child_type &&7000 return a.data.array.child_type == b.data.array.child_type &&
...@@ -8266,11 +8299,21 @@ static void resolve_llvm_types_pointer(CodeGen *g, ZigType *type, ResolveStatus...@@ -8266,11 +8299,21 @@ static void resolve_llvm_types_pointer(CodeGen *g, ZigType *type, ResolveStatus
82668299
8267 if (type->data.pointer.is_const || type->data.pointer.is_volatile ||8300 if (type->data.pointer.is_const || type->data.pointer.is_volatile ||
8268 type->data.pointer.explicit_alignment != 0 || type->data.pointer.ptr_len != PtrLenSingle ||8301 type->data.pointer.explicit_alignment != 0 || type->data.pointer.ptr_len != PtrLenSingle ||
8269 type->data.pointer.bit_offset_in_host != 0 || type->data.pointer.allow_zero)8302 type->data.pointer.bit_offset_in_host != 0 || type->data.pointer.allow_zero ||
8303 type->data.pointer.vector_index != VECTOR_INDEX_NONE)
8270 {8304 {
8271 assertNoError(type_resolve(g, elem_type, ResolveStatusLLVMFwdDecl));8305 assertNoError(type_resolve(g, elem_type, ResolveStatusLLVMFwdDecl));
8272 ZigType *peer_type = get_pointer_to_type_extra(g, elem_type, false, false,8306 ZigType *peer_type;
8273 PtrLenSingle, 0, 0, type->data.pointer.host_int_bytes, false);8307 if (type->data.pointer.vector_index == VECTOR_INDEX_NONE) {
8308 peer_type = get_pointer_to_type_extra2(g, elem_type, false, false,
8309 PtrLenSingle, 0, 0, type->data.pointer.host_int_bytes, false,
8310 VECTOR_INDEX_NONE);
8311 } else {
8312 uint32_t host_vec_len = type->data.pointer.host_int_bytes;
8313 ZigType *host_vec_type = get_vector_type(g, host_vec_len, elem_type);
8314 peer_type = get_pointer_to_type_extra2(g, host_vec_type, false, false,
8315 PtrLenSingle, 0, 0, 0, false, VECTOR_INDEX_NONE);
8316 }
8274 type->llvm_type = get_llvm_type(g, peer_type);8317 type->llvm_type = get_llvm_type(g, peer_type);
8275 type->llvm_di_type = get_llvm_di_type(g, peer_type);8318 type->llvm_di_type = get_llvm_di_type(g, peer_type);
8276 assertNoError(type_resolve(g, elem_type, wanted_resolve_status));8319 assertNoError(type_resolve(g, elem_type, wanted_resolve_status));
src/analyze.hpp+6-2
...@@ -17,10 +17,14 @@ ErrorMsg *add_error_note(CodeGen *g, ErrorMsg *parent_msg, const AstNode *node,...@@ -17,10 +17,14 @@ ErrorMsg *add_error_note(CodeGen *g, ErrorMsg *parent_msg, const AstNode *node,
17ZigType *new_type_table_entry(ZigTypeId id);17ZigType *new_type_table_entry(ZigTypeId id);
18ZigType *get_fn_frame_type(CodeGen *g, ZigFn *fn);18ZigType *get_fn_frame_type(CodeGen *g, ZigFn *fn);
19ZigType *get_pointer_to_type(CodeGen *g, ZigType *child_type, bool is_const);19ZigType *get_pointer_to_type(CodeGen *g, ZigType *child_type, bool is_const);
20ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_const,20ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type,
21 bool is_volatile, PtrLen ptr_len,21 bool is_const, bool is_volatile, PtrLen ptr_len,
22 uint32_t byte_alignment, uint32_t bit_offset, uint32_t unaligned_bit_count,22 uint32_t byte_alignment, uint32_t bit_offset, uint32_t unaligned_bit_count,
23 bool allow_zero);23 bool allow_zero);
24ZigType *get_pointer_to_type_extra2(CodeGen *g, ZigType *child_type,
25 bool is_const, bool is_volatile, PtrLen ptr_len,
26 uint32_t byte_alignment, uint32_t bit_offset, uint32_t unaligned_bit_count,
27 bool allow_zero, uint32_t vector_index);
24uint64_t type_size(CodeGen *g, ZigType *type_entry);28uint64_t type_size(CodeGen *g, ZigType *type_entry);
25uint64_t type_size_bits(CodeGen *g, ZigType *type_entry);29uint64_t type_size_bits(CodeGen *g, ZigType *type_entry);
26ZigType *get_int_type(CodeGen *g, bool is_signed, uint32_t size_in_bits);30ZigType *get_int_type(CodeGen *g, bool is_signed, uint32_t size_in_bits);
src/codegen.cpp+68-14
...@@ -838,6 +838,11 @@ static LLVMValueRef get_handle_value(CodeGen *g, LLVMValueRef ptr, ZigType *type...@@ -838,6 +838,11 @@ static LLVMValueRef get_handle_value(CodeGen *g, LLVMValueRef ptr, ZigType *type
838 }838 }
839}839}
840840
841static void ir_assert(bool ok, IrInstruction *source_instruction) {
842 if (ok) return;
843 src_assert(ok, source_instruction->source_node);
844}
845
841static bool ir_want_fast_math(CodeGen *g, IrInstruction *instruction) {846static bool ir_want_fast_math(CodeGen *g, IrInstruction *instruction) {
842 // TODO memoize847 // TODO memoize
843 Scope *scope = instruction->scope;848 Scope *scope = instruction->scope;
...@@ -1635,6 +1640,17 @@ static void gen_assign_raw(CodeGen *g, LLVMValueRef ptr, ZigType *ptr_type,...@@ -1635,6 +1640,17 @@ static void gen_assign_raw(CodeGen *g, LLVMValueRef ptr, ZigType *ptr_type,
1635 return;1640 return;
1636 }1641 }
16371642
1643 assert(ptr_type->data.pointer.vector_index != VECTOR_INDEX_RUNTIME);
1644 if (ptr_type->data.pointer.vector_index != VECTOR_INDEX_NONE) {
1645 LLVMValueRef index_val = LLVMConstInt(LLVMInt32Type(),
1646 ptr_type->data.pointer.vector_index, false);
1647 LLVMValueRef loaded_vector = gen_load(g, ptr, ptr_type, "");
1648 LLVMValueRef new_vector = LLVMBuildInsertElement(g->builder, loaded_vector, value,
1649 index_val, "");
1650 gen_store(g, new_vector, ptr, ptr_type);
1651 return;
1652 }
1653
1638 uint32_t host_int_bytes = ptr_type->data.pointer.host_int_bytes;1654 uint32_t host_int_bytes = ptr_type->data.pointer.host_int_bytes;
1639 if (host_int_bytes == 0) {1655 if (host_int_bytes == 0) {
1640 gen_store(g, value, ptr, ptr_type);1656 gen_store(g, value, ptr, ptr_type);
...@@ -1695,11 +1711,11 @@ static LLVMValueRef ir_llvm_value(CodeGen *g, IrInstruction *instruction) {...@@ -1695,11 +1711,11 @@ static LLVMValueRef ir_llvm_value(CodeGen *g, IrInstruction *instruction) {
1695 }1711 }
1696 if (instruction->spill != nullptr) {1712 if (instruction->spill != nullptr) {
1697 ZigType *ptr_type = instruction->spill->value.type;1713 ZigType *ptr_type = instruction->spill->value.type;
1698 src_assert(ptr_type->id == ZigTypeIdPointer, instruction->source_node);1714 ir_assert(ptr_type->id == ZigTypeIdPointer, instruction);
1699 return get_handle_value(g, ir_llvm_value(g, instruction->spill),1715 return get_handle_value(g, ir_llvm_value(g, instruction->spill),
1700 ptr_type->data.pointer.child_type, instruction->spill->value.type);1716 ptr_type->data.pointer.child_type, instruction->spill->value.type);
1701 }1717 }
1702 src_assert(instruction->value.special != ConstValSpecialRuntime, instruction->source_node);1718 ir_assert(instruction->value.special != ConstValSpecialRuntime, instruction);
1703 assert(instruction->value.type);1719 assert(instruction->value.type);
1704 render_const_val(g, &instruction->value, "");1720 render_const_val(g, &instruction->value, "");
1705 // we might have to do some pointer casting here due to the way union1721 // we might have to do some pointer casting here due to the way union
...@@ -2428,8 +2444,7 @@ static LLVMValueRef ir_render_return(CodeGen *g, IrExecutable *executable, IrIns...@@ -2428,8 +2444,7 @@ static LLVMValueRef ir_render_return(CodeGen *g, IrExecutable *executable, IrIns
2428 return nullptr;2444 return nullptr;
2429 }2445 }
2430 assert(g->cur_ret_ptr);2446 assert(g->cur_ret_ptr);
2431 src_assert(instruction->operand->value.special != ConstValSpecialRuntime,2447 ir_assert(instruction->operand->value.special != ConstValSpecialRuntime, &instruction->base);
2432 instruction->base.source_node);
2433 LLVMValueRef value = ir_llvm_value(g, instruction->operand);2448 LLVMValueRef value = ir_llvm_value(g, instruction->operand);
2434 ZigType *return_type = instruction->operand->value.type;2449 ZigType *return_type = instruction->operand->value.type;
2435 gen_assign_raw(g, g->cur_ret_ptr, get_pointer_to_type(g, return_type, false), value);2450 gen_assign_raw(g, g->cur_ret_ptr, get_pointer_to_type(g, return_type, false), value);
...@@ -3399,7 +3414,9 @@ static LLVMValueRef ir_render_decl_var(CodeGen *g, IrExecutable *executable, IrI...@@ -3399,7 +3414,9 @@ static LLVMValueRef ir_render_decl_var(CodeGen *g, IrExecutable *executable, IrI
3399 return nullptr;3414 return nullptr;
3400}3415}
34013416
3402static LLVMValueRef ir_render_load_ptr(CodeGen *g, IrExecutable *executable, IrInstructionLoadPtrGen *instruction) {3417static LLVMValueRef ir_render_load_ptr(CodeGen *g, IrExecutable *executable,
3418 IrInstructionLoadPtrGen *instruction)
3419{
3403 ZigType *child_type = instruction->base.value.type;3420 ZigType *child_type = instruction->base.value.type;
3404 if (!type_has_bits(child_type))3421 if (!type_has_bits(child_type))
3405 return nullptr;3422 return nullptr;
...@@ -3408,6 +3425,14 @@ static LLVMValueRef ir_render_load_ptr(CodeGen *g, IrExecutable *executable, IrI...@@ -3408,6 +3425,14 @@ static LLVMValueRef ir_render_load_ptr(CodeGen *g, IrExecutable *executable, IrI
3408 ZigType *ptr_type = instruction->ptr->value.type;3425 ZigType *ptr_type = instruction->ptr->value.type;
3409 assert(ptr_type->id == ZigTypeIdPointer);3426 assert(ptr_type->id == ZigTypeIdPointer);
34103427
3428 ir_assert(ptr_type->data.pointer.vector_index != VECTOR_INDEX_RUNTIME, &instruction->base);
3429 if (ptr_type->data.pointer.vector_index != VECTOR_INDEX_NONE) {
3430 LLVMValueRef index_val = LLVMConstInt(LLVMInt32Type(),
3431 ptr_type->data.pointer.vector_index, false);
3432 LLVMValueRef loaded_vector = LLVMBuildLoad(g->builder, ptr, "");
3433 return LLVMBuildExtractElement(g->builder, loaded_vector, index_val, "");
3434 }
3435
3411 uint32_t host_int_bytes = ptr_type->data.pointer.host_int_bytes;3436 uint32_t host_int_bytes = ptr_type->data.pointer.host_int_bytes;
3412 if (host_int_bytes == 0)3437 if (host_int_bytes == 0)
3413 return get_handle_value(g, ptr, child_type, ptr_type);3438 return get_handle_value(g, ptr, child_type, ptr_type);
...@@ -3619,6 +3644,19 @@ static LLVMValueRef ir_render_store_ptr(CodeGen *g, IrExecutable *executable, Ir...@@ -3619,6 +3644,19 @@ static LLVMValueRef ir_render_store_ptr(CodeGen *g, IrExecutable *executable, Ir
3619 return nullptr;3644 return nullptr;
3620}3645}
36213646
3647static LLVMValueRef ir_render_vector_store_elem(CodeGen *g, IrExecutable *executable,
3648 IrInstructionVectorStoreElem *instruction)
3649{
3650 LLVMValueRef vector_ptr = ir_llvm_value(g, instruction->vector_ptr);
3651 LLVMValueRef index = ir_llvm_value(g, instruction->index);
3652 LLVMValueRef value = ir_llvm_value(g, instruction->value);
3653
3654 LLVMValueRef loaded_vector = gen_load(g, vector_ptr, instruction->vector_ptr->value.type, "");
3655 LLVMValueRef modified_vector = LLVMBuildInsertElement(g->builder, loaded_vector, value, index, "");
3656 gen_store(g, modified_vector, vector_ptr, instruction->vector_ptr->value.type);
3657 return nullptr;
3658}
3659
3622static LLVMValueRef ir_render_var_ptr(CodeGen *g, IrExecutable *executable, IrInstructionVarPtr *instruction) {3660static LLVMValueRef ir_render_var_ptr(CodeGen *g, IrExecutable *executable, IrInstructionVarPtr *instruction) {
3623 if (instruction->base.value.special != ConstValSpecialRuntime)3661 if (instruction->base.value.special != ConstValSpecialRuntime)
3624 return ir_llvm_value(g, &instruction->base);3662 return ir_llvm_value(g, &instruction->base);
...@@ -3636,7 +3674,7 @@ static LLVMValueRef ir_render_return_ptr(CodeGen *g, IrExecutable *executable,...@@ -3636,7 +3674,7 @@ static LLVMValueRef ir_render_return_ptr(CodeGen *g, IrExecutable *executable,
3636{3674{
3637 if (!type_has_bits(instruction->base.value.type))3675 if (!type_has_bits(instruction->base.value.type))
3638 return nullptr;3676 return nullptr;
3639 src_assert(g->cur_ret_ptr != nullptr, instruction->base.source_node);3677 ir_assert(g->cur_ret_ptr != nullptr, &instruction->base);
3640 return g->cur_ret_ptr;3678 return g->cur_ret_ptr;
3641}3679}
36423680
...@@ -3645,7 +3683,6 @@ static LLVMValueRef ir_render_elem_ptr(CodeGen *g, IrExecutable *executable, IrI...@@ -3645,7 +3683,6 @@ static LLVMValueRef ir_render_elem_ptr(CodeGen *g, IrExecutable *executable, IrI
3645 ZigType *array_ptr_type = instruction->array_ptr->value.type;3683 ZigType *array_ptr_type = instruction->array_ptr->value.type;
3646 assert(array_ptr_type->id == ZigTypeIdPointer);3684 assert(array_ptr_type->id == ZigTypeIdPointer);
3647 ZigType *array_type = array_ptr_type->data.pointer.child_type;3685 ZigType *array_type = array_ptr_type->data.pointer.child_type;
3648 LLVMValueRef array_ptr = get_handle_value(g, array_ptr_ptr, array_type, array_ptr_type);
3649 LLVMValueRef subscript_value = ir_llvm_value(g, instruction->elem_index);3686 LLVMValueRef subscript_value = ir_llvm_value(g, instruction->elem_index);
3650 assert(subscript_value);3687 assert(subscript_value);
36513688
...@@ -3657,6 +3694,7 @@ static LLVMValueRef ir_render_elem_ptr(CodeGen *g, IrExecutable *executable, IrI...@@ -3657,6 +3694,7 @@ static LLVMValueRef ir_render_elem_ptr(CodeGen *g, IrExecutable *executable, IrI
3657 if (array_type->id == ZigTypeIdArray ||3694 if (array_type->id == ZigTypeIdArray ||
3658 (array_type->id == ZigTypeIdPointer && array_type->data.pointer.ptr_len == PtrLenSingle))3695 (array_type->id == ZigTypeIdPointer && array_type->data.pointer.ptr_len == PtrLenSingle))
3659 {3696 {
3697 LLVMValueRef array_ptr = get_handle_value(g, array_ptr_ptr, array_type, array_ptr_type);
3660 if (array_type->id == ZigTypeIdPointer) {3698 if (array_type->id == ZigTypeIdPointer) {
3661 assert(array_type->data.pointer.child_type->id == ZigTypeIdArray);3699 assert(array_type->data.pointer.child_type->id == ZigTypeIdArray);
3662 array_type = array_type->data.pointer.child_type;3700 array_type = array_type->data.pointer.child_type;
...@@ -3696,12 +3734,14 @@ static LLVMValueRef ir_render_elem_ptr(CodeGen *g, IrExecutable *executable, IrI...@@ -3696,12 +3734,14 @@ static LLVMValueRef ir_render_elem_ptr(CodeGen *g, IrExecutable *executable, IrI
3696 };3734 };
3697 return LLVMBuildInBoundsGEP(g->builder, array_ptr, indices, 2, "");3735 return LLVMBuildInBoundsGEP(g->builder, array_ptr, indices, 2, "");
3698 } else if (array_type->id == ZigTypeIdPointer) {3736 } else if (array_type->id == ZigTypeIdPointer) {
3737 LLVMValueRef array_ptr = get_handle_value(g, array_ptr_ptr, array_type, array_ptr_type);
3699 assert(LLVMGetTypeKind(LLVMTypeOf(array_ptr)) == LLVMPointerTypeKind);3738 assert(LLVMGetTypeKind(LLVMTypeOf(array_ptr)) == LLVMPointerTypeKind);
3700 LLVMValueRef indices[] = {3739 LLVMValueRef indices[] = {
3701 subscript_value3740 subscript_value
3702 };3741 };
3703 return LLVMBuildInBoundsGEP(g->builder, array_ptr, indices, 1, "");3742 return LLVMBuildInBoundsGEP(g->builder, array_ptr, indices, 1, "");
3704 } else if (array_type->id == ZigTypeIdStruct) {3743 } else if (array_type->id == ZigTypeIdStruct) {
3744 LLVMValueRef array_ptr = get_handle_value(g, array_ptr_ptr, array_type, array_ptr_type);
3705 assert(array_type->data.structure.is_slice);3745 assert(array_type->data.structure.is_slice);
37063746
3707 ZigType *ptr_type = instruction->base.value.type;3747 ZigType *ptr_type = instruction->base.value.type;
...@@ -3729,6 +3769,8 @@ static LLVMValueRef ir_render_elem_ptr(CodeGen *g, IrExecutable *executable, IrI...@@ -3729,6 +3769,8 @@ static LLVMValueRef ir_render_elem_ptr(CodeGen *g, IrExecutable *executable, IrI
3729 LLVMValueRef ptr_ptr = LLVMBuildStructGEP(g->builder, array_ptr, (unsigned)ptr_index, "");3769 LLVMValueRef ptr_ptr = LLVMBuildStructGEP(g->builder, array_ptr, (unsigned)ptr_index, "");
3730 LLVMValueRef ptr = gen_load_untyped(g, ptr_ptr, 0, false, "");3770 LLVMValueRef ptr = gen_load_untyped(g, ptr_ptr, 0, false, "");
3731 return LLVMBuildInBoundsGEP(g->builder, ptr, &subscript_value, 1, "");3771 return LLVMBuildInBoundsGEP(g->builder, ptr, &subscript_value, 1, "");
3772 } else if (array_type->id == ZigTypeIdVector) {
3773 return array_ptr_ptr;
3732 } else {3774 } else {
3733 zig_unreachable();3775 zig_unreachable();
3734 }3776 }
...@@ -3917,9 +3959,9 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr...@@ -3917,9 +3959,9 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr
3917 if (instruction->modifier == CallModifierAsync) {3959 if (instruction->modifier == CallModifierAsync) {
3918 frame_result_loc = result_loc;3960 frame_result_loc = result_loc;
3919 } else {3961 } else {
3920 src_assert(instruction->frame_result_loc != nullptr, instruction->base.source_node);3962 ir_assert(instruction->frame_result_loc != nullptr, &instruction->base);
3921 frame_result_loc_uncasted = ir_llvm_value(g, instruction->frame_result_loc);3963 frame_result_loc_uncasted = ir_llvm_value(g, instruction->frame_result_loc);
3922 src_assert(instruction->fn_entry != nullptr, instruction->base.source_node);3964 ir_assert(instruction->fn_entry != nullptr, &instruction->base);
3923 frame_result_loc = LLVMBuildBitCast(g->builder, frame_result_loc_uncasted,3965 frame_result_loc = LLVMBuildBitCast(g->builder, frame_result_loc_uncasted,
3924 LLVMPointerType(get_llvm_type(g, instruction->fn_entry->frame_type), 0), "");3966 LLVMPointerType(get_llvm_type(g, instruction->fn_entry->frame_type), 0), "");
3925 }3967 }
...@@ -4271,10 +4313,10 @@ static LLVMValueRef ir_render_struct_field_ptr(CodeGen *g, IrExecutable *executa...@@ -4271,10 +4313,10 @@ static LLVMValueRef ir_render_struct_field_ptr(CodeGen *g, IrExecutable *executa
4271 if ((err = type_resolve(g, struct_type, ResolveStatusLLVMFull)))4313 if ((err = type_resolve(g, struct_type, ResolveStatusLLVMFull)))
4272 codegen_report_errors_and_exit(g);4314 codegen_report_errors_and_exit(g);
42734315
4274 src_assert(field->gen_index != SIZE_MAX, instruction->base.source_node);4316 ir_assert(field->gen_index != SIZE_MAX, &instruction->base);
4275 LLVMValueRef field_ptr_val = LLVMBuildStructGEP(g->builder, struct_ptr, (unsigned)field->gen_index, "");4317 LLVMValueRef field_ptr_val = LLVMBuildStructGEP(g->builder, struct_ptr, (unsigned)field->gen_index, "");
4276 ZigType *res_type = instruction->base.value.type;4318 ZigType *res_type = instruction->base.value.type;
4277 src_assert(res_type->id == ZigTypeIdPointer, instruction->base.source_node);4319 ir_assert(res_type->id == ZigTypeIdPointer, &instruction->base);
4278 if (res_type->data.pointer.host_int_bytes != 0) {4320 if (res_type->data.pointer.host_int_bytes != 0) {
4279 // We generate packed structs with get_llvm_type_of_n_bytes, which is4321 // We generate packed structs with get_llvm_type_of_n_bytes, which is
4280 // u8 for 1 byte or [n]u8 for multiple bytes. But the pointer to the type4322 // u8 for 1 byte or [n]u8 for multiple bytes. But the pointer to the type
...@@ -4684,7 +4726,7 @@ static LLVMValueRef ir_render_shuffle_vector(CodeGen *g, IrExecutable *executabl...@@ -4684,7 +4726,7 @@ static LLVMValueRef ir_render_shuffle_vector(CodeGen *g, IrExecutable *executabl
46844726
4685static LLVMValueRef ir_render_splat(CodeGen *g, IrExecutable *executable, IrInstructionSplatGen *instruction) {4727static LLVMValueRef ir_render_splat(CodeGen *g, IrExecutable *executable, IrInstructionSplatGen *instruction) {
4686 ZigType *result_type = instruction->base.value.type;4728 ZigType *result_type = instruction->base.value.type;
4687 src_assert(result_type->id == ZigTypeIdVector, instruction->base.source_node);4729 ir_assert(result_type->id == ZigTypeIdVector, &instruction->base);
4688 uint32_t len = result_type->data.vector.len;4730 uint32_t len = result_type->data.vector.len;
4689 LLVMTypeRef op_llvm_type = LLVMVectorType(get_llvm_type(g, instruction->scalar->value.type), 1);4731 LLVMTypeRef op_llvm_type = LLVMVectorType(get_llvm_type(g, instruction->scalar->value.type), 1);
4690 LLVMTypeRef mask_llvm_type = LLVMVectorType(LLVMInt32Type(), len);4732 LLVMTypeRef mask_llvm_type = LLVMVectorType(LLVMInt32Type(), len);
...@@ -5039,8 +5081,8 @@ static LLVMValueRef ir_render_cmpxchg(CodeGen *g, IrExecutable *executable, IrIn...@@ -5039,8 +5081,8 @@ static LLVMValueRef ir_render_cmpxchg(CodeGen *g, IrExecutable *executable, IrIn
5039 }5081 }
50405082
5041 LLVMValueRef result_loc = ir_llvm_value(g, instruction->result_loc);5083 LLVMValueRef result_loc = ir_llvm_value(g, instruction->result_loc);
5042 src_assert(result_loc != nullptr, instruction->base.source_node);5084 ir_assert(result_loc != nullptr, &instruction->base);
5043 src_assert(type_has_bits(child_type), instruction->base.source_node);5085 ir_assert(type_has_bits(child_type), &instruction->base);
50445086
5045 LLVMValueRef payload_val = LLVMBuildExtractValue(g->builder, result_val, 0, "");5087 LLVMValueRef payload_val = LLVMBuildExtractValue(g->builder, result_val, 0, "");
5046 LLVMValueRef val_ptr = LLVMBuildStructGEP(g->builder, result_loc, maybe_child_index, "");5088 LLVMValueRef val_ptr = LLVMBuildStructGEP(g->builder, result_loc, maybe_child_index, "");
...@@ -5973,6 +6015,14 @@ static LLVMValueRef ir_render_spill_end(CodeGen *g, IrExecutable *executable, Ir...@@ -5973,6 +6015,14 @@ static LLVMValueRef ir_render_spill_end(CodeGen *g, IrExecutable *executable, Ir
5973 zig_unreachable();6015 zig_unreachable();
5974}6016}
59756017
6018static LLVMValueRef ir_render_vector_extract_elem(CodeGen *g, IrExecutable *executable,
6019 IrInstructionVectorExtractElem *instruction)
6020{
6021 LLVMValueRef vector = ir_llvm_value(g, instruction->vector);
6022 LLVMValueRef index = ir_llvm_value(g, instruction->index);
6023 return LLVMBuildExtractElement(g->builder, vector, index, "");
6024}
6025
5976static void set_debug_location(CodeGen *g, IrInstruction *instruction) {6026static void set_debug_location(CodeGen *g, IrInstruction *instruction) {
5977 AstNode *source_node = instruction->source_node;6027 AstNode *source_node = instruction->source_node;
5978 Scope *scope = instruction->scope;6028 Scope *scope = instruction->scope;
...@@ -6093,6 +6143,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,...@@ -6093,6 +6143,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
6093 return ir_render_load_ptr(g, executable, (IrInstructionLoadPtrGen *)instruction);6143 return ir_render_load_ptr(g, executable, (IrInstructionLoadPtrGen *)instruction);
6094 case IrInstructionIdStorePtr:6144 case IrInstructionIdStorePtr:
6095 return ir_render_store_ptr(g, executable, (IrInstructionStorePtr *)instruction);6145 return ir_render_store_ptr(g, executable, (IrInstructionStorePtr *)instruction);
6146 case IrInstructionIdVectorStoreElem:
6147 return ir_render_vector_store_elem(g, executable, (IrInstructionVectorStoreElem *)instruction);
6096 case IrInstructionIdVarPtr:6148 case IrInstructionIdVarPtr:
6097 return ir_render_var_ptr(g, executable, (IrInstructionVarPtr *)instruction);6149 return ir_render_var_ptr(g, executable, (IrInstructionVarPtr *)instruction);
6098 case IrInstructionIdReturnPtr:6150 case IrInstructionIdReturnPtr:
...@@ -6233,6 +6285,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,...@@ -6233,6 +6285,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
6233 return ir_render_shuffle_vector(g, executable, (IrInstructionShuffleVector *) instruction);6285 return ir_render_shuffle_vector(g, executable, (IrInstructionShuffleVector *) instruction);
6234 case IrInstructionIdSplatGen:6286 case IrInstructionIdSplatGen:
6235 return ir_render_splat(g, executable, (IrInstructionSplatGen *) instruction);6287 return ir_render_splat(g, executable, (IrInstructionSplatGen *) instruction);
6288 case IrInstructionIdVectorExtractElem:
6289 return ir_render_vector_extract_elem(g, executable, (IrInstructionVectorExtractElem *) instruction);
6236 }6290 }
6237 zig_unreachable();6291 zig_unreachable();
6238}6292}
src/ir.cpp+111-10
...@@ -491,6 +491,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionStorePtr *) {...@@ -491,6 +491,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionStorePtr *) {
491 return IrInstructionIdStorePtr;491 return IrInstructionIdStorePtr;
492}492}
493493
494static constexpr IrInstructionId ir_instruction_id(IrInstructionVectorStoreElem *) {
495 return IrInstructionIdVectorStoreElem;
496}
497
494static constexpr IrInstructionId ir_instruction_id(IrInstructionFieldPtr *) {498static constexpr IrInstructionId ir_instruction_id(IrInstructionFieldPtr *) {
495 return IrInstructionIdFieldPtr;499 return IrInstructionIdFieldPtr;
496}500}
...@@ -1083,6 +1087,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionSpillEnd *) {...@@ -1083,6 +1087,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionSpillEnd *) {
1083 return IrInstructionIdSpillEnd;1087 return IrInstructionIdSpillEnd;
1084}1088}
10851089
1090static constexpr IrInstructionId ir_instruction_id(IrInstructionVectorExtractElem *) {
1091 return IrInstructionIdVectorExtractElem;
1092}
1093
1086template<typename T>1094template<typename T>
1087static T *ir_create_instruction(IrBuilder *irb, Scope *scope, AstNode *source_node) {1095static T *ir_create_instruction(IrBuilder *irb, Scope *scope, AstNode *source_node) {
1088 const char *name = nullptr;1096 const char *name = nullptr;
...@@ -1627,6 +1635,23 @@ static IrInstructionStorePtr *ir_build_store_ptr(IrBuilder *irb, Scope *scope, A...@@ -1627,6 +1635,23 @@ static IrInstructionStorePtr *ir_build_store_ptr(IrBuilder *irb, Scope *scope, A
1627 return instruction;1635 return instruction;
1628}1636}
16291637
1638static IrInstruction *ir_build_vector_store_elem(IrAnalyze *ira, IrInstruction *source_instruction,
1639 IrInstruction *vector_ptr, IrInstruction *index, IrInstruction *value)
1640{
1641 IrInstructionVectorStoreElem *inst = ir_build_instruction<IrInstructionVectorStoreElem>(
1642 &ira->new_irb, source_instruction->scope, source_instruction->source_node);
1643 inst->base.value.type = ira->codegen->builtin_types.entry_void;
1644 inst->vector_ptr = vector_ptr;
1645 inst->index = index;
1646 inst->value = value;
1647
1648 ir_ref_instruction(vector_ptr, ira->new_irb.current_basic_block);
1649 ir_ref_instruction(index, ira->new_irb.current_basic_block);
1650 ir_ref_instruction(value, ira->new_irb.current_basic_block);
1651
1652 return &inst->base;
1653}
1654
1630static IrInstruction *ir_build_var_decl_src(IrBuilder *irb, Scope *scope, AstNode *source_node,1655static IrInstruction *ir_build_var_decl_src(IrBuilder *irb, Scope *scope, AstNode *source_node,
1631 ZigVar *var, IrInstruction *align_value, IrInstruction *ptr)1656 ZigVar *var, IrInstruction *align_value, IrInstruction *ptr)
1632{1657{
...@@ -3419,6 +3444,21 @@ static IrInstruction *ir_build_spill_end(IrBuilder *irb, Scope *scope, AstNode *...@@ -3419,6 +3444,21 @@ static IrInstruction *ir_build_spill_end(IrBuilder *irb, Scope *scope, AstNode *
3419 return &instruction->base;3444 return &instruction->base;
3420}3445}
34213446
3447static IrInstruction *ir_build_vector_extract_elem(IrAnalyze *ira, IrInstruction *source_instruction,
3448 IrInstruction *vector, IrInstruction *index)
3449{
3450 IrInstructionVectorExtractElem *instruction = ir_build_instruction<IrInstructionVectorExtractElem>(
3451 &ira->new_irb, source_instruction->scope, source_instruction->source_node);
3452 instruction->base.value.type = vector->value.type->data.vector.elem_type;
3453 instruction->vector = vector;
3454 instruction->index = index;
3455
3456 ir_ref_instruction(vector, ira->new_irb.current_basic_block);
3457 ir_ref_instruction(index, ira->new_irb.current_basic_block);
3458
3459 return &instruction->base;
3460}
3461
3422static void ir_count_defers(IrBuilder *irb, Scope *inner_scope, Scope *outer_scope, size_t *results) {3462static void ir_count_defers(IrBuilder *irb, Scope *inner_scope, Scope *outer_scope, size_t *results) {
3423 results[ReturnKindUnconditional] = 0;3463 results[ReturnKindUnconditional] = 0;
3424 results[ReturnKindError] = 0;3464 results[ReturnKindError] = 0;
...@@ -12908,18 +12948,18 @@ static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruc...@@ -12908,18 +12948,18 @@ static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruc
12908 ResultLoc *result_loc)12948 ResultLoc *result_loc)
12909{12949{
12910 Error err;12950 Error err;
12911 ZigType *type_entry = ptr->value.type;12951 ZigType *ptr_type = ptr->value.type;
12912 if (type_is_invalid(type_entry))12952 if (type_is_invalid(ptr_type))
12913 return ira->codegen->invalid_instruction;12953 return ira->codegen->invalid_instruction;
1291412954
12915 if (type_entry->id != ZigTypeIdPointer) {12955 if (ptr_type->id != ZigTypeIdPointer) {
12916 ir_add_error_node(ira, source_instruction->source_node,12956 ir_add_error_node(ira, source_instruction->source_node,
12917 buf_sprintf("attempt to dereference non-pointer type '%s'",12957 buf_sprintf("attempt to dereference non-pointer type '%s'",
12918 buf_ptr(&type_entry->name)));12958 buf_ptr(&ptr_type->name)));
12919 return ira->codegen->invalid_instruction;12959 return ira->codegen->invalid_instruction;
12920 }12960 }
1292112961
12922 ZigType *child_type = type_entry->data.pointer.child_type;12962 ZigType *child_type = ptr_type->data.pointer.child_type;
12923 // if the child type has one possible value, the deref is comptime12963 // if the child type has one possible value, the deref is comptime
12924 switch (type_has_one_possible_value(ira->codegen, child_type)) {12964 switch (type_has_one_possible_value(ira->codegen, child_type)) {
12925 case OnePossibleValueInvalid:12965 case OnePossibleValueInvalid:
...@@ -12949,14 +12989,36 @@ static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruc...@@ -12949,14 +12989,36 @@ static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruc
12949 }12989 }
12950 }12990 }
12951 }12991 }
12992
12952 // if the instruction is a const ref instruction we can skip it12993 // if the instruction is a const ref instruction we can skip it
12953 if (ptr->id == IrInstructionIdRef) {12994 if (ptr->id == IrInstructionIdRef) {
12954 IrInstructionRef *ref_inst = reinterpret_cast<IrInstructionRef *>(ptr);12995 IrInstructionRef *ref_inst = reinterpret_cast<IrInstructionRef *>(ptr);
12955 return ref_inst->value;12996 return ref_inst->value;
12956 }12997 }
1295712998
12999 // If the instruction is a element pointer instruction to a vector, we emit
13000 // vector element extract instruction rather than load pointer. If the
13001 // pointer type has non-VECTOR_INDEX_RUNTIME value, it would have been
13002 // possible to implement this in the codegen for IrInstructionLoadPtrGen.
13003 // However if it has VECTOR_INDEX_RUNTIME then we must emit a compile error
13004 // if the vector index cannot be determined right here, right now, because
13005 // the type information does not contain enough information to actually
13006 // perform a dereference.
13007 if (ptr_type->data.pointer.vector_index == VECTOR_INDEX_RUNTIME) {
13008 if (ptr->id == IrInstructionIdElemPtr) {
13009 IrInstructionElemPtr *elem_ptr = (IrInstructionElemPtr *)ptr;
13010 IrInstruction *vector_loaded = ir_get_deref(ira, elem_ptr->array_ptr,
13011 elem_ptr->array_ptr, nullptr);
13012 IrInstruction *elem_index = elem_ptr->elem_index;
13013 return ir_build_vector_extract_elem(ira, source_instruction, vector_loaded, elem_index);
13014 }
13015 ir_add_error(ira, ptr,
13016 buf_sprintf("unable to determine vector element index of type '%s'", buf_ptr(&ptr_type->name)));
13017 return ira->codegen->invalid_instruction;
13018 }
13019
12958 IrInstruction *result_loc_inst;13020 IrInstruction *result_loc_inst;
12959 if (type_entry->data.pointer.host_int_bytes != 0 && handle_is_ptr(child_type)) {13021 if (ptr_type->data.pointer.host_int_bytes != 0 && handle_is_ptr(child_type)) {
12960 if (result_loc == nullptr) result_loc = no_result_loc();13022 if (result_loc == nullptr) result_loc = no_result_loc();
12961 result_loc_inst = ir_resolve_result(ira, source_instruction, result_loc, child_type, nullptr,13023 result_loc_inst = ir_resolve_result(ira, source_instruction, result_loc, child_type, nullptr,
12962 true, false, true);13024 true, false, true);
...@@ -16085,6 +16147,24 @@ static IrInstruction *ir_analyze_store_ptr(IrAnalyze *ira, IrInstruction *source...@@ -16085,6 +16147,24 @@ static IrInstruction *ir_analyze_store_ptr(IrAnalyze *ira, IrInstruction *source
16085 mark_comptime_value_escape(ira, source_instr, &value->value);16147 mark_comptime_value_escape(ira, source_instr, &value->value);
16086 }16148 }
1608716149
16150 // If this is a store to a pointer with a runtime-known vector index,
16151 // we have to figure out the IrInstruction which represents the index and
16152 // emit a IrInstructionVectorStoreElem, or emit a compile error
16153 // explaining why it is impossible for this store to work. Which is that
16154 // the pointer address is of the vector; without the element index being known
16155 // we cannot properly perform the insertion.
16156 if (ptr->value.type->data.pointer.vector_index == VECTOR_INDEX_RUNTIME) {
16157 if (ptr->id == IrInstructionIdElemPtr) {
16158 IrInstructionElemPtr *elem_ptr = (IrInstructionElemPtr *)ptr;
16159 return ir_build_vector_store_elem(ira, source_instr, elem_ptr->array_ptr,
16160 elem_ptr->elem_index, value);
16161 }
16162 ir_add_error(ira, ptr,
16163 buf_sprintf("unable to determine vector element index of type '%s'",
16164 buf_ptr(&ptr->value.type->name)));
16165 return ira->codegen->invalid_instruction;
16166 }
16167
16088 IrInstructionStorePtr *store_ptr = ir_build_store_ptr(&ira->new_irb, source_instr->scope,16168 IrInstructionStorePtr *store_ptr = ir_build_store_ptr(&ira->new_irb, source_instr->scope,
16089 source_instr->source_node, ptr, value);16169 source_instr->source_node, ptr, value);
16090 return &store_ptr->base;16170 return &store_ptr->base;
...@@ -17488,6 +17568,9 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct...@@ -17488,6 +17568,9 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct
17488 return ir_get_const_ptr(ira, &elem_ptr_instruction->base, &ira->codegen->const_void_val,17568 return ir_get_const_ptr(ira, &elem_ptr_instruction->base, &ira->codegen->const_void_val,
17489 ira->codegen->builtin_types.entry_void, ConstPtrMutComptimeConst, is_const, is_volatile, 0);17569 ira->codegen->builtin_types.entry_void, ConstPtrMutComptimeConst, is_const, is_volatile, 0);
17490 }17570 }
17571 } else if (array_type->id == ZigTypeIdVector) {
17572 // This depends on whether the element index is comptime, so it is computed later.
17573 return_type = nullptr;
17491 } else {17574 } else {
17492 ir_add_error_node(ira, elem_ptr_instruction->base.source_node,17575 ir_add_error_node(ira, elem_ptr_instruction->base.source_node,
17493 buf_sprintf("array access of non-array type '%s'", buf_ptr(&array_type->name)));17576 buf_sprintf("array access of non-array type '%s'", buf_ptr(&array_type->name)));
...@@ -17512,8 +17595,14 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct...@@ -17512,8 +17595,14 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct
17512 }17595 }
17513 safety_check_on = false;17596 safety_check_on = false;
17514 }17597 }
1751517598 if (array_type->id == ZigTypeIdVector) {
17516 if (return_type->data.pointer.explicit_alignment != 0) {17599 ZigType *elem_type = array_type->data.vector.elem_type;
17600 uint32_t host_vec_len = array_type->data.vector.len;
17601 return_type = get_pointer_to_type_extra2(ira->codegen, elem_type,
17602 ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile,
17603 elem_ptr_instruction->ptr_len,
17604 get_ptr_align(ira->codegen, ptr_type), 0, host_vec_len, false, (uint32_t)index);
17605 } else if (return_type->data.pointer.explicit_alignment != 0) {
17517 // figure out the largest alignment possible17606 // figure out the largest alignment possible
1751817607
17519 if ((err = type_resolve(ira->codegen, return_type->data.pointer.child_type, ResolveStatusSizeKnown)))17608 if ((err = type_resolve(ira->codegen, return_type->data.pointer.child_type, ResolveStatusSizeKnown)))
...@@ -17551,7 +17640,7 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct...@@ -17551,7 +17640,7 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct
17551 return ira->codegen->invalid_instruction;17640 return ira->codegen->invalid_instruction;
1755217641
17553 if (array_ptr_val->special == ConstValSpecialUndef && elem_ptr_instruction->init_array_type != nullptr) {17642 if (array_ptr_val->special == ConstValSpecialUndef && elem_ptr_instruction->init_array_type != nullptr) {
17554 if (array_type->id == ZigTypeIdArray) {17643 if (array_type->id == ZigTypeIdArray || array_type->id == ZigTypeIdVector) {
17555 array_ptr_val->data.x_array.special = ConstArraySpecialNone;17644 array_ptr_val->data.x_array.special = ConstArraySpecialNone;
17556 array_ptr_val->data.x_array.data.s_none.elements = create_const_vals(array_type->data.array.len);17645 array_ptr_val->data.x_array.data.s_none.elements = create_const_vals(array_type->data.array.len);
17557 array_ptr_val->special = ConstValSpecialStatic;17646 array_ptr_val->special = ConstValSpecialStatic;
...@@ -17720,7 +17809,7 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct...@@ -17720,7 +17809,7 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct
17720 zig_panic("TODO elem ptr on a slice has a null pointer");17809 zig_panic("TODO elem ptr on a slice has a null pointer");
17721 }17810 }
17722 return result;17811 return result;
17723 } else if (array_type->id == ZigTypeIdArray) {17812 } else if (array_type->id == ZigTypeIdArray || array_type->id == ZigTypeIdVector) {
17724 IrInstruction *result;17813 IrInstruction *result;
17725 if (orig_array_ptr_val->data.x_ptr.mut == ConstPtrMutInfer) {17814 if (orig_array_ptr_val->data.x_ptr.mut == ConstPtrMutInfer) {
17726 result = ir_build_elem_ptr(&ira->new_irb, elem_ptr_instruction->base.scope,17815 result = ir_build_elem_ptr(&ira->new_irb, elem_ptr_instruction->base.scope,
...@@ -17742,6 +17831,14 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct...@@ -17742,6 +17831,14 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct
17742 }17831 }
17743 }17832 }
17744 }17833 }
17834 } else if (array_type->id == ZigTypeIdVector) {
17835 // runtime known element index
17836 ZigType *elem_type = array_type->data.vector.elem_type;
17837 uint32_t host_vec_len = array_type->data.vector.len;
17838 return_type = get_pointer_to_type_extra2(ira->codegen, elem_type,
17839 ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile,
17840 elem_ptr_instruction->ptr_len,
17841 get_ptr_align(ira->codegen, ptr_type), 0, host_vec_len, false, VECTOR_INDEX_RUNTIME);
17745 } else {17842 } else {
17746 // runtime known element index17843 // runtime known element index
17747 switch (type_requires_comptime(ira->codegen, return_type)) {17844 switch (type_requires_comptime(ira->codegen, return_type)) {
...@@ -26004,6 +26101,8 @@ static IrInstruction *ir_analyze_instruction_base(IrAnalyze *ira, IrInstruction...@@ -26004,6 +26101,8 @@ static IrInstruction *ir_analyze_instruction_base(IrAnalyze *ira, IrInstruction
26004 case IrInstructionIdFrameSizeGen:26101 case IrInstructionIdFrameSizeGen:
26005 case IrInstructionIdAwaitGen:26102 case IrInstructionIdAwaitGen:
26006 case IrInstructionIdSplatGen:26103 case IrInstructionIdSplatGen:
26104 case IrInstructionIdVectorExtractElem:
26105 case IrInstructionIdVectorStoreElem:
26007 zig_unreachable();26106 zig_unreachable();
2600826107
26009 case IrInstructionIdReturn:26108 case IrInstructionIdReturn:
...@@ -26387,6 +26486,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {...@@ -26387,6 +26486,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {
26387 case IrInstructionIdDeclVarSrc:26486 case IrInstructionIdDeclVarSrc:
26388 case IrInstructionIdDeclVarGen:26487 case IrInstructionIdDeclVarGen:
26389 case IrInstructionIdStorePtr:26488 case IrInstructionIdStorePtr:
26489 case IrInstructionIdVectorStoreElem:
26390 case IrInstructionIdCallSrc:26490 case IrInstructionIdCallSrc:
26391 case IrInstructionIdCallGen:26491 case IrInstructionIdCallGen:
26392 case IrInstructionIdReturn:26492 case IrInstructionIdReturn:
...@@ -26539,6 +26639,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {...@@ -26539,6 +26639,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {
26539 case IrInstructionIdAllocaSrc:26639 case IrInstructionIdAllocaSrc:
26540 case IrInstructionIdAllocaGen:26640 case IrInstructionIdAllocaGen:
26541 case IrInstructionIdSpillEnd:26641 case IrInstructionIdSpillEnd:
26642 case IrInstructionIdVectorExtractElem:
26542 return false;26643 return false;
2654326644
26544 case IrInstructionIdAsm:26645 case IrInstructionIdAsm:
src/ir_print.cpp+27
...@@ -78,6 +78,8 @@ const char* ir_instruction_type_str(IrInstructionId id) {...@@ -78,6 +78,8 @@ const char* ir_instruction_type_str(IrInstructionId id) {
78 return "LoadPtrGen";78 return "LoadPtrGen";
79 case IrInstructionIdStorePtr:79 case IrInstructionIdStorePtr:
80 return "StorePtr";80 return "StorePtr";
81 case IrInstructionIdVectorStoreElem:
82 return "VectorStoreElem";
81 case IrInstructionIdFieldPtr:83 case IrInstructionIdFieldPtr:
82 return "FieldPtr";84 return "FieldPtr";
83 case IrInstructionIdStructFieldPtr:85 case IrInstructionIdStructFieldPtr:
...@@ -370,6 +372,8 @@ const char* ir_instruction_type_str(IrInstructionId id) {...@@ -370,6 +372,8 @@ const char* ir_instruction_type_str(IrInstructionId id) {
370 return "SpillBegin";372 return "SpillBegin";
371 case IrInstructionIdSpillEnd:373 case IrInstructionIdSpillEnd:
372 return "SpillEnd";374 return "SpillEnd";
375 case IrInstructionIdVectorExtractElem:
376 return "VectorExtractElem";
373 }377 }
374 zig_unreachable();378 zig_unreachable();
375}379}
...@@ -788,6 +792,15 @@ static void ir_print_store_ptr(IrPrint *irp, IrInstructionStorePtr *instruction)...@@ -788,6 +792,15 @@ static void ir_print_store_ptr(IrPrint *irp, IrInstructionStorePtr *instruction)
788 ir_print_other_instruction(irp, instruction->value);792 ir_print_other_instruction(irp, instruction->value);
789}793}
790794
795static void ir_print_vector_store_elem(IrPrint *irp, IrInstructionVectorStoreElem *instruction) {
796 fprintf(irp->f, "vector_ptr=");
797 ir_print_var_instruction(irp, instruction->vector_ptr);
798 fprintf(irp->f, ",index=");
799 ir_print_var_instruction(irp, instruction->index);
800 fprintf(irp->f, ",value=");
801 ir_print_other_instruction(irp, instruction->value);
802}
803
791static void ir_print_typeof(IrPrint *irp, IrInstructionTypeOf *instruction) {804static void ir_print_typeof(IrPrint *irp, IrInstructionTypeOf *instruction) {
792 fprintf(irp->f, "@typeOf(");805 fprintf(irp->f, "@typeOf(");
793 ir_print_other_instruction(irp, instruction->value);806 ir_print_other_instruction(irp, instruction->value);
...@@ -1969,6 +1982,14 @@ static void ir_print_spill_end(IrPrint *irp, IrInstructionSpillEnd *instruction)...@@ -1969,6 +1982,14 @@ static void ir_print_spill_end(IrPrint *irp, IrInstructionSpillEnd *instruction)
1969 fprintf(irp->f, ")");1982 fprintf(irp->f, ")");
1970}1983}
19711984
1985static void ir_print_vector_extract_elem(IrPrint *irp, IrInstructionVectorExtractElem *instruction) {
1986 fprintf(irp->f, "@vectorExtractElem(");
1987 ir_print_other_instruction(irp, instruction->vector);
1988 fprintf(irp->f, ",");
1989 ir_print_other_instruction(irp, instruction->index);
1990 fprintf(irp->f, ")");
1991}
1992
1972static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction, bool trailing) {1993static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction, bool trailing) {
1973 ir_print_prefix(irp, instruction, trailing);1994 ir_print_prefix(irp, instruction, trailing);
1974 switch (instruction->id) {1995 switch (instruction->id) {
...@@ -2037,6 +2058,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction, bool...@@ -2037,6 +2058,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction, bool
2037 case IrInstructionIdStorePtr:2058 case IrInstructionIdStorePtr:
2038 ir_print_store_ptr(irp, (IrInstructionStorePtr *)instruction);2059 ir_print_store_ptr(irp, (IrInstructionStorePtr *)instruction);
2039 break;2060 break;
2061 case IrInstructionIdVectorStoreElem:
2062 ir_print_vector_store_elem(irp, (IrInstructionVectorStoreElem *)instruction);
2063 break;
2040 case IrInstructionIdTypeOf:2064 case IrInstructionIdTypeOf:
2041 ir_print_typeof(irp, (IrInstructionTypeOf *)instruction);2065 ir_print_typeof(irp, (IrInstructionTypeOf *)instruction);
2042 break;2066 break;
...@@ -2466,6 +2490,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction, bool...@@ -2466,6 +2490,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction, bool
2466 case IrInstructionIdSpillEnd:2490 case IrInstructionIdSpillEnd:
2467 ir_print_spill_end(irp, (IrInstructionSpillEnd *)instruction);2491 ir_print_spill_end(irp, (IrInstructionSpillEnd *)instruction);
2468 break;2492 break;
2493 case IrInstructionIdVectorExtractElem:
2494 ir_print_vector_extract_elem(irp, (IrInstructionVectorExtractElem *)instruction);
2495 break;
2469 }2496 }
2470 fprintf(irp->f, "\n");2497 fprintf(irp->f, "\n");
2471}2498}
test/compile_errors.zig+32
...@@ -24,6 +24,38 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -24,6 +24,38 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
24 "tmp.zig:4:20: note: referenced here",24 "tmp.zig:4:20: note: referenced here",
25 );25 );
2626
27 cases.add(
28 "store vector pointer with unknown runtime index",
29 \\export fn entry() void {
30 \\ var v: @Vector(4, i32) = [_]i32{ 1, 5, 3, undefined };
31 \\
32 \\ var i: u32 = 0;
33 \\ storev(&v[i], 42);
34 \\}
35 \\
36 \\fn storev(ptr: var, val: i32) void {
37 \\ ptr.* = val;
38 \\}
39 ,
40 "tmp.zig:9:8: error: unable to determine vector element index of type '*align(16:0:4:?) i32",
41 );
42
43 cases.add(
44 "load vector pointer with unknown runtime index",
45 \\export fn entry() void {
46 \\ var v: @Vector(4, i32) = [_]i32{ 1, 5, 3, undefined };
47 \\
48 \\ var i: u32 = 0;
49 \\ var x = loadv(&v[i]);
50 \\}
51 \\
52 \\fn loadv(ptr: var) i32 {
53 \\ return ptr.*;
54 \\}
55 ,
56 "tmp.zig:9:12: error: unable to determine vector element index of type '*align(16:0:4:?) i32",
57 );
58
27 cases.add(59 cases.add(
28 "using an unknown len ptr type instead of array",60 "using an unknown len ptr type instead of array",
29 \\const resolutions = [*][*]const u8{61 \\const resolutions = [*][*]const u8{
test/stage1/behavior/vector.zig+91
...@@ -159,3 +159,94 @@ test "vector @splat" {...@@ -159,3 +159,94 @@ test "vector @splat" {
159 S.doTheTest();159 S.doTheTest();
160 comptime S.doTheTest();160 comptime S.doTheTest();
161}161}
162
163test "load vector elements via comptime index" {
164 const S = struct {
165 fn doTheTest() void {
166 var v: @Vector(4, i32) = [_]i32{ 1, 2, 3, undefined };
167 expect(v[0] == 1);
168 expect(v[1] == 2);
169 expect(loadv(&v[2]) == 3);
170 }
171 fn loadv(ptr: var) i32 {
172 return ptr.*;
173 }
174 };
175
176 S.doTheTest();
177 comptime S.doTheTest();
178}
179
180test "store vector elements via comptime index" {
181 const S = struct {
182 fn doTheTest() void {
183 var v: @Vector(4, i32) = [_]i32{ 1, 5, 3, undefined };
184
185 v[2] = 42;
186 expect(v[1] == 5);
187 v[3] = -364;
188 expect(v[2] == 42);
189 expect(-364 == v[3]);
190
191 storev(&v[0], 100);
192 expect(v[0] == 100);
193 }
194 fn storev(ptr: var, x: i32) void {
195 ptr.* = x;
196 }
197 };
198
199 S.doTheTest();
200 comptime S.doTheTest();
201}
202
203test "load vector elements via runtime index" {
204 const S = struct {
205 fn doTheTest() void {
206 var v: @Vector(4, i32) = [_]i32{ 1, 2, 3, undefined };
207 var i: u32 = 0;
208 expect(v[i] == 1);
209 i += 1;
210 expect(v[i] == 2);
211 i += 1;
212 expect(v[i] == 3);
213 }
214 };
215
216 S.doTheTest();
217 comptime S.doTheTest();
218}
219
220test "store vector elements via runtime index" {
221 const S = struct {
222 fn doTheTest() void {
223 var v: @Vector(4, i32) = [_]i32{ 1, 5, 3, undefined };
224 var i: u32 = 2;
225 v[i] = 1;
226 expect(v[1] == 5);
227 expect(v[2] == 1);
228 i += 1;
229 v[i] = -364;
230 expect(-364 == v[3]);
231 }
232 };
233
234 S.doTheTest();
235 comptime S.doTheTest();
236}
237
238test "initialize vector which is a struct field" {
239 const Vec4Obj = struct {
240 data: @Vector(4, f32),
241 };
242
243 const S = struct {
244 fn doTheTest() void {
245 var foo = Vec4Obj{
246 .data = [_]f32{ 1, 2, 3, 4 },
247 };
248 }
249 };
250 S.doTheTest();
251 comptime S.doTheTest();
252}