authorgravatar for thatlemon@gmail.comLemonBoy <thatlemon@gmail.com> 2020-03-30 13:27:19+02:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-03-30 11:03:56-04:00
logc1cc1ebc35f7a56669db2f88b6d4ff8f1603ec59
tree17e1064c3d862df1bed5ea4f2e73d789afb1893f
parent8cad45349510b2995a49fc907bdc3c8bf86aa21b

ir: Avoid constant-folding ptr to sentinels

Constant-folding the pointers to the expected sentinel value have some big problems: it hides the real content of the array, makes the pointer to the sentinel point to a completely different memory region and treats it like a const value even when the underlying array is mutable. Fixes #4840

2 files changed, 16 insertions(+), 12 deletions(-)

src/ir.cpp+2-7
...@@ -20880,13 +20880,8 @@ static IrInstGen *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstSrcElemP...@@ -20880,13 +20880,8 @@ static IrInstGen *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstSrcElemP
20880 if (instr_is_comptime(casted_elem_index)) {20880 if (instr_is_comptime(casted_elem_index)) {
20881 uint64_t index = bigint_as_u64(&casted_elem_index->value->data.x_bigint);20881 uint64_t index = bigint_as_u64(&casted_elem_index->value->data.x_bigint);
20882 if (array_type->id == ZigTypeIdArray) {20882 if (array_type->id == ZigTypeIdArray) {
20883 uint64_t array_len = array_type->data.array.len;20883 uint64_t array_len = array_type->data.array.len +
20884 if (index == array_len && array_type->data.array.sentinel != nullptr) {20884 (array_type->data.array.sentinel != nullptr);
20885 ZigType *elem_type = array_type->data.array.child_type;
20886 IrInstGen *sentinel_elem = ir_const(ira, &elem_ptr_instruction->base.base, elem_type);
20887 copy_const_val(ira->codegen, sentinel_elem->value, array_type->data.array.sentinel);
20888 return ir_get_ref(ira, &elem_ptr_instruction->base.base, sentinel_elem, true, false);
20889 }
20890 if (index >= array_len) {20885 if (index >= array_len) {
20891 ir_add_error_node(ira, elem_ptr_instruction->base.base.source_node,20886 ir_add_error_node(ira, elem_ptr_instruction->base.base.source_node,
20892 buf_sprintf("index %" ZIG_PRI_u64 " outside array of size %" ZIG_PRI_u64,20887 buf_sprintf("index %" ZIG_PRI_u64 " outside array of size %" ZIG_PRI_u64,
test/stage1/behavior/array.zig+14-5
...@@ -31,14 +31,23 @@ fn getArrayLen(a: []const u32) usize {...@@ -31,14 +31,23 @@ fn getArrayLen(a: []const u32) usize {
31test "array with sentinels" {31test "array with sentinels" {
32 const S = struct {32 const S = struct {
33 fn doTheTest(is_ct: bool) void {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) {34 if (is_ct) {
35 var zero_sized: [0:0xde]u8 = [_:0xde]u8{};
36 // Disabled at runtime because of
37 // https://github.com/ziglang/zig/issues/4372
38 expectEqual(@as(u8, 0xde), zero_sized[0]);
39 var reinterpreted = @ptrCast(*[1]u8, &zero_sized);39 var reinterpreted = @ptrCast(*[1]u8, &zero_sized);
40 expectEqual(@as(u8, 0xde), reinterpreted[0]);40 expectEqual(@as(u8, 0xde), reinterpreted[0]);
41 }41 }
42 var arr: [3:0x55]u8 = undefined;
43 // Make sure the sentinel pointer is pointing after the last element
44 if (!is_ct) {
45 const sentinel_ptr = @ptrToInt(&arr[3]);
46 const last_elem_ptr = @ptrToInt(&arr[2]);
47 expectEqual(@as(usize, 1), sentinel_ptr - last_elem_ptr);
48 }
49 // Make sure the sentinel is writeable
50 arr[3] = 0x55;
42 }51 }
43 };52 };
4453
...@@ -372,7 +381,7 @@ test "access the null element of a null terminated array" {...@@ -372,7 +381,7 @@ test "access the null element of a null terminated array" {
372 const S = struct {381 const S = struct {
373 fn doTheTest() void {382 fn doTheTest() void {
374 var array: [4:0]u8 = .{ 'a', 'o', 'e', 'u' };383 var array: [4:0]u8 = .{ 'a', 'o', 'e', 'u' };
375 comptime expect(array[4] == 0);384 expect(array[4] == 0);
376 var len: usize = 4;385 var len: usize = 4;
377 expect(array[len] == 0);386 expect(array[len] == 0);
378 }387 }