authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-11-01 18:13:37-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-11-05 12:11:16-05:00
log55e54d98c47a0f1fb951f2011c6fc221af68d537
tree031f12e33101d46cfd00849f811d1097d3300d3b
parenta26e9fa7238e972301f761db80434fa0205d1016
signaturelock-open Commit is signed but in an unrecognized format.

runtime load vector element with comptime index


6 files changed, 163 insertions(+), 38 deletions(-)

src/all_types.hpp+13-1
......@@ -1183,13 +1183,22 @@ struct FnTypeId {
11831183uint32_t fn_type_id_hash(FnTypeId*);
11841184bool 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
11861189struct ZigTypePointer {
11871190 ZigType *child_type;
11881191 ZigType *slice_parent;
1192
11891193 PtrLen ptr_len;
11901194 uint32_t explicit_alignment; // 0 means use ABI alignment
1195
11911196 uint32_t bit_offset_in_host;
1192 uint32_t host_int_bytes; // size of host integer. 0 means no host integer; this field is aligned
1197 // 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
11931202 bool is_const;
11941203 bool is_volatile;
11951204 bool allow_zero;
......@@ -1732,8 +1741,11 @@ struct TypeId {
17321741 ZigType *child_type;
17331742 PtrLen ptr_len;
17341743 uint32_t alignment;
1744
17351745 uint32_t bit_offset_in_host;
17361746 uint32_t host_int_bytes;
1747
1748 uint32_t vector_index;
17371749 bool is_const;
17381750 bool is_volatile;
17391751 bool allow_zero;
src/analyze.cpp+57-14
......@@ -480,9 +480,10 @@ ZigType *get_fn_frame_type(CodeGen *g, ZigFn *fn) {
480480 return entry;
481481}
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,
484484 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)
486487{
487488 assert(ptr_len != PtrLenC || allow_zero);
488489 assert(!type_is_invalid(child_type));
......@@ -494,7 +495,7 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons
494495 byte_alignment = 0;
495496 }
496497
497 if (host_int_bytes != 0) {
498 if (host_int_bytes != 0 && vector_index == VECTOR_INDEX_NONE) {
498499 uint32_t child_type_bits = type_size_bits(g, child_type);
499500 if (host_int_bytes * 8 == child_type_bits) {
500501 assert(bit_offset_in_host == 0);
......@@ -504,7 +505,9 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons
504505
505506 TypeId type_id = {};
506507 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 {
508511 type_id.id = ZigTypeIdPointer;
509512 type_id.data.pointer.child_type = child_type;
510513 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
514517 type_id.data.pointer.host_int_bytes = host_int_bytes;
515518 type_id.data.pointer.ptr_len = ptr_len;
516519 type_id.data.pointer.allow_zero = allow_zero;
520 type_id.data.pointer.vector_index = vector_index;
517521
518522 auto existing_entry = g->type_table.maybe_get(type_id);
519523 if (existing_entry)
......@@ -540,19 +544,36 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons
540544 allow_zero_str = allow_zero ? "allowzero " : "";
541545 }
542546 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) {
544548 buf_appendf(&entry->name, "%s%s%s%s%s",
545549 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) {
547551 buf_appendf(&entry->name, "%salign(%" PRIu32 ") %s%s%s%s", star_str, byte_alignment,
548552 const_str, volatile_str, allow_zero_str, buf_ptr(&child_type->name));
549553 } else if (byte_alignment == 0) {
550 buf_appendf(&entry->name, "%salign(:%" PRIu32 ":%" PRIu32 ") %s%s%s%s", star_str,
551 bit_offset_in_host, host_int_bytes, const_str, volatile_str, allow_zero_str,
554 assert(vector_index == VECTOR_INDEX_NONE);
555 buf_appendf(&entry->name, "%salign(:%" PRIu32 ":%" PRIu32 ":%" PRIu32 ") %s%s%s%s",
556 star_str,
557 bit_offset_in_host, host_int_bytes, vector_index,
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,
552571 buf_ptr(&child_type->name));
553572 } else {
554 buf_appendf(&entry->name, "%salign(%" PRIu32 ":%" PRIu32 ":%" PRIu32 ") %s%s%s%s", star_str, byte_alignment,
555 bit_offset_in_host, host_int_bytes, const_str, volatile_str, allow_zero_str,
573 buf_appendf(&entry->name, "%salign(%" PRIu32 ":%" PRIu32 ":%" PRIu32 ":%" PRIu32 ") %s%s%s%s",
574 star_str, byte_alignment,
575 bit_offset_in_host, host_int_bytes, vector_index,
576 const_str, volatile_str, allow_zero_str,
556577 buf_ptr(&child_type->name));
557578 }
558579
......@@ -581,6 +602,7 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons
581602 entry->data.pointer.bit_offset_in_host = bit_offset_in_host;
582603 entry->data.pointer.host_int_bytes = host_int_bytes;
583604 entry->data.pointer.allow_zero = allow_zero;
605 entry->data.pointer.vector_index = vector_index;
584606
585607 if (parent_pointer) {
586608 *parent_pointer = entry;
......@@ -590,8 +612,17 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons
590612 return entry;
591613}
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
593623ZigType *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);
595626}
596627
597628ZigType *get_optional_type(CodeGen *g, ZigType *child_type) {
......@@ -6910,6 +6941,7 @@ uint32_t type_id_hash(TypeId x) {
69106941 (x.data.pointer.allow_zero ? (uint32_t)3324284834 : (uint32_t)3584904923) +
69116942 (((uint32_t)x.data.pointer.alignment) ^ (uint32_t)0x777fbe0e) +
69126943 (((uint32_t)x.data.pointer.bit_offset_in_host) ^ (uint32_t)2639019452) +
6944 (((uint32_t)x.data.pointer.vector_index) ^ (uint32_t)0x19199716) +
69136945 (((uint32_t)x.data.pointer.host_int_bytes) ^ (uint32_t)529908881);
69146946 case ZigTypeIdArray:
69156947 return hash_ptr(x.data.array.child_type) +
......@@ -6962,6 +6994,7 @@ bool type_id_eql(TypeId a, TypeId b) {
69626994 a.data.pointer.allow_zero == b.data.pointer.allow_zero &&
69636995 a.data.pointer.alignment == b.data.pointer.alignment &&
69646996 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 &&
69656998 a.data.pointer.host_int_bytes == b.data.pointer.host_int_bytes;
69666999 case ZigTypeIdArray:
69677000 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
82668299
82678300 if (type->data.pointer.is_const || type->data.pointer.is_volatile ||
82688301 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)
82708304 {
82718305 assertNoError(type_resolve(g, elem_type, ResolveStatusLLVMFwdDecl));
8272 ZigType *peer_type = get_pointer_to_type_extra(g, elem_type, false, false,
8273 PtrLenSingle, 0, 0, type->data.pointer.host_int_bytes, false);
8306 ZigType *peer_type;
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 }
82748317 type->llvm_type = get_llvm_type(g, peer_type);
82758318 type->llvm_di_type = get_llvm_di_type(g, peer_type);
82768319 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,
1717ZigType *new_type_table_entry(ZigTypeId id);
1818ZigType *get_fn_frame_type(CodeGen *g, ZigFn *fn);
1919ZigType *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,
21 bool is_volatile, PtrLen ptr_len,
20ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type,
21 bool is_const, bool is_volatile, PtrLen ptr_len,
2222 uint32_t byte_alignment, uint32_t bit_offset, uint32_t unaligned_bit_count,
2323 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);
2428uint64_t type_size(CodeGen *g, ZigType *type_entry);
2529uint64_t type_size_bits(CodeGen *g, ZigType *type_entry);
2630ZigType *get_int_type(CodeGen *g, bool is_signed, uint32_t size_in_bits);
src/codegen.cpp+30-13
......@@ -838,6 +838,11 @@ static LLVMValueRef get_handle_value(CodeGen *g, LLVMValueRef ptr, ZigType *type
838838 }
839839}
840840
841static void ir_assert(bool ok, IrInstruction *source_instruction) {
842 if (ok) return;
843 src_assert(ok, source_instruction->source_node);
844}
845
841846static bool ir_want_fast_math(CodeGen *g, IrInstruction *instruction) {
842847 // TODO memoize
843848 Scope *scope = instruction->scope;
......@@ -1695,11 +1700,11 @@ static LLVMValueRef ir_llvm_value(CodeGen *g, IrInstruction *instruction) {
16951700 }
16961701 if (instruction->spill != nullptr) {
16971702 ZigType *ptr_type = instruction->spill->value.type;
1698 src_assert(ptr_type->id == ZigTypeIdPointer, instruction->source_node);
1703 ir_assert(ptr_type->id == ZigTypeIdPointer, instruction);
16991704 return get_handle_value(g, ir_llvm_value(g, instruction->spill),
17001705 ptr_type->data.pointer.child_type, instruction->spill->value.type);
17011706 }
1702 src_assert(instruction->value.special != ConstValSpecialRuntime, instruction->source_node);
1707 ir_assert(instruction->value.special != ConstValSpecialRuntime, instruction);
17031708 assert(instruction->value.type);
17041709 render_const_val(g, &instruction->value, "");
17051710 // we might have to do some pointer casting here due to the way union
......@@ -2428,8 +2433,7 @@ static LLVMValueRef ir_render_return(CodeGen *g, IrExecutable *executable, IrIns
24282433 return nullptr;
24292434 }
24302435 assert(g->cur_ret_ptr);
2431 src_assert(instruction->operand->value.special != ConstValSpecialRuntime,
2432 instruction->base.source_node);
2436 ir_assert(instruction->operand->value.special != ConstValSpecialRuntime, &instruction->base);
24332437 LLVMValueRef value = ir_llvm_value(g, instruction->operand);
24342438 ZigType *return_type = instruction->operand->value.type;
24352439 gen_assign_raw(g, g->cur_ret_ptr, get_pointer_to_type(g, return_type, false), value);
......@@ -3399,7 +3403,9 @@ static LLVMValueRef ir_render_decl_var(CodeGen *g, IrExecutable *executable, IrI
33993403 return nullptr;
34003404}
34013405
3402static LLVMValueRef ir_render_load_ptr(CodeGen *g, IrExecutable *executable, IrInstructionLoadPtrGen *instruction) {
3406static LLVMValueRef ir_render_load_ptr(CodeGen *g, IrExecutable *executable,
3407 IrInstructionLoadPtrGen *instruction)
3408{
34033409 ZigType *child_type = instruction->base.value.type;
34043410 if (!type_has_bits(child_type))
34053411 return nullptr;
......@@ -3409,6 +3415,15 @@ static LLVMValueRef ir_render_load_ptr(CodeGen *g, IrExecutable *executable, IrI
34093415 assert(ptr_type->id == ZigTypeIdPointer);
34103416
34113417 uint32_t host_int_bytes = ptr_type->data.pointer.host_int_bytes;
3418
3419 ir_assert(ptr_type->data.pointer.vector_index != VECTOR_INDEX_RUNTIME, &instruction->base);
3420 if (ptr_type->data.pointer.vector_index != VECTOR_INDEX_NONE) {
3421 LLVMValueRef index_val = LLVMConstInt(LLVMInt32Type(),
3422 ptr_type->data.pointer.vector_index, false);
3423 LLVMValueRef loaded_vector = LLVMBuildLoad(g->builder, ptr, "");
3424 return LLVMBuildExtractElement(g->builder, loaded_vector, index_val, "");
3425 }
3426
34123427 if (host_int_bytes == 0)
34133428 return get_handle_value(g, ptr, child_type, ptr_type);
34143429
......@@ -3636,7 +3651,7 @@ static LLVMValueRef ir_render_return_ptr(CodeGen *g, IrExecutable *executable,
36363651{
36373652 if (!type_has_bits(instruction->base.value.type))
36383653 return nullptr;
3639 src_assert(g->cur_ret_ptr != nullptr, instruction->base.source_node);
3654 ir_assert(g->cur_ret_ptr != nullptr, &instruction->base);
36403655 return g->cur_ret_ptr;
36413656}
36423657
......@@ -3729,6 +3744,8 @@ static LLVMValueRef ir_render_elem_ptr(CodeGen *g, IrExecutable *executable, IrI
37293744 LLVMValueRef ptr_ptr = LLVMBuildStructGEP(g->builder, array_ptr, (unsigned)ptr_index, "");
37303745 LLVMValueRef ptr = gen_load_untyped(g, ptr_ptr, 0, false, "");
37313746 return LLVMBuildInBoundsGEP(g->builder, ptr, &subscript_value, 1, "");
3747 } else if (array_type->id == ZigTypeIdVector) {
3748 return array_ptr_ptr;
37323749 } else {
37333750 zig_unreachable();
37343751 }
......@@ -3917,9 +3934,9 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr
39173934 if (instruction->modifier == CallModifierAsync) {
39183935 frame_result_loc = result_loc;
39193936 } else {
3920 src_assert(instruction->frame_result_loc != nullptr, instruction->base.source_node);
3937 ir_assert(instruction->frame_result_loc != nullptr, &instruction->base);
39213938 frame_result_loc_uncasted = ir_llvm_value(g, instruction->frame_result_loc);
3922 src_assert(instruction->fn_entry != nullptr, instruction->base.source_node);
3939 ir_assert(instruction->fn_entry != nullptr, &instruction->base);
39233940 frame_result_loc = LLVMBuildBitCast(g->builder, frame_result_loc_uncasted,
39243941 LLVMPointerType(get_llvm_type(g, instruction->fn_entry->frame_type), 0), "");
39253942 }
......@@ -4271,10 +4288,10 @@ static LLVMValueRef ir_render_struct_field_ptr(CodeGen *g, IrExecutable *executa
42714288 if ((err = type_resolve(g, struct_type, ResolveStatusLLVMFull)))
42724289 codegen_report_errors_and_exit(g);
42734290
4274 src_assert(field->gen_index != SIZE_MAX, instruction->base.source_node);
4291 ir_assert(field->gen_index != SIZE_MAX, &instruction->base);
42754292 LLVMValueRef field_ptr_val = LLVMBuildStructGEP(g->builder, struct_ptr, (unsigned)field->gen_index, "");
42764293 ZigType *res_type = instruction->base.value.type;
4277 src_assert(res_type->id == ZigTypeIdPointer, instruction->base.source_node);
4294 ir_assert(res_type->id == ZigTypeIdPointer, &instruction->base);
42784295 if (res_type->data.pointer.host_int_bytes != 0) {
42794296 // We generate packed structs with get_llvm_type_of_n_bytes, which is
42804297 // u8 for 1 byte or [n]u8 for multiple bytes. But the pointer to the type
......@@ -4684,7 +4701,7 @@ static LLVMValueRef ir_render_shuffle_vector(CodeGen *g, IrExecutable *executabl
46844701
46854702static LLVMValueRef ir_render_splat(CodeGen *g, IrExecutable *executable, IrInstructionSplatGen *instruction) {
46864703 ZigType *result_type = instruction->base.value.type;
4687 src_assert(result_type->id == ZigTypeIdVector, instruction->base.source_node);
4704 ir_assert(result_type->id == ZigTypeIdVector, &instruction->base);
46884705 uint32_t len = result_type->data.vector.len;
46894706 LLVMTypeRef op_llvm_type = LLVMVectorType(get_llvm_type(g, instruction->scalar->value.type), 1);
46904707 LLVMTypeRef mask_llvm_type = LLVMVectorType(LLVMInt32Type(), len);
......@@ -5039,8 +5056,8 @@ static LLVMValueRef ir_render_cmpxchg(CodeGen *g, IrExecutable *executable, IrIn
50395056 }
50405057
50415058 LLVMValueRef result_loc = ir_llvm_value(g, instruction->result_loc);
5042 src_assert(result_loc != nullptr, instruction->base.source_node);
5043 src_assert(type_has_bits(child_type), instruction->base.source_node);
5059 ir_assert(result_loc != nullptr, &instruction->base);
5060 ir_assert(type_has_bits(child_type), &instruction->base);
50445061
50455062 LLVMValueRef payload_val = LLVMBuildExtractValue(g->builder, result_val, 0, "");
50465063 LLVMValueRef val_ptr = LLVMBuildStructGEP(g->builder, result_loc, maybe_child_index, "");
src/ir.cpp+40-8
......@@ -12908,18 +12908,18 @@ static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruc
1290812908 ResultLoc *result_loc)
1290912909{
1291012910 Error err;
12911 ZigType *type_entry = ptr->value.type;
12912 if (type_is_invalid(type_entry))
12911 ZigType *ptr_type = ptr->value.type;
12912 if (type_is_invalid(ptr_type))
1291312913 return ira->codegen->invalid_instruction;
1291412914
12915 if (type_entry->id != ZigTypeIdPointer) {
12915 if (ptr_type->id != ZigTypeIdPointer) {
1291612916 ir_add_error_node(ira, source_instruction->source_node,
1291712917 buf_sprintf("attempt to dereference non-pointer type '%s'",
12918 buf_ptr(&type_entry->name)));
12918 buf_ptr(&ptr_type->name)));
1291912919 return ira->codegen->invalid_instruction;
1292012920 }
1292112921
12922 ZigType *child_type = type_entry->data.pointer.child_type;
12922 ZigType *child_type = ptr_type->data.pointer.child_type;
1292312923 // if the child type has one possible value, the deref is comptime
1292412924 switch (type_has_one_possible_value(ira->codegen, child_type)) {
1292512925 case OnePossibleValueInvalid:
......@@ -12949,14 +12949,29 @@ static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruc
1294912949 }
1295012950 }
1295112951 }
12952
1295212953 // if the instruction is a const ref instruction we can skip it
1295312954 if (ptr->id == IrInstructionIdRef) {
1295412955 IrInstructionRef *ref_inst = reinterpret_cast<IrInstructionRef *>(ptr);
1295512956 return ref_inst->value;
1295612957 }
1295712958
12959 // If the instruction is a element pointer instruction to a vector, we emit
12960 // vector element extract instruction rather than load pointer. If the
12961 // pointer type has non-VECTOR_INDEX_RUNTIME value, it would have been
12962 // possible to implement this in the codegen for IrInstructionLoadPtrGen.
12963 // However if it has VECTOR_INDEX_RUNTIME then we must emit a compile error
12964 // if the vector index cannot be determined right here, right now, because
12965 // the type information does not contain enough information to actually
12966 // perform a dereference.
12967 if (ptr_type->data.pointer.vector_index == VECTOR_INDEX_RUNTIME) {
12968 ir_add_error(ira, ptr,
12969 buf_sprintf("unable to determine element index in order to dereference vector pointer"));
12970 return ira->codegen->invalid_instruction;
12971 }
12972
1295812973 IrInstruction *result_loc_inst;
12959 if (type_entry->data.pointer.host_int_bytes != 0 && handle_is_ptr(child_type)) {
12974 if (ptr_type->data.pointer.host_int_bytes != 0 && handle_is_ptr(child_type)) {
1296012975 if (result_loc == nullptr) result_loc = no_result_loc();
1296112976 result_loc_inst = ir_resolve_result(ira, source_instruction, result_loc, child_type, nullptr,
1296212977 true, false, true);
......@@ -17488,6 +17503,9 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct
1748817503 return ir_get_const_ptr(ira, &elem_ptr_instruction->base, &ira->codegen->const_void_val,
1748917504 ira->codegen->builtin_types.entry_void, ConstPtrMutComptimeConst, is_const, is_volatile, 0);
1749017505 }
17506 } else if (array_type->id == ZigTypeIdVector) {
17507 // This depends on whether the element index is comptime, so it is computed later.
17508 return_type = nullptr;
1749117509 } else {
1749217510 ir_add_error_node(ira, elem_ptr_instruction->base.source_node,
1749317511 buf_sprintf("array access of non-array type '%s'", buf_ptr(&array_type->name)));
......@@ -17512,8 +17530,14 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct
1751217530 }
1751317531 safety_check_on = false;
1751417532 }
17515
17516 if (return_type->data.pointer.explicit_alignment != 0) {
17533 if (array_type->id == ZigTypeIdVector) {
17534 ZigType *elem_type = array_type->data.vector.elem_type;
17535 uint32_t host_vec_len = array_type->data.vector.len;
17536 return_type = get_pointer_to_type_extra2(ira->codegen, elem_type,
17537 ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile,
17538 elem_ptr_instruction->ptr_len,
17539 get_ptr_align(ira->codegen, ptr_type), 0, host_vec_len, false, (uint32_t)index);
17540 } else if (return_type->data.pointer.explicit_alignment != 0) {
1751717541 // figure out the largest alignment possible
1751817542
1751917543 if ((err = type_resolve(ira->codegen, return_type->data.pointer.child_type, ResolveStatusSizeKnown)))
......@@ -17742,6 +17766,14 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct
1774217766 }
1774317767 }
1774417768 }
17769 } else if (array_type->id == ZigTypeIdVector) {
17770 // runtime known element index
17771 ZigType *elem_type = array_type->data.vector.elem_type;
17772 uint32_t host_vec_len = array_type->data.vector.len;
17773 return_type = get_pointer_to_type_extra2(ira->codegen, elem_type,
17774 ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile,
17775 elem_ptr_instruction->ptr_len,
17776 get_ptr_align(ira->codegen, ptr_type), 0, host_vec_len, false, VECTOR_INDEX_RUNTIME);
1774517777 } else {
1774617778 // runtime known element index
1774717779 switch (type_requires_comptime(ira->codegen, return_type)) {
test/stage1/behavior/vector.zig+17
......@@ -159,3 +159,20 @@ test "vector @splat" {
159159 S.doTheTest();
160160 comptime S.doTheTest();
161161}
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}