Skip to content

Support sentinel in @Type #3814

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/all_types.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2023,12 +2023,14 @@ struct CodeGen {
ZigValue x_null;
ZigValue x_unreachable;
ZigValue zero_byte;
ZigValue optional_zero_byte;

ZigValue *for_undefined();
ZigValue *for_void();
ZigValue *for_null();
ZigValue *for_unreachable();
ZigValue *for_zero_byte();
ZigValue *for_optional_zero_byte();
} intern;

ZigType *align_amt_type;
Expand Down
38 changes: 24 additions & 14 deletions src/analyze.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -533,9 +533,10 @@ ZigType *get_pointer_to_type_extra2(CodeGen *g, ZigType *child_type, bool is_con

TypeId type_id = {};
ZigType **parent_pointer = nullptr;
ZigValue *sentinel_unwrapped = get_sentinel_value(sentinel);
if (host_int_bytes != 0 || is_volatile || byte_alignment != 0 || ptr_len != PtrLenSingle ||
allow_zero || vector_index != VECTOR_INDEX_NONE || inferred_struct_field != nullptr ||
sentinel != nullptr)
sentinel_unwrapped != nullptr)
{
type_id.id = ZigTypeIdPointer;
type_id.data.pointer.codegen = g;
Expand Down Expand Up @@ -577,13 +578,13 @@ ZigType *get_pointer_to_type_extra2(CodeGen *g, ZigType *child_type, bool is_con
buf_appendf(&entry->name, "[*");
break;
case PtrLenC:
assert(sentinel == nullptr);
assert(sentinel_unwrapped == nullptr);
buf_appendf(&entry->name, "[*c]");
break;
}
if (sentinel != nullptr) {
if (sentinel_unwrapped != nullptr) {
buf_appendf(&entry->name, ":");
render_const_value(g, &entry->name, sentinel);
render_const_value(g, &entry->name, sentinel_unwrapped);
}
switch (ptr_len) {
case PtrLenSingle:
Expand Down Expand Up @@ -775,20 +776,22 @@ ZigType *get_array_type(CodeGen *g, ZigType *child_type, uint64_t array_size, Zi
assert(type_is_resolved(child_type, ResolveStatusSizeKnown));

ZigType *entry = new_type_table_entry(ZigTypeIdArray);
ZigValue *sentinel_unwrapped = get_sentinel_value(sentinel);

buf_resize(&entry->name, 0);
buf_appendf(&entry->name, "[%" ZIG_PRI_u64, array_size);
if (sentinel != nullptr) {
if (sentinel_unwrapped != nullptr) {
assert(sentinel_unwrapped->type == child_type);
buf_appendf(&entry->name, ":");
render_const_value(g, &entry->name, sentinel);
render_const_value(g, &entry->name, sentinel_unwrapped);
}
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);
full_array_size = array_size + ((sentinel_unwrapped != nullptr) ? 1 : 0);
}

entry->size_in_bits = child_type->size_in_bits * full_array_size;
Expand Down Expand Up @@ -816,9 +819,12 @@ ZigType *get_slice_type(CodeGen *g, ZigType *ptr_type) {

buf_resize(&entry->name, 0);
buf_appendf(&entry->name, "[");
if (ptr_type->data.pointer.sentinel != nullptr) {
buf_appendf(&entry->name, ":");
render_const_value(g, &entry->name, ptr_type->data.pointer.sentinel);
{
ZigValue *sentinel = get_sentinel_value(ptr_type->data.pointer.sentinel);
if (sentinel != nullptr) {
buf_appendf(&entry->name, ":");
render_const_value(g, &entry->name, sentinel);
}
}
buf_appendf(&entry->name, "]");
append_ptr_type_attrs(&entry->name, ptr_type);
Expand Down Expand Up @@ -5660,7 +5666,7 @@ void init_const_str_lit(CodeGen *g, ZigValue *const_val, Buf *str) {
// first we build the underlying array
ZigValue *array_val = create_const_vals(1);
array_val->special = ConstValSpecialStatic;
array_val->type = get_array_type(g, g->builtin_types.entry_u8, buf_len(str), g->intern.for_zero_byte());
array_val->type = get_array_type(g, g->builtin_types.entry_u8, buf_len(str), g->intern.for_optional_zero_byte());
array_val->data.x_array.special = ConstArraySpecialBuf;
array_val->data.x_array.data.s_buf = str;

Expand Down Expand Up @@ -7067,11 +7073,13 @@ uint32_t type_id_hash(TypeId x) {
(((uint32_t)x.data.pointer.bit_offset_in_host) ^ (uint32_t)2639019452) +
(((uint32_t)x.data.pointer.vector_index) ^ (uint32_t)0x19199716) +
(((uint32_t)x.data.pointer.host_int_bytes) ^ (uint32_t)529908881) *
(x.data.pointer.sentinel ? hash_const_val(x.data.pointer.sentinel) : (uint32_t)2955491856);
(get_sentinel_value(x.data.pointer.sentinel) ?
hash_const_val(get_sentinel_value(x.data.pointer.sentinel)) : (uint32_t)2955491856);
case ZigTypeIdArray:
return hash_ptr(x.data.array.child_type) *
((uint32_t)x.data.array.size ^ (uint32_t)2122979968) *
(x.data.array.sentinel ? hash_const_val(x.data.array.sentinel) : (uint32_t)1927201585);
(get_sentinel_value(x.data.array.sentinel) ?
hash_const_val(get_sentinel_value(x.data.array.sentinel)) : (uint32_t)1927201585);
case ZigTypeIdInt:
return (x.data.integer.is_signed ? (uint32_t)2652528194 : (uint32_t)163929201) +
(((uint32_t)x.data.integer.bit_count) ^ (uint32_t)2998081557);
Expand Down Expand Up @@ -8687,7 +8695,9 @@ static void resolve_llvm_types_array(CodeGen *g, ZigType *type) {

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

uint64_t extra_len_from_sentinel = (type->data.array.sentinel != nullptr) ? 1 : 0;
// TODO: should this size be 1 or sizeof sentinel?
ZigValue *sentinel = get_sentinel_value(type->data.array.sentinel);
uint64_t extra_len_from_sentinel = (sentinel != nullptr) ? 1 : 0;
uint64_t full_len = type->data.array.len + extra_len_from_sentinel;
// TODO https://github.com/ziglang/zig/issues/1424
type->llvm_type = LLVMArrayType(get_llvm_type(g, elem_type), (unsigned)full_len);
Expand Down
34 changes: 26 additions & 8 deletions src/codegen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3707,7 +3707,9 @@ static LLVMValueRef ir_render_elem_ptr(CodeGen *g, IrExecutable *executable, IrI
array_type = array_type->data.pointer.child_type;
}
if (safety_check_on) {
uint64_t extra_len_from_sentinel = (array_type->data.array.sentinel != nullptr) ? 1 : 0;
ZigValue *sentinel = get_sentinel_value(array_type->data.array.sentinel);
// TODO: should this size be 1 or the size of the child element?
uint64_t extra_len_from_sentinel = (sentinel != nullptr) ? 1 : 0;
uint64_t full_len = array_type->data.array.len + extra_len_from_sentinel;
LLVMValueRef end = LLVMConstInt(g->builtin_types.entry_usize->llvm_type, full_len, false);
add_bounds_check(g, subscript_value, LLVMIntEQ, nullptr, LLVMIntULT, end);
Expand Down Expand Up @@ -3769,7 +3771,8 @@ static LLVMValueRef ir_render_elem_ptr(CodeGen *g, IrExecutable *executable, IrI
assert(len_index != SIZE_MAX);
LLVMValueRef len_ptr = LLVMBuildStructGEP(g->builder, array_ptr, (unsigned)len_index, "");
LLVMValueRef len = gen_load_untyped(g, len_ptr, 0, false, "");
LLVMIntPredicate upper_op = (ptr_type->data.pointer.sentinel != nullptr) ? LLVMIntULE : LLVMIntULT;
LLVMIntPredicate upper_op = (get_sentinel_value(ptr_type->data.pointer.sentinel) != nullptr) ?
LLVMIntULE : LLVMIntULT;
add_bounds_check(g, subscript_value, LLVMIntEQ, nullptr, upper_op, len);
}

Expand Down Expand Up @@ -6635,8 +6638,8 @@ static LLVMValueRef gen_const_val_ptr(CodeGen *g, ZigValue *const_val, const cha
ZigValue *array_const_val = const_val->data.x_ptr.data.base_array.array_val;
assert(array_const_val->type->id == ZigTypeIdArray);
if (!type_has_bits(array_const_val->type)) {
if (array_const_val->type->data.array.sentinel != nullptr) {
ZigValue *pointee = array_const_val->type->data.array.sentinel;
ZigValue *pointee = get_sentinel_value(array_const_val->type->data.array.sentinel);
if (pointee != nullptr) {
render_const_val(g, pointee, "");
render_const_val_global(g, pointee, "");
const_val->llvm_value = LLVMConstBitCast(pointee->llvm_global,
Expand Down Expand Up @@ -6957,7 +6960,9 @@ check: switch (const_val->special) {
case ConstArraySpecialUndef:
return LLVMGetUndef(get_llvm_type(g, type_entry));
case ConstArraySpecialNone: {
uint64_t extra_len_from_sentinel = (type_entry->data.array.sentinel != nullptr) ? 1 : 0;
ZigValue *sentinel = get_sentinel_value(type_entry->data.array.sentinel);
// TODO: is this supposed to be 1 or sizeof(sentinel)?
uint64_t extra_len_from_sentinel = (sentinel != nullptr) ? 1 : 0;
uint64_t full_len = len + extra_len_from_sentinel;
LLVMValueRef *values = allocate<LLVMValueRef>(full_len);
LLVMTypeRef element_type_ref = get_llvm_type(g, type_entry->data.array.child_type);
Expand All @@ -6968,8 +6973,8 @@ check: switch (const_val->special) {
values[i] = val;
make_unnamed_struct = make_unnamed_struct || is_llvm_value_unnamed_type(g, elem_value->type, val);
}
if (type_entry->data.array.sentinel != nullptr) {
values[len] = gen_const_val(g, type_entry->data.array.sentinel, "");
if (sentinel != nullptr) {
values[len] = gen_const_val(g, sentinel, "");
}
if (make_unnamed_struct) {
return LLVMConstStruct(values, full_len, true);
Expand All @@ -6980,7 +6985,7 @@ check: switch (const_val->special) {
case ConstArraySpecialBuf: {
Buf *buf = const_val->data.x_array.data.s_buf;
return LLVMConstString(buf_ptr(buf), (unsigned)buf_len(buf),
type_entry->data.array.sentinel == nullptr);
get_sentinel_value(type_entry->data.array.sentinel) == nullptr);
}
}
zig_unreachable();
Expand Down Expand Up @@ -8023,6 +8028,12 @@ static void define_intern_values(CodeGen *g) {
value.special = ConstValSpecialStatic;
bigint_init_unsigned(&value.data.x_bigint, 0);
}
{
auto& value = g->intern.optional_zero_byte;
value.type = get_optional_type(g, g->builtin_types.entry_u8);
value.special = ConstValSpecialStatic;
value.data.x_optional = &g->intern.zero_byte;
}
}

static BuiltinFnEntry *create_builtin_fn(CodeGen *g, BuiltinFnId id, const char *name, size_t count) {
Expand Down Expand Up @@ -10618,3 +10629,10 @@ ZigValue *CodeGen::Intern::for_zero_byte() {
#endif
return &this->zero_byte;
}

ZigValue *CodeGen::Intern::for_optional_zero_byte() {
#ifdef ZIG_ENABLE_MEM_PROFILE
memprof_intern_count.optional_zero_byte += 1;
#endif
return &this->optional_zero_byte;
}
Loading