| author | |
| committer | |
| log | 70be308c4315c53d42889d568d5731ba227dcf88 |
| tree | 181b9f099af8dee8637535adfe87550f0355a2f3 |
| parent | 76d188551eb3f742c2feb086c8c51c6b0815184d |
| signature | Commit is signed but in an unrecognized format. |
6 files changed, 93 insertions(+), 1 deletions(-)
src/all_types.hpp+8| ... | @@ -2575,6 +2575,7 @@ enum IrInstructionId { | ... | @@ -2575,6 +2575,7 @@ enum IrInstructionId { |
| 2575 | IrInstructionIdResume, | 2575 | IrInstructionIdResume, |
| 2576 | IrInstructionIdSpillBegin, | 2576 | IrInstructionIdSpillBegin, |
| 2577 | IrInstructionIdSpillEnd, | 2577 | IrInstructionIdSpillEnd, |
| 2578 | IrInstructionIdVectorExtractElem, | ||
| 2578 | }; | 2579 | }; |
| 2579 | 2580 | ||
| 2580 | struct IrInstruction { | 2581 | struct IrInstruction { |
| ... | @@ -3902,6 +3903,13 @@ struct IrInstructionSpillEnd { | ... | @@ -3902,6 +3903,13 @@ struct IrInstructionSpillEnd { |
| 3902 | IrInstructionSpillBegin *begin; | 3903 | IrInstructionSpillBegin *begin; |
| 3903 | }; | 3904 | }; |
| 3904 | 3905 | ||
| 3906 | struct IrInstructionVectorExtractElem { | ||
| 3907 | IrInstruction base; | ||
| 3908 | |||
| 3909 | IrInstruction *vector; | ||
| 3910 | IrInstruction *index; | ||
| 3911 | }; | ||
| 3912 | |||
| 3905 | enum ResultLocId { | 3913 | enum ResultLocId { |
| 3906 | ResultLocIdInvalid, | 3914 | ResultLocIdInvalid, |
| 3907 | ResultLocIdNone, | 3915 | ResultLocIdNone, |
src/codegen.cpp+10| ... | @@ -6002,6 +6002,14 @@ static LLVMValueRef ir_render_spill_end(CodeGen *g, IrExecutable *executable, Ir | ... | @@ -6002,6 +6002,14 @@ static LLVMValueRef ir_render_spill_end(CodeGen *g, IrExecutable *executable, Ir |
| 6002 | zig_unreachable(); | 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 | static void set_debug_location(CodeGen *g, IrInstruction *instruction) { | 6013 | static void set_debug_location(CodeGen *g, IrInstruction *instruction) { |
| 6006 | AstNode *source_node = instruction->source_node; | 6014 | AstNode *source_node = instruction->source_node; |
| 6007 | Scope *scope = instruction->scope; | 6015 | Scope *scope = instruction->scope; |
| ... | @@ -6262,6 +6270,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, | ... | @@ -6262,6 +6270,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, |
| 6262 | return ir_render_shuffle_vector(g, executable, (IrInstructionShuffleVector *) instruction); | 6270 | return ir_render_shuffle_vector(g, executable, (IrInstructionShuffleVector *) instruction); |
| 6263 | case IrInstructionIdSplatGen: | 6271 | case IrInstructionIdSplatGen: |
| 6264 | return ir_render_splat(g, executable, (IrInstructionSplatGen *) instruction); | 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 | zig_unreachable(); | 6276 | zig_unreachable(); |
| 6267 | } | 6277 | } |
src/ir.cpp+29-1| ... | @@ -1083,6 +1083,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionSpillEnd *) { | ... | @@ -1083,6 +1083,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionSpillEnd *) { |
| 1083 | return IrInstructionIdSpillEnd; | 1083 | return IrInstructionIdSpillEnd; |
| 1084 | } | 1084 | } |
| 1085 | 1085 | ||
| 1086 | static constexpr IrInstructionId ir_instruction_id(IrInstructionVectorExtractElem *) { | ||
| 1087 | return IrInstructionIdVectorExtractElem; | ||
| 1088 | } | ||
| 1089 | |||
| 1086 | template<typename T> | 1090 | template<typename T> |
| 1087 | static T *ir_create_instruction(IrBuilder *irb, Scope *scope, AstNode *source_node) { | 1091 | static T *ir_create_instruction(IrBuilder *irb, Scope *scope, AstNode *source_node) { |
| 1088 | const char *name = nullptr; | 1092 | const char *name = nullptr; |
| ... | @@ -3419,6 +3423,21 @@ static IrInstruction *ir_build_spill_end(IrBuilder *irb, Scope *scope, AstNode * | ... | @@ -3419,6 +3423,21 @@ static IrInstruction *ir_build_spill_end(IrBuilder *irb, Scope *scope, AstNode * |
| 3419 | return &instruction->base; | 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 | static void ir_count_defers(IrBuilder *irb, Scope *inner_scope, Scope *outer_scope, size_t *results) { | 3441 | static void ir_count_defers(IrBuilder *irb, Scope *inner_scope, Scope *outer_scope, size_t *results) { |
| 3423 | results[ReturnKindUnconditional] = 0; | 3442 | results[ReturnKindUnconditional] = 0; |
| 3424 | results[ReturnKindError] = 0; | 3443 | results[ReturnKindError] = 0; |
| ... | @@ -12965,8 +12984,15 @@ static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruc | ... | @@ -12965,8 +12984,15 @@ static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruc |
| 12965 | // the type information does not contain enough information to actually | 12984 | // the type information does not contain enough information to actually |
| 12966 | // perform a dereference. | 12985 | // perform a dereference. |
| 12967 | if (ptr_type->data.pointer.vector_index == VECTOR_INDEX_RUNTIME) { | 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 | ir_add_error(ira, ptr, | 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 | return ira->codegen->invalid_instruction; | 12996 | return ira->codegen->invalid_instruction; |
| 12971 | } | 12997 | } |
| 12972 | 12998 | ||
| ... | @@ -26036,6 +26062,7 @@ static IrInstruction *ir_analyze_instruction_base(IrAnalyze *ira, IrInstruction | ... | @@ -26036,6 +26062,7 @@ static IrInstruction *ir_analyze_instruction_base(IrAnalyze *ira, IrInstruction |
| 26036 | case IrInstructionIdFrameSizeGen: | 26062 | case IrInstructionIdFrameSizeGen: |
| 26037 | case IrInstructionIdAwaitGen: | 26063 | case IrInstructionIdAwaitGen: |
| 26038 | case IrInstructionIdSplatGen: | 26064 | case IrInstructionIdSplatGen: |
| 26065 | case IrInstructionIdVectorExtractElem: | ||
| 26039 | zig_unreachable(); | 26066 | zig_unreachable(); |
| 26040 | 26067 | ||
| 26041 | case IrInstructionIdReturn: | 26068 | case IrInstructionIdReturn: |
| ... | @@ -26571,6 +26598,7 @@ bool ir_has_side_effects(IrInstruction *instruction) { | ... | @@ -26571,6 +26598,7 @@ bool ir_has_side_effects(IrInstruction *instruction) { |
| 26571 | case IrInstructionIdAllocaSrc: | 26598 | case IrInstructionIdAllocaSrc: |
| 26572 | case IrInstructionIdAllocaGen: | 26599 | case IrInstructionIdAllocaGen: |
| 26573 | case IrInstructionIdSpillEnd: | 26600 | case IrInstructionIdSpillEnd: |
| 26601 | case IrInstructionIdVectorExtractElem: | ||
| 26574 | return false; | 26602 | return false; |
| 26575 | 26603 | ||
| 26576 | case IrInstructionIdAsm: | 26604 | case IrInstructionIdAsm: |
src/ir_print.cpp+13| ... | @@ -370,6 +370,8 @@ const char* ir_instruction_type_str(IrInstructionId id) { | ... | @@ -370,6 +370,8 @@ const char* ir_instruction_type_str(IrInstructionId id) { |
| 370 | return "SpillBegin"; | 370 | return "SpillBegin"; |
| 371 | case IrInstructionIdSpillEnd: | 371 | case IrInstructionIdSpillEnd: |
| 372 | return "SpillEnd"; | 372 | return "SpillEnd"; |
| 373 | case IrInstructionIdVectorExtractElem: | ||
| 374 | return "VectorExtractElem"; | ||
| 373 | } | 375 | } |
| 374 | zig_unreachable(); | 376 | zig_unreachable(); |
| 375 | } | 377 | } |
| ... | @@ -1969,6 +1971,14 @@ static void ir_print_spill_end(IrPrint *irp, IrInstructionSpillEnd *instruction) | ... | @@ -1969,6 +1971,14 @@ static void ir_print_spill_end(IrPrint *irp, IrInstructionSpillEnd *instruction) |
| 1969 | fprintf(irp->f, ")"); | 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 | static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction, bool trailing) { | 1982 | static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction, bool trailing) { |
| 1973 | ir_print_prefix(irp, instruction, trailing); | 1983 | ir_print_prefix(irp, instruction, trailing); |
| 1974 | switch (instruction->id) { | 1984 | switch (instruction->id) { |
| ... | @@ -2466,6 +2476,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction, bool | ... | @@ -2466,6 +2476,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction, bool |
| 2466 | case IrInstructionIdSpillEnd: | 2476 | case IrInstructionIdSpillEnd: |
| 2467 | ir_print_spill_end(irp, (IrInstructionSpillEnd *)instruction); | 2477 | ir_print_spill_end(irp, (IrInstructionSpillEnd *)instruction); |
| 2468 | break; | 2478 | break; |
| 2479 | case IrInstructionIdVectorExtractElem: | ||
| 2480 | ir_print_vector_extract_elem(irp, (IrInstructionVectorExtractElem *)instruction); | ||
| 2481 | break; | ||
| 2469 | } | 2482 | } |
| 2470 | fprintf(irp->f, "\n"); | 2483 | fprintf(irp->f, "\n"); |
| 2471 | } | 2484 | } |
test/compile_errors.zig+16| ... | @@ -24,6 +24,22 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { | ... | @@ -24,6 +24,22 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 24 | "tmp.zig:4:20: note: referenced here", | 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 | cases.add( | 43 | cases.add( |
| 28 | "using an unknown len ptr type instead of array", | 44 | "using an unknown len ptr type instead of array", |
| 29 | \\const resolutions = [*][*]const u8{ | 45 | \\const resolutions = [*][*]const u8{ |
test/stage1/behavior/vector.zig+17| ... | @@ -199,3 +199,20 @@ test "store vector elements via comptime index" { | ... | @@ -199,3 +199,20 @@ test "store vector elements via comptime index" { |
| 199 | S.doTheTest(); | 199 | S.doTheTest(); |
| 200 | comptime S.doTheTest(); | 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 | } |