authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2020-11-23 01:59:44+02:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2020-12-25 14:57:46+02:00
log990eccf282f278b977f8e232fca5522649eff20f
tree86d457863e59b32a8c68987f5763a4e1c8288c7c
parented028fd66041e660b0986ceca0edbcfd5089b2f1
signaturelock-open Commit is signed but in an unrecognized format.

stage1: implement type coercion of pointer to anon list to array/struct/union/slice


5 files changed, 202 insertions(+), 31 deletions(-)

src/stage1/ir.cpp+84-31
...@@ -14996,25 +14996,16 @@ static IrInstGen *ir_analyze_enum_literal(IrAnalyze *ira, IrInst* source_instr,...@@ -14996,25 +14996,16 @@ static IrInstGen *ir_analyze_enum_literal(IrAnalyze *ira, IrInst* source_instr,
14996}14996}
1499714997
14998static IrInstGen *ir_analyze_struct_literal_to_array(IrAnalyze *ira, IrInst* source_instr,14998static IrInstGen *ir_analyze_struct_literal_to_array(IrAnalyze *ira, IrInst* source_instr,
14999 IrInstGen *struct_operand, ZigType *wanted_type)14999 IrInstGen *struct_ptr, ZigType *actual_type, ZigType *wanted_type)
15000{15000{
15001 Error err;15001 Error err;
1500215002
15003 IrInstGen *struct_ptr = ir_get_ref(ira, source_instr, struct_operand, true, false);
15004 if (type_is_invalid(struct_ptr->value->type))
15005 return ira->codegen->invalid_inst_gen;
15006
15007 if ((err = type_resolve(ira->codegen, wanted_type, ResolveStatusSizeKnown)))15003 if ((err = type_resolve(ira->codegen, wanted_type, ResolveStatusSizeKnown)))
15008 return ira->codegen->invalid_inst_gen;15004 return ira->codegen->invalid_inst_gen;
15009 15005
15010 size_t array_len = wanted_type->data.array.len;15006 size_t array_len = wanted_type->data.array.len;
15011 size_t instr_field_count = struct_operand->value->type->data.structure.src_field_count;15007 size_t instr_field_count = actual_type->data.structure.src_field_count;
1501215008 assert(array_len == instr_field_count);
15013 if (instr_field_count != array_len) {
15014 ir_add_error(ira, source_instr, buf_sprintf("expected %" ZIG_PRI_usize " fields, found %" ZIG_PRI_usize,
15015 array_len, instr_field_count));
15016 return ira->codegen->invalid_inst_gen;
15017 }
1501815009
15019 bool need_comptime = ir_should_inline(ira->old_irb.exec, source_instr->scope)15010 bool need_comptime = ir_should_inline(ira->old_irb.exec, source_instr->scope)
15020 || type_requires_comptime(ira->codegen, wanted_type) == ReqCompTimeYes;15011 || type_requires_comptime(ira->codegen, wanted_type) == ReqCompTimeYes;
...@@ -15028,10 +15019,10 @@ static IrInstGen *ir_analyze_struct_literal_to_array(IrAnalyze *ira, IrInst* sou...@@ -15028,10 +15019,10 @@ static IrInstGen *ir_analyze_struct_literal_to_array(IrAnalyze *ira, IrInst* sou
15028 IrInstGen *const_result = ir_const(ira, source_instr, wanted_type);15019 IrInstGen *const_result = ir_const(ira, source_instr, wanted_type);
1502915020
15030 for (size_t i = 0; i < array_len; i += 1) {15021 for (size_t i = 0; i < array_len; i += 1) {
15031 TypeStructField *src_field = struct_operand->value->type->data.structure.fields[i];15022 TypeStructField *src_field = actual_type->data.structure.fields[i];
1503215023
15033 IrInstGen *field_ptr = ir_analyze_struct_field_ptr(ira, source_instr, src_field, struct_ptr,15024 IrInstGen *field_ptr = ir_analyze_struct_field_ptr(ira, source_instr, src_field, struct_ptr,
15034 struct_operand->value->type, false);15025 actual_type, false);
15035 if (type_is_invalid(field_ptr->value->type))15026 if (type_is_invalid(field_ptr->value->type))
15036 return ira->codegen->invalid_inst_gen;15027 return ira->codegen->invalid_inst_gen;
15037 IrInstGen *field_value = ir_get_deref(ira, source_instr, field_ptr, nullptr);15028 IrInstGen *field_value = ir_get_deref(ira, source_instr, field_ptr, nullptr);
...@@ -15087,18 +15078,14 @@ static IrInstGen *ir_analyze_struct_literal_to_array(IrAnalyze *ira, IrInst* sou...@@ -15087,18 +15078,14 @@ static IrInstGen *ir_analyze_struct_literal_to_array(IrAnalyze *ira, IrInst* sou
15087 heap::c_allocator.deallocate(elem_values, array_len);15078 heap::c_allocator.deallocate(elem_values, array_len);
15088 heap::c_allocator.deallocate(casted_fields, array_len);15079 heap::c_allocator.deallocate(casted_fields, array_len);
1508915080
15090 return ir_get_deref(ira, source_instr, result_loc_inst, nullptr);15081 return result_loc_inst;
15091}15082}
1509215083
15093static IrInstGen *ir_analyze_struct_literal_to_struct(IrAnalyze *ira, IrInst* source_instr,15084static IrInstGen *ir_analyze_struct_literal_to_struct(IrAnalyze *ira, IrInst* source_instr,
15094 IrInstGen *struct_operand, ZigType *wanted_type)15085 IrInstGen *struct_ptr, ZigType *actual_type, ZigType *wanted_type)
15095{15086{
15096 Error err;15087 Error err;
1509715088
15098 IrInstGen *struct_ptr = ir_get_ref(ira, source_instr, struct_operand, true, false);
15099 if (type_is_invalid(struct_ptr->value->type))
15100 return ira->codegen->invalid_inst_gen;
15101
15102 if (wanted_type->data.structure.resolve_status == ResolveStatusBeingInferred) {15089 if (wanted_type->data.structure.resolve_status == ResolveStatusBeingInferred) {
15103 ir_add_error(ira, source_instr, buf_sprintf("type coercion of anon struct literal to inferred struct"));15090 ir_add_error(ira, source_instr, buf_sprintf("type coercion of anon struct literal to inferred struct"));
15104 return ira->codegen->invalid_inst_gen;15091 return ira->codegen->invalid_inst_gen;
...@@ -15108,7 +15095,7 @@ static IrInstGen *ir_analyze_struct_literal_to_struct(IrAnalyze *ira, IrInst* so...@@ -15108,7 +15095,7 @@ static IrInstGen *ir_analyze_struct_literal_to_struct(IrAnalyze *ira, IrInst* so
15108 return ira->codegen->invalid_inst_gen;15095 return ira->codegen->invalid_inst_gen;
1510915096
15110 size_t actual_field_count = wanted_type->data.structure.src_field_count;15097 size_t actual_field_count = wanted_type->data.structure.src_field_count;
15111 size_t instr_field_count = struct_operand->value->type->data.structure.src_field_count;15098 size_t instr_field_count = actual_type->data.structure.src_field_count;
1511215099
15113 bool need_comptime = ir_should_inline(ira->old_irb.exec, source_instr->scope)15100 bool need_comptime = ir_should_inline(ira->old_irb.exec, source_instr->scope)
15114 || type_requires_comptime(ira->codegen, wanted_type) == ReqCompTimeYes;15101 || type_requires_comptime(ira->codegen, wanted_type) == ReqCompTimeYes;
...@@ -15122,7 +15109,7 @@ static IrInstGen *ir_analyze_struct_literal_to_struct(IrAnalyze *ira, IrInst* so...@@ -15122,7 +15109,7 @@ static IrInstGen *ir_analyze_struct_literal_to_struct(IrAnalyze *ira, IrInst* so
15122 IrInstGen *const_result = ir_const(ira, source_instr, wanted_type);15109 IrInstGen *const_result = ir_const(ira, source_instr, wanted_type);
1512315110
15124 for (size_t i = 0; i < instr_field_count; i += 1) {15111 for (size_t i = 0; i < instr_field_count; i += 1) {
15125 TypeStructField *src_field = struct_operand->value->type->data.structure.fields[i];15112 TypeStructField *src_field = actual_type->data.structure.fields[i];
15126 TypeStructField *dst_field = find_struct_type_field(wanted_type, src_field->name);15113 TypeStructField *dst_field = find_struct_type_field(wanted_type, src_field->name);
15127 if (dst_field == nullptr) {15114 if (dst_field == nullptr) {
15128 ErrorMsg *msg = ir_add_error(ira, source_instr, buf_sprintf("no field named '%s' in struct '%s'",15115 ErrorMsg *msg = ir_add_error(ira, source_instr, buf_sprintf("no field named '%s' in struct '%s'",
...@@ -15146,7 +15133,7 @@ static IrInstGen *ir_analyze_struct_literal_to_struct(IrAnalyze *ira, IrInst* so...@@ -15146,7 +15133,7 @@ static IrInstGen *ir_analyze_struct_literal_to_struct(IrAnalyze *ira, IrInst* so
15146 field_assign_nodes[dst_field->src_index] = src_field->decl_node;15133 field_assign_nodes[dst_field->src_index] = src_field->decl_node;
1514715134
15148 IrInstGen *field_ptr = ir_analyze_struct_field_ptr(ira, source_instr, src_field, struct_ptr,15135 IrInstGen *field_ptr = ir_analyze_struct_field_ptr(ira, source_instr, src_field, struct_ptr,
15149 struct_operand->value->type, false);15136 actual_type, false);
15150 if (type_is_invalid(field_ptr->value->type))15137 if (type_is_invalid(field_ptr->value->type))
15151 return ira->codegen->invalid_inst_gen;15138 return ira->codegen->invalid_inst_gen;
15152 IrInstGen *field_value = ir_get_deref(ira, source_instr, field_ptr, nullptr);15139 IrInstGen *field_value = ir_get_deref(ira, source_instr, field_ptr, nullptr);
...@@ -15226,14 +15213,13 @@ static IrInstGen *ir_analyze_struct_literal_to_struct(IrAnalyze *ira, IrInst* so...@@ -15226,14 +15213,13 @@ static IrInstGen *ir_analyze_struct_literal_to_struct(IrAnalyze *ira, IrInst* so
15226 heap::c_allocator.deallocate(field_values, actual_field_count);15213 heap::c_allocator.deallocate(field_values, actual_field_count);
15227 heap::c_allocator.deallocate(casted_fields, actual_field_count);15214 heap::c_allocator.deallocate(casted_fields, actual_field_count);
1522815215
15229 return ir_get_deref(ira, source_instr, result_loc_inst, nullptr);15216 return result_loc_inst;
15230}15217}
1523115218
15232static IrInstGen *ir_analyze_struct_literal_to_union(IrAnalyze *ira, IrInst* source_instr,15219static IrInstGen *ir_analyze_struct_literal_to_union(IrAnalyze *ira, IrInst* source_instr,
15233 IrInstGen *value, ZigType *union_type)15220 IrInstGen *struct_ptr, ZigType *struct_type, ZigType *union_type)
15234{15221{
15235 Error err;15222 Error err;
15236 ZigType *struct_type = value->value->type;
1523715223
15238 assert(struct_type->id == ZigTypeIdStruct);15224 assert(struct_type->id == ZigTypeIdStruct);
15239 assert(union_type->id == ZigTypeIdUnion);15225 assert(union_type->id == ZigTypeIdUnion);
...@@ -15256,7 +15242,11 @@ static IrInstGen *ir_analyze_struct_literal_to_union(IrAnalyze *ira, IrInst* sou...@@ -15256,7 +15242,11 @@ static IrInstGen *ir_analyze_struct_literal_to_union(IrAnalyze *ira, IrInst* sou
15256 if (payload_type == nullptr)15242 if (payload_type == nullptr)
15257 return ira->codegen->invalid_inst_gen;15243 return ira->codegen->invalid_inst_gen;
1525815244
15259 IrInstGen *field_value = ir_analyze_struct_value_field_value(ira, source_instr, value, only_field);15245 IrInstGen *field_ptr = ir_analyze_struct_field_ptr(ira, source_instr, only_field, struct_ptr,
15246 struct_type, false);
15247 if (type_is_invalid(field_ptr->value->type))
15248 return ira->codegen->invalid_inst_gen;
15249 IrInstGen *field_value = ir_get_deref(ira, source_instr, field_ptr, nullptr);
15260 if (type_is_invalid(field_value->value->type))15250 if (type_is_invalid(field_value->value->type))
15261 return ira->codegen->invalid_inst_gen;15251 return ira->codegen->invalid_inst_gen;
1526215252
...@@ -15294,7 +15284,7 @@ static IrInstGen *ir_analyze_struct_literal_to_union(IrAnalyze *ira, IrInst* sou...@@ -15294,7 +15284,7 @@ static IrInstGen *ir_analyze_struct_literal_to_union(IrAnalyze *ira, IrInst* sou
15294 if (type_is_invalid(store_ptr_inst->value->type))15284 if (type_is_invalid(store_ptr_inst->value->type))
15295 return ira->codegen->invalid_inst_gen;15285 return ira->codegen->invalid_inst_gen;
1529615286
15297 return ir_get_deref(ira, source_instr, result_loc_inst, nullptr);15287 return result_loc_inst;
15298}15288}
1529915289
15300// Add a compile error and return ErrorSemanticAnalyzeFail if the pointer alignment does not work,15290// Add a compile error and return ErrorSemanticAnalyzeFail if the pointer alignment does not work,
...@@ -15927,13 +15917,76 @@ static IrInstGen *ir_analyze_cast(IrAnalyze *ira, IrInst *source_instr,...@@ -15927,13 +15917,76 @@ static IrInstGen *ir_analyze_cast(IrAnalyze *ira, IrInst *source_instr,
15927 if (wanted_type->id == ZigTypeIdArray && (is_array_init || field_count == 0) &&15917 if (wanted_type->id == ZigTypeIdArray && (is_array_init || field_count == 0) &&
15928 wanted_type->data.array.len == field_count)15918 wanted_type->data.array.len == field_count)
15929 {15919 {
15930 return ir_analyze_struct_literal_to_array(ira, source_instr, value, wanted_type);15920 IrInstGen *struct_ptr = ir_get_ref(ira, source_instr, value, true, false);
15921 if (type_is_invalid(struct_ptr->value->type))
15922 return ira->codegen->invalid_inst_gen;
15923
15924 IrInstGen *ptr = ir_analyze_struct_literal_to_array(ira, source_instr, struct_ptr, actual_type, wanted_type);
15925 if (ptr->value->type->id != ZigTypeIdPointer)
15926 return ptr;
15927 return ir_get_deref(ira, source_instr, ptr, nullptr);
15931 } else if (wanted_type->id == ZigTypeIdStruct && !is_slice(wanted_type) &&15928 } else if (wanted_type->id == ZigTypeIdStruct && !is_slice(wanted_type) &&
15932 (!is_array_init || field_count == 0))15929 (!is_array_init || field_count == 0))
15933 {15930 {
15934 return ir_analyze_struct_literal_to_struct(ira, source_instr, value, wanted_type);15931 IrInstGen *struct_ptr = ir_get_ref(ira, source_instr, value, true, false);
15932 if (type_is_invalid(struct_ptr->value->type))
15933 return ira->codegen->invalid_inst_gen;
15934
15935 IrInstGen *ptr = ir_analyze_struct_literal_to_struct(ira, source_instr, struct_ptr, actual_type, wanted_type);
15936 if (ptr->value->type->id != ZigTypeIdPointer)
15937 return ptr;
15938 return ir_get_deref(ira, source_instr, ptr, nullptr);
15935 } else if (wanted_type->id == ZigTypeIdUnion && !is_array_init && field_count == 1) {15939 } else if (wanted_type->id == ZigTypeIdUnion && !is_array_init && field_count == 1) {
15936 return ir_analyze_struct_literal_to_union(ira, source_instr, value, wanted_type);15940 IrInstGen *struct_ptr = ir_get_ref(ira, source_instr, value, true, false);
15941 if (type_is_invalid(struct_ptr->value->type))
15942 return ira->codegen->invalid_inst_gen;
15943
15944 IrInstGen *ptr = ir_analyze_struct_literal_to_union(ira, source_instr, struct_ptr, actual_type, wanted_type);
15945 if (ptr->value->type->id != ZigTypeIdPointer)
15946 return ptr;
15947 return ir_get_deref(ira, source_instr, ptr, nullptr);
15948 }
15949 }
15950
15951 // cast from pointer to inferred struct type to pointer to array, union, or struct
15952 if (actual_type->id == ZigTypeIdPointer && is_anon_container(actual_type->data.pointer.child_type)) {
15953 ZigType *anon_type = actual_type->data.pointer.child_type;
15954 const bool is_array_init =
15955 anon_type->data.structure.special == StructSpecialInferredTuple;
15956 const uint32_t field_count = anon_type->data.structure.src_field_count;
15957
15958 if (wanted_type->id == ZigTypeIdPointer) {
15959 ZigType *wanted_child = wanted_type->data.pointer.child_type;
15960 if (wanted_child->id == ZigTypeIdArray && (is_array_init || field_count == 0) &&
15961 wanted_child->data.array.len == field_count)
15962 {
15963 IrInstGen *res = ir_analyze_struct_literal_to_array(ira, source_instr, value, anon_type, wanted_child);
15964 if (res->value->type->id == ZigTypeIdPointer)
15965 return res;
15966 return ir_get_ref(ira, source_instr, res, wanted_type->data.pointer.is_const, wanted_type->data.pointer.is_volatile);
15967 } else if (wanted_child->id == ZigTypeIdStruct && !is_slice(wanted_type) &&
15968 (!is_array_init || field_count == 0))
15969 {
15970 IrInstGen *res = ir_analyze_struct_literal_to_struct(ira, source_instr, value, anon_type, wanted_child);
15971 if (res->value->type->id == ZigTypeIdPointer)
15972 return res;
15973 return ir_get_ref(ira, source_instr, res, wanted_type->data.pointer.is_const, wanted_type->data.pointer.is_volatile);
15974 } else if (wanted_child->id == ZigTypeIdUnion && !is_array_init && field_count == 1) {
15975 IrInstGen *res = ir_analyze_struct_literal_to_union(ira, source_instr, value, anon_type, wanted_child);
15976 if (res->value->type->id == ZigTypeIdPointer)
15977 return res;
15978 return ir_get_ref(ira, source_instr, res, wanted_type->data.pointer.is_const, wanted_type->data.pointer.is_volatile);
15979 }
15980 } else if (is_slice(wanted_type) && (is_array_init || field_count == 0)) {
15981 ZigType *slice_child_type = wanted_type->data.structure.fields[slice_ptr_index]->type_entry->data.pointer.child_type;
15982 ZigType *slice_array_type = get_array_type(ira->codegen, slice_child_type, field_count, nullptr);
15983 IrInstGen *res = ir_analyze_struct_literal_to_array(ira, source_instr, value, anon_type, slice_array_type);
15984 if (type_is_invalid(res->value->type))
15985 return ira->codegen->invalid_inst_gen;
15986 if (res->value->type->id != ZigTypeIdPointer)
15987 res = ir_get_ref(ira, source_instr, res, wanted_type->data.pointer.is_const, wanted_type->data.pointer.is_volatile);
15988
15989 return ir_resolve_ptr_of_array_to_slice(ira, source_instr, res, wanted_type, nullptr);
15937 }15990 }
15938 }15991 }
1593915992
test/stage1/behavior/array.zig+28
...@@ -459,3 +459,31 @@ test "type coercion of anon struct literal to array" {...@@ -459,3 +459,31 @@ test "type coercion of anon struct literal to array" {
459 S.doTheTest();459 S.doTheTest();
460 comptime S.doTheTest();460 comptime S.doTheTest();
461}461}
462
463test "type coercion of pointer to anon struct literal to pointer to array" {
464 const S = struct {
465 const U = union{
466 a: u32,
467 b: bool,
468 c: []const u8,
469 };
470
471 fn doTheTest() void {
472 var x1: u8 = 42;
473 const t1 = &.{ x1, 56, 54 };
474 var arr1: *[3]u8 = t1;
475 expect(arr1[0] == 42);
476 expect(arr1[1] == 56);
477 expect(arr1[2] == 54);
478
479 var x2: U = .{ .a = 42 };
480 const t2 = &.{ x2, .{ .b = true }, .{ .c = "hello" } };
481 var arr2: *[3]U = t2;
482 expect(arr2[0].a == 42);
483 expect(arr2[1].b == true);
484 expect(mem.eql(u8, arr2[2].c, "hello"));
485 }
486 };
487 S.doTheTest();
488 comptime S.doTheTest();
489}
test/stage1/behavior/slice.zig+30
...@@ -304,3 +304,33 @@ test "slice of hardcoded address to pointer" {...@@ -304,3 +304,33 @@ test "slice of hardcoded address to pointer" {
304304
305 S.doTheTest();305 S.doTheTest();
306}306}
307
308test "type coercion of pointer to anon struct literal to pointer to slice" {
309 const S = struct {
310 const U = union{
311 a: u32,
312 b: bool,
313 c: []const u8,
314 };
315
316 fn doTheTest() void {
317 var x1: u8 = 42;
318 const t1 = &.{ x1, 56, 54 };
319 var slice1: []u8 = t1;
320 expect(slice1.len == 3);
321 expect(slice1[0] == 42);
322 expect(slice1[1] == 56);
323 expect(slice1[2] == 54);
324
325 var x2: []const u8 = "hello";
326 const t2 = &.{ x2, ", ", "world!" };
327 var slice2: [][]const u8 = t2;
328 expect(slice2.len == 3);
329 expect(mem.eql(u8, slice2[0], "hello"));
330 expect(mem.eql(u8, slice2[1], ", "));
331 expect(mem.eql(u8, slice2[2], "world!"));
332 }
333 };
334 S.doTheTest();
335 comptime S.doTheTest();
336}
test/stage1/behavior/struct.zig+33
...@@ -885,6 +885,39 @@ test "type coercion of anon struct literal to struct" {...@@ -885,6 +885,39 @@ test "type coercion of anon struct literal to struct" {
885 comptime S.doTheTest();885 comptime S.doTheTest();
886}886}
887887
888test "type coercion of pointer to anon struct literal to pointer to struct" {
889 const S = struct {
890 const S2 = struct {
891 A: u32,
892 B: []const u8,
893 C: void,
894 D: Foo = .{},
895 };
896
897 const Foo = struct {
898 field: i32 = 1234,
899 };
900
901 fn doTheTest() void {
902 var y: u32 = 42;
903 const t0 = &.{ .A = 123, .B = "foo", .C = {} };
904 const t1 = &.{ .A = y, .B = "foo", .C = {} };
905 const y0: *S2 = t0;
906 var y1: *S2 = t1;
907 expect(y0.A == 123);
908 expect(std.mem.eql(u8, y0.B, "foo"));
909 expect(y0.C == {});
910 expect(y0.D.field == 1234);
911 expect(y1.A == y);
912 expect(std.mem.eql(u8, y1.B, "foo"));
913 expect(y1.C == {});
914 expect(y1.D.field == 1234);
915 }
916 };
917 S.doTheTest();
918 comptime S.doTheTest();
919}
920
888test "packed struct with undefined initializers" {921test "packed struct with undefined initializers" {
889 const S = struct {922 const S = struct {
890 const P = packed struct {923 const P = packed struct {
test/stage1/behavior/union.zig+27
...@@ -667,6 +667,33 @@ test "cast from anonymous struct to union" {...@@ -667,6 +667,33 @@ test "cast from anonymous struct to union" {
667 comptime S.doTheTest();667 comptime S.doTheTest();
668}668}
669669
670test "cast from pointer to anonymous struct to pointer to union" {
671 const S = struct {
672 const U = union(enum) {
673 A: u32,
674 B: []const u8,
675 C: void,
676 };
677 fn doTheTest() void {
678 var y: u32 = 42;
679 const t0 = &.{ .A = 123 };
680 const t1 = &.{ .B = "foo" };
681 const t2 = &.{ .C = {} };
682 const t3 = &.{ .A = y };
683 const x0: *U = t0;
684 var x1: *U = t1;
685 const x2: *U = t2;
686 var x3: *U = t3;
687 expect(x0.A == 123);
688 expect(std.mem.eql(u8, x1.B, "foo"));
689 expect(x2.* == .C);
690 expect(x3.A == y);
691 }
692 };
693 S.doTheTest();
694 comptime S.doTheTest();
695}
696
670test "method call on an empty union" {697test "method call on an empty union" {
671 const S = struct {698 const S = struct {
672 const MyUnion = union(Tag) {699 const MyUnion = union(Tag) {