diff --git a/src/all_types.hpp b/src/all_types.hpp index 4cfaf836d4..ed6d05ac40 100644 --- a/src/all_types.hpp +++ b/src/all_types.hpp @@ -1183,13 +1183,22 @@ struct FnTypeId { uint32_t fn_type_id_hash(FnTypeId*); bool fn_type_id_eql(FnTypeId *a, FnTypeId *b); +static const uint32_t VECTOR_INDEX_NONE = UINT32_MAX; +static const uint32_t VECTOR_INDEX_RUNTIME = UINT32_MAX - 1; + struct ZigTypePointer { ZigType *child_type; ZigType *slice_parent; + PtrLen ptr_len; uint32_t explicit_alignment; // 0 means use ABI alignment + uint32_t bit_offset_in_host; - uint32_t host_int_bytes; // size of host integer. 0 means no host integer; this field is aligned + // size of host integer. 0 means no host integer; this field is aligned + // when vector_index != VECTOR_INDEX_NONE this is the len of the containing vector + uint32_t host_int_bytes; + + uint32_t vector_index; // see the VECTOR_INDEX_* constants bool is_const; bool is_volatile; bool allow_zero; @@ -1732,8 +1741,11 @@ struct TypeId { ZigType *child_type; PtrLen ptr_len; uint32_t alignment; + uint32_t bit_offset_in_host; uint32_t host_int_bytes; + + uint32_t vector_index; bool is_const; bool is_volatile; bool allow_zero; diff --git a/src/analyze.cpp b/src/analyze.cpp index 9c7ee3ca53..69eb76ca68 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -480,9 +480,10 @@ ZigType *get_fn_frame_type(CodeGen *g, ZigFn *fn) { return entry; } -ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_const, +ZigType *get_pointer_to_type_extra2(CodeGen *g, ZigType *child_type, bool is_const, bool is_volatile, PtrLen ptr_len, uint32_t byte_alignment, - uint32_t bit_offset_in_host, uint32_t host_int_bytes, bool allow_zero) + uint32_t bit_offset_in_host, uint32_t host_int_bytes, bool allow_zero, + uint32_t vector_index) { assert(ptr_len != PtrLenC || allow_zero); assert(!type_is_invalid(child_type)); @@ -494,7 +495,7 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons byte_alignment = 0; } - if (host_int_bytes != 0) { + if (host_int_bytes != 0 && vector_index == VECTOR_INDEX_NONE) { uint32_t child_type_bits = type_size_bits(g, child_type); if (host_int_bytes * 8 == child_type_bits) { assert(bit_offset_in_host == 0); @@ -504,7 +505,9 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons TypeId type_id = {}; ZigType **parent_pointer = nullptr; - if (host_int_bytes != 0 || is_volatile || byte_alignment != 0 || ptr_len != PtrLenSingle || allow_zero) { + if (host_int_bytes != 0 || is_volatile || byte_alignment != 0 || ptr_len != PtrLenSingle || + allow_zero || vector_index != VECTOR_INDEX_NONE) + { type_id.id = ZigTypeIdPointer; type_id.data.pointer.child_type = child_type; 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 type_id.data.pointer.host_int_bytes = host_int_bytes; type_id.data.pointer.ptr_len = ptr_len; type_id.data.pointer.allow_zero = allow_zero; + type_id.data.pointer.vector_index = vector_index; auto existing_entry = g->type_table.maybe_get(type_id); if (existing_entry) @@ -540,19 +544,36 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons allow_zero_str = allow_zero ? "allowzero " : ""; } buf_resize(&entry->name, 0); - if (host_int_bytes == 0 && byte_alignment == 0) { + if (host_int_bytes == 0 && byte_alignment == 0 && vector_index == VECTOR_INDEX_NONE) { buf_appendf(&entry->name, "%s%s%s%s%s", star_str, const_str, volatile_str, allow_zero_str, buf_ptr(&child_type->name)); - } else if (host_int_bytes == 0) { + } else if (host_int_bytes == 0 && vector_index == VECTOR_INDEX_NONE) { buf_appendf(&entry->name, "%salign(%" PRIu32 ") %s%s%s%s", star_str, byte_alignment, const_str, volatile_str, allow_zero_str, buf_ptr(&child_type->name)); } else if (byte_alignment == 0) { - buf_appendf(&entry->name, "%salign(:%" PRIu32 ":%" PRIu32 ") %s%s%s%s", star_str, - bit_offset_in_host, host_int_bytes, const_str, volatile_str, allow_zero_str, + assert(vector_index == VECTOR_INDEX_NONE); + buf_appendf(&entry->name, "%salign(:%" PRIu32 ":%" PRIu32 ":%" PRIu32 ") %s%s%s%s", + star_str, + bit_offset_in_host, host_int_bytes, vector_index, + const_str, volatile_str, allow_zero_str, + buf_ptr(&child_type->name)); + } else if (vector_index == VECTOR_INDEX_NONE) { + buf_appendf(&entry->name, "%salign(%" PRIu32 ":%" PRIu32 ":%" PRIu32 ") %s%s%s%s", + star_str, byte_alignment, + bit_offset_in_host, host_int_bytes, + const_str, volatile_str, allow_zero_str, + buf_ptr(&child_type->name)); + } else if (vector_index == VECTOR_INDEX_RUNTIME) { + buf_appendf(&entry->name, "%salign(%" PRIu32 ":%" PRIu32 ":%" PRIu32 ":?) %s%s%s%s", + star_str, byte_alignment, + bit_offset_in_host, host_int_bytes, + const_str, volatile_str, allow_zero_str, buf_ptr(&child_type->name)); } else { - buf_appendf(&entry->name, "%salign(%" PRIu32 ":%" PRIu32 ":%" PRIu32 ") %s%s%s%s", star_str, byte_alignment, - bit_offset_in_host, host_int_bytes, const_str, volatile_str, allow_zero_str, + buf_appendf(&entry->name, "%salign(%" PRIu32 ":%" PRIu32 ":%" PRIu32 ":%" PRIu32 ") %s%s%s%s", + star_str, byte_alignment, + bit_offset_in_host, host_int_bytes, vector_index, + const_str, volatile_str, allow_zero_str, buf_ptr(&child_type->name)); } @@ -581,6 +602,7 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons entry->data.pointer.bit_offset_in_host = bit_offset_in_host; entry->data.pointer.host_int_bytes = host_int_bytes; entry->data.pointer.allow_zero = allow_zero; + entry->data.pointer.vector_index = vector_index; if (parent_pointer) { *parent_pointer = entry; @@ -590,8 +612,17 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons return entry; } +ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_const, + bool is_volatile, PtrLen ptr_len, uint32_t byte_alignment, + uint32_t bit_offset_in_host, uint32_t host_int_bytes, bool allow_zero) +{ + return get_pointer_to_type_extra2(g, child_type, is_const, is_volatile, ptr_len, + byte_alignment, bit_offset_in_host, host_int_bytes, allow_zero, VECTOR_INDEX_NONE); +} + ZigType *get_pointer_to_type(CodeGen *g, ZigType *child_type, bool is_const) { - return get_pointer_to_type_extra(g, child_type, is_const, false, PtrLenSingle, 0, 0, 0, false); + return get_pointer_to_type_extra2(g, child_type, is_const, false, PtrLenSingle, 0, 0, 0, false, + VECTOR_INDEX_NONE); } ZigType *get_optional_type(CodeGen *g, ZigType *child_type) { @@ -6910,6 +6941,7 @@ uint32_t type_id_hash(TypeId x) { (x.data.pointer.allow_zero ? (uint32_t)3324284834 : (uint32_t)3584904923) + (((uint32_t)x.data.pointer.alignment) ^ (uint32_t)0x777fbe0e) + (((uint32_t)x.data.pointer.bit_offset_in_host) ^ (uint32_t)2639019452) + + (((uint32_t)x.data.pointer.vector_index) ^ (uint32_t)0x19199716) + (((uint32_t)x.data.pointer.host_int_bytes) ^ (uint32_t)529908881); case ZigTypeIdArray: return hash_ptr(x.data.array.child_type) + @@ -6962,6 +6994,7 @@ bool type_id_eql(TypeId a, TypeId b) { a.data.pointer.allow_zero == b.data.pointer.allow_zero && a.data.pointer.alignment == b.data.pointer.alignment && a.data.pointer.bit_offset_in_host == b.data.pointer.bit_offset_in_host && + a.data.pointer.vector_index == b.data.pointer.vector_index && a.data.pointer.host_int_bytes == b.data.pointer.host_int_bytes; case ZigTypeIdArray: 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 if (type->data.pointer.is_const || type->data.pointer.is_volatile || type->data.pointer.explicit_alignment != 0 || type->data.pointer.ptr_len != PtrLenSingle || - type->data.pointer.bit_offset_in_host != 0 || type->data.pointer.allow_zero) + type->data.pointer.bit_offset_in_host != 0 || type->data.pointer.allow_zero || + type->data.pointer.vector_index != VECTOR_INDEX_NONE) { assertNoError(type_resolve(g, elem_type, ResolveStatusLLVMFwdDecl)); - ZigType *peer_type = get_pointer_to_type_extra(g, elem_type, false, false, - PtrLenSingle, 0, 0, type->data.pointer.host_int_bytes, false); + ZigType *peer_type; + if (type->data.pointer.vector_index == VECTOR_INDEX_NONE) { + peer_type = get_pointer_to_type_extra2(g, elem_type, false, false, + PtrLenSingle, 0, 0, type->data.pointer.host_int_bytes, false, + VECTOR_INDEX_NONE); + } else { + uint32_t host_vec_len = type->data.pointer.host_int_bytes; + ZigType *host_vec_type = get_vector_type(g, host_vec_len, elem_type); + peer_type = get_pointer_to_type_extra2(g, host_vec_type, false, false, + PtrLenSingle, 0, 0, 0, false, VECTOR_INDEX_NONE); + } type->llvm_type = get_llvm_type(g, peer_type); type->llvm_di_type = get_llvm_di_type(g, peer_type); assertNoError(type_resolve(g, elem_type, wanted_resolve_status)); diff --git a/src/analyze.hpp b/src/analyze.hpp index 5168dd2d7d..a6af371e25 100644 --- a/src/analyze.hpp +++ b/src/analyze.hpp @@ -17,10 +17,14 @@ ErrorMsg *add_error_note(CodeGen *g, ErrorMsg *parent_msg, const AstNode *node, ZigType *new_type_table_entry(ZigTypeId id); ZigType *get_fn_frame_type(CodeGen *g, ZigFn *fn); ZigType *get_pointer_to_type(CodeGen *g, ZigType *child_type, bool is_const); -ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_const, - bool is_volatile, PtrLen ptr_len, +ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, + bool is_const, bool is_volatile, PtrLen ptr_len, uint32_t byte_alignment, uint32_t bit_offset, uint32_t unaligned_bit_count, bool allow_zero); +ZigType *get_pointer_to_type_extra2(CodeGen *g, ZigType *child_type, + bool is_const, bool is_volatile, PtrLen ptr_len, + uint32_t byte_alignment, uint32_t bit_offset, uint32_t unaligned_bit_count, + bool allow_zero, uint32_t vector_index); uint64_t type_size(CodeGen *g, ZigType *type_entry); uint64_t type_size_bits(CodeGen *g, ZigType *type_entry); ZigType *get_int_type(CodeGen *g, bool is_signed, uint32_t size_in_bits); diff --git a/src/codegen.cpp b/src/codegen.cpp index a172ca39a7..d05919cb95 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -838,6 +838,11 @@ static LLVMValueRef get_handle_value(CodeGen *g, LLVMValueRef ptr, ZigType *type } } +static void ir_assert(bool ok, IrInstruction *source_instruction) { + if (ok) return; + src_assert(ok, source_instruction->source_node); +} + static bool ir_want_fast_math(CodeGen *g, IrInstruction *instruction) { // TODO memoize Scope *scope = instruction->scope; @@ -1695,11 +1700,11 @@ static LLVMValueRef ir_llvm_value(CodeGen *g, IrInstruction *instruction) { } if (instruction->spill != nullptr) { ZigType *ptr_type = instruction->spill->value.type; - src_assert(ptr_type->id == ZigTypeIdPointer, instruction->source_node); + ir_assert(ptr_type->id == ZigTypeIdPointer, instruction); return get_handle_value(g, ir_llvm_value(g, instruction->spill), ptr_type->data.pointer.child_type, instruction->spill->value.type); } - src_assert(instruction->value.special != ConstValSpecialRuntime, instruction->source_node); + ir_assert(instruction->value.special != ConstValSpecialRuntime, instruction); assert(instruction->value.type); render_const_val(g, &instruction->value, ""); // 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 return nullptr; } assert(g->cur_ret_ptr); - src_assert(instruction->operand->value.special != ConstValSpecialRuntime, - instruction->base.source_node); + ir_assert(instruction->operand->value.special != ConstValSpecialRuntime, &instruction->base); LLVMValueRef value = ir_llvm_value(g, instruction->operand); ZigType *return_type = instruction->operand->value.type; 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 return nullptr; } -static LLVMValueRef ir_render_load_ptr(CodeGen *g, IrExecutable *executable, IrInstructionLoadPtrGen *instruction) { +static LLVMValueRef ir_render_load_ptr(CodeGen *g, IrExecutable *executable, + IrInstructionLoadPtrGen *instruction) +{ ZigType *child_type = instruction->base.value.type; if (!type_has_bits(child_type)) return nullptr; @@ -3409,6 +3415,15 @@ static LLVMValueRef ir_render_load_ptr(CodeGen *g, IrExecutable *executable, IrI assert(ptr_type->id == ZigTypeIdPointer); uint32_t host_int_bytes = ptr_type->data.pointer.host_int_bytes; + + ir_assert(ptr_type->data.pointer.vector_index != VECTOR_INDEX_RUNTIME, &instruction->base); + if (ptr_type->data.pointer.vector_index != VECTOR_INDEX_NONE) { + LLVMValueRef index_val = LLVMConstInt(LLVMInt32Type(), + ptr_type->data.pointer.vector_index, false); + LLVMValueRef loaded_vector = LLVMBuildLoad(g->builder, ptr, ""); + return LLVMBuildExtractElement(g->builder, loaded_vector, index_val, ""); + } + if (host_int_bytes == 0) return get_handle_value(g, ptr, child_type, ptr_type); @@ -3636,7 +3651,7 @@ static LLVMValueRef ir_render_return_ptr(CodeGen *g, IrExecutable *executable, { if (!type_has_bits(instruction->base.value.type)) return nullptr; - src_assert(g->cur_ret_ptr != nullptr, instruction->base.source_node); + ir_assert(g->cur_ret_ptr != nullptr, &instruction->base); return g->cur_ret_ptr; } @@ -3729,6 +3744,8 @@ static LLVMValueRef ir_render_elem_ptr(CodeGen *g, IrExecutable *executable, IrI LLVMValueRef ptr_ptr = LLVMBuildStructGEP(g->builder, array_ptr, (unsigned)ptr_index, ""); LLVMValueRef ptr = gen_load_untyped(g, ptr_ptr, 0, false, ""); return LLVMBuildInBoundsGEP(g->builder, ptr, &subscript_value, 1, ""); + } else if (array_type->id == ZigTypeIdVector) { + return array_ptr_ptr; } else { zig_unreachable(); } @@ -3917,9 +3934,9 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr if (instruction->modifier == CallModifierAsync) { frame_result_loc = result_loc; } else { - src_assert(instruction->frame_result_loc != nullptr, instruction->base.source_node); + ir_assert(instruction->frame_result_loc != nullptr, &instruction->base); frame_result_loc_uncasted = ir_llvm_value(g, instruction->frame_result_loc); - src_assert(instruction->fn_entry != nullptr, instruction->base.source_node); + ir_assert(instruction->fn_entry != nullptr, &instruction->base); frame_result_loc = LLVMBuildBitCast(g->builder, frame_result_loc_uncasted, LLVMPointerType(get_llvm_type(g, instruction->fn_entry->frame_type), 0), ""); } @@ -4271,10 +4288,10 @@ static LLVMValueRef ir_render_struct_field_ptr(CodeGen *g, IrExecutable *executa if ((err = type_resolve(g, struct_type, ResolveStatusLLVMFull))) codegen_report_errors_and_exit(g); - src_assert(field->gen_index != SIZE_MAX, instruction->base.source_node); + ir_assert(field->gen_index != SIZE_MAX, &instruction->base); LLVMValueRef field_ptr_val = LLVMBuildStructGEP(g->builder, struct_ptr, (unsigned)field->gen_index, ""); ZigType *res_type = instruction->base.value.type; - src_assert(res_type->id == ZigTypeIdPointer, instruction->base.source_node); + ir_assert(res_type->id == ZigTypeIdPointer, &instruction->base); if (res_type->data.pointer.host_int_bytes != 0) { // We generate packed structs with get_llvm_type_of_n_bytes, which is // 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 static LLVMValueRef ir_render_splat(CodeGen *g, IrExecutable *executable, IrInstructionSplatGen *instruction) { ZigType *result_type = instruction->base.value.type; - src_assert(result_type->id == ZigTypeIdVector, instruction->base.source_node); + ir_assert(result_type->id == ZigTypeIdVector, &instruction->base); uint32_t len = result_type->data.vector.len; LLVMTypeRef op_llvm_type = LLVMVectorType(get_llvm_type(g, instruction->scalar->value.type), 1); LLVMTypeRef mask_llvm_type = LLVMVectorType(LLVMInt32Type(), len); @@ -5039,8 +5056,8 @@ static LLVMValueRef ir_render_cmpxchg(CodeGen *g, IrExecutable *executable, IrIn } LLVMValueRef result_loc = ir_llvm_value(g, instruction->result_loc); - src_assert(result_loc != nullptr, instruction->base.source_node); - src_assert(type_has_bits(child_type), instruction->base.source_node); + ir_assert(result_loc != nullptr, &instruction->base); + ir_assert(type_has_bits(child_type), &instruction->base); LLVMValueRef payload_val = LLVMBuildExtractValue(g->builder, result_val, 0, ""); LLVMValueRef val_ptr = LLVMBuildStructGEP(g->builder, result_loc, maybe_child_index, ""); diff --git a/src/ir.cpp b/src/ir.cpp index d5633b0538..f47d5cf072 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -12908,18 +12908,18 @@ static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruc ResultLoc *result_loc) { Error err; - ZigType *type_entry = ptr->value.type; - if (type_is_invalid(type_entry)) + ZigType *ptr_type = ptr->value.type; + if (type_is_invalid(ptr_type)) return ira->codegen->invalid_instruction; - if (type_entry->id != ZigTypeIdPointer) { + if (ptr_type->id != ZigTypeIdPointer) { ir_add_error_node(ira, source_instruction->source_node, buf_sprintf("attempt to dereference non-pointer type '%s'", - buf_ptr(&type_entry->name))); + buf_ptr(&ptr_type->name))); return ira->codegen->invalid_instruction; } - ZigType *child_type = type_entry->data.pointer.child_type; + ZigType *child_type = ptr_type->data.pointer.child_type; // if the child type has one possible value, the deref is comptime switch (type_has_one_possible_value(ira->codegen, child_type)) { case OnePossibleValueInvalid: @@ -12949,14 +12949,29 @@ static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruc } } } + // if the instruction is a const ref instruction we can skip it if (ptr->id == IrInstructionIdRef) { IrInstructionRef *ref_inst = reinterpret_cast(ptr); return ref_inst->value; } + // If the instruction is a element pointer instruction to a vector, we emit + // vector element extract instruction rather than load pointer. If the + // pointer type has non-VECTOR_INDEX_RUNTIME value, it would have been + // possible to implement this in the codegen for IrInstructionLoadPtrGen. + // However if it has VECTOR_INDEX_RUNTIME then we must emit a compile error + // if the vector index cannot be determined right here, right now, because + // the type information does not contain enough information to actually + // perform a dereference. + if (ptr_type->data.pointer.vector_index == VECTOR_INDEX_RUNTIME) { + ir_add_error(ira, ptr, + buf_sprintf("unable to determine element index in order to dereference vector pointer")); + return ira->codegen->invalid_instruction; + } + IrInstruction *result_loc_inst; - if (type_entry->data.pointer.host_int_bytes != 0 && handle_is_ptr(child_type)) { + if (ptr_type->data.pointer.host_int_bytes != 0 && handle_is_ptr(child_type)) { if (result_loc == nullptr) result_loc = no_result_loc(); result_loc_inst = ir_resolve_result(ira, source_instruction, result_loc, child_type, nullptr, true, false, true); @@ -17488,6 +17503,9 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct return ir_get_const_ptr(ira, &elem_ptr_instruction->base, &ira->codegen->const_void_val, ira->codegen->builtin_types.entry_void, ConstPtrMutComptimeConst, is_const, is_volatile, 0); } + } else if (array_type->id == ZigTypeIdVector) { + // This depends on whether the element index is comptime, so it is computed later. + return_type = nullptr; } else { ir_add_error_node(ira, elem_ptr_instruction->base.source_node, 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 } safety_check_on = false; } - - if (return_type->data.pointer.explicit_alignment != 0) { + if (array_type->id == ZigTypeIdVector) { + ZigType *elem_type = array_type->data.vector.elem_type; + uint32_t host_vec_len = array_type->data.vector.len; + return_type = get_pointer_to_type_extra2(ira->codegen, elem_type, + ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile, + elem_ptr_instruction->ptr_len, + get_ptr_align(ira->codegen, ptr_type), 0, host_vec_len, false, (uint32_t)index); + } else if (return_type->data.pointer.explicit_alignment != 0) { // figure out the largest alignment possible 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 } } } + } else if (array_type->id == ZigTypeIdVector) { + // runtime known element index + ZigType *elem_type = array_type->data.vector.elem_type; + uint32_t host_vec_len = array_type->data.vector.len; + return_type = get_pointer_to_type_extra2(ira->codegen, elem_type, + ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile, + elem_ptr_instruction->ptr_len, + get_ptr_align(ira->codegen, ptr_type), 0, host_vec_len, false, VECTOR_INDEX_RUNTIME); } else { // runtime known element index switch (type_requires_comptime(ira->codegen, return_type)) { diff --git a/test/stage1/behavior/vector.zig b/test/stage1/behavior/vector.zig index 26f3b34038..3caa855bfd 100644 --- a/test/stage1/behavior/vector.zig +++ b/test/stage1/behavior/vector.zig @@ -159,3 +159,20 @@ test "vector @splat" { S.doTheTest(); comptime S.doTheTest(); } + +test "load vector elements via comptime index" { + const S = struct { + fn doTheTest() void { + var v: @Vector(4, i32) = [_]i32{ 1, 2, 3, undefined }; + expect(v[0] == 1); + expect(v[1] == 2); + expect(loadv(&v[2]) == 3); + } + fn loadv(ptr: var) i32 { + return ptr.*; + } + }; + + S.doTheTest(); + //comptime S.doTheTest(); +}