mirror of
https://github.com/ziglang/zig.git
synced 2026-02-14 21:38:33 +00:00
implement loading vector elements via runtime index
This commit is contained in:
parent
76d188551e
commit
70be308c43
@ -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,
|
||||
|
||||
@ -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();
|
||||
}
|
||||
|
||||
30
src/ir.cpp
30
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:
|
||||
|
||||
@ -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");
|
||||
}
|
||||
|
||||
@ -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{
|
||||
|
||||
@ -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();
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user