| author | |
| committer | |
| log | 70be308c4315c53d42889d568d5731ba227dcf88 |
| tree | 181b9f099af8dee8637535adfe87550f0355a2f3 |
| parent | 76d188551eb3f742c2feb086c8c51c6b0815184d |
| signature |
6 files changed, 93 insertions(+), 1 deletions(-)
src/all_types.hpp+8| ... | ... | @@ -2575,6 +2575,7 @@ enum IrInstructionId { |
| 2575 | 2575 | IrInstructionIdResume, |
| 2576 | 2576 | IrInstructionIdSpillBegin, |
| 2577 | 2577 | IrInstructionIdSpillEnd, |
| 2578 | IrInstructionIdVectorExtractElem, | |
| 2578 | 2579 | }; |
| 2579 | 2580 | |
| 2580 | 2581 | struct IrInstruction { |
| ... | ... | @@ -3902,6 +3903,13 @@ struct IrInstructionSpillEnd { |
| 3902 | 3903 | IrInstructionSpillBegin *begin; |
| 3903 | 3904 | }; |
| 3904 | 3905 | |
| 3906 | struct IrInstructionVectorExtractElem { | |
| 3907 | IrInstruction base; | |
| 3908 | ||
| 3909 | IrInstruction *vector; | |
| 3910 | IrInstruction *index; | |
| 3911 | }; | |
| 3912 | ||
| 3905 | 3913 | enum ResultLocId { |
| 3906 | 3914 | ResultLocIdInvalid, |
| 3907 | 3915 | ResultLocIdNone, |
src/codegen.cpp+10| ... | ... | @@ -6002,6 +6002,14 @@ static LLVMValueRef ir_render_spill_end(CodeGen *g, IrExecutable *executable, Ir |
| 6002 | 6002 | zig_unreachable(); |
| 6003 | 6003 | } |
| 6004 | 6004 | |
| 6005 | static LLVMValueRef ir_render_vector_extract_elem(CodeGen *g, IrExecutable *executable, | |
| 6006 | IrInstructionVectorExtractElem *instruction) | |
| 6007 | { | |
| 6008 | LLVMValueRef vector = ir_llvm_value(g, instruction->vector); | |
| 6009 | LLVMValueRef index = ir_llvm_value(g, instruction->index); | |
| 6010 | return LLVMBuildExtractElement(g->builder, vector, index, ""); | |
| 6011 | } | |
| 6012 | ||
| 6005 | 6013 | static void set_debug_location(CodeGen *g, IrInstruction *instruction) { |
| 6006 | 6014 | AstNode *source_node = instruction->source_node; |
| 6007 | 6015 | Scope *scope = instruction->scope; |
| ... | ... | @@ -6262,6 +6270,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, |
| 6262 | 6270 | return ir_render_shuffle_vector(g, executable, (IrInstructionShuffleVector *) instruction); |
| 6263 | 6271 | case IrInstructionIdSplatGen: |
| 6264 | 6272 | return ir_render_splat(g, executable, (IrInstructionSplatGen *) instruction); |
| 6273 | case IrInstructionIdVectorExtractElem: | |
| 6274 | return ir_render_vector_extract_elem(g, executable, (IrInstructionVectorExtractElem *) instruction); | |
| 6265 | 6275 | } |
| 6266 | 6276 | zig_unreachable(); |
| 6267 | 6277 | } |
src/ir.cpp+29-1| ... | ... | @@ -1083,6 +1083,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionSpillEnd *) { |
| 1083 | 1083 | return IrInstructionIdSpillEnd; |
| 1084 | 1084 | } |
| 1085 | 1085 | |
| 1086 | static constexpr IrInstructionId ir_instruction_id(IrInstructionVectorExtractElem *) { | |
| 1087 | return IrInstructionIdVectorExtractElem; | |
| 1088 | } | |
| 1089 | ||
| 1086 | 1090 | template<typename T> |
| 1087 | 1091 | static T *ir_create_instruction(IrBuilder *irb, Scope *scope, AstNode *source_node) { |
| 1088 | 1092 | const char *name = nullptr; |
| ... | ... | @@ -3419,6 +3423,21 @@ static IrInstruction *ir_build_spill_end(IrBuilder *irb, Scope *scope, AstNode * |
| 3419 | 3423 | return &instruction->base; |
| 3420 | 3424 | } |
| 3421 | 3425 | |
| 3426 | static IrInstruction *ir_build_vector_extract_elem(IrAnalyze *ira, IrInstruction *source_instruction, | |
| 3427 | IrInstruction *vector, IrInstruction *index) | |
| 3428 | { | |
| 3429 | IrInstructionVectorExtractElem *instruction = ir_build_instruction<IrInstructionVectorExtractElem>( | |
| 3430 | &ira->new_irb, source_instruction->scope, source_instruction->source_node); | |
| 3431 | instruction->base.value.type = vector->value.type->data.vector.elem_type; | |
| 3432 | instruction->vector = vector; | |
| 3433 | instruction->index = index; | |
| 3434 | ||
| 3435 | ir_ref_instruction(vector, ira->new_irb.current_basic_block); | |
| 3436 | ir_ref_instruction(index, ira->new_irb.current_basic_block); | |
| 3437 | ||
| 3438 | return &instruction->base; | |
| 3439 | } | |
| 3440 | ||
| 3422 | 3441 | static void ir_count_defers(IrBuilder *irb, Scope *inner_scope, Scope *outer_scope, size_t *results) { |
| 3423 | 3442 | results[ReturnKindUnconditional] = 0; |
| 3424 | 3443 | results[ReturnKindError] = 0; |
| ... | ... | @@ -12965,8 +12984,15 @@ static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruc |
| 12965 | 12984 | // the type information does not contain enough information to actually |
| 12966 | 12985 | // perform a dereference. |
| 12967 | 12986 | if (ptr_type->data.pointer.vector_index == VECTOR_INDEX_RUNTIME) { |
| 12987 | if (ptr->id == IrInstructionIdElemPtr) { | |
| 12988 | IrInstructionElemPtr *elem_ptr = (IrInstructionElemPtr *)ptr; | |
| 12989 | IrInstruction *vector_loaded = ir_get_deref(ira, elem_ptr->array_ptr, | |
| 12990 | elem_ptr->array_ptr, nullptr); | |
| 12991 | IrInstruction *elem_index = elem_ptr->elem_index; | |
| 12992 | return ir_build_vector_extract_elem(ira, source_instruction, vector_loaded, elem_index); | |
| 12993 | } | |
| 12968 | 12994 | ir_add_error(ira, ptr, |
| 12969 | buf_sprintf("unable to determine element index in order to dereference vector pointer")); | |
| 12995 | buf_sprintf("unable to determine vector element index of type '%s'", buf_ptr(&ptr_type->name))); | |
| 12970 | 12996 | return ira->codegen->invalid_instruction; |
| 12971 | 12997 | } |
| 12972 | 12998 | |
| ... | ... | @@ -26036,6 +26062,7 @@ static IrInstruction *ir_analyze_instruction_base(IrAnalyze *ira, IrInstruction |
| 26036 | 26062 | case IrInstructionIdFrameSizeGen: |
| 26037 | 26063 | case IrInstructionIdAwaitGen: |
| 26038 | 26064 | case IrInstructionIdSplatGen: |
| 26065 | case IrInstructionIdVectorExtractElem: | |
| 26039 | 26066 | zig_unreachable(); |
| 26040 | 26067 | |
| 26041 | 26068 | case IrInstructionIdReturn: |
| ... | ... | @@ -26571,6 +26598,7 @@ bool ir_has_side_effects(IrInstruction *instruction) { |
| 26571 | 26598 | case IrInstructionIdAllocaSrc: |
| 26572 | 26599 | case IrInstructionIdAllocaGen: |
| 26573 | 26600 | case IrInstructionIdSpillEnd: |
| 26601 | case IrInstructionIdVectorExtractElem: | |
| 26574 | 26602 | return false; |
| 26575 | 26603 | |
| 26576 | 26604 | case IrInstructionIdAsm: |
src/ir_print.cpp+13| ... | ... | @@ -370,6 +370,8 @@ const char* ir_instruction_type_str(IrInstructionId id) { |
| 370 | 370 | return "SpillBegin"; |
| 371 | 371 | case IrInstructionIdSpillEnd: |
| 372 | 372 | return "SpillEnd"; |
| 373 | case IrInstructionIdVectorExtractElem: | |
| 374 | return "VectorExtractElem"; | |
| 373 | 375 | } |
| 374 | 376 | zig_unreachable(); |
| 375 | 377 | } |
| ... | ... | @@ -1969,6 +1971,14 @@ static void ir_print_spill_end(IrPrint *irp, IrInstructionSpillEnd *instruction) |
| 1969 | 1971 | fprintf(irp->f, ")"); |
| 1970 | 1972 | } |
| 1971 | 1973 | |
| 1974 | static void ir_print_vector_extract_elem(IrPrint *irp, IrInstructionVectorExtractElem *instruction) { | |
| 1975 | fprintf(irp->f, "@vectorExtractElem("); | |
| 1976 | ir_print_other_instruction(irp, instruction->vector); | |
| 1977 | fprintf(irp->f, ","); | |
| 1978 | ir_print_other_instruction(irp, instruction->index); | |
| 1979 | fprintf(irp->f, ")"); | |
| 1980 | } | |
| 1981 | ||
| 1972 | 1982 | static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction, bool trailing) { |
| 1973 | 1983 | ir_print_prefix(irp, instruction, trailing); |
| 1974 | 1984 | switch (instruction->id) { |
| ... | ... | @@ -2466,6 +2476,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction, bool |
| 2466 | 2476 | case IrInstructionIdSpillEnd: |
| 2467 | 2477 | ir_print_spill_end(irp, (IrInstructionSpillEnd *)instruction); |
| 2468 | 2478 | break; |
| 2479 | case IrInstructionIdVectorExtractElem: | |
| 2480 | ir_print_vector_extract_elem(irp, (IrInstructionVectorExtractElem *)instruction); | |
| 2481 | break; | |
| 2469 | 2482 | } |
| 2470 | 2483 | fprintf(irp->f, "\n"); |
| 2471 | 2484 | } |
test/compile_errors.zig+16| ... | ... | @@ -24,6 +24,22 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 24 | 24 | "tmp.zig:4:20: note: referenced here", |
| 25 | 25 | ); |
| 26 | 26 | |
| 27 | cases.add( | |
| 28 | "dereference vector pointer with unknown runtime index", | |
| 29 | \\export fn entry() void { | |
| 30 | \\ var v: @Vector(4, i32) = [_]i32{ 1, 5, 3, undefined }; | |
| 31 | \\ | |
| 32 | \\ var i: u32 = 0; | |
| 33 | \\ var x = loadv(&v[i]); | |
| 34 | \\} | |
| 35 | \\ | |
| 36 | \\fn loadv(ptr: var) i32 { | |
| 37 | \\ return ptr.*; | |
| 38 | \\} | |
| 39 | , | |
| 40 | "tmp.zig:9:12: error: unable to determine vector element index of type '*align(16:0:4:?) i32", | |
| 41 | ); | |
| 42 | ||
| 27 | 43 | cases.add( |
| 28 | 44 | "using an unknown len ptr type instead of array", |
| 29 | 45 | \\const resolutions = [*][*]const u8{ |
test/stage1/behavior/vector.zig+17| ... | ... | @@ -199,3 +199,20 @@ test "store vector elements via comptime index" { |
| 199 | 199 | S.doTheTest(); |
| 200 | 200 | comptime S.doTheTest(); |
| 201 | 201 | } |
| 202 | ||
| 203 | test "load vector elements via runtime index" { | |
| 204 | const S = struct { | |
| 205 | fn doTheTest() void { | |
| 206 | var v: @Vector(4, i32) = [_]i32{ 1, 2, 3, undefined }; | |
| 207 | var i: u32 = 0; | |
| 208 | expect(v[i] == 1); | |
| 209 | i += 1; | |
| 210 | expect(v[i] == 2); | |
| 211 | i += 1; | |
| 212 | expect(v[i] == 3); | |
| 213 | } | |
| 214 | }; | |
| 215 | ||
| 216 | S.doTheTest(); | |
| 217 | comptime S.doTheTest(); | |
| 218 | } |