authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-12-08 22:44:41-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-12-08 22:44:41-05:00
log5874cb04bd544ca155d1489bb0bdf9397fa3b41c
tree219eceefaa401051a63fd2328724ae82d55897a3
parent6504c5098ead851b369af0525c11ad2ea4cee8a2
signature Commit is signed but in an unrecognized format.

implement tuple concatenation


4 files changed, 133 insertions(+), 8 deletions(-)

src/analyze.cpp+3-6
...@@ -2142,7 +2142,6 @@ static Error resolve_struct_type(CodeGen *g, ZigType *struct_type) {...@@ -2142,7 +2142,6 @@ static Error resolve_struct_type(CodeGen *g, ZigType *struct_type) {
2142 }2142 }
21432143
2144 assert(struct_type->data.structure.fields || struct_type->data.structure.src_field_count == 0);2144 assert(struct_type->data.structure.fields || struct_type->data.structure.src_field_count == 0);
2145 assert(decl_node->type == NodeTypeContainerDecl || decl_node->type == NodeTypeContainerInitExpr);
21462145
2147 size_t field_count = struct_type->data.structure.src_field_count;2146 size_t field_count = struct_type->data.structure.src_field_count;
21482147
...@@ -2749,10 +2748,9 @@ static Error resolve_struct_zero_bits(CodeGen *g, ZigType *struct_type) {...@@ -2749,10 +2748,9 @@ static Error resolve_struct_zero_bits(CodeGen *g, ZigType *struct_type) {
27492748
2750 src_assert(struct_type->data.structure.fields == nullptr, decl_node);2749 src_assert(struct_type->data.structure.fields == nullptr, decl_node);
2751 struct_type->data.structure.fields = alloc_type_struct_fields(field_count);2750 struct_type->data.structure.fields = alloc_type_struct_fields(field_count);
2752 } else if (decl_node->type == NodeTypeContainerInitExpr) {2751 } else if (is_anon_container(struct_type)) {
2753 field_count = struct_type->data.structure.src_field_count;2752 field_count = struct_type->data.structure.src_field_count;
27542753
2755 src_assert(is_anon_container(struct_type), decl_node);
2756 src_assert(field_count == 0 || struct_type->data.structure.fields != nullptr, decl_node);2754 src_assert(field_count == 0 || struct_type->data.structure.fields != nullptr, decl_node);
2757 } else zig_unreachable();2755 } else zig_unreachable();
27582756
...@@ -2785,7 +2783,7 @@ static Error resolve_struct_zero_bits(CodeGen *g, ZigType *struct_type) {...@@ -2785,7 +2783,7 @@ static Error resolve_struct_zero_bits(CodeGen *g, ZigType *struct_type) {
2785 struct_type->data.structure.resolve_status = ResolveStatusInvalid;2783 struct_type->data.structure.resolve_status = ResolveStatusInvalid;
2786 return ErrorSemanticAnalyzeFail;2784 return ErrorSemanticAnalyzeFail;
2787 }2785 }
2788 } else if (decl_node->type == NodeTypeContainerInitExpr) {2786 } else if (is_anon_container(struct_type)) {
2789 field_node = type_struct_field->decl_node;2787 field_node = type_struct_field->decl_node;
27902788
2791 src_assert(type_struct_field->type_entry != nullptr, field_node);2789 src_assert(type_struct_field->type_entry != nullptr, field_node);
...@@ -2812,7 +2810,7 @@ static Error resolve_struct_zero_bits(CodeGen *g, ZigType *struct_type) {...@@ -2812,7 +2810,7 @@ static Error resolve_struct_zero_bits(CodeGen *g, ZigType *struct_type) {
2812 type_struct_field->type_val = field_type_val;2810 type_struct_field->type_val = field_type_val;
2813 if (struct_type->data.structure.resolve_status == ResolveStatusInvalid)2811 if (struct_type->data.structure.resolve_status == ResolveStatusInvalid)
2814 return ErrorSemanticAnalyzeFail;2812 return ErrorSemanticAnalyzeFail;
2815 } else if (decl_node->type == NodeTypeContainerInitExpr) {2813 } else if (is_anon_container(struct_type)) {
2816 field_type_val = type_struct_field->type_val;2814 field_type_val = type_struct_field->type_val;
2817 } else zig_unreachable();2815 } else zig_unreachable();
28182816
...@@ -2901,7 +2899,6 @@ static Error resolve_struct_alignment(CodeGen *g, ZigType *struct_type) {...@@ -2901,7 +2899,6 @@ static Error resolve_struct_alignment(CodeGen *g, ZigType *struct_type) {
2901 }2899 }
29022900
2903 struct_type->data.structure.resolve_loop_flag_other = true;2901 struct_type->data.structure.resolve_loop_flag_other = true;
2904 assert(decl_node->type == NodeTypeContainerDecl || decl_node->type == NodeTypeContainerInitExpr);
29052902
2906 size_t field_count = struct_type->data.structure.src_field_count;2903 size_t field_count = struct_type->data.structure.src_field_count;
2907 bool packed = struct_type->data.structure.layout == ContainerLayoutPacked;2904 bool packed = struct_type->data.structure.layout == ContainerLayoutPacked;
src/ir.cpp+111-2
...@@ -15573,6 +15573,110 @@ static IrInstruction *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp...@@ -15573,6 +15573,110 @@ static IrInstruction *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp
15573 return result;15573 return result;
15574}15574}
1557515575
15576static IrInstruction *ir_analyze_tuple_cat(IrAnalyze *ira, IrInstruction *source_instr,
15577 IrInstruction *op1, IrInstruction *op2)
15578{
15579 Error err;
15580 ZigType *op1_type = op1->value->type;
15581 ZigType *op2_type = op2->value->type;
15582
15583 uint32_t op1_field_count = op1_type->data.structure.src_field_count;
15584 uint32_t op2_field_count = op2_type->data.structure.src_field_count;
15585
15586 Buf *bare_name = buf_alloc();
15587 Buf *name = get_anon_type_name(ira->codegen, nullptr, container_string(ContainerKindStruct),
15588 source_instr->scope, source_instr->source_node, bare_name);
15589 ZigType *new_type = get_partial_container_type(ira->codegen, source_instr->scope,
15590 ContainerKindStruct, source_instr->source_node, buf_ptr(name), bare_name, ContainerLayoutAuto);
15591 new_type->data.structure.special = StructSpecialInferredTuple;
15592 new_type->data.structure.resolve_status = ResolveStatusBeingInferred;
15593
15594 bool is_comptime = ir_should_inline(ira->new_irb.exec, source_instr->scope);
15595
15596 IrInstruction *new_struct_ptr = ir_resolve_result(ira, source_instr, no_result_loc(),
15597 new_type, nullptr, false, false, true);
15598 uint32_t new_field_count = op1_field_count + op2_field_count;
15599
15600 new_type->data.structure.src_field_count = new_field_count;
15601 new_type->data.structure.fields = realloc_type_struct_fields(new_type->data.structure.fields,
15602 0, new_field_count);
15603 for (uint32_t i = 0; i < new_field_count; i += 1) {
15604 TypeStructField *src_field;
15605 if (i < op1_field_count) {
15606 src_field = op1_type->data.structure.fields[i];
15607 } else {
15608 src_field = op2_type->data.structure.fields[i - op1_field_count];
15609 }
15610 TypeStructField *new_field = new_type->data.structure.fields[i];
15611 new_field->name = buf_sprintf("%" PRIu32, i);
15612 new_field->type_entry = src_field->type_entry;
15613 new_field->type_val = src_field->type_val;
15614 new_field->src_index = i;
15615 new_field->decl_node = src_field->decl_node;
15616 new_field->init_val = src_field->init_val;
15617 new_field->is_comptime = src_field->is_comptime;
15618 }
15619 if ((err = type_resolve(ira->codegen, new_type, ResolveStatusZeroBitsKnown)))
15620 return ira->codegen->invalid_instruction;
15621
15622 ZigList<IrInstruction *> const_ptrs = {};
15623 IrInstruction *first_non_const_instruction = nullptr;
15624 for (uint32_t i = 0; i < new_field_count; i += 1) {
15625 TypeStructField *dst_field = new_type->data.structure.fields[i];
15626 IrInstruction *src_struct_op;
15627 TypeStructField *src_field;
15628 if (i < op1_field_count) {
15629 src_field = op1_type->data.structure.fields[i];
15630 src_struct_op = op1;
15631 } else {
15632 src_field = op2_type->data.structure.fields[i - op1_field_count];
15633 src_struct_op = op2;
15634 }
15635 IrInstruction *field_value = ir_analyze_struct_value_field_value(ira, source_instr,
15636 src_struct_op, src_field);
15637 if (type_is_invalid(field_value->value->type))
15638 return ira->codegen->invalid_instruction;
15639 IrInstruction *dest_ptr = ir_analyze_struct_field_ptr(ira, source_instr, dst_field,
15640 new_struct_ptr, new_type, true);
15641 if (type_is_invalid(dest_ptr->value->type))
15642 return ira->codegen->invalid_instruction;
15643 if (instr_is_comptime(field_value)) {
15644 const_ptrs.append(dest_ptr);
15645 } else {
15646 first_non_const_instruction = field_value;
15647 }
15648 IrInstruction *store_ptr_inst = ir_analyze_store_ptr(ira, source_instr, dest_ptr, field_value,
15649 true);
15650 if (type_is_invalid(store_ptr_inst->value->type))
15651 return ira->codegen->invalid_instruction;
15652 }
15653 if (const_ptrs.length != new_field_count) {
15654 new_struct_ptr->value->special = ConstValSpecialRuntime;
15655 for (size_t i = 0; i < const_ptrs.length; i += 1) {
15656 IrInstruction *elem_result_loc = const_ptrs.at(i);
15657 assert(elem_result_loc->value->special == ConstValSpecialStatic);
15658 if (elem_result_loc->value->type->data.pointer.inferred_struct_field != nullptr) {
15659 // This field will be generated comptime; no need to do this.
15660 continue;
15661 }
15662 IrInstruction *deref = ir_get_deref(ira, elem_result_loc, elem_result_loc, nullptr);
15663 elem_result_loc->value->special = ConstValSpecialRuntime;
15664 ir_analyze_store_ptr(ira, elem_result_loc, elem_result_loc, deref, false);
15665 }
15666 }
15667 IrInstruction *result = ir_get_deref(ira, source_instr, new_struct_ptr, nullptr);
15668 if (instr_is_comptime(result))
15669 return result;
15670
15671 if (is_comptime) {
15672 ir_add_error_node(ira, first_non_const_instruction->source_node,
15673 buf_sprintf("unable to evaluate constant expression"));
15674 return ira->codegen->invalid_instruction;
15675 }
15676
15677 return result;
15678}
15679
15576static IrInstruction *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *instruction) {15680static IrInstruction *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *instruction) {
15577 IrInstruction *op1 = instruction->op1->child;15681 IrInstruction *op1 = instruction->op1->child;
15578 ZigType *op1_type = op1->value->type;15682 ZigType *op1_type = op1->value->type;
...@@ -15584,6 +15688,10 @@ static IrInstruction *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *i...@@ -15584,6 +15688,10 @@ static IrInstruction *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *i
15584 if (type_is_invalid(op2_type))15688 if (type_is_invalid(op2_type))
15585 return ira->codegen->invalid_instruction;15689 return ira->codegen->invalid_instruction;
1558615690
15691 if (is_tuple(op1_type) && is_tuple(op2_type)) {
15692 return ir_analyze_tuple_cat(ira, &instruction->base, op1, op2);
15693 }
15694
15587 ZigValue *op1_val = ir_resolve_const(ira, op1, UndefBad);15695 ZigValue *op1_val = ir_resolve_const(ira, op1, UndefBad);
15588 if (!op1_val)15696 if (!op1_val)
15589 return ira->codegen->invalid_instruction;15697 return ira->codegen->invalid_instruction;
...@@ -17446,11 +17554,12 @@ static IrInstruction *ir_analyze_store_ptr(IrAnalyze *ira, IrInstruction *source...@@ -17446,11 +17554,12 @@ static IrInstruction *ir_analyze_store_ptr(IrAnalyze *ira, IrInstruction *source
17446 }17554 }
1744717555
17448 if (instr_is_comptime(ptr) && ptr->value->data.x_ptr.special != ConstPtrSpecialHardCodedAddr) {17556 if (instr_is_comptime(ptr) && ptr->value->data.x_ptr.special != ConstPtrSpecialHardCodedAddr) {
17449 if (ptr->value->data.x_ptr.mut == ConstPtrMutComptimeConst) {17557 if (!allow_write_through_const && ptr->value->data.x_ptr.mut == ConstPtrMutComptimeConst) {
17450 ir_add_error(ira, source_instr, buf_sprintf("cannot assign to constant"));17558 ir_add_error(ira, source_instr, buf_sprintf("cannot assign to constant"));
17451 return ira->codegen->invalid_instruction;17559 return ira->codegen->invalid_instruction;
17452 }17560 }
17453 if (ptr->value->data.x_ptr.mut == ConstPtrMutComptimeVar ||17561 if ((allow_write_through_const && ptr->value->data.x_ptr.mut == ConstPtrMutComptimeConst) ||
17562 ptr->value->data.x_ptr.mut == ConstPtrMutComptimeVar ||
17454 ptr->value->data.x_ptr.mut == ConstPtrMutInfer)17563 ptr->value->data.x_ptr.mut == ConstPtrMutInfer)
17455 {17564 {
17456 if (instr_is_comptime(value)) {17565 if (instr_is_comptime(value)) {
test/stage1/behavior.zig+1
...@@ -103,6 +103,7 @@ comptime {...@@ -103,6 +103,7 @@ comptime {
103 _ = @import("behavior/this.zig");103 _ = @import("behavior/this.zig");
104 _ = @import("behavior/truncate.zig");104 _ = @import("behavior/truncate.zig");
105 _ = @import("behavior/try.zig");105 _ = @import("behavior/try.zig");
106 _ = @import("behavior/tuple.zig");
106 _ = @import("behavior/type.zig");107 _ = @import("behavior/type.zig");
107 _ = @import("behavior/type_info.zig");108 _ = @import("behavior/type_info.zig");
108 _ = @import("behavior/typename.zig");109 _ = @import("behavior/typename.zig");
test/stage1/behavior/tuple.zig created+18
...@@ -0,0 +1,18 @@
1const std = @import("std");
2const expect = std.testing.expect;
3
4test "tuple concatenation" {
5 const S = struct {
6 fn doTheTest() void {
7 var a: i32 = 1;
8 var b: i32 = 2;
9 var x = .{a};
10 var y = .{b};
11 var c = x ++ y;
12 expect(c[0] == 1);
13 expect(c[1] == 2);
14 }
15 };
16 S.doTheTest();
17 comptime S.doTheTest();
18}