aboutsummaryrefslogtreecommitdiff
path: root/src/analyze.cpp
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2019-11-25 02:20:08 -0500
committerGitHub <noreply@github.com>2019-11-25 02:20:08 -0500
commit5a98dd42b38b9188cfb96c9ab57dc91af923029f (patch)
tree5b48dea38aeb28cf82b9ee98092bad4aea004d90 /src/analyze.cpp
parent69b780647abd14f0809a58006242397f3e94ac51 (diff)
parent321726465d3151d80e651b0c3001177a3ef53fff (diff)
downloadzig-5a98dd42b38b9188cfb96c9ab57dc91af923029f.tar.gz
zig-5a98dd42b38b9188cfb96c9ab57dc91af923029f.zip
Merge pull request #3728 from ziglang/null-terminated-pointers
sentinel-terminated pointers
Diffstat (limited to 'src/analyze.cpp')
-rw-r--r--src/analyze.cpp355
1 files changed, 199 insertions, 156 deletions
diff --git a/src/analyze.cpp b/src/analyze.cpp
index d8c2d29486..70dfd4f181 100644
--- a/src/analyze.cpp
+++ b/src/analyze.cpp
@@ -452,18 +452,6 @@ ZigType *get_any_frame_type(CodeGen *g, ZigType *result_type) {
return entry;
}
-static const char *ptr_len_to_star_str(PtrLen ptr_len) {
- switch (ptr_len) {
- case PtrLenSingle:
- return "*";
- case PtrLenUnknown:
- return "[*]";
- case PtrLenC:
- return "[*c]";
- }
- zig_unreachable();
-}
-
ZigType *get_fn_frame_type(CodeGen *g, ZigFn *fn) {
if (fn->frame_type != nullptr) {
return fn->frame_type;
@@ -483,10 +471,47 @@ ZigType *get_fn_frame_type(CodeGen *g, ZigFn *fn) {
return entry;
}
+static void append_ptr_type_attrs(Buf *type_name, ZigType *ptr_type) {
+ const char *const_str = ptr_type->data.pointer.is_const ? "const " : "";
+ const char *volatile_str = ptr_type->data.pointer.is_volatile ? "volatile " : "";
+ const char *allow_zero_str;
+ if (ptr_type->data.pointer.ptr_len == PtrLenC) {
+ assert(ptr_type->data.pointer.allow_zero);
+ allow_zero_str = "";
+ } else {
+ allow_zero_str = ptr_type->data.pointer.allow_zero ? "allowzero " : "";
+ }
+ if (ptr_type->data.pointer.explicit_alignment != 0 || ptr_type->data.pointer.host_int_bytes != 0 ||
+ ptr_type->data.pointer.vector_index != VECTOR_INDEX_NONE)
+ {
+ buf_appendf(type_name, "align(");
+ if (ptr_type->data.pointer.explicit_alignment != 0) {
+ buf_appendf(type_name, "%" PRIu32, ptr_type->data.pointer.explicit_alignment);
+ }
+ if (ptr_type->data.pointer.host_int_bytes != 0) {
+ buf_appendf(type_name, ":%" PRIu32 ":%" PRIu32, ptr_type->data.pointer.bit_offset_in_host, ptr_type->data.pointer.host_int_bytes);
+ }
+ if (ptr_type->data.pointer.vector_index == VECTOR_INDEX_RUNTIME) {
+ buf_appendf(type_name, ":?");
+ } else if (ptr_type->data.pointer.vector_index != VECTOR_INDEX_NONE) {
+ buf_appendf(type_name, ":%" PRIu32, ptr_type->data.pointer.vector_index);
+ }
+ buf_appendf(type_name, ") ");
+ }
+ buf_appendf(type_name, "%s%s%s", const_str, volatile_str, allow_zero_str);
+ if (ptr_type->data.pointer.inferred_struct_field != nullptr) {
+ buf_appendf(type_name, " field '%s' of %s)",
+ buf_ptr(ptr_type->data.pointer.inferred_struct_field->field_name),
+ buf_ptr(&ptr_type->data.pointer.inferred_struct_field->inferred_struct_type->name));
+ } else {
+ buf_appendf(type_name, "%s", buf_ptr(&ptr_type->data.pointer.child_type->name));
+ }
+}
+
ZigType *get_pointer_to_type_extra2(CodeGen *g, ZigType *child_type, bool is_const,
bool is_volatile, PtrLen ptr_len, uint32_t byte_alignment,
uint32_t bit_offset_in_host, uint32_t host_int_bytes, bool allow_zero,
- uint32_t vector_index, InferredStructField *inferred_struct_field)
+ uint32_t vector_index, InferredStructField *inferred_struct_field, ConstExprValue *sentinel)
{
assert(ptr_len != PtrLenC || allow_zero);
assert(!type_is_invalid(child_type));
@@ -509,9 +534,11 @@ ZigType *get_pointer_to_type_extra2(CodeGen *g, ZigType *child_type, bool is_con
TypeId type_id = {};
ZigType **parent_pointer = nullptr;
if (host_int_bytes != 0 || is_volatile || byte_alignment != 0 || ptr_len != PtrLenSingle ||
- allow_zero || vector_index != VECTOR_INDEX_NONE || inferred_struct_field != nullptr)
+ allow_zero || vector_index != VECTOR_INDEX_NONE || inferred_struct_field != nullptr ||
+ sentinel != nullptr)
{
type_id.id = ZigTypeIdPointer;
+ type_id.data.pointer.codegen = g;
type_id.data.pointer.child_type = child_type;
type_id.data.pointer.is_const = is_const;
type_id.data.pointer.is_volatile = is_volatile;
@@ -522,6 +549,7 @@ ZigType *get_pointer_to_type_extra2(CodeGen *g, ZigType *child_type, bool is_con
type_id.data.pointer.allow_zero = allow_zero;
type_id.data.pointer.vector_index = vector_index;
type_id.data.pointer.inferred_struct_field = inferred_struct_field;
+ type_id.data.pointer.sentinel = sentinel;
auto existing_entry = g->type_table.maybe_get(type_id);
if (existing_entry)
@@ -537,56 +565,35 @@ ZigType *get_pointer_to_type_extra2(CodeGen *g, ZigType *child_type, bool is_con
ZigType *entry = new_type_table_entry(ZigTypeIdPointer);
- const char *star_str = ptr_len_to_star_str(ptr_len);
- const char *const_str = is_const ? "const " : "";
- const char *volatile_str = is_volatile ? "volatile " : "";
- const char *allow_zero_str;
- if (ptr_len == PtrLenC) {
- assert(allow_zero);
- allow_zero_str = "";
- } else {
- allow_zero_str = allow_zero ? "allowzero " : "";
- }
buf_resize(&entry->name, 0);
- if (host_int_bytes == 0 && byte_alignment == 0 && vector_index == VECTOR_INDEX_NONE) {
- if (inferred_struct_field == nullptr) {
- buf_appendf(&entry->name, "%s%s%s%s%s",
- star_str, const_str, volatile_str, allow_zero_str, buf_ptr(&child_type->name));
- } else {
- buf_appendf(&entry->name, "(%s%s%s%s field '%s' of %s)",
- star_str, const_str, volatile_str, allow_zero_str,
- buf_ptr(inferred_struct_field->field_name),
- buf_ptr(&inferred_struct_field->inferred_struct_type->name));
- }
- } else if (host_int_bytes == 0 && vector_index == VECTOR_INDEX_NONE) {
- buf_appendf(&entry->name, "%salign(%" PRIu32 ") %s%s%s%s", star_str, byte_alignment,
- const_str, volatile_str, allow_zero_str, buf_ptr(&child_type->name));
- } else if (byte_alignment == 0) {
- assert(vector_index == VECTOR_INDEX_NONE);
- buf_appendf(&entry->name, "%salign(:%" PRIu32 ":%" PRIu32 ") %s%s%s%s",
- star_str,
- bit_offset_in_host, host_int_bytes,
- const_str, volatile_str, allow_zero_str,
- buf_ptr(&child_type->name));
- } else if (vector_index == VECTOR_INDEX_NONE) {
- buf_appendf(&entry->name, "%salign(%" PRIu32 ":%" PRIu32 ":%" PRIu32 ") %s%s%s%s",
- star_str, byte_alignment,
- bit_offset_in_host, host_int_bytes,
- const_str, volatile_str, allow_zero_str,
- buf_ptr(&child_type->name));
- } else if (vector_index == VECTOR_INDEX_RUNTIME) {
- buf_appendf(&entry->name, "%salign(%" PRIu32 ":%" PRIu32 ":%" PRIu32 ":?) %s%s%s%s",
- star_str, byte_alignment,
- bit_offset_in_host, host_int_bytes,
- const_str, volatile_str, allow_zero_str,
- buf_ptr(&child_type->name));
- } else {
- buf_appendf(&entry->name, "%salign(%" PRIu32 ":%" PRIu32 ":%" PRIu32 ":%" PRIu32 ") %s%s%s%s",
- star_str, byte_alignment,
- bit_offset_in_host, host_int_bytes, vector_index,
- const_str, volatile_str, allow_zero_str,
- buf_ptr(&child_type->name));
+ if (inferred_struct_field != nullptr) {
+ buf_appendf(&entry->name, "(");
+ }
+ switch (ptr_len) {
+ case PtrLenSingle:
+ buf_appendf(&entry->name, "*");
+ break;
+ case PtrLenUnknown:
+ buf_appendf(&entry->name, "[*");
+ break;
+ case PtrLenC:
+ assert(sentinel == nullptr);
+ buf_appendf(&entry->name, "[*c]");
+ break;
+ }
+ if (sentinel != nullptr) {
+ buf_appendf(&entry->name, ":");
+ render_const_value(g, &entry->name, sentinel);
}
+ switch (ptr_len) {
+ case PtrLenSingle:
+ case PtrLenC:
+ break;
+ case PtrLenUnknown:
+ buf_appendf(&entry->name, "]");
+ break;
+ }
+
if (type_is_resolved(child_type, ResolveStatusZeroBitsKnown)) {
if (type_has_bits(child_type)) {
@@ -615,6 +622,9 @@ ZigType *get_pointer_to_type_extra2(CodeGen *g, ZigType *child_type, bool is_con
entry->data.pointer.allow_zero = allow_zero;
entry->data.pointer.vector_index = vector_index;
entry->data.pointer.inferred_struct_field = inferred_struct_field;
+ entry->data.pointer.sentinel = sentinel;
+
+ append_ptr_type_attrs(&entry->name, entry);
if (parent_pointer) {
*parent_pointer = entry;
@@ -629,12 +639,12 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons
uint32_t bit_offset_in_host, uint32_t host_int_bytes, bool allow_zero)
{
return get_pointer_to_type_extra2(g, child_type, is_const, is_volatile, ptr_len,
- byte_alignment, bit_offset_in_host, host_int_bytes, allow_zero, VECTOR_INDEX_NONE, nullptr);
+ byte_alignment, bit_offset_in_host, host_int_bytes, allow_zero, VECTOR_INDEX_NONE, nullptr, nullptr);
}
ZigType *get_pointer_to_type(CodeGen *g, ZigType *child_type, bool is_const) {
return get_pointer_to_type_extra2(g, child_type, is_const, false, PtrLenSingle, 0, 0, 0, false,
- VECTOR_INDEX_NONE, nullptr);
+ VECTOR_INDEX_NONE, nullptr, nullptr);
}
ZigType *get_optional_type(CodeGen *g, ZigType *child_type) {
@@ -750,11 +760,13 @@ ZigType *get_error_union_type(CodeGen *g, ZigType *err_set_type, ZigType *payloa
return entry;
}
-ZigType *get_array_type(CodeGen *g, ZigType *child_type, uint64_t array_size) {
+ZigType *get_array_type(CodeGen *g, ZigType *child_type, uint64_t array_size, ConstExprValue *sentinel) {
TypeId type_id = {};
type_id.id = ZigTypeIdArray;
+ type_id.data.array.codegen = g;
type_id.data.array.child_type = child_type;
type_id.data.array.size = array_size;
+ type_id.data.array.sentinel = sentinel;
auto existing_entry = g->type_table.maybe_get(type_id);
if (existing_entry) {
return existing_entry->value;
@@ -765,14 +777,27 @@ ZigType *get_array_type(CodeGen *g, ZigType *child_type, uint64_t array_size) {
ZigType *entry = new_type_table_entry(ZigTypeIdArray);
buf_resize(&entry->name, 0);
- buf_appendf(&entry->name, "[%" ZIG_PRI_u64 "]%s", array_size, buf_ptr(&child_type->name));
+ buf_appendf(&entry->name, "[%" ZIG_PRI_u64, array_size);
+ if (sentinel != nullptr) {
+ buf_appendf(&entry->name, ":");
+ render_const_value(g, &entry->name, sentinel);
+ }
+ 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);
+ }
- entry->size_in_bits = child_type->size_in_bits * array_size;
+ 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 * array_size;
+ entry->abi_size = child_type->abi_size * full_array_size;
entry->data.array.child_type = child_type;
entry->data.array.len = array_size;
+ entry->data.array.sentinel = sentinel;
g->type_table.put(type_id, entry);
return entry;
@@ -789,10 +814,14 @@ ZigType *get_slice_type(CodeGen *g, ZigType *ptr_type) {
ZigType *entry = new_type_table_entry(ZigTypeIdStruct);
- // replace the & with [] to go from a ptr type name to a slice type name
buf_resize(&entry->name, 0);
- size_t name_offset = (ptr_type->data.pointer.ptr_len == PtrLenSingle) ? 1 : 3;
- buf_appendf(&entry->name, "[]%s", buf_ptr(&ptr_type->name) + name_offset);
+ 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);
+ }
+ buf_appendf(&entry->name, "]");
+ append_ptr_type_attrs(&entry->name, ptr_type);
unsigned element_count = 2;
Buf *ptr_field_name = buf_create_from_str("ptr");
@@ -832,22 +861,6 @@ ZigType *get_slice_type(CodeGen *g, ZigType *ptr_type) {
entry->data.structure.fields[slice_len_index]->gen_index = 0;
}
- ZigType *child_type = ptr_type->data.pointer.child_type;
- if (ptr_type->data.pointer.is_const || ptr_type->data.pointer.is_volatile ||
- ptr_type->data.pointer.explicit_alignment != 0 || ptr_type->data.pointer.allow_zero)
- {
- ZigType *peer_ptr_type = get_pointer_to_type_extra(g, child_type, false, false,
- PtrLenUnknown, 0, 0, 0, false);
- ZigType *peer_slice_type = get_slice_type(g, peer_ptr_type);
-
- entry->size_in_bits = peer_slice_type->size_in_bits;
- entry->abi_size = peer_slice_type->abi_size;
- entry->abi_align = peer_slice_type->abi_align;
-
- *parent_pointer = entry;
- return entry;
- }
-
if (type_has_bits(ptr_type)) {
entry->size_in_bits = ptr_type->size_in_bits + g->builtin_types.entry_usize->size_in_bits;
entry->abi_size = ptr_type->abi_size + g->builtin_types.entry_usize->abi_size;
@@ -1150,6 +1163,10 @@ Error type_val_resolve_zero_bits(CodeGen *g, ConstExprValue *type_val, ZigType *
Error type_val_resolve_is_opaque_type(CodeGen *g, ConstExprValue *type_val, bool *is_opaque_type) {
if (type_val->special != ConstValSpecialLazy) {
assert(type_val->special == ConstValSpecialStatic);
+ if (type_val->data.x_type == g->builtin_types.entry_var) {
+ *is_opaque_type = false;
+ return ErrorNone;
+ }
*is_opaque_type = (type_val->data.x_type->id == ZigTypeIdOpaque);
return ErrorNone;
}
@@ -3638,6 +3655,7 @@ void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node) {
case NodeTypeEnumLiteral:
case NodeTypeAnyFrameType:
case NodeTypeErrorSetField:
+ case NodeTypeVarFieldType:
zig_unreachable();
}
}
@@ -5041,7 +5059,6 @@ static uint32_t hash_const_val_ptr(ConstExprValue *const_val) {
hash_val += (uint32_t)1764906839;
hash_val += hash_ptr(const_val->data.x_ptr.data.base_array.array_val);
hash_val += hash_size(const_val->data.x_ptr.data.base_array.elem_index);
- hash_val += const_val->data.x_ptr.data.base_array.is_cstr ? 1297263887 : 200363492;
return hash_val;
case ConstPtrSpecialBaseStruct:
hash_val += (uint32_t)3518317043;
@@ -5545,8 +5562,23 @@ OnePossibleValue type_has_one_possible_value(CodeGen *g, ZigType *type_entry) {
zig_unreachable();
}
+ConstExprValue *get_the_one_possible_value(CodeGen *g, ZigType *type_entry) {
+ auto entry = g->one_possible_values.maybe_get(type_entry);
+ if (entry != nullptr) {
+ return entry->value;
+ }
+ ConstExprValue *result = create_const_vals(1);
+ result->type = type_entry;
+ result->special = ConstValSpecialStatic;
+ g->one_possible_values.put(type_entry, result);
+ return result;
+}
+
ReqCompTime type_requires_comptime(CodeGen *g, ZigType *ty) {
Error err;
+ if (ty == g->builtin_types.entry_var) {
+ return ReqCompTimeYes;
+ }
switch (ty->id) {
case ZigTypeIdInvalid:
zig_unreachable();
@@ -5612,52 +5644,26 @@ void init_const_str_lit(CodeGen *g, ConstExprValue *const_val, Buf *str) {
return;
}
- const_val->special = ConstValSpecialStatic;
- const_val->type = get_array_type(g, g->builtin_types.entry_u8, buf_len(str));
- const_val->data.x_array.special = ConstArraySpecialBuf;
- const_val->data.x_array.data.s_buf = str;
-
- g->string_literals_table.put(str, const_val);
-}
-
-ConstExprValue *create_const_str_lit(CodeGen *g, Buf *str) {
- ConstExprValue *const_val = create_const_vals(1);
- init_const_str_lit(g, const_val, str);
- return const_val;
-}
-
-void init_const_c_str_lit(CodeGen *g, ConstExprValue *const_val, Buf *str) {
// first we build the underlying array
- size_t len_with_null = buf_len(str) + 1;
ConstExprValue *array_val = create_const_vals(1);
array_val->special = ConstValSpecialStatic;
- array_val->type = get_array_type(g, g->builtin_types.entry_u8, len_with_null);
- // TODO buf optimization
- array_val->data.x_array.data.s_none.elements = create_const_vals(len_with_null);
- for (size_t i = 0; i < buf_len(str); i += 1) {
- ConstExprValue *this_char = &array_val->data.x_array.data.s_none.elements[i];
- this_char->special = ConstValSpecialStatic;
- this_char->type = g->builtin_types.entry_u8;
- bigint_init_unsigned(&this_char->data.x_bigint, (uint8_t)buf_ptr(str)[i]);
- }
- ConstExprValue *null_char = &array_val->data.x_array.data.s_none.elements[len_with_null - 1];
- null_char->special = ConstValSpecialStatic;
- null_char->type = g->builtin_types.entry_u8;
- bigint_init_unsigned(&null_char->data.x_bigint, 0);
+ array_val->type = get_array_type(g, g->builtin_types.entry_u8, buf_len(str), &g->const_zero_byte);
+ array_val->data.x_array.special = ConstArraySpecialBuf;
+ array_val->data.x_array.data.s_buf = str;
// then make the pointer point to it
const_val->special = ConstValSpecialStatic;
- // TODO make this `[*]null u8` instead of `[*]u8`
- const_val->type = get_pointer_to_type_extra(g, g->builtin_types.entry_u8, true, false,
- PtrLenUnknown, 0, 0, 0, false);
- const_val->data.x_ptr.special = ConstPtrSpecialBaseArray;
- const_val->data.x_ptr.data.base_array.array_val = array_val;
- const_val->data.x_ptr.data.base_array.elem_index = 0;
- const_val->data.x_ptr.data.base_array.is_cstr = true;
+ const_val->type = get_pointer_to_type_extra2(g, array_val->type, true, false,
+ PtrLenSingle, 0, 0, 0, false, VECTOR_INDEX_NONE, nullptr, nullptr);
+ const_val->data.x_ptr.special = ConstPtrSpecialRef;
+ const_val->data.x_ptr.data.ref.pointee = array_val;
+
+ g->string_literals_table.put(str, const_val);
}
-ConstExprValue *create_const_c_str_lit(CodeGen *g, Buf *str) {
+
+ConstExprValue *create_const_str_lit(CodeGen *g, Buf *str) {
ConstExprValue *const_val = create_const_vals(1);
- init_const_c_str_lit(g, const_val, str);
+ init_const_str_lit(g, const_val, str);
return const_val;
}
@@ -5707,6 +5713,18 @@ ConstExprValue *create_const_signed(ZigType *type, int64_t x) {
return const_val;
}
+void init_const_null(ConstExprValue *const_val, ZigType *type) {
+ const_val->special = ConstValSpecialStatic;
+ const_val->type = type;
+ const_val->data.x_optional = nullptr;
+}
+
+ConstExprValue *create_const_null(ZigType *type) {
+ ConstExprValue *const_val = create_const_vals(1);
+ init_const_null(const_val, type);
+ return const_val;
+}
+
void init_const_float(ConstExprValue *const_val, ZigType *type, double value) {
const_val->special = ConstValSpecialStatic;
const_val->type = type;
@@ -6069,7 +6087,7 @@ static Error resolve_async_frame(CodeGen *g, ZigType *frame_type) {
fields.append({"@stack_trace", get_stack_trace_type(g), 0});
fields.append({"@instruction_addresses",
- get_array_type(g, g->builtin_types.entry_usize, stack_trace_ptr_count), 0});
+ get_array_type(g, g->builtin_types.entry_usize, stack_trace_ptr_count, nullptr), 0});
}
frame_type->data.frame.locals_struct = get_struct_type(g, buf_ptr(&frame_type->name),
@@ -6277,7 +6295,7 @@ static Error resolve_async_frame(CodeGen *g, ZigType *frame_type) {
if (codegen_fn_has_err_ret_tracing_stack(g, fn, true)) {
fields.append({"@stack_trace", get_stack_trace_type(g), 0});
fields.append({"@instruction_addresses",
- get_array_type(g, g->builtin_types.entry_usize, stack_trace_ptr_count), 0});
+ get_array_type(g, g->builtin_types.entry_usize, stack_trace_ptr_count, nullptr), 0});
}
for (size_t alloca_i = 0; alloca_i < fn->alloca_gen_list.length; alloca_i += 1) {
@@ -6441,8 +6459,6 @@ bool ir_get_var_is_comptime(ZigVar *var) {
bool const_values_equal_ptr(ConstExprValue *a, ConstExprValue *b) {
if (a->data.x_ptr.special != b->data.x_ptr.special)
return false;
- if (a->data.x_ptr.mut != b->data.x_ptr.mut)
- return false;
switch (a->data.x_ptr.special) {
case ConstPtrSpecialInvalid:
zig_unreachable();
@@ -6459,8 +6475,6 @@ bool const_values_equal_ptr(ConstExprValue *a, ConstExprValue *b) {
}
if (a->data.x_ptr.data.base_array.elem_index != b->data.x_ptr.data.base_array.elem_index)
return false;
- if (a->data.x_ptr.data.base_array.is_cstr != b->data.x_ptr.data.base_array.is_cstr)
- return false;
return true;
case ConstPtrSpecialBaseStruct:
if (a->data.x_ptr.data.base_struct.struct_val != b->data.x_ptr.data.base_struct.struct_val &&
@@ -6536,9 +6550,19 @@ static bool const_values_equal_array(CodeGen *g, ConstExprValue *a, ConstExprVal
}
bool const_values_equal(CodeGen *g, ConstExprValue *a, ConstExprValue *b) {
- assert(a->type->id == b->type->id);
+ if (a->type->id != b->type->id) return false;
assert(a->special == ConstValSpecialStatic);
assert(b->special == ConstValSpecialStatic);
+ if (a->type == b->type) {
+ switch (type_has_one_possible_value(g, a->type)) {
+ case OnePossibleValueInvalid:
+ zig_unreachable();
+ case OnePossibleValueNo:
+ break;
+ case OnePossibleValueYes:
+ return true;
+ }
+ }
switch (a->type->id) {
case ZigTypeIdOpaque:
zig_unreachable();
@@ -6704,15 +6728,10 @@ static void render_const_val_ptr(CodeGen *g, Buf *buf, ConstExprValue *const_val
render_const_value(g, buf, const_ptr_pointee(nullptr, g, const_val, nullptr));
return;
case ConstPtrSpecialBaseArray:
- if (const_val->data.x_ptr.data.base_array.is_cstr) {
- buf_appendf(buf, "*(c str lit)");
- return;
- } else {
- buf_appendf(buf, "*");
- // TODO we need a source node for const_ptr_pointee because it can generate compile errors
- render_const_value(g, buf, const_ptr_pointee(nullptr, g, const_val, nullptr));
- return;
- }
+ buf_appendf(buf, "*");
+ // TODO we need a source node for const_ptr_pointee because it can generate compile errors
+ render_const_value(g, buf, const_ptr_pointee(nullptr, g, const_val, nullptr));
+ return;
case ConstPtrSpecialHardCodedAddr:
buf_appendf(buf, "(%s)(%" ZIG_PRI_x64 ")", buf_ptr(&type_entry->name),
const_val->data.x_ptr.data.hard_coded_addr.addr);
@@ -7032,17 +7051,19 @@ uint32_t type_id_hash(TypeId x) {
return hash_ptr(x.data.error_union.err_set_type) ^ hash_ptr(x.data.error_union.payload_type);
case ZigTypeIdPointer:
return hash_ptr(x.data.pointer.child_type) +
- ((x.data.pointer.ptr_len == PtrLenSingle) ? (uint32_t)1120226602 : (uint32_t)3200913342) +
+ (uint32_t)x.data.pointer.ptr_len * 1120226602u +
(x.data.pointer.is_const ? (uint32_t)2749109194 : (uint32_t)4047371087) +
(x.data.pointer.is_volatile ? (uint32_t)536730450 : (uint32_t)1685612214) +
(x.data.pointer.allow_zero ? (uint32_t)3324284834 : (uint32_t)3584904923) +
(((uint32_t)x.data.pointer.alignment) ^ (uint32_t)0x777fbe0e) +
(((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);
+ (((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);
case ZigTypeIdArray:
- return hash_ptr(x.data.array.child_type) +
- ((uint32_t)x.data.array.size ^ (uint32_t)2122979968);
+ 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);
case ZigTypeIdInt:
return (x.data.integer.is_signed ? (uint32_t)2652528194 : (uint32_t)163929201) +
(((uint32_t)x.data.integer.bit_count) ^ (uint32_t)2998081557);
@@ -7094,6 +7115,11 @@ bool type_id_eql(TypeId a, TypeId b) {
a.data.pointer.vector_index == b.data.pointer.vector_index &&
a.data.pointer.host_int_bytes == b.data.pointer.host_int_bytes &&
(
+ a.data.pointer.sentinel == b.data.pointer.sentinel ||
+ (a.data.pointer.sentinel != nullptr && b.data.pointer.sentinel != nullptr &&
+ const_values_equal(a.data.pointer.codegen, a.data.pointer.sentinel, b.data.pointer.sentinel))
+ ) &&
+ (
a.data.pointer.inferred_struct_field == b.data.pointer.inferred_struct_field ||
(a.data.pointer.inferred_struct_field != nullptr &&
b.data.pointer.inferred_struct_field != nullptr &&
@@ -7104,7 +7130,12 @@ bool type_id_eql(TypeId a, TypeId b) {
);
case ZigTypeIdArray:
return a.data.array.child_type == b.data.array.child_type &&
- a.data.array.size == b.data.array.size;
+ a.data.array.size == b.data.array.size &&
+ (
+ a.data.array.sentinel == b.data.array.sentinel ||
+ (a.data.array.sentinel != nullptr && b.data.array.sentinel != nullptr &&
+ const_values_equal(a.data.array.codegen, a.data.array.sentinel, b.data.array.sentinel))
+ );
case ZigTypeIdInt:
return a.data.integer.is_signed == b.data.integer.is_signed &&
a.data.integer.bit_count == b.data.integer.bit_count;
@@ -7761,7 +7792,8 @@ static void resolve_llvm_types_slice(CodeGen *g, ZigType *type, ResolveStatus wa
bool done = false;
if (ptr_type->data.pointer.is_const || ptr_type->data.pointer.is_volatile ||
- ptr_type->data.pointer.explicit_alignment != 0 || ptr_type->data.pointer.allow_zero)
+ ptr_type->data.pointer.explicit_alignment != 0 || ptr_type->data.pointer.allow_zero ||
+ ptr_type->data.pointer.sentinel != nullptr)
{
ZigType *peer_ptr_type = get_pointer_to_type_extra(g, child_type, false, false,
PtrLenUnknown, 0, 0, 0, false);
@@ -7780,7 +7812,8 @@ static void resolve_llvm_types_slice(CodeGen *g, ZigType *type, ResolveStatus wa
ZigType *child_ptr_type = child_type->data.structure.fields[slice_ptr_index]->type_entry;
assert(child_ptr_type->id == ZigTypeIdPointer);
if (child_ptr_type->data.pointer.is_const || child_ptr_type->data.pointer.is_volatile ||
- child_ptr_type->data.pointer.explicit_alignment != 0 || child_ptr_type->data.pointer.allow_zero)
+ child_ptr_type->data.pointer.explicit_alignment != 0 || child_ptr_type->data.pointer.allow_zero ||
+ child_ptr_type->data.pointer.sentinel != nullptr)
{
ZigType *grand_child_type = child_ptr_type->data.pointer.child_type;
ZigType *bland_child_ptr_type = get_pointer_to_type_extra(g, grand_child_type, false, false,
@@ -8290,7 +8323,7 @@ static void resolve_llvm_types_union(CodeGen *g, ZigType *union_type, ResolveSta
size_t padding_bytes = union_type->data.unionation.union_abi_size - most_aligned_union_member->type_entry->abi_size;
if (padding_bytes > 0) {
ZigType *u8_type = get_int_type(g, false, 8);
- ZigType *padding_array = get_array_type(g, u8_type, padding_bytes);
+ ZigType *padding_array = get_array_type(g, u8_type, padding_bytes, nullptr);
LLVMTypeRef union_element_types[] = {
most_aligned_union_member->type_entry->llvm_type,
get_llvm_type(g, padding_array),
@@ -8324,7 +8357,7 @@ static void resolve_llvm_types_union(CodeGen *g, ZigType *union_type, ResolveSta
union_type_ref = get_llvm_type(g, most_aligned_union_member->type_entry);
} else {
ZigType *u8_type = get_int_type(g, false, 8);
- ZigType *padding_array = get_array_type(g, u8_type, padding_bytes);
+ ZigType *padding_array = get_array_type(g, u8_type, padding_bytes, nullptr);
LLVMTypeRef union_element_types[] = {
get_llvm_type(g, most_aligned_union_member->type_entry),
get_llvm_type(g, padding_array),
@@ -8405,19 +8438,19 @@ static void resolve_llvm_types_pointer(CodeGen *g, ZigType *type, ResolveStatus
if (type->data.pointer.is_const || type->data.pointer.is_volatile ||
type->data.pointer.explicit_alignment != 0 || type->data.pointer.ptr_len != PtrLenSingle ||
type->data.pointer.bit_offset_in_host != 0 || type->data.pointer.allow_zero ||
- type->data.pointer.vector_index != VECTOR_INDEX_NONE)
+ type->data.pointer.vector_index != VECTOR_INDEX_NONE || type->data.pointer.sentinel != nullptr)
{
assertNoError(type_resolve(g, elem_type, ResolveStatusLLVMFwdDecl));
ZigType *peer_type;
if (type->data.pointer.vector_index == VECTOR_INDEX_NONE) {
peer_type = get_pointer_to_type_extra2(g, elem_type, false, false,
PtrLenSingle, 0, 0, type->data.pointer.host_int_bytes, false,
- VECTOR_INDEX_NONE, nullptr);
+ VECTOR_INDEX_NONE, nullptr, nullptr);
} else {
uint32_t host_vec_len = type->data.pointer.host_int_bytes;
ZigType *host_vec_type = get_vector_type(g, host_vec_len, elem_type);
peer_type = get_pointer_to_type_extra2(g, host_vec_type, false, false,
- PtrLenSingle, 0, 0, 0, false, VECTOR_INDEX_NONE, nullptr);
+ PtrLenSingle, 0, 0, 0, false, VECTOR_INDEX_NONE, nullptr, nullptr);
}
type->llvm_type = get_llvm_type(g, peer_type);
type->llvm_di_type = get_llvm_di_type(g, peer_type);
@@ -8646,14 +8679,16 @@ 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;
+ 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)type->data.array.len);
+ type->llvm_type = LLVMArrayType(get_llvm_type(g, elem_type), (unsigned)full_len);
uint64_t debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, type->llvm_type);
uint64_t debug_align_in_bits = 8*LLVMABISizeOfType(g->target_data_ref, type->llvm_type);
type->llvm_di_type = ZigLLVMCreateDebugArrayType(g->dbuilder, debug_size_in_bits,
- debug_align_in_bits, get_llvm_di_type(g, elem_type), (int)type->data.array.len);
+ debug_align_in_bits, get_llvm_di_type(g, elem_type), (int)full_len);
}
static void resolve_llvm_types_fn_type(CodeGen *g, ZigType *fn_type) {
@@ -9143,3 +9178,11 @@ Error analyze_import(CodeGen *g, ZigType *source_import, Buf *import_target_str,
*out_import = add_source_file(g, target_package, resolved_path, import_code, source_kind);
return ErrorNone;
}
+
+
+void IrExecutable::src() {
+ IrExecutable *it;
+ for (it = this; it != nullptr && it->source_node != nullptr; it = it->parent_exec) {
+ it->source_node->src();
+ }
+}