Skip to content

Commit e3c92d0

Browse files
LemonBoyandrewrk
authored andcommitted
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.
1 parent 7a36175 commit e3c92d0

File tree

4 files changed

+44
-28
lines changed

4 files changed

+44
-28
lines changed

src/analyze.cpp

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5806,18 +5806,13 @@ ZigValue *get_the_one_possible_value(CodeGen *g, ZigType *type_entry) {
58065806
// The elements array cannot be left unpopulated
58075807
ZigType *array_type = result->type;
58085808
ZigType *elem_type = array_type->data.array.child_type;
5809-
ZigValue *sentinel_value = array_type->data.array.sentinel;
5810-
const size_t elem_count = array_type->data.array.len + (sentinel_value != nullptr);
5809+
const size_t elem_count = array_type->data.array.len;
58115810

58125811
result->data.x_array.data.s_none.elements = g->pass1_arena->allocate<ZigValue>(elem_count);
58135812
for (size_t i = 0; i < elem_count; i += 1) {
58145813
ZigValue *elem_val = &result->data.x_array.data.s_none.elements[i];
58155814
copy_const_val(g, elem_val, get_the_one_possible_value(g, elem_type));
58165815
}
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-
}
58215816
} else if (result->type->id == ZigTypeIdPointer) {
58225817
result->data.x_ptr.special = ConstPtrSpecialRef;
58235818
result->data.x_ptr.data.ref.pointee = get_the_one_possible_value(g, result->type->data.pointer.child_type);

src/codegen.cpp

Lines changed: 22 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -3584,9 +3584,7 @@ static bool value_is_all_undef(CodeGen *g, ZigValue *const_val) {
35843584
}
35853585
return true;
35863586
} else if (const_val->type->id == ZigTypeIdArray) {
3587-
const size_t full_len = 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);
3587+
return value_is_all_undef_array(g, const_val, const_val->type->data.array.len);
35903588
} else if (const_val->type->id == ZigTypeIdVector) {
35913589
return value_is_all_undef_array(g, const_val, const_val->type->data.vector.len);
35923590
} else {
@@ -6792,6 +6790,22 @@ static LLVMValueRef pack_const_int(CodeGen *g, LLVMTypeRef big_int_type_ref, Zig
67926790
used_bits += packed_bits_size;
67936791
}
67946792
}
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+
}
67956809
return val;
67966810
}
67976811
case ZigTypeIdVector:
@@ -6858,20 +6872,11 @@ static LLVMValueRef gen_const_val_ptr(CodeGen *g, ZigValue *const_val, const cha
68586872
ZigValue *array_const_val = const_val->data.x_ptr.data.base_array.array_val;
68596873
assert(array_const_val->type->id == ZigTypeIdArray);
68606874
if (!type_has_bits(g, array_const_val->type)) {
6861-
if (array_const_val->type->data.array.sentinel != nullptr) {
6862-
ZigValue *pointee = array_const_val->type->data.array.sentinel;
6863-
render_const_val(g, pointee, "");
6864-
render_const_val_global(g, pointee, "");
6865-
const_val->llvm_value = LLVMConstBitCast(pointee->llvm_global,
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+
// make this a null pointer
6876+
ZigType *usize = g->builtin_types.entry_usize;
6877+
const_val->llvm_value = LLVMConstIntToPtr(LLVMConstNull(usize->llvm_type),
6878+
get_llvm_type(g, const_val->type));
6879+
return const_val->llvm_value;
68756880
}
68766881
size_t elem_index = const_val->data.x_ptr.data.base_array.elem_index;
68776882
LLVMValueRef uncasted_ptr_val = gen_const_ptr_array_recursive(g, array_const_val, elem_index);

src/ir.cpp

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20578,11 +20578,6 @@ static IrInstGen *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstSrcElemP
2057820578
}
2057920579

2058020580
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-
}
2058620581
ZigType *child_type = array_type->data.array.child_type;
2058720582
if (ptr_type->data.pointer.host_int_bytes == 0) {
2058820583
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
2765727652
buf_write_value_bytes(codegen, &buf[buf_i], elem);
2765827653
buf_i += type_size(codegen, elem->type);
2765927654
}
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+
}
2766027658
}
2766127659

2766227660
static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ZigValue *val) {

test/stage1/behavior/array.zig

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,24 @@ fn getArrayLen(a: []const u32) usize {
2828
return a.len;
2929
}
3030

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+
3149
test "void arrays" {
3250
var array: [4]void = undefined;
3351
array[0] = void{};

0 commit comments

Comments
 (0)