authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-11-01 23:16:49-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-11-05 12:11:57-05:00
logcbaa10fc3bcd2d5f8d48b9038e840ae508fe2822
treed5dbbb0d4edee73b54dbd03802ab6885d5699a99
parent70be308c4315c53d42889d568d5731ba227dcf88
signaturelock-open Commit is signed but in an unrecognized format.

implement storing vector elements via runtime index


6 files changed, 114 insertions(+), 0 deletions(-)

src/all_types.hpp+9
...@@ -2426,6 +2426,7 @@ enum IrInstructionId {...@@ -2426,6 +2426,7 @@ enum IrInstructionId {
2426 IrInstructionIdLoadPtr,2426 IrInstructionIdLoadPtr,
2427 IrInstructionIdLoadPtrGen,2427 IrInstructionIdLoadPtrGen,
2428 IrInstructionIdStorePtr,2428 IrInstructionIdStorePtr,
2429 IrInstructionIdVectorStoreElem,
2429 IrInstructionIdFieldPtr,2430 IrInstructionIdFieldPtr,
2430 IrInstructionIdStructFieldPtr,2431 IrInstructionIdStructFieldPtr,
2431 IrInstructionIdUnionFieldPtr,2432 IrInstructionIdUnionFieldPtr,
...@@ -2770,6 +2771,14 @@ struct IrInstructionStorePtr {...@@ -2770,6 +2771,14 @@ struct IrInstructionStorePtr {
2770 IrInstruction *value;2771 IrInstruction *value;
2771};2772};
27722773
2774struct IrInstructionVectorStoreElem {
2775 IrInstruction base;
2776
2777 IrInstruction *vector_ptr;
2778 IrInstruction *index;
2779 IrInstruction *value;
2780};
2781
2773struct IrInstructionFieldPtr {2782struct IrInstructionFieldPtr {
2774 IrInstruction base;2783 IrInstruction base;
27752784
src/codegen.cpp+15
...@@ -3644,6 +3644,19 @@ static LLVMValueRef ir_render_store_ptr(CodeGen *g, IrExecutable *executable, Ir...@@ -3644,6 +3644,19 @@ static LLVMValueRef ir_render_store_ptr(CodeGen *g, IrExecutable *executable, Ir
3644 return nullptr;3644 return nullptr;
3645}3645}
36463646
3647static LLVMValueRef ir_render_vector_store_elem(CodeGen *g, IrExecutable *executable,
3648 IrInstructionVectorStoreElem *instruction)
3649{
3650 LLVMValueRef vector_ptr = ir_llvm_value(g, instruction->vector_ptr);
3651 LLVMValueRef index = ir_llvm_value(g, instruction->index);
3652 LLVMValueRef value = ir_llvm_value(g, instruction->value);
3653
3654 LLVMValueRef loaded_vector = gen_load(g, vector_ptr, instruction->vector_ptr->value.type, "");
3655 LLVMValueRef modified_vector = LLVMBuildInsertElement(g->builder, loaded_vector, value, index, "");
3656 gen_store(g, modified_vector, vector_ptr, instruction->vector_ptr->value.type);
3657 return nullptr;
3658}
3659
3647static LLVMValueRef ir_render_var_ptr(CodeGen *g, IrExecutable *executable, IrInstructionVarPtr *instruction) {3660static LLVMValueRef ir_render_var_ptr(CodeGen *g, IrExecutable *executable, IrInstructionVarPtr *instruction) {
3648 if (instruction->base.value.special != ConstValSpecialRuntime)3661 if (instruction->base.value.special != ConstValSpecialRuntime)
3649 return ir_llvm_value(g, &instruction->base);3662 return ir_llvm_value(g, &instruction->base);
...@@ -6130,6 +6143,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,...@@ -6130,6 +6143,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
6130 return ir_render_load_ptr(g, executable, (IrInstructionLoadPtrGen *)instruction);6143 return ir_render_load_ptr(g, executable, (IrInstructionLoadPtrGen *)instruction);
6131 case IrInstructionIdStorePtr:6144 case IrInstructionIdStorePtr:
6132 return ir_render_store_ptr(g, executable, (IrInstructionStorePtr *)instruction);6145 return ir_render_store_ptr(g, executable, (IrInstructionStorePtr *)instruction);
6146 case IrInstructionIdVectorStoreElem:
6147 return ir_render_vector_store_elem(g, executable, (IrInstructionVectorStoreElem *)instruction);
6133 case IrInstructionIdVarPtr:6148 case IrInstructionIdVarPtr:
6134 return ir_render_var_ptr(g, executable, (IrInstructionVarPtr *)instruction);6149 return ir_render_var_ptr(g, executable, (IrInstructionVarPtr *)instruction);
6135 case IrInstructionIdReturnPtr:6150 case IrInstructionIdReturnPtr:
src/ir.cpp+41
...@@ -491,6 +491,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionStorePtr *) {...@@ -491,6 +491,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionStorePtr *) {
491 return IrInstructionIdStorePtr;491 return IrInstructionIdStorePtr;
492}492}
493493
494static constexpr IrInstructionId ir_instruction_id(IrInstructionVectorStoreElem *) {
495 return IrInstructionIdVectorStoreElem;
496}
497
494static constexpr IrInstructionId ir_instruction_id(IrInstructionFieldPtr *) {498static constexpr IrInstructionId ir_instruction_id(IrInstructionFieldPtr *) {
495 return IrInstructionIdFieldPtr;499 return IrInstructionIdFieldPtr;
496}500}
...@@ -1631,6 +1635,23 @@ static IrInstructionStorePtr *ir_build_store_ptr(IrBuilder *irb, Scope *scope, A...@@ -1631,6 +1635,23 @@ static IrInstructionStorePtr *ir_build_store_ptr(IrBuilder *irb, Scope *scope, A
1631 return instruction;1635 return instruction;
1632}1636}
16331637
1638static IrInstruction *ir_build_vector_store_elem(IrAnalyze *ira, IrInstruction *source_instruction,
1639 IrInstruction *vector_ptr, IrInstruction *index, IrInstruction *value)
1640{
1641 IrInstructionVectorStoreElem *inst = ir_build_instruction<IrInstructionVectorStoreElem>(
1642 &ira->new_irb, source_instruction->scope, source_instruction->source_node);
1643 inst->base.value.type = ira->codegen->builtin_types.entry_void;
1644 inst->vector_ptr = vector_ptr;
1645 inst->index = index;
1646 inst->value = value;
1647
1648 ir_ref_instruction(vector_ptr, ira->new_irb.current_basic_block);
1649 ir_ref_instruction(index, ira->new_irb.current_basic_block);
1650 ir_ref_instruction(value, ira->new_irb.current_basic_block);
1651
1652 return &inst->base;
1653}
1654
1634static IrInstruction *ir_build_var_decl_src(IrBuilder *irb, Scope *scope, AstNode *source_node,1655static IrInstruction *ir_build_var_decl_src(IrBuilder *irb, Scope *scope, AstNode *source_node,
1635 ZigVar *var, IrInstruction *align_value, IrInstruction *ptr)1656 ZigVar *var, IrInstruction *align_value, IrInstruction *ptr)
1636{1657{
...@@ -16126,6 +16147,24 @@ static IrInstruction *ir_analyze_store_ptr(IrAnalyze *ira, IrInstruction *source...@@ -16126,6 +16147,24 @@ static IrInstruction *ir_analyze_store_ptr(IrAnalyze *ira, IrInstruction *source
16126 mark_comptime_value_escape(ira, source_instr, &value->value);16147 mark_comptime_value_escape(ira, source_instr, &value->value);
16127 }16148 }
1612816149
16150 // If this is a store to a pointer with a runtime-known vector index,
16151 // we have to figure out the IrInstruction which represents the index and
16152 // emit a IrInstructionVectorStoreElem, or emit a compile error
16153 // explaining why it is impossible for this store to work. Which is that
16154 // the pointer address is of the vector; without the element index being known
16155 // we cannot properly perform the insertion.
16156 if (ptr->value.type->data.pointer.vector_index == VECTOR_INDEX_RUNTIME) {
16157 if (ptr->id == IrInstructionIdElemPtr) {
16158 IrInstructionElemPtr *elem_ptr = (IrInstructionElemPtr *)ptr;
16159 return ir_build_vector_store_elem(ira, source_instr, elem_ptr->array_ptr,
16160 elem_ptr->elem_index, value);
16161 }
16162 ir_add_error(ira, ptr,
16163 buf_sprintf("unable to determine vector element index of type '%s'",
16164 buf_ptr(&ptr->value.type->name)));
16165 return ira->codegen->invalid_instruction;
16166 }
16167
16129 IrInstructionStorePtr *store_ptr = ir_build_store_ptr(&ira->new_irb, source_instr->scope,16168 IrInstructionStorePtr *store_ptr = ir_build_store_ptr(&ira->new_irb, source_instr->scope,
16130 source_instr->source_node, ptr, value);16169 source_instr->source_node, ptr, value);
16131 return &store_ptr->base;16170 return &store_ptr->base;
...@@ -26063,6 +26102,7 @@ static IrInstruction *ir_analyze_instruction_base(IrAnalyze *ira, IrInstruction...@@ -26063,6 +26102,7 @@ static IrInstruction *ir_analyze_instruction_base(IrAnalyze *ira, IrInstruction
26063 case IrInstructionIdAwaitGen:26102 case IrInstructionIdAwaitGen:
26064 case IrInstructionIdSplatGen:26103 case IrInstructionIdSplatGen:
26065 case IrInstructionIdVectorExtractElem:26104 case IrInstructionIdVectorExtractElem:
26105 case IrInstructionIdVectorStoreElem:
26066 zig_unreachable();26106 zig_unreachable();
2606726107
26068 case IrInstructionIdReturn:26108 case IrInstructionIdReturn:
...@@ -26446,6 +26486,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {...@@ -26446,6 +26486,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {
26446 case IrInstructionIdDeclVarSrc:26486 case IrInstructionIdDeclVarSrc:
26447 case IrInstructionIdDeclVarGen:26487 case IrInstructionIdDeclVarGen:
26448 case IrInstructionIdStorePtr:26488 case IrInstructionIdStorePtr:
26489 case IrInstructionIdVectorStoreElem:
26449 case IrInstructionIdCallSrc:26490 case IrInstructionIdCallSrc:
26450 case IrInstructionIdCallGen:26491 case IrInstructionIdCallGen:
26451 case IrInstructionIdReturn:26492 case IrInstructionIdReturn:
src/ir_print.cpp+14
...@@ -78,6 +78,8 @@ const char* ir_instruction_type_str(IrInstructionId id) {...@@ -78,6 +78,8 @@ const char* ir_instruction_type_str(IrInstructionId id) {
78 return "LoadPtrGen";78 return "LoadPtrGen";
79 case IrInstructionIdStorePtr:79 case IrInstructionIdStorePtr:
80 return "StorePtr";80 return "StorePtr";
81 case IrInstructionIdVectorStoreElem:
82 return "VectorStoreElem";
81 case IrInstructionIdFieldPtr:83 case IrInstructionIdFieldPtr:
82 return "FieldPtr";84 return "FieldPtr";
83 case IrInstructionIdStructFieldPtr:85 case IrInstructionIdStructFieldPtr:
...@@ -790,6 +792,15 @@ static void ir_print_store_ptr(IrPrint *irp, IrInstructionStorePtr *instruction)...@@ -790,6 +792,15 @@ static void ir_print_store_ptr(IrPrint *irp, IrInstructionStorePtr *instruction)
790 ir_print_other_instruction(irp, instruction->value);792 ir_print_other_instruction(irp, instruction->value);
791}793}
792794
795static void ir_print_vector_store_elem(IrPrint *irp, IrInstructionVectorStoreElem *instruction) {
796 fprintf(irp->f, "vector_ptr=");
797 ir_print_var_instruction(irp, instruction->vector_ptr);
798 fprintf(irp->f, ",index=");
799 ir_print_var_instruction(irp, instruction->index);
800 fprintf(irp->f, ",value=");
801 ir_print_other_instruction(irp, instruction->value);
802}
803
793static void ir_print_typeof(IrPrint *irp, IrInstructionTypeOf *instruction) {804static void ir_print_typeof(IrPrint *irp, IrInstructionTypeOf *instruction) {
794 fprintf(irp->f, "@typeOf(");805 fprintf(irp->f, "@typeOf(");
795 ir_print_other_instruction(irp, instruction->value);806 ir_print_other_instruction(irp, instruction->value);
...@@ -2047,6 +2058,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction, bool...@@ -2047,6 +2058,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction, bool
2047 case IrInstructionIdStorePtr:2058 case IrInstructionIdStorePtr:
2048 ir_print_store_ptr(irp, (IrInstructionStorePtr *)instruction);2059 ir_print_store_ptr(irp, (IrInstructionStorePtr *)instruction);
2049 break;2060 break;
2061 case IrInstructionIdVectorStoreElem:
2062 ir_print_vector_store_elem(irp, (IrInstructionVectorStoreElem *)instruction);
2063 break;
2050 case IrInstructionIdTypeOf:2064 case IrInstructionIdTypeOf:
2051 ir_print_typeof(irp, (IrInstructionTypeOf *)instruction);2065 ir_print_typeof(irp, (IrInstructionTypeOf *)instruction);
2052 break;2066 break;
test/compile_errors.zig+17
...@@ -26,6 +26,23 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -26,6 +26,23 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
2626
27 cases.add(27 cases.add(
28 "dereference vector pointer with unknown runtime index",28 "dereference vector pointer with unknown runtime index",
29 "store vector pointer with unknown runtime index",
30 \\export fn entry() void {
31 \\ var v: @Vector(4, i32) = [_]i32{ 1, 5, 3, undefined };
32 \\
33 \\ var i: u32 = 0;
34 \\ storev(&v[i], 42);
35 \\}
36 \\
37 \\fn storev(ptr: var, val: i32) void {
38 \\ ptr.* = val;
39 \\}
40 ,
41 "tmp.zig:9:8: error: unable to determine vector element index of type '*align(16:0:4:?) i32",
42 );
43
44 cases.add(
45 "load vector pointer with unknown runtime index",
29 \\export fn entry() void {46 \\export fn entry() void {
30 \\ var v: @Vector(4, i32) = [_]i32{ 1, 5, 3, undefined };47 \\ var v: @Vector(4, i32) = [_]i32{ 1, 5, 3, undefined };
31 \\48 \\
test/stage1/behavior/vector.zig+18
...@@ -216,3 +216,21 @@ test "load vector elements via runtime index" {...@@ -216,3 +216,21 @@ test "load vector elements via runtime index" {
216 S.doTheTest();216 S.doTheTest();
217 comptime S.doTheTest();217 comptime S.doTheTest();
218}218}
219
220test "store vector elements via runtime index" {
221 const S = struct {
222 fn doTheTest() void {
223 var v: @Vector(4, i32) = [_]i32{ 1, 5, 3, undefined };
224 var i: u32 = 2;
225 v[i] = 1;
226 expect(v[1] == 5);
227 expect(v[2] == 1);
228 i += 1;
229 v[i] = -364;
230 expect(-364 == v[3]);
231 }
232 };
233
234 S.doTheTest();
235 comptime S.doTheTest();
236}