From 1479c28b496e7c1db134b51f23dd2eb934b123bb Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Mon, 16 Mar 2020 18:42:01 +0100 Subject: [PATCH] ir: Correct ABI size calculation for arrays Zero-length array with a sentinel may not have zero size. Closes #4749 --- src/analyze.cpp | 17 +++++++---------- src/codegen.cpp | 4 +++- test/stage1/behavior/array.zig | 20 ++++++++++++++++++++ 3 files changed, 30 insertions(+), 11 deletions(-) diff --git a/src/analyze.cpp b/src/analyze.cpp index 33d28269b..d0f8979c7 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -803,13 +803,7 @@ ZigType *get_array_type(CodeGen *g, ZigType *child_type, uint64_t array_size, Zi } buf_appendf(&entry->name, "]%s", buf_ptr(&child_type->name)); - size_t full_array_size; - if (array_size == 0) { - full_array_size = 0; - } else { - full_array_size = array_size + ((sentinel != nullptr) ? 1 : 0); - } - + size_t full_array_size = array_size + ((sentinel != nullptr) ? 1 : 0); entry->size_in_bits = child_type->size_in_bits * full_array_size; entry->abi_align = child_type->abi_align; entry->abi_size = child_type->abi_size * full_array_size; @@ -1197,7 +1191,8 @@ Error type_val_resolve_zero_bits(CodeGen *g, ZigValue *type_val, ZigType *parent LazyValueArrayType *lazy_array_type = reinterpret_cast(type_val->data.x_lazy); - if (lazy_array_type->length < 1) { + // The sentinel counts as an extra element + if (lazy_array_type->length == 0 && lazy_array_type->sentinel == nullptr) { *is_zero_bits = true; return ErrorNone; } @@ -1452,7 +1447,8 @@ static OnePossibleValue type_val_resolve_has_one_possible_value(CodeGen *g, ZigV case LazyValueIdArrayType: { LazyValueArrayType *lazy_array_type = reinterpret_cast(type_val->data.x_lazy); - if (lazy_array_type->length < 1) + // The sentinel counts as an extra element + if (lazy_array_type->length == 0 && lazy_array_type->sentinel == nullptr) return OnePossibleValueYes; return type_val_resolve_has_one_possible_value(g, lazy_array_type->elem_type->value); } @@ -5739,7 +5735,8 @@ OnePossibleValue type_has_one_possible_value(CodeGen *g, ZigType *type_entry) { case ZigTypeIdUnreachable: return OnePossibleValueYes; case ZigTypeIdArray: - if (type_entry->data.array.len == 0) + // The sentinel counts as an extra element + if (type_entry->data.array.len == 0 && type_entry->data.array.sentinel == nullptr) return OnePossibleValueYes; return type_has_one_possible_value(g, type_entry->data.array.child_type); case ZigTypeIdStruct: diff --git a/src/codegen.cpp b/src/codegen.cpp index dc6fe04cb..75f322325 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -3584,7 +3584,9 @@ static bool value_is_all_undef(CodeGen *g, ZigValue *const_val) { } return true; } else if (const_val->type->id == ZigTypeIdArray) { - return value_is_all_undef_array(g, const_val, const_val->type->data.array.len); + const size_t full_len = const_val->type->data.array.len + + (const_val->type->data.array.sentinel != nullptr); + return value_is_all_undef_array(g, const_val, full_len); } else if (const_val->type->id == ZigTypeIdVector) { return value_is_all_undef_array(g, const_val, const_val->type->data.vector.len); } else { diff --git a/test/stage1/behavior/array.zig b/test/stage1/behavior/array.zig index da56864cc..1f2d4a2f6 100644 --- a/test/stage1/behavior/array.zig +++ b/test/stage1/behavior/array.zig @@ -376,3 +376,23 @@ test "type deduction for array subscript expression" { S.doTheTest(); comptime S.doTheTest(); } + +test "sentinel element count towards the ABI size calculation" { + const S = struct { + fn doTheTest() void { + const T = packed struct { + fill_pre: u8 = 0x55, + data: [0:0]u8 = undefined, + fill_post: u8 = 0xAA, + }; + var x = T{}; + var as_slice = mem.asBytes(&x); + expectEqual(@as(usize, 3), as_slice.len); + expectEqual(@as(u8, 0x55), as_slice[0]); + expectEqual(@as(u8, 0xAA), as_slice[2]); + } + }; + + S.doTheTest(); + comptime S.doTheTest(); +}