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 {
24262426 IrInstructionIdLoadPtr,
24272427 IrInstructionIdLoadPtrGen,
24282428 IrInstructionIdStorePtr,
2429 IrInstructionIdVectorStoreElem,
24292430 IrInstructionIdFieldPtr,
24302431 IrInstructionIdStructFieldPtr,
24312432 IrInstructionIdUnionFieldPtr,
......@@ -2770,6 +2771,14 @@ struct IrInstructionStorePtr {
27702771 IrInstruction *value;
27712772};
27722773
2774struct IrInstructionVectorStoreElem {
2775 IrInstruction base;
2776
2777 IrInstruction *vector_ptr;
2778 IrInstruction *index;
2779 IrInstruction *value;
2780};
2781
27732782struct IrInstructionFieldPtr {
27742783 IrInstruction base;
27752784
src/codegen.cpp+15
......@@ -3644,6 +3644,19 @@ static LLVMValueRef ir_render_store_ptr(CodeGen *g, IrExecutable *executable, Ir
36443644 return nullptr;
36453645}
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
36473660static LLVMValueRef ir_render_var_ptr(CodeGen *g, IrExecutable *executable, IrInstructionVarPtr *instruction) {
36483661 if (instruction->base.value.special != ConstValSpecialRuntime)
36493662 return ir_llvm_value(g, &instruction->base);
......@@ -6130,6 +6143,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
61306143 return ir_render_load_ptr(g, executable, (IrInstructionLoadPtrGen *)instruction);
61316144 case IrInstructionIdStorePtr:
61326145 return ir_render_store_ptr(g, executable, (IrInstructionStorePtr *)instruction);
6146 case IrInstructionIdVectorStoreElem:
6147 return ir_render_vector_store_elem(g, executable, (IrInstructionVectorStoreElem *)instruction);
61336148 case IrInstructionIdVarPtr:
61346149 return ir_render_var_ptr(g, executable, (IrInstructionVarPtr *)instruction);
61356150 case IrInstructionIdReturnPtr:
src/ir.cpp+41
......@@ -491,6 +491,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionStorePtr *) {
491491 return IrInstructionIdStorePtr;
492492}
493493
494static constexpr IrInstructionId ir_instruction_id(IrInstructionVectorStoreElem *) {
495 return IrInstructionIdVectorStoreElem;
496}
497
494498static constexpr IrInstructionId ir_instruction_id(IrInstructionFieldPtr *) {
495499 return IrInstructionIdFieldPtr;
496500}
......@@ -1631,6 +1635,23 @@ static IrInstructionStorePtr *ir_build_store_ptr(IrBuilder *irb, Scope *scope, A
16311635 return instruction;
16321636}
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
16341655static IrInstruction *ir_build_var_decl_src(IrBuilder *irb, Scope *scope, AstNode *source_node,
16351656 ZigVar *var, IrInstruction *align_value, IrInstruction *ptr)
16361657{
......@@ -16126,6 +16147,24 @@ static IrInstruction *ir_analyze_store_ptr(IrAnalyze *ira, IrInstruction *source
1612616147 mark_comptime_value_escape(ira, source_instr, &value->value);
1612716148 }
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
1612916168 IrInstructionStorePtr *store_ptr = ir_build_store_ptr(&ira->new_irb, source_instr->scope,
1613016169 source_instr->source_node, ptr, value);
1613116170 return &store_ptr->base;
......@@ -26063,6 +26102,7 @@ static IrInstruction *ir_analyze_instruction_base(IrAnalyze *ira, IrInstruction
2606326102 case IrInstructionIdAwaitGen:
2606426103 case IrInstructionIdSplatGen:
2606526104 case IrInstructionIdVectorExtractElem:
26105 case IrInstructionIdVectorStoreElem:
2606626106 zig_unreachable();
2606726107
2606826108 case IrInstructionIdReturn:
......@@ -26446,6 +26486,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {
2644626486 case IrInstructionIdDeclVarSrc:
2644726487 case IrInstructionIdDeclVarGen:
2644826488 case IrInstructionIdStorePtr:
26489 case IrInstructionIdVectorStoreElem:
2644926490 case IrInstructionIdCallSrc:
2645026491 case IrInstructionIdCallGen:
2645126492 case IrInstructionIdReturn:
src/ir_print.cpp+14
......@@ -78,6 +78,8 @@ const char* ir_instruction_type_str(IrInstructionId id) {
7878 return "LoadPtrGen";
7979 case IrInstructionIdStorePtr:
8080 return "StorePtr";
81 case IrInstructionIdVectorStoreElem:
82 return "VectorStoreElem";
8183 case IrInstructionIdFieldPtr:
8284 return "FieldPtr";
8385 case IrInstructionIdStructFieldPtr:
......@@ -790,6 +792,15 @@ static void ir_print_store_ptr(IrPrint *irp, IrInstructionStorePtr *instruction)
790792 ir_print_other_instruction(irp, instruction->value);
791793}
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
793804static void ir_print_typeof(IrPrint *irp, IrInstructionTypeOf *instruction) {
794805 fprintf(irp->f, "@typeOf(");
795806 ir_print_other_instruction(irp, instruction->value);
......@@ -2047,6 +2058,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction, bool
20472058 case IrInstructionIdStorePtr:
20482059 ir_print_store_ptr(irp, (IrInstructionStorePtr *)instruction);
20492060 break;
2061 case IrInstructionIdVectorStoreElem:
2062 ir_print_vector_store_elem(irp, (IrInstructionVectorStoreElem *)instruction);
2063 break;
20502064 case IrInstructionIdTypeOf:
20512065 ir_print_typeof(irp, (IrInstructionTypeOf *)instruction);
20522066 break;
test/compile_errors.zig+17
......@@ -26,6 +26,23 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
2626
2727 cases.add(
2828 "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",
2946 \\export fn entry() void {
3047 \\ var v: @Vector(4, i32) = [_]i32{ 1, 5, 3, undefined };
3148 \\
test/stage1/behavior/vector.zig+18
......@@ -216,3 +216,21 @@ test "load vector elements via runtime index" {
216216 S.doTheTest();
217217 comptime S.doTheTest();
218218}
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}