authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2020-11-23 00:26:34+02:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2020-12-25 14:57:46+02:00
loged028fd66041e660b0986ceca0edbcfd5089b2f1
tree71d77b1cc59c241c3fa852d02f675e3f75e35127
parent830bc41b1f71d5366037f3944d35618d8ca46e51
signaturelock-open Commit is signed but in an unrecognized format.

stage1: implement type coercion of anon list to array


2 files changed, 119 insertions(+), 3 deletions(-)

src/stage1/ir.cpp+91-3
......@@ -14996,10 +14996,98 @@ static IrInstGen *ir_analyze_enum_literal(IrAnalyze *ira, IrInst* source_instr,
1499614996}
1499714997
1499814998static IrInstGen *ir_analyze_struct_literal_to_array(IrAnalyze *ira, IrInst* source_instr,
14999 IrInstGen *value, ZigType *wanted_type)
14999 IrInstGen *struct_operand, ZigType *wanted_type)
1500015000{
15001 ir_add_error(ira, source_instr, buf_sprintf("TODO: type coercion of anon list literal to array"));
15002 return ira->codegen->invalid_inst_gen;
15001 Error err;
15002
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)))
15008 return ira->codegen->invalid_inst_gen;
15009
15010 size_t array_len = wanted_type->data.array.len;
15011 size_t instr_field_count = struct_operand->value->type->data.structure.src_field_count;
15012
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 }
15018
15019 bool need_comptime = ir_should_inline(ira->old_irb.exec, source_instr->scope)
15020 || type_requires_comptime(ira->codegen, wanted_type) == ReqCompTimeYes;
15021 bool is_comptime = true;
15022
15023 ZigType *elem_type = wanted_type->data.array.child_type;
15024
15025 // Determine if the struct_operand will be comptime.
15026 ZigValue *elem_values = heap::c_allocator.allocate<ZigValue>(array_len);
15027 IrInstGen **casted_fields = heap::c_allocator.allocate<IrInstGen *>(array_len);
15028 IrInstGen *const_result = ir_const(ira, source_instr, wanted_type);
15029
15030 for (size_t i = 0; i < array_len; i += 1) {
15031 TypeStructField *src_field = struct_operand->value->type->data.structure.fields[i];
15032
15033 IrInstGen *field_ptr = ir_analyze_struct_field_ptr(ira, source_instr, src_field, struct_ptr,
15034 struct_operand->value->type, false);
15035 if (type_is_invalid(field_ptr->value->type))
15036 return ira->codegen->invalid_inst_gen;
15037 IrInstGen *field_value = ir_get_deref(ira, source_instr, field_ptr, nullptr);
15038 if (type_is_invalid(field_value->value->type))
15039 return ira->codegen->invalid_inst_gen;
15040 IrInstGen *casted_value = ir_implicit_cast(ira, field_value, elem_type);
15041 if (type_is_invalid(casted_value->value->type))
15042 return ira->codegen->invalid_inst_gen;
15043
15044 casted_fields[i] = casted_value;
15045 if (need_comptime || instr_is_comptime(casted_value)) {
15046 ZigValue *field_val = ir_resolve_const(ira, casted_value, UndefOk);
15047 if (field_val == nullptr)
15048 return ira->codegen->invalid_inst_gen;
15049
15050 field_val->parent.id = ConstParentIdArray;
15051 field_val->parent.data.p_array.array_val = const_result->value;
15052 field_val->parent.data.p_array.elem_index = i;
15053 elem_values[i] = *field_val;
15054 if (field_val->type->id == ZigTypeIdUndefined) {
15055 elem_values[i].special = ConstValSpecialUndef;
15056 }
15057 } else {
15058 is_comptime = false;
15059 }
15060 }
15061
15062 if (is_comptime) {
15063 IrInstGen *const_result = ir_const(ira, source_instr, wanted_type);
15064 const_result->value->data.x_array.special = ConstArraySpecialNone;
15065 const_result->value->data.x_array.data.s_none.elements = elem_values;
15066 return const_result;
15067 }
15068
15069 IrInstGen *result_loc_inst = ir_resolve_result(ira, source_instr, no_result_loc(),
15070 wanted_type, nullptr, true, true);
15071 if (type_is_invalid(result_loc_inst->value->type) || result_loc_inst->value->type->id == ZigTypeIdUnreachable) {
15072 return ira->codegen->invalid_inst_gen;
15073 }
15074
15075 ZigType *elem_type_ptr = get_pointer_to_type(ira->codegen, elem_type, false);
15076 for (size_t i = 0; i < array_len; i += 1) {
15077 IrInstGen *index_val = ir_const(ira, source_instr, ira->codegen->builtin_types.entry_usize);
15078 bigint_init_unsigned(&index_val->value->data.x_bigint, i);
15079
15080 IrInstGen *elem_ptr = ir_build_elem_ptr_gen(ira, source_instr->scope, source_instr->source_node,
15081 result_loc_inst, index_val, false, elem_type_ptr);
15082 IrInstGen *store_ptr_inst = ir_analyze_store_ptr(ira, source_instr, elem_ptr, casted_fields[i], true);
15083 if (type_is_invalid(store_ptr_inst->value->type))
15084 return ira->codegen->invalid_inst_gen;
15085 }
15086
15087 heap::c_allocator.deallocate(elem_values, array_len);
15088 heap::c_allocator.deallocate(casted_fields, array_len);
15089
15090 return ir_get_deref(ira, source_instr, result_loc_inst, nullptr);
1500315091}
1500415092
1500515093static IrInstGen *ir_analyze_struct_literal_to_struct(IrAnalyze *ira, IrInst* source_instr,
test/stage1/behavior/array.zig+28
......@@ -431,3 +431,31 @@ test "zero-sized array with recursive type definition" {
431431 var t: S = .{ .list = .{ .s = undefined } };
432432 expectEqual(@as(usize, 0), t.list.x);
433433}
434
435test "type coercion of anon struct literal to array" {
436 const S = struct {
437 const U = union{
438 a: u32,
439 b: bool,
440 c: []const u8,
441 };
442
443 fn doTheTest() void {
444 var x1: u8 = 42;
445 const t1 = .{ x1, 56, 54 };
446 var arr1: [3]u8 = t1;
447 expect(arr1[0] == 42);
448 expect(arr1[1] == 56);
449 expect(arr1[2] == 54);
450
451 var x2: U = .{ .a = 42 };
452 const t2 = .{ x2, .{ .b = true }, .{ .c = "hello" } };
453 var arr2: [3]U = t2;
454 expect(arr2[0].a == 42);
455 expect(arr2[1].b == true);
456 expect(mem.eql(u8, arr2[2].c, "hello"));
457 }
458 };
459 S.doTheTest();
460 comptime S.doTheTest();
461}