implement loading vector elements via runtime index

This commit is contained in:
Andrew Kelley 2019-11-01 22:57:19 -04:00
parent 76d188551e
commit 70be308c43
No known key found for this signature in database
GPG Key ID: 7C5F548F728501A9
6 changed files with 93 additions and 1 deletions

View File

@ -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,

View File

@ -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();
}

View File

@ -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:

View File

@ -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");
}

View File

@ -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{

View File

@ -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();
}