| author | |
| committer | |
| log | e3c92d05328d7b40927bed66e7c2500a7853cdc8 |
| tree | 4e6a1b8e5ee17cf644288144bf66fe59f189c7b5 |
| parent | 7a361751e563c131399050f339dc47edf3c32325 |
* 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 unpopulated | 5806 | // 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); | ||
| 5811 | 5810 | ||
| 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 | } |
| 20579 | 20579 | ||
| 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 | } |
| 27661 | 27659 | ||
| 27662 | static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ZigValue *val) { | 27660 | static 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 | } |
| 30 | 30 | ||
| 31 | test "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 | |||
| 31 | test "void arrays" { | 49 | test "void arrays" { |
| 32 | var array: [4]void = undefined; | 50 | var array: [4]void = undefined; |
| 33 | array[0] = void{}; | 51 | array[0] = void{}; |