authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-03-04 17:09:43-05:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2020-03-04 17:09:43-05:00
log24fc69acad303d9049a99683d3bf1f41185d22db
tree031bbe712fda861e6a1aa62203b0ff7287c72e7c
parentf247a905419f47f794837c3818636553eebb929c
parentb838122cc0bfef2d986c6addc688a35318777034
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #4573 from alexnask/tuple_concat

Allow concatenation of tuples that contain a mix of runtime and comptime values

2 files changed, 46 insertions(+), 17 deletions(-)

src/ir.cpp+8-17
...@@ -16966,8 +16966,6 @@ static IrInstGen *ir_analyze_tuple_cat(IrAnalyze *ira, IrInst* source_instr,...@@ -16966,8 +16966,6 @@ static IrInstGen *ir_analyze_tuple_cat(IrAnalyze *ira, IrInst* source_instr,
16966 new_type->data.structure.special = StructSpecialInferredTuple;16966 new_type->data.structure.special = StructSpecialInferredTuple;
16967 new_type->data.structure.resolve_status = ResolveStatusBeingInferred;16967 new_type->data.structure.resolve_status = ResolveStatusBeingInferred;
1696816968
16969 bool is_comptime = ir_should_inline(ira->old_irb.exec, source_instr->scope);
16970
16971 IrInstGen *new_struct_ptr = ir_resolve_result(ira, source_instr, no_result_loc(),16969 IrInstGen *new_struct_ptr = ir_resolve_result(ira, source_instr, no_result_loc(),
16972 new_type, nullptr, false, true);16970 new_type, nullptr, false, true);
16973 uint32_t new_field_count = op1_field_count + op2_field_count;16971 uint32_t new_field_count = op1_field_count + op2_field_count;
...@@ -16995,7 +16993,6 @@ static IrInstGen *ir_analyze_tuple_cat(IrAnalyze *ira, IrInst* source_instr,...@@ -16995,7 +16993,6 @@ static IrInstGen *ir_analyze_tuple_cat(IrAnalyze *ira, IrInst* source_instr,
16995 return ira->codegen->invalid_inst_gen;16993 return ira->codegen->invalid_inst_gen;
1699616994
16997 ZigList<IrInstGen *> const_ptrs = {};16995 ZigList<IrInstGen *> const_ptrs = {};
16998 IrInstGen *first_non_const_instruction = nullptr;
16999 for (uint32_t i = 0; i < new_field_count; i += 1) {16996 for (uint32_t i = 0; i < new_field_count; i += 1) {
17000 TypeStructField *dst_field = new_type->data.structure.fields[i];16997 TypeStructField *dst_field = new_type->data.structure.fields[i];
17001 IrInstGen *src_struct_op;16998 IrInstGen *src_struct_op;
...@@ -17017,8 +17014,6 @@ static IrInstGen *ir_analyze_tuple_cat(IrAnalyze *ira, IrInst* source_instr,...@@ -17017,8 +17014,6 @@ static IrInstGen *ir_analyze_tuple_cat(IrAnalyze *ira, IrInst* source_instr,
17017 return ira->codegen->invalid_inst_gen;17014 return ira->codegen->invalid_inst_gen;
17018 if (instr_is_comptime(field_value)) {17015 if (instr_is_comptime(field_value)) {
17019 const_ptrs.append(dest_ptr);17016 const_ptrs.append(dest_ptr);
17020 } else {
17021 first_non_const_instruction = field_value;
17022 }17017 }
17023 IrInstGen *store_ptr_inst = ir_analyze_store_ptr(ira, source_instr, dest_ptr, field_value,17018 IrInstGen *store_ptr_inst = ir_analyze_store_ptr(ira, source_instr, dest_ptr, field_value,
17024 true);17019 true);
...@@ -17035,20 +17030,13 @@ static IrInstGen *ir_analyze_tuple_cat(IrAnalyze *ira, IrInst* source_instr,...@@ -17035,20 +17030,13 @@ static IrInstGen *ir_analyze_tuple_cat(IrAnalyze *ira, IrInst* source_instr,
17035 continue;17030 continue;
17036 }17031 }
17037 IrInstGen *deref = ir_get_deref(ira, &elem_result_loc->base, elem_result_loc, nullptr);17032 IrInstGen *deref = ir_get_deref(ira, &elem_result_loc->base, elem_result_loc, nullptr);
17038 elem_result_loc->value->special = ConstValSpecialRuntime;17033 if (!type_requires_comptime(ira->codegen, elem_result_loc->value->type->data.pointer.child_type)) {
17039 ir_analyze_store_ptr(ira, &elem_result_loc->base, elem_result_loc, deref, false);17034 elem_result_loc->value->special = ConstValSpecialRuntime;
17035 }
17036 ir_analyze_store_ptr(ira, &elem_result_loc->base, elem_result_loc, deref, true);
17040 }17037 }
17041 }17038 }
17042 IrInstGen *result = ir_get_deref(ira, source_instr, new_struct_ptr, nullptr);17039 IrInstGen *result = ir_get_deref(ira, source_instr, new_struct_ptr, nullptr);
17043 if (instr_is_comptime(result))
17044 return result;
17045
17046 if (is_comptime) {
17047 ir_add_error(ira, &first_non_const_instruction->base,
17048 buf_sprintf("unable to evaluate constant expression"));
17049 return ira->codegen->invalid_inst_gen;
17050 }
17051
17052 return result;17040 return result;
17053}17041}
1705417042
...@@ -23065,8 +23053,11 @@ static IrInstGen *ir_analyze_instruction_container_init_list(IrAnalyze *ira,...@@ -23065,8 +23053,11 @@ static IrInstGen *ir_analyze_instruction_container_init_list(IrAnalyze *ira,
23065 }23053 }
23066 }23054 }
2306723055
23056 const_ptrs.deinit();
23057
23068 IrInstGen *result = ir_get_deref(ira, &instruction->base.base, result_loc, nullptr);23058 IrInstGen *result = ir_get_deref(ira, &instruction->base.base, result_loc, nullptr);
23069 if (instr_is_comptime(result))23059 // If the result is a tuple, we are allowed to return a struct that uses ConstValSpecialRuntime fields at comptime.
23060 if (instr_is_comptime(result) || is_tuple(container_type))
23070 return result;23061 return result;
2307123062
23072 if (is_comptime) {23063 if (is_comptime) {
test/stage1/behavior/tuple.zig+38
...@@ -15,4 +15,42 @@ test "tuple concatenation" {...@@ -15,4 +15,42 @@ test "tuple concatenation" {
15 };15 };
16 S.doTheTest();16 S.doTheTest();
17 comptime S.doTheTest();17 comptime S.doTheTest();
18
19 const T = struct {
20 fn consume_tuple(tuple: var, len: usize) void {
21 expect(tuple.len == len);
22 }
23
24 fn doTheTest() void {
25 const t1 = .{};
26
27 var rt_var: u8 = 42;
28 const t2 = .{rt_var} ++ .{};
29
30 expect(t2.len == 1);
31 expect(t2.@"0" == rt_var);
32 expect(t2.@"0" == 42);
33 expect(&t2.@"0" != &rt_var);
34
35 consume_tuple(t1 ++ t1, 0);
36 consume_tuple(.{} ++ .{}, 0);
37 consume_tuple(.{0} ++ .{}, 1);
38 consume_tuple(.{0} ++ .{1}, 2);
39 consume_tuple(.{0, 1, 2} ++ .{u8, 1, noreturn}, 6);
40 consume_tuple(t2 ++ t1, 1);
41 consume_tuple(t1 ++ t2, 1);
42 consume_tuple(t2 ++ t2, 2);
43 consume_tuple(.{rt_var} ++ .{}, 1);
44 consume_tuple(.{rt_var} ++ t1, 1);
45 consume_tuple(.{} ++ .{rt_var}, 1);
46 consume_tuple(t2 ++ .{void}, 2);
47 consume_tuple(t2 ++ .{0}, 2);
48 consume_tuple(.{0} ++ t2, 2);
49 consume_tuple(.{void} ++ t2, 2);
50 consume_tuple(.{u8} ++ .{rt_var} ++ .{true}, 3);
51 }
52 };
53
54 T.doTheTest();
55 comptime T.doTheTest();
18}56}