authorgravatar for thatlemon@gmail.comLemonBoy <thatlemon@gmail.com> 2020-03-09 20:58:25+01:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-03-09 22:08:56-04:00
log1f44b29724b52433d84b43345a52da59f9220e62
treea02ff60c378f78fee29d6559d44954b13ce0417a
parent638d5c3aca7ce1e4fd10060079caa0acb66144c0

ir: Fix codegen of ?*T types where T is zero-sized

* Fix codegen for optional types that decay to a pointer, the type behaves as a boolean * Fix comptime evaluation of zero-sized arrays, always initialize the internal array elements Closes #4673

5 files changed, 77 insertions(+), 19 deletions(-)

src/analyze.cpp+34
......@@ -5797,6 +5797,7 @@ ZigValue *get_the_one_possible_value(CodeGen *g, ZigType *type_entry) {
57975797 ZigValue *result = g->pass1_arena->create<ZigValue>();
57985798 result->type = type_entry;
57995799 result->special = ConstValSpecialStatic;
5800
58005801 if (result->type->id == ZigTypeIdStruct) {
58015802 // The fields array cannot be left unpopulated
58025803 const ZigType *struct_type = result->type;
......@@ -5808,6 +5809,22 @@ ZigValue *get_the_one_possible_value(CodeGen *g, ZigType *type_entry) {
58085809 assert(field_type != nullptr);
58095810 result->data.x_struct.fields[i] = get_the_one_possible_value(g, field_type);
58105811 }
5812 } else if (result->type->id == ZigTypeIdArray) {
5813 // The elements array cannot be left unpopulated
5814 ZigType *array_type = result->type;
5815 ZigType *elem_type = array_type->data.array.child_type;
5816 ZigValue *sentinel_value = array_type->data.array.sentinel;
5817 const size_t elem_count = array_type->data.array.len + (sentinel_value != nullptr);
5818
5819 result->data.x_array.data.s_none.elements = g->pass1_arena->allocate<ZigValue>(elem_count);
5820 for (size_t i = 0; i < elem_count; i += 1) {
5821 ZigValue *elem_val = &result->data.x_array.data.s_none.elements[i];
5822 copy_const_val(g, elem_val, get_the_one_possible_value(g, elem_type));
5823 }
5824 if (sentinel_value != nullptr) {
5825 ZigValue *last_elem_val = &result->data.x_array.data.s_none.elements[elem_count - 1];
5826 copy_const_val(g, last_elem_val, sentinel_value);
5827 }
58115828 } else if (result->type->id == ZigTypeIdPointer) {
58125829 result->data.x_ptr.special = ConstPtrSpecialRef;
58135830 result->data.x_ptr.data.ref.pointee = get_the_one_possible_value(g, result->type->data.pointer.child_type);
......@@ -9537,6 +9554,23 @@ void copy_const_val(CodeGen *g, ZigValue *dest, ZigValue *src) {
95379554 }
95389555}
95399556
9557bool optional_value_is_null(ZigValue *val) {
9558 assert(val->special == ConstValSpecialStatic);
9559 if (get_src_ptr_type(val->type) != nullptr) {
9560 if (val->data.x_ptr.special == ConstPtrSpecialNull) {
9561 return true;
9562 } else if (val->data.x_ptr.special == ConstPtrSpecialHardCodedAddr) {
9563 return val->data.x_ptr.data.hard_coded_addr.addr == 0;
9564 } else {
9565 return false;
9566 }
9567 } else if (is_opt_err_set(val->type)) {
9568 return val->data.x_err_set == nullptr;
9569 } else {
9570 return val->data.x_optional == nullptr;
9571 }
9572}
9573
95409574bool type_is_numeric(ZigType *ty) {
95419575 switch (ty->id) {
95429576 case ZigTypeIdInvalid:
src/analyze.hpp+1
......@@ -198,6 +198,7 @@ size_t type_id_index(ZigType *entry);
198198ZigType *get_generic_fn_type(CodeGen *g, FnTypeId *fn_type_id);
199199LinkLib *create_link_lib(Buf *name);
200200LinkLib *add_link_lib(CodeGen *codegen, Buf *lib);
201bool optional_value_is_null(ZigValue *val);
201202
202203uint32_t get_abi_alignment(CodeGen *g, ZigType *type_entry);
203204ZigType *get_align_amt_type(CodeGen *g);
src/codegen.cpp+11-1
......@@ -6902,8 +6902,18 @@ check: switch (const_val->special) {
69026902 case ZigTypeIdOptional:
69036903 {
69046904 ZigType *child_type = type_entry->data.maybe.child_type;
6905
69056906 if (get_src_ptr_type(type_entry) != nullptr) {
6906 return gen_const_val_ptr(g, const_val, name);
6907 bool has_bits;
6908 if ((err = type_has_bits2(g, child_type, &has_bits)))
6909 codegen_report_errors_and_exit(g);
6910
6911 if (has_bits)
6912 return gen_const_val_ptr(g, const_val, name);
6913
6914 // No bits, treat this value as a boolean
6915 const unsigned bool_val = optional_value_is_null(const_val) ? 0 : 1;
6916 return LLVMConstInt(LLVMInt1Type(), bool_val, false);
69076917 } else if (child_type->id == ZigTypeIdErrorSet) {
69086918 return gen_const_val_err_set(g, const_val, name);
69096919 } else if (!type_has_bits(g, child_type)) {
src/ir.cpp+8-18
......@@ -15478,23 +15478,6 @@ static bool resolve_cmp_op_id(IrBinOp op_id, Cmp cmp) {
1547815478 }
1547915479}
1548015480
15481static bool optional_value_is_null(ZigValue *val) {
15482 assert(val->special == ConstValSpecialStatic);
15483 if (get_src_ptr_type(val->type) != nullptr) {
15484 if (val->data.x_ptr.special == ConstPtrSpecialNull) {
15485 return true;
15486 } else if (val->data.x_ptr.special == ConstPtrSpecialHardCodedAddr) {
15487 return val->data.x_ptr.data.hard_coded_addr.addr == 0;
15488 } else {
15489 return false;
15490 }
15491 } else if (is_opt_err_set(val->type)) {
15492 return val->data.x_err_set == nullptr;
15493 } else {
15494 return val->data.x_optional == nullptr;
15495 }
15496}
15497
1549815481static void set_optional_value_to_null(ZigValue *val) {
1549915482 assert(val->special == ConstValSpecialStatic);
1550015483 if (val->type->id == ZigTypeIdNull) return; // nothing to do
......@@ -17594,7 +17577,14 @@ static IrInstGen *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstSrcDeclV
1759417577
1759517578 ZigValue *init_val = nullptr;
1759617579 if (instr_is_comptime(var_ptr) && var_ptr->value->data.x_ptr.mut != ConstPtrMutRuntimeVar) {
17597 init_val = const_ptr_pointee(ira, ira->codegen, var_ptr->value, decl_var_instruction->base.base.source_node);
17580 ZigValue *ptr_val = ir_resolve_const(ira, var_ptr, UndefBad);
17581 if (ptr_val == nullptr)
17582 return ira->codegen->invalid_inst_gen;
17583
17584 init_val = const_ptr_pointee(ira, ira->codegen, ptr_val, decl_var_instruction->base.base.source_node);
17585 if (init_val == nullptr)
17586 return ira->codegen->invalid_inst_gen;
17587
1759817588 if (is_comptime_var) {
1759917589 if (var->gen_is_const) {
1760017590 var->const_value = init_val;
test/stage1/behavior/optional.zig+23
......@@ -175,3 +175,26 @@ test "0-bit child type coerced to optional return ptr result location" {
175175 S.doTheTest();
176176 comptime S.doTheTest();
177177}
178
179test "0-bit child type coerced to optional" {
180 const S = struct {
181 fn doTheTest() void {
182 var it: Foo = .{
183 .list = undefined,
184 };
185 expect(it.foo() != null);
186 }
187
188 const Empty = struct {};
189 const Foo = struct {
190 list: [10]Empty,
191
192 fn foo(self: *Foo) ?*Empty {
193 const data = &self.list[0];
194 return data;
195 }
196 };
197 };
198 S.doTheTest();
199 comptime S.doTheTest();
200}