Skip to content

Commit 7d85c14

Browse files
committed
Support sentinel in @type
1 parent 951dc45 commit 7d85c14

File tree

8 files changed

+147
-60
lines changed

8 files changed

+147
-60
lines changed

src/all_types.hpp

+2
Original file line numberDiff line numberDiff line change
@@ -2027,12 +2027,14 @@ struct CodeGen {
20272027
ZigValue x_null;
20282028
ZigValue x_unreachable;
20292029
ZigValue zero_byte;
2030+
ZigValue optional_zero_byte;
20302031

20312032
ZigValue *for_undefined();
20322033
ZigValue *for_void();
20332034
ZigValue *for_null();
20342035
ZigValue *for_unreachable();
20352036
ZigValue *for_zero_byte();
2037+
ZigValue *for_optional_zero_byte();
20362038
} intern;
20372039

20382040
ZigType *align_amt_type;

src/analyze.cpp

+19-7
Original file line numberDiff line numberDiff line change
@@ -549,6 +549,7 @@ ZigType *get_pointer_to_type_extra2(CodeGen *g, ZigType *child_type, bool is_con
549549
type_id.data.pointer.allow_zero = allow_zero;
550550
type_id.data.pointer.vector_index = vector_index;
551551
type_id.data.pointer.inferred_struct_field = inferred_struct_field;
552+
assert(!sentinel || sentinel->type->id == ZigTypeIdOptional);
552553
type_id.data.pointer.sentinel = sentinel;
553554

554555
auto existing_entry = g->type_table.maybe_get(type_id);
@@ -622,6 +623,7 @@ ZigType *get_pointer_to_type_extra2(CodeGen *g, ZigType *child_type, bool is_con
622623
entry->data.pointer.allow_zero = allow_zero;
623624
entry->data.pointer.vector_index = vector_index;
624625
entry->data.pointer.inferred_struct_field = inferred_struct_field;
626+
assert(!sentinel || sentinel->type->id == ZigTypeIdOptional);
625627
entry->data.pointer.sentinel = sentinel;
626628

627629
append_ptr_type_attrs(&entry->name, entry);
@@ -766,6 +768,7 @@ ZigType *get_array_type(CodeGen *g, ZigType *child_type, uint64_t array_size, Zi
766768
type_id.data.array.codegen = g;
767769
type_id.data.array.child_type = child_type;
768770
type_id.data.array.size = array_size;
771+
assert(!sentinel || sentinel->type->id == ZigTypeIdOptional);
769772
type_id.data.array.sentinel = sentinel;
770773
auto existing_entry = g->type_table.maybe_get(type_id);
771774
if (existing_entry) {
@@ -779,6 +782,7 @@ ZigType *get_array_type(CodeGen *g, ZigType *child_type, uint64_t array_size, Zi
779782
buf_resize(&entry->name, 0);
780783
buf_appendf(&entry->name, "[%" ZIG_PRI_u64, array_size);
781784
if (sentinel != nullptr) {
785+
assert(sentinel->type == get_optional_type(g, child_type));
782786
buf_appendf(&entry->name, ":");
783787
render_const_value(g, &entry->name, sentinel);
784788
}
@@ -797,6 +801,7 @@ ZigType *get_array_type(CodeGen *g, ZigType *child_type, uint64_t array_size, Zi
797801

798802
entry->data.array.child_type = child_type;
799803
entry->data.array.len = array_size;
804+
assert(!sentinel || sentinel->type->id == ZigTypeIdOptional);
800805
entry->data.array.sentinel = sentinel;
801806

802807
g->type_table.put(type_id, entry);
@@ -816,9 +821,12 @@ ZigType *get_slice_type(CodeGen *g, ZigType *ptr_type) {
816821

817822
buf_resize(&entry->name, 0);
818823
buf_appendf(&entry->name, "[");
819-
if (ptr_type->data.pointer.sentinel != nullptr) {
820-
buf_appendf(&entry->name, ":");
821-
render_const_value(g, &entry->name, ptr_type->data.pointer.sentinel);
824+
{
825+
ZigValue *sentinel = get_sentinel_value(ptr_type->data.pointer.sentinel);
826+
if (sentinel != nullptr) {
827+
buf_appendf(&entry->name, ":");
828+
render_const_value(g, &entry->name, sentinel);
829+
}
822830
}
823831
buf_appendf(&entry->name, "]");
824832
append_ptr_type_attrs(&entry->name, ptr_type);
@@ -5659,7 +5667,7 @@ void init_const_str_lit(CodeGen *g, ZigValue *const_val, Buf *str) {
56595667
// first we build the underlying array
56605668
ZigValue *array_val = create_const_vals(1);
56615669
array_val->special = ConstValSpecialStatic;
5662-
array_val->type = get_array_type(g, g->builtin_types.entry_u8, buf_len(str), g->intern.for_zero_byte());
5670+
array_val->type = get_array_type(g, g->builtin_types.entry_u8, buf_len(str), g->intern.for_optional_zero_byte());
56635671
array_val->data.x_array.special = ConstArraySpecialBuf;
56645672
array_val->data.x_array.data.s_buf = str;
56655673

@@ -7072,11 +7080,13 @@ uint32_t type_id_hash(TypeId x) {
70727080
(((uint32_t)x.data.pointer.bit_offset_in_host) ^ (uint32_t)2639019452) +
70737081
(((uint32_t)x.data.pointer.vector_index) ^ (uint32_t)0x19199716) +
70747082
(((uint32_t)x.data.pointer.host_int_bytes) ^ (uint32_t)529908881) *
7075-
(x.data.pointer.sentinel ? hash_const_val(x.data.pointer.sentinel) : (uint32_t)2955491856);
7083+
(get_sentinel_value(x.data.pointer.sentinel) ?
7084+
hash_const_val(get_sentinel_value(x.data.pointer.sentinel)) : (uint32_t)2955491856);
70767085
case ZigTypeIdArray:
70777086
return hash_ptr(x.data.array.child_type) *
70787087
((uint32_t)x.data.array.size ^ (uint32_t)2122979968) *
7079-
(x.data.array.sentinel ? hash_const_val(x.data.array.sentinel) : (uint32_t)1927201585);
7088+
(get_sentinel_value(x.data.array.sentinel) ?
7089+
hash_const_val(get_sentinel_value(x.data.array.sentinel)) : (uint32_t)1927201585);
70807090
case ZigTypeIdInt:
70817091
return (x.data.integer.is_signed ? (uint32_t)2652528194 : (uint32_t)163929201) +
70827092
(((uint32_t)x.data.integer.bit_count) ^ (uint32_t)2998081557);
@@ -8692,7 +8702,9 @@ static void resolve_llvm_types_array(CodeGen *g, ZigType *type) {
86928702

86938703
ZigType *elem_type = type->data.array.child_type;
86948704

8695-
uint64_t extra_len_from_sentinel = (type->data.array.sentinel != nullptr) ? 1 : 0;
8705+
// TODO: should this size be 1 or sizeof sentinel?
8706+
ZigValue *sentinel = get_sentinel_value(type->data.array.sentinel);
8707+
uint64_t extra_len_from_sentinel = (sentinel != nullptr) ? 1 : 0;
86968708
uint64_t full_len = type->data.array.len + extra_len_from_sentinel;
86978709
// TODO https://github.com/ziglang/zig/issues/1424
86988710
type->llvm_type = LLVMArrayType(get_llvm_type(g, elem_type), (unsigned)full_len);

src/codegen.cpp

+27-8
Original file line numberDiff line numberDiff line change
@@ -3707,7 +3707,9 @@ static LLVMValueRef ir_render_elem_ptr(CodeGen *g, IrExecutable *executable, IrI
37073707
array_type = array_type->data.pointer.child_type;
37083708
}
37093709
if (safety_check_on) {
3710-
uint64_t extra_len_from_sentinel = (array_type->data.array.sentinel != nullptr) ? 1 : 0;
3710+
ZigValue *sentinel = get_sentinel_value(array_type->data.array.sentinel);
3711+
// TODO: should this size be 1 or the size of the child element?
3712+
uint64_t extra_len_from_sentinel = (sentinel != nullptr) ? 1 : 0;
37113713
uint64_t full_len = array_type->data.array.len + extra_len_from_sentinel;
37123714
LLVMValueRef end = LLVMConstInt(g->builtin_types.entry_usize->llvm_type, full_len, false);
37133715
add_bounds_check(g, subscript_value, LLVMIntEQ, nullptr, LLVMIntULT, end);
@@ -3769,7 +3771,8 @@ static LLVMValueRef ir_render_elem_ptr(CodeGen *g, IrExecutable *executable, IrI
37693771
assert(len_index != SIZE_MAX);
37703772
LLVMValueRef len_ptr = LLVMBuildStructGEP(g->builder, array_ptr, (unsigned)len_index, "");
37713773
LLVMValueRef len = gen_load_untyped(g, len_ptr, 0, false, "");
3772-
LLVMIntPredicate upper_op = (ptr_type->data.pointer.sentinel != nullptr) ? LLVMIntULE : LLVMIntULT;
3774+
LLVMIntPredicate upper_op = (get_sentinel_value(ptr_type->data.pointer.sentinel) != nullptr) ?
3775+
LLVMIntULE : LLVMIntULT;
37733776
add_bounds_check(g, subscript_value, LLVMIntEQ, nullptr, upper_op, len);
37743777
}
37753778

@@ -6637,8 +6640,8 @@ static LLVMValueRef gen_const_val_ptr(CodeGen *g, ZigValue *const_val, const cha
66376640
ZigValue *array_const_val = const_val->data.x_ptr.data.base_array.array_val;
66386641
assert(array_const_val->type->id == ZigTypeIdArray);
66396642
if (!type_has_bits(array_const_val->type)) {
6640-
if (array_const_val->type->data.array.sentinel != nullptr) {
6641-
ZigValue *pointee = array_const_val->type->data.array.sentinel;
6643+
ZigValue *pointee = get_sentinel_value(array_const_val->type->data.array.sentinel);
6644+
if (pointee != nullptr) {
66426645
render_const_val(g, pointee, "");
66436646
render_const_val_global(g, pointee, "");
66446647
const_val->global_refs->llvm_value = LLVMConstBitCast(pointee->global_refs->llvm_global,
@@ -6964,7 +6967,9 @@ check: switch (const_val->special) {
69646967
case ConstArraySpecialUndef:
69656968
return LLVMGetUndef(get_llvm_type(g, type_entry));
69666969
case ConstArraySpecialNone: {
6967-
uint64_t extra_len_from_sentinel = (type_entry->data.array.sentinel != nullptr) ? 1 : 0;
6970+
ZigValue *sentinel = get_sentinel_value(type_entry->data.array.sentinel);
6971+
// TODO: is this supposed to be 1 or sizeof(sentinel)?
6972+
uint64_t extra_len_from_sentinel = (sentinel != nullptr) ? 1 : 0;
69686973
uint64_t full_len = len + extra_len_from_sentinel;
69696974
LLVMValueRef *values = allocate<LLVMValueRef>(full_len);
69706975
LLVMTypeRef element_type_ref = get_llvm_type(g, type_entry->data.array.child_type);
@@ -6975,8 +6980,8 @@ check: switch (const_val->special) {
69756980
values[i] = val;
69766981
make_unnamed_struct = make_unnamed_struct || is_llvm_value_unnamed_type(g, elem_value->type, val);
69776982
}
6978-
if (type_entry->data.array.sentinel != nullptr) {
6979-
values[len] = gen_const_val(g, type_entry->data.array.sentinel, "");
6983+
if (sentinel != nullptr) {
6984+
values[len] = gen_const_val(g, sentinel, "");
69806985
}
69816986
if (make_unnamed_struct) {
69826987
return LLVMConstStruct(values, full_len, true);
@@ -6987,7 +6992,7 @@ check: switch (const_val->special) {
69876992
case ConstArraySpecialBuf: {
69886993
Buf *buf = const_val->data.x_array.data.s_buf;
69896994
return LLVMConstString(buf_ptr(buf), (unsigned)buf_len(buf),
6990-
type_entry->data.array.sentinel == nullptr);
6995+
get_sentinel_value(type_entry->data.array.sentinel) == nullptr);
69916996
}
69926997
}
69936998
zig_unreachable();
@@ -8040,6 +8045,13 @@ static void define_intern_values(CodeGen *g) {
80408045
value.special = ConstValSpecialStatic;
80418046
bigint_init_unsigned(&value.data.x_bigint, 0);
80428047
}
8048+
{
8049+
auto& value = g->intern.optional_zero_byte;
8050+
value.type = get_optional_type(g, g->builtin_types.entry_u8);
8051+
value.global_refs = allocate<ConstGlobalRefs>(1, "ConstGlobalRefs.optional_zero_byte");
8052+
value.special = ConstValSpecialStatic;
8053+
value.data.x_optional = &g->intern.zero_byte;
8054+
}
80438055
}
80448056

80458057
static BuiltinFnEntry *create_builtin_fn(CodeGen *g, BuiltinFnId id, const char *name, size_t count) {
@@ -10644,3 +10656,10 @@ ZigValue *CodeGen::Intern::for_zero_byte() {
1064410656
#endif
1064510657
return &this->zero_byte;
1064610658
}
10659+
10660+
ZigValue *CodeGen::Intern::for_optional_zero_byte() {
10661+
#ifdef ZIG_ENABLE_MEM_PROFILE
10662+
memprof_intern_count.optional_zero_byte += 1;
10663+
#endif
10664+
return &this->optional_zero_byte;
10665+
}

0 commit comments

Comments
 (0)