authorgravatar for thatlemon@gmail.comLemonBoy <thatlemon@gmail.com> 2020-03-19 11:52:15+01:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-03-19 09:53:30-04:00
loge3c92d05328d7b40927bed66e7c2500a7853cdc8
tree4e6a1b8e5ee17cf644288144bf66fe59f189c7b5
parent7a361751e563c131399050f339dc47edf3c32325

ir: More changes to sentinel-terminated const arrays

* Don't add an extra slot for the sentinel. Most of the code keeps using the constant value from the type descriptor, let's harmonize all the code dealing with sentinels. * Properly write out sentinel values when reinterpreting pointers at comptime. * Allow the reading of the 0th element in a `[0:S]T` type.

4 files changed, 44 insertions(+), 28 deletions(-)

src/analyze.cpp+1-6
...@@ -5806,18 +5806,13 @@ ZigValue *get_the_one_possible_value(CodeGen *g, ZigType *type_entry) {...@@ -5806,18 +5806,13 @@ ZigValue *get_the_one_possible_value(CodeGen *g, ZigType *type_entry) {
5806 // The elements array cannot be left unpopulated5806 // The elements array cannot be left unpopulated
5807 ZigType *array_type = result->type;5807 ZigType *array_type = result->type;
5808 ZigType *elem_type = array_type->data.array.child_type;5808 ZigType *elem_type = array_type->data.array.child_type;
5809 ZigValue *sentinel_value = array_type->data.array.sentinel;5809 const size_t elem_count = array_type->data.array.len;
5810 const size_t elem_count = array_type->data.array.len + (sentinel_value != nullptr);
58115810
5812 result->data.x_array.data.s_none.elements = g->pass1_arena->allocate<ZigValue>(elem_count);5811 result->data.x_array.data.s_none.elements = g->pass1_arena->allocate<ZigValue>(elem_count);
5813 for (size_t i = 0; i < elem_count; i += 1) {5812 for (size_t i = 0; i < elem_count; i += 1) {
5814 ZigValue *elem_val = &result->data.x_array.data.s_none.elements[i];5813 ZigValue *elem_val = &result->data.x_array.data.s_none.elements[i];
5815 copy_const_val(g, elem_val, get_the_one_possible_value(g, elem_type));5814 copy_const_val(g, elem_val, get_the_one_possible_value(g, elem_type));
5816 }5815 }
5817 if (sentinel_value != nullptr) {
5818 ZigValue *last_elem_val = &result->data.x_array.data.s_none.elements[elem_count - 1];
5819 copy_const_val(g, last_elem_val, sentinel_value);
5820 }
5821 } else if (result->type->id == ZigTypeIdPointer) {5816 } else if (result->type->id == ZigTypeIdPointer) {
5822 result->data.x_ptr.special = ConstPtrSpecialRef;5817 result->data.x_ptr.special = ConstPtrSpecialRef;
5823 result->data.x_ptr.data.ref.pointee = get_the_one_possible_value(g, result->type->data.pointer.child_type);5818 result->data.x_ptr.data.ref.pointee = get_the_one_possible_value(g, result->type->data.pointer.child_type);
src/codegen.cpp+22-17
...@@ -3584,9 +3584,7 @@ static bool value_is_all_undef(CodeGen *g, ZigValue *const_val) {...@@ -3584,9 +3584,7 @@ static bool value_is_all_undef(CodeGen *g, ZigValue *const_val) {
3584 }3584 }
3585 return true;3585 return true;
3586 } else if (const_val->type->id == ZigTypeIdArray) {3586 } else if (const_val->type->id == ZigTypeIdArray) {
3587 const size_t full_len = const_val->type->data.array.len +3587 return value_is_all_undef_array(g, const_val, const_val->type->data.array.len);
3588 (const_val->type->data.array.sentinel != nullptr);
3589 return value_is_all_undef_array(g, const_val, full_len);
3590 } else if (const_val->type->id == ZigTypeIdVector) {3588 } else if (const_val->type->id == ZigTypeIdVector) {
3591 return value_is_all_undef_array(g, const_val, const_val->type->data.vector.len);3589 return value_is_all_undef_array(g, const_val, const_val->type->data.vector.len);
3592 } else {3590 } else {
...@@ -6792,6 +6790,22 @@ static LLVMValueRef pack_const_int(CodeGen *g, LLVMTypeRef big_int_type_ref, Zig...@@ -6792,6 +6790,22 @@ static LLVMValueRef pack_const_int(CodeGen *g, LLVMTypeRef big_int_type_ref, Zig
6792 used_bits += packed_bits_size;6790 used_bits += packed_bits_size;
6793 }6791 }
6794 }6792 }
6793
6794 if (type_entry->data.array.sentinel != nullptr) {
6795 ZigValue *elem_val = type_entry->data.array.sentinel;
6796 LLVMValueRef child_val = pack_const_int(g, big_int_type_ref, elem_val);
6797
6798 if (is_big_endian) {
6799 LLVMValueRef shift_amt = LLVMConstInt(big_int_type_ref, packed_bits_size, false);
6800 val = LLVMConstShl(val, shift_amt);
6801 val = LLVMConstOr(val, child_val);
6802 } else {
6803 LLVMValueRef shift_amt = LLVMConstInt(big_int_type_ref, used_bits, false);
6804 LLVMValueRef child_val_shifted = LLVMConstShl(child_val, shift_amt);
6805 val = LLVMConstOr(val, child_val_shifted);
6806 used_bits += packed_bits_size;
6807 }
6808 }
6795 return val;6809 return val;
6796 }6810 }
6797 case ZigTypeIdVector:6811 case ZigTypeIdVector:
...@@ -6858,20 +6872,11 @@ static LLVMValueRef gen_const_val_ptr(CodeGen *g, ZigValue *const_val, const cha...@@ -6858,20 +6872,11 @@ static LLVMValueRef gen_const_val_ptr(CodeGen *g, ZigValue *const_val, const cha
6858 ZigValue *array_const_val = const_val->data.x_ptr.data.base_array.array_val;6872 ZigValue *array_const_val = const_val->data.x_ptr.data.base_array.array_val;
6859 assert(array_const_val->type->id == ZigTypeIdArray);6873 assert(array_const_val->type->id == ZigTypeIdArray);
6860 if (!type_has_bits(g, array_const_val->type)) {6874 if (!type_has_bits(g, array_const_val->type)) {
6861 if (array_const_val->type->data.array.sentinel != nullptr) {6875 // make this a null pointer
6862 ZigValue *pointee = array_const_val->type->data.array.sentinel;6876 ZigType *usize = g->builtin_types.entry_usize;
6863 render_const_val(g, pointee, "");6877 const_val->llvm_value = LLVMConstIntToPtr(LLVMConstNull(usize->llvm_type),
6864 render_const_val_global(g, pointee, "");6878 get_llvm_type(g, const_val->type));
6865 const_val->llvm_value = LLVMConstBitCast(pointee->llvm_global,6879 return const_val->llvm_value;
6866 get_llvm_type(g, const_val->type));
6867 return const_val->llvm_value;
6868 } else {
6869 // make this a null pointer
6870 ZigType *usize = g->builtin_types.entry_usize;
6871 const_val->llvm_value = LLVMConstIntToPtr(LLVMConstNull(usize->llvm_type),
6872 get_llvm_type(g, const_val->type));
6873 return const_val->llvm_value;
6874 }
6875 }6880 }
6876 size_t elem_index = const_val->data.x_ptr.data.base_array.elem_index;6881 size_t elem_index = const_val->data.x_ptr.data.base_array.elem_index;
6877 LLVMValueRef uncasted_ptr_val = gen_const_ptr_array_recursive(g, array_const_val, elem_index);6882 LLVMValueRef uncasted_ptr_val = gen_const_ptr_array_recursive(g, array_const_val, elem_index);
src/ir.cpp+3-5
...@@ -20578,11 +20578,6 @@ static IrInstGen *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstSrcElemP...@@ -20578,11 +20578,6 @@ static IrInstGen *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstSrcElemP
20578 }20578 }
2057920579
20580 if (array_type->id == ZigTypeIdArray) {20580 if (array_type->id == ZigTypeIdArray) {
20581 if (array_type->data.array.len == 0) {
20582 ir_add_error_node(ira, elem_ptr_instruction->base.base.source_node,
20583 buf_sprintf("index 0 outside array of size 0"));
20584 return ira->codegen->invalid_inst_gen;
20585 }
20586 ZigType *child_type = array_type->data.array.child_type;20581 ZigType *child_type = array_type->data.array.child_type;
20587 if (ptr_type->data.pointer.host_int_bytes == 0) {20582 if (ptr_type->data.pointer.host_int_bytes == 0) {
20588 return_type = get_pointer_to_type_extra(ira->codegen, child_type,20583 return_type = get_pointer_to_type_extra(ira->codegen, child_type,
...@@ -27657,6 +27652,9 @@ static void buf_write_value_bytes_array(CodeGen *codegen, uint8_t *buf, ZigValue...@@ -27657,6 +27652,9 @@ static void buf_write_value_bytes_array(CodeGen *codegen, uint8_t *buf, ZigValue
27657 buf_write_value_bytes(codegen, &buf[buf_i], elem);27652 buf_write_value_bytes(codegen, &buf[buf_i], elem);
27658 buf_i += type_size(codegen, elem->type);27653 buf_i += type_size(codegen, elem->type);
27659 }27654 }
27655 if (val->type->id == ZigTypeIdArray && val->type->data.array.sentinel != nullptr) {
27656 buf_write_value_bytes(codegen, &buf[buf_i], val->type->data.array.sentinel);
27657 }
27660}27658}
2766127659
27662static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ZigValue *val) {27660static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ZigValue *val) {
test/stage1/behavior/array.zig+18
...@@ -28,6 +28,24 @@ fn getArrayLen(a: []const u32) usize {...@@ -28,6 +28,24 @@ fn getArrayLen(a: []const u32) usize {
28 return a.len;28 return a.len;
29}29}
3030
31test "array with sentinels" {
32 const S = struct {
33 fn doTheTest(is_ct: bool) void {
34 var zero_sized: [0:0xde]u8 = [_:0xde]u8{};
35 expectEqual(@as(u8, 0xde), zero_sized[0]);
36 // Disabled at runtime because of
37 // https://github.com/ziglang/zig/issues/4372
38 if (is_ct) {
39 var reinterpreted = @ptrCast(*[1]u8, &zero_sized);
40 expectEqual(@as(u8, 0xde), reinterpreted[0]);
41 }
42 }
43 };
44
45 S.doTheTest(false);
46 comptime S.doTheTest(true);
47}
48
31test "void arrays" {49test "void arrays" {
32 var array: [4]void = undefined;50 var array: [4]void = undefined;
33 array[0] = void{};51 array[0] = void{};