authorgravatar for thatlemon@gmail.comLemonBoy <thatlemon@gmail.com> 2020-03-03 21:46:30+01:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-04-06 14:03:43-04:00
loga59d31bd28f82e002f68ce25581c0437463137ed
tree7c634e05cd176b74d18482d89d0b80ac6ba6d7d0
parente4eb817f7999a2ee9ff62f59a6bf72a57bdf40a5

ir: Support tuple multiplication


2 files changed, 141 insertions(+), 12 deletions(-)

src/ir.cpp+113-9
...@@ -17351,14 +17351,15 @@ static IrInstGen *ir_analyze_tuple_cat(IrAnalyze *ira, IrInst* source_instr,...@@ -17351,14 +17351,15 @@ static IrInstGen *ir_analyze_tuple_cat(IrAnalyze *ira, IrInst* source_instr,
17351 ContainerKindStruct, source_instr->source_node, buf_ptr(name), bare_name, ContainerLayoutAuto);17351 ContainerKindStruct, source_instr->source_node, buf_ptr(name), bare_name, ContainerLayoutAuto);
17352 new_type->data.structure.special = StructSpecialInferredTuple;17352 new_type->data.structure.special = StructSpecialInferredTuple;
17353 new_type->data.structure.resolve_status = ResolveStatusBeingInferred;17353 new_type->data.structure.resolve_status = ResolveStatusBeingInferred;
17354
17355 IrInstGen *new_struct_ptr = ir_resolve_result(ira, source_instr, no_result_loc(),
17356 new_type, nullptr, false, true);
17357 uint32_t new_field_count = op1_field_count + op2_field_count;17354 uint32_t new_field_count = op1_field_count + op2_field_count;
1735817355
17359 new_type->data.structure.src_field_count = new_field_count;17356 new_type->data.structure.src_field_count = new_field_count;
17360 new_type->data.structure.fields = realloc_type_struct_fields(new_type->data.structure.fields,17357 new_type->data.structure.fields = realloc_type_struct_fields(new_type->data.structure.fields,
17361 0, new_field_count);17358 0, new_field_count);
17359
17360 IrInstGen *new_struct_ptr = ir_resolve_result(ira, source_instr, no_result_loc(),
17361 new_type, nullptr, false, true);
17362
17362 for (uint32_t i = 0; i < new_field_count; i += 1) {17363 for (uint32_t i = 0; i < new_field_count; i += 1) {
17363 TypeStructField *src_field;17364 TypeStructField *src_field;
17364 if (i < op1_field_count) {17365 if (i < op1_field_count) {
...@@ -17422,8 +17423,10 @@ static IrInstGen *ir_analyze_tuple_cat(IrAnalyze *ira, IrInst* source_instr,...@@ -17422,8 +17423,10 @@ static IrInstGen *ir_analyze_tuple_cat(IrAnalyze *ira, IrInst* source_instr,
17422 ir_analyze_store_ptr(ira, &elem_result_loc->base, elem_result_loc, deref, true);17423 ir_analyze_store_ptr(ira, &elem_result_loc->base, elem_result_loc, deref, true);
17423 }17424 }
17424 }17425 }
17425 IrInstGen *result = ir_get_deref(ira, source_instr, new_struct_ptr, nullptr);17426
17426 return result;17427 const_ptrs.deinit();
17428
17429 return ir_get_deref(ira, source_instr, new_struct_ptr, nullptr);
17427}17430}
1742817431
17429static IrInstGen *ir_analyze_array_cat(IrAnalyze *ira, IrInstSrcBinOp *instruction) {17432static IrInstGen *ir_analyze_array_cat(IrAnalyze *ira, IrInstSrcBinOp *instruction) {
...@@ -17480,8 +17483,9 @@ static IrInstGen *ir_analyze_array_cat(IrAnalyze *ira, IrInstSrcBinOp *instructi...@@ -17480,8 +17483,9 @@ static IrInstGen *ir_analyze_array_cat(IrAnalyze *ira, IrInstSrcBinOp *instructi
17480 ZigValue *len_val = op1_val->data.x_struct.fields[slice_len_index];17483 ZigValue *len_val = op1_val->data.x_struct.fields[slice_len_index];
17481 op1_array_end = op1_array_index + bigint_as_usize(&len_val->data.x_bigint);17484 op1_array_end = op1_array_index + bigint_as_usize(&len_val->data.x_bigint);
17482 sentinel1 = ptr_type->data.pointer.sentinel;17485 sentinel1 = ptr_type->data.pointer.sentinel;
17483 } else if (op1_type->id == ZigTypeIdPointer && op1_type->data.pointer.ptr_len == PtrLenSingle &&17486 } else if (op1_type->id == ZigTypeIdPointer &&
17484 op1_type->data.pointer.child_type->id == ZigTypeIdArray)17487 op1_type->data.pointer.ptr_len == PtrLenSingle &&
17488 op1_type->data.pointer.child_type->id == ZigTypeIdArray)
17485 {17489 {
17486 ZigType *array_type = op1_type->data.pointer.child_type;17490 ZigType *array_type = op1_type->data.pointer.child_type;
17487 child_type = array_type->data.array.child_type;17491 child_type = array_type->data.array.child_type;
...@@ -17654,6 +17658,103 @@ static IrInstGen *ir_analyze_array_cat(IrAnalyze *ira, IrInstSrcBinOp *instructi...@@ -17654,6 +17658,103 @@ static IrInstGen *ir_analyze_array_cat(IrAnalyze *ira, IrInstSrcBinOp *instructi
17654 return result;17658 return result;
17655}17659}
1765617660
17661static IrInstGen *ir_analyze_tuple_mult(IrAnalyze *ira, IrInst* source_instr,
17662 IrInstGen *op1, IrInstGen *op2)
17663{
17664 Error err;
17665 ZigType *op1_type = op1->value->type;
17666 uint64_t op1_field_count = op1_type->data.structure.src_field_count;
17667
17668 uint64_t mult_amt;
17669 if (!ir_resolve_usize(ira, op2, &mult_amt))
17670 return ira->codegen->invalid_inst_gen;
17671
17672 uint64_t new_field_count;
17673 if (mul_u64_overflow(op1_field_count, mult_amt, &new_field_count)) {
17674 ir_add_error(ira, source_instr, buf_sprintf("operation results in overflow"));
17675 return ira->codegen->invalid_inst_gen;
17676 }
17677
17678 Buf *bare_name = buf_alloc();
17679 Buf *name = get_anon_type_name(ira->codegen, nullptr, container_string(ContainerKindStruct),
17680 source_instr->scope, source_instr->source_node, bare_name);
17681 ZigType *new_type = get_partial_container_type(ira->codegen, source_instr->scope,
17682 ContainerKindStruct, source_instr->source_node, buf_ptr(name), bare_name, ContainerLayoutAuto);
17683 new_type->data.structure.special = StructSpecialInferredTuple;
17684 new_type->data.structure.resolve_status = ResolveStatusBeingInferred;
17685 new_type->data.structure.src_field_count = new_field_count;
17686 new_type->data.structure.fields = realloc_type_struct_fields(
17687 new_type->data.structure.fields, 0, new_field_count);
17688
17689 IrInstGen *new_struct_ptr = ir_resolve_result(ira, source_instr, no_result_loc(),
17690 new_type, nullptr, false, true);
17691
17692 for (uint64_t i = 0; i < new_field_count; i += 1) {
17693 TypeStructField *src_field = op1_type->data.structure.fields[i % op1_field_count];
17694 TypeStructField *new_field = new_type->data.structure.fields[i];
17695
17696 new_field->name = buf_sprintf("%lu", i);
17697 new_field->type_entry = src_field->type_entry;
17698 new_field->type_val = src_field->type_val;
17699 new_field->src_index = i;
17700 new_field->decl_node = src_field->decl_node;
17701 new_field->init_val = src_field->init_val;
17702 new_field->is_comptime = src_field->is_comptime;
17703 }
17704
17705 if ((err = type_resolve(ira->codegen, new_type, ResolveStatusZeroBitsKnown)))
17706 return ira->codegen->invalid_inst_gen;
17707
17708 ZigList<IrInstGen *> const_ptrs = {};
17709 for (uint64_t i = 0; i < new_field_count; i += 1) {
17710 TypeStructField *src_field = op1_type->data.structure.fields[i % op1_field_count];
17711 TypeStructField *dst_field = new_type->data.structure.fields[i];
17712
17713 IrInstGen *field_value = ir_analyze_struct_value_field_value(
17714 ira, source_instr, op1, src_field);
17715 if (type_is_invalid(field_value->value->type))
17716 return ira->codegen->invalid_inst_gen;
17717
17718 IrInstGen *dest_ptr = ir_analyze_struct_field_ptr(
17719 ira, source_instr, dst_field, new_struct_ptr, new_type, true);
17720 if (type_is_invalid(dest_ptr->value->type))
17721 return ira->codegen->invalid_inst_gen;
17722
17723 if (instr_is_comptime(field_value)) {
17724 const_ptrs.append(dest_ptr);
17725 }
17726
17727 IrInstGen *store_ptr_inst = ir_analyze_store_ptr(
17728 ira, source_instr, dest_ptr, field_value, true);
17729 if (type_is_invalid(store_ptr_inst->value->type))
17730 return ira->codegen->invalid_inst_gen;
17731 }
17732
17733 if (const_ptrs.length != new_field_count) {
17734 new_struct_ptr->value->special = ConstValSpecialRuntime;
17735 for (size_t i = 0; i < const_ptrs.length; i += 1) {
17736 IrInstGen *elem_result_loc = const_ptrs.at(i);
17737 assert(elem_result_loc->value->special == ConstValSpecialStatic);
17738 if (elem_result_loc->value->type->data.pointer.inferred_struct_field != nullptr) {
17739 // This field will be generated comptime; no need to do this.
17740 continue;
17741 }
17742 IrInstGen *deref = ir_get_deref(ira, &elem_result_loc->base, elem_result_loc, nullptr);
17743 if (!type_requires_comptime(ira->codegen, elem_result_loc->value->type->data.pointer.child_type)) {
17744 elem_result_loc->value->special = ConstValSpecialRuntime;
17745 }
17746 IrInstGen *store_ptr_inst = ir_analyze_store_ptr(
17747 ira, &elem_result_loc->base, elem_result_loc, deref, true);
17748 if (type_is_invalid(store_ptr_inst->value->type))
17749 return ira->codegen->invalid_inst_gen;
17750 }
17751 }
17752
17753 const_ptrs.deinit();
17754
17755 return ir_get_deref(ira, source_instr, new_struct_ptr, nullptr);
17756}
17757
17657static IrInstGen *ir_analyze_array_mult(IrAnalyze *ira, IrInstSrcBinOp *instruction) {17758static IrInstGen *ir_analyze_array_mult(IrAnalyze *ira, IrInstSrcBinOp *instruction) {
17658 IrInstGen *op1 = instruction->op1->child;17759 IrInstGen *op1 = instruction->op1->child;
17659 if (type_is_invalid(op1->value->type))17760 if (type_is_invalid(op1->value->type))
...@@ -17671,8 +17772,9 @@ static IrInstGen *ir_analyze_array_mult(IrAnalyze *ira, IrInstSrcBinOp *instruct...@@ -17671,8 +17772,9 @@ static IrInstGen *ir_analyze_array_mult(IrAnalyze *ira, IrInstSrcBinOp *instruct
17671 array_val = ir_resolve_const(ira, op1, UndefOk);17772 array_val = ir_resolve_const(ira, op1, UndefOk);
17672 if (array_val == nullptr)17773 if (array_val == nullptr)
17673 return ira->codegen->invalid_inst_gen;17774 return ira->codegen->invalid_inst_gen;
17674 } else if (op1->value->type->id == ZigTypeIdPointer && op1->value->type->data.pointer.ptr_len == PtrLenSingle &&17775 } else if (op1->value->type->id == ZigTypeIdPointer &&
17675 op1->value->type->data.pointer.child_type->id == ZigTypeIdArray)17776 op1->value->type->data.pointer.ptr_len == PtrLenSingle &&
17777 op1->value->type->data.pointer.child_type->id == ZigTypeIdArray)
17676 {17778 {
17677 array_type = op1->value->type->data.pointer.child_type;17779 array_type = op1->value->type->data.pointer.child_type;
17678 IrInstGen *array_inst = ir_get_deref(ira, &op1->base, op1, nullptr);17780 IrInstGen *array_inst = ir_get_deref(ira, &op1->base, op1, nullptr);
...@@ -17682,6 +17784,8 @@ static IrInstGen *ir_analyze_array_mult(IrAnalyze *ira, IrInstSrcBinOp *instruct...@@ -17682,6 +17784,8 @@ static IrInstGen *ir_analyze_array_mult(IrAnalyze *ira, IrInstSrcBinOp *instruct
17682 if (array_val == nullptr)17784 if (array_val == nullptr)
17683 return ira->codegen->invalid_inst_gen;17785 return ira->codegen->invalid_inst_gen;
17684 want_ptr_to_array = true;17786 want_ptr_to_array = true;
17787 } else if (is_tuple(op1->value->type)) {
17788 return ir_analyze_tuple_mult(ira, &instruction->base.base, op1, op2);
17685 } else {17789 } else {
17686 ir_add_error(ira, &op1->base, buf_sprintf("expected array type, found '%s'", buf_ptr(&op1->value->type->name)));17790 ir_add_error(ira, &op1->base, buf_sprintf("expected array type, found '%s'", buf_ptr(&op1->value->type->name)));
17687 return ira->codegen->invalid_inst_gen;17791 return ira->codegen->invalid_inst_gen;
test/stage1/behavior/tuple.zig+28-3
...@@ -1,5 +1,7 @@...@@ -1,5 +1,7 @@
1const std = @import("std");1const std = @import("std");
2const expect = std.testing.expect;2const testing = std.testing;
3const expect = testing.expect;
4const expectEqual = testing.expectEqual;
35
4test "tuple concatenation" {6test "tuple concatenation" {
5 const S = struct {7 const S = struct {
...@@ -9,8 +11,31 @@ test "tuple concatenation" {...@@ -9,8 +11,31 @@ test "tuple concatenation" {
9 var x = .{a};11 var x = .{a};
10 var y = .{b};12 var y = .{b};
11 var c = x ++ y;13 var c = x ++ y;
12 expect(c[0] == 1);14 expectEqual(@as(i32, 1), c[0]);
13 expect(c[1] == 2);15 expectEqual(@as(i32, 2), c[1]);
16 }
17 };
18 S.doTheTest();
19 comptime S.doTheTest();
20}
21
22test "tuple multiplication" {
23 const S = struct {
24 fn doTheTest() void {
25 {
26 const t = .{} ** 4;
27 expectEqual(0, @typeInfo(@TypeOf(t)).Struct.fields.len);
28 }
29 {
30 const t = .{'a'} ** 4;
31 expectEqual(4, @typeInfo(@TypeOf(t)).Struct.fields.len);
32 inline for (t) |x| expectEqual('a', x);
33 }
34 {
35 const t = .{ 1, 2, 3 } ** 4;
36 expectEqual(12, @typeInfo(@TypeOf(t)).Struct.fields.len);
37 inline for (t) |x, i| expectEqual(1 + i % 3, x);
38 }
14 }39 }
15 };40 };
16 S.doTheTest();41 S.doTheTest();