Commit 70be308c43
Changed files (6)
test
stage1
behavior
src/all_types.hpp
@@ -2575,6 +2575,7 @@ enum IrInstructionId {
IrInstructionIdResume,
IrInstructionIdSpillBegin,
IrInstructionIdSpillEnd,
+ IrInstructionIdVectorExtractElem,
};
struct IrInstruction {
@@ -3902,6 +3903,13 @@ struct IrInstructionSpillEnd {
IrInstructionSpillBegin *begin;
};
+struct IrInstructionVectorExtractElem {
+ IrInstruction base;
+
+ IrInstruction *vector;
+ IrInstruction *index;
+};
+
enum ResultLocId {
ResultLocIdInvalid,
ResultLocIdNone,
src/codegen.cpp
@@ -6002,6 +6002,14 @@ static LLVMValueRef ir_render_spill_end(CodeGen *g, IrExecutable *executable, Ir
zig_unreachable();
}
+static LLVMValueRef ir_render_vector_extract_elem(CodeGen *g, IrExecutable *executable,
+ IrInstructionVectorExtractElem *instruction)
+{
+ LLVMValueRef vector = ir_llvm_value(g, instruction->vector);
+ LLVMValueRef index = ir_llvm_value(g, instruction->index);
+ return LLVMBuildExtractElement(g->builder, vector, index, "");
+}
+
static void set_debug_location(CodeGen *g, IrInstruction *instruction) {
AstNode *source_node = instruction->source_node;
Scope *scope = instruction->scope;
@@ -6262,6 +6270,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
return ir_render_shuffle_vector(g, executable, (IrInstructionShuffleVector *) instruction);
case IrInstructionIdSplatGen:
return ir_render_splat(g, executable, (IrInstructionSplatGen *) instruction);
+ case IrInstructionIdVectorExtractElem:
+ return ir_render_vector_extract_elem(g, executable, (IrInstructionVectorExtractElem *) instruction);
}
zig_unreachable();
}
src/ir.cpp
@@ -1083,6 +1083,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionSpillEnd *) {
return IrInstructionIdSpillEnd;
}
+static constexpr IrInstructionId ir_instruction_id(IrInstructionVectorExtractElem *) {
+ return IrInstructionIdVectorExtractElem;
+}
+
template<typename T>
static T *ir_create_instruction(IrBuilder *irb, Scope *scope, AstNode *source_node) {
const char *name = nullptr;
@@ -3419,6 +3423,21 @@ static IrInstruction *ir_build_spill_end(IrBuilder *irb, Scope *scope, AstNode *
return &instruction->base;
}
+static IrInstruction *ir_build_vector_extract_elem(IrAnalyze *ira, IrInstruction *source_instruction,
+ IrInstruction *vector, IrInstruction *index)
+{
+ IrInstructionVectorExtractElem *instruction = ir_build_instruction<IrInstructionVectorExtractElem>(
+ &ira->new_irb, source_instruction->scope, source_instruction->source_node);
+ instruction->base.value.type = vector->value.type->data.vector.elem_type;
+ instruction->vector = vector;
+ instruction->index = index;
+
+ ir_ref_instruction(vector, ira->new_irb.current_basic_block);
+ ir_ref_instruction(index, ira->new_irb.current_basic_block);
+
+ return &instruction->base;
+}
+
static void ir_count_defers(IrBuilder *irb, Scope *inner_scope, Scope *outer_scope, size_t *results) {
results[ReturnKindUnconditional] = 0;
results[ReturnKindError] = 0;
@@ -12965,8 +12984,15 @@ static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruc
// the type information does not contain enough information to actually
// perform a dereference.
if (ptr_type->data.pointer.vector_index == VECTOR_INDEX_RUNTIME) {
+ if (ptr->id == IrInstructionIdElemPtr) {
+ IrInstructionElemPtr *elem_ptr = (IrInstructionElemPtr *)ptr;
+ IrInstruction *vector_loaded = ir_get_deref(ira, elem_ptr->array_ptr,
+ elem_ptr->array_ptr, nullptr);
+ IrInstruction *elem_index = elem_ptr->elem_index;
+ return ir_build_vector_extract_elem(ira, source_instruction, vector_loaded, elem_index);
+ }
ir_add_error(ira, ptr,
- buf_sprintf("unable to determine element index in order to dereference vector pointer"));
+ buf_sprintf("unable to determine vector element index of type '%s'", buf_ptr(&ptr_type->name)));
return ira->codegen->invalid_instruction;
}
@@ -26036,6 +26062,7 @@ static IrInstruction *ir_analyze_instruction_base(IrAnalyze *ira, IrInstruction
case IrInstructionIdFrameSizeGen:
case IrInstructionIdAwaitGen:
case IrInstructionIdSplatGen:
+ case IrInstructionIdVectorExtractElem:
zig_unreachable();
case IrInstructionIdReturn:
@@ -26571,6 +26598,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {
case IrInstructionIdAllocaSrc:
case IrInstructionIdAllocaGen:
case IrInstructionIdSpillEnd:
+ case IrInstructionIdVectorExtractElem:
return false;
case IrInstructionIdAsm:
src/ir_print.cpp
@@ -370,6 +370,8 @@ const char* ir_instruction_type_str(IrInstructionId id) {
return "SpillBegin";
case IrInstructionIdSpillEnd:
return "SpillEnd";
+ case IrInstructionIdVectorExtractElem:
+ return "VectorExtractElem";
}
zig_unreachable();
}
@@ -1969,6 +1971,14 @@ static void ir_print_spill_end(IrPrint *irp, IrInstructionSpillEnd *instruction)
fprintf(irp->f, ")");
}
+static void ir_print_vector_extract_elem(IrPrint *irp, IrInstructionVectorExtractElem *instruction) {
+ fprintf(irp->f, "@vectorExtractElem(");
+ ir_print_other_instruction(irp, instruction->vector);
+ fprintf(irp->f, ",");
+ ir_print_other_instruction(irp, instruction->index);
+ fprintf(irp->f, ")");
+}
+
static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction, bool trailing) {
ir_print_prefix(irp, instruction, trailing);
switch (instruction->id) {
@@ -2466,6 +2476,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction, bool
case IrInstructionIdSpillEnd:
ir_print_spill_end(irp, (IrInstructionSpillEnd *)instruction);
break;
+ case IrInstructionIdVectorExtractElem:
+ ir_print_vector_extract_elem(irp, (IrInstructionVectorExtractElem *)instruction);
+ break;
}
fprintf(irp->f, "\n");
}
test/stage1/behavior/vector.zig
@@ -199,3 +199,20 @@ test "store vector elements via comptime index" {
S.doTheTest();
comptime S.doTheTest();
}
+
+test "load vector elements via runtime index" {
+ const S = struct {
+ fn doTheTest() void {
+ var v: @Vector(4, i32) = [_]i32{ 1, 2, 3, undefined };
+ var i: u32 = 0;
+ expect(v[i] == 1);
+ i += 1;
+ expect(v[i] == 2);
+ i += 1;
+ expect(v[i] == 3);
+ }
+ };
+
+ S.doTheTest();
+ comptime S.doTheTest();
+}
test/compile_errors.zig
@@ -24,6 +24,22 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
"tmp.zig:4:20: note: referenced here",
);
+ cases.add(
+ "dereference vector pointer with unknown runtime index",
+ \\export fn entry() void {
+ \\ var v: @Vector(4, i32) = [_]i32{ 1, 5, 3, undefined };
+ \\
+ \\ var i: u32 = 0;
+ \\ var x = loadv(&v[i]);
+ \\}
+ \\
+ \\fn loadv(ptr: var) i32 {
+ \\ return ptr.*;
+ \\}
+ ,
+ "tmp.zig:9:12: error: unable to determine vector element index of type '*align(16:0:4:?) i32",
+ );
+
cases.add(
"using an unknown len ptr type instead of array",
\\const resolutions = [*][*]const u8{