aboutsummaryrefslogtreecommitdiff
path: root/src/analyze.cpp
diff options
context:
space:
mode:
authorBenoitJGirard <BenoitJGirard@users.noreply.github.com>2019-02-17 14:38:55 -0500
committerGitHub <noreply@github.com>2019-02-17 14:38:55 -0500
commit6daa041932ae5ab03eed953dacf3ca506078390c (patch)
tree0f51f6c2ff84dde51b61bba6799e5c5abccf91b4 /src/analyze.cpp
parentf0ec308e26ff957c7fbb50ccc69d3d549c42c4da (diff)
parent8d2a902945ef97f28152c3d5a68bb974809c8539 (diff)
downloadzig-6daa041932ae5ab03eed953dacf3ca506078390c.tar.gz
zig-6daa041932ae5ab03eed953dacf3ca506078390c.zip
Merge pull request #2 from ziglang/master
Refreshing fork.
Diffstat (limited to 'src/analyze.cpp')
-rw-r--r--src/analyze.cpp919
1 files changed, 651 insertions, 268 deletions
diff --git a/src/analyze.cpp b/src/analyze.cpp
index 2f4b173c5f..9941104bc4 100644
--- a/src/analyze.cpp
+++ b/src/analyze.cpp
@@ -28,28 +28,10 @@ static Error ATTRIBUTE_MUST_USE resolve_enum_zero_bits(CodeGen *g, ZigType *enum
static Error ATTRIBUTE_MUST_USE resolve_union_zero_bits(CodeGen *g, ZigType *union_type);
static void analyze_fn_body(CodeGen *g, ZigFn *fn_table_entry);
-ErrorMsg *add_node_error(CodeGen *g, AstNode *node, Buf *msg) {
- if (node->owner->c_import_node != nullptr) {
- // if this happens, then translate_c generated code that
- // failed semantic analysis, which isn't supposed to happen
- ErrorMsg *err = add_node_error(g, node->owner->c_import_node,
- buf_sprintf("compiler bug: @cImport generated invalid zig code"));
-
- add_error_note(g, err, node, msg);
-
- g->errors.append(err);
- return err;
- }
-
- ErrorMsg *err = err_msg_create_with_line(node->owner->path, node->line, node->column,
- node->owner->source_code, node->owner->line_offsets, msg);
-
- g->errors.append(err);
- return err;
-}
-
-ErrorMsg *add_error_note(CodeGen *g, ErrorMsg *parent_msg, AstNode *node, Buf *msg) {
- if (node->owner->c_import_node != nullptr) {
+static ErrorMsg *add_error_note_token(CodeGen *g, ErrorMsg *parent_msg, ImportTableEntry *owner, Token *token,
+ Buf *msg)
+{
+ if (owner->c_import_node != nullptr) {
// if this happens, then translate_c generated code that
// failed semantic analysis, which isn't supposed to happen
@@ -64,13 +46,46 @@ ErrorMsg *add_error_note(CodeGen *g, ErrorMsg *parent_msg, AstNode *node, Buf *m
return note;
}
- ErrorMsg *err = err_msg_create_with_line(node->owner->path, node->line, node->column,
- node->owner->source_code, node->owner->line_offsets, msg);
+ ErrorMsg *err = err_msg_create_with_line(owner->path, token->start_line, token->start_column,
+ owner->source_code, owner->line_offsets, msg);
err_msg_add_note(parent_msg, err);
return err;
}
+ErrorMsg *add_token_error(CodeGen *g, ImportTableEntry *owner, Token *token, Buf *msg) {
+ if (owner->c_import_node != nullptr) {
+ // if this happens, then translate_c generated code that
+ // failed semantic analysis, which isn't supposed to happen
+ ErrorMsg *err = add_node_error(g, owner->c_import_node,
+ buf_sprintf("compiler bug: @cImport generated invalid zig code"));
+
+ add_error_note_token(g, err, owner, token, msg);
+
+ g->errors.append(err);
+ return err;
+ }
+ ErrorMsg *err = err_msg_create_with_line(owner->path, token->start_line, token->start_column,
+ owner->source_code, owner->line_offsets, msg);
+
+ g->errors.append(err);
+ return err;
+}
+
+ErrorMsg *add_node_error(CodeGen *g, AstNode *node, Buf *msg) {
+ Token fake_token;
+ fake_token.start_line = node->line;
+ fake_token.start_column = node->column;
+ return add_token_error(g, node->owner, &fake_token, msg);
+}
+
+ErrorMsg *add_error_note(CodeGen *g, ErrorMsg *parent_msg, AstNode *node, Buf *msg) {
+ Token fake_token;
+ fake_token.start_line = node->line;
+ fake_token.start_column = node->column;
+ return add_error_note_token(g, parent_msg, node->owner, &fake_token, msg);
+}
+
ZigType *new_type_table_entry(ZigTypeId id) {
ZigType *entry = allocate<ZigType>(1);
entry->id = id;
@@ -250,6 +265,7 @@ AstNode *type_decl_node(ZigType *type_entry) {
case ZigTypeIdBoundFn:
case ZigTypeIdArgTuple:
case ZigTypeIdPromise:
+ case ZigTypeIdVector:
return nullptr;
}
zig_unreachable();
@@ -311,6 +327,7 @@ bool type_is_resolved(ZigType *type_entry, ResolveStatus status) {
case ZigTypeIdBoundFn:
case ZigTypeIdArgTuple:
case ZigTypeIdPromise:
+ case ZigTypeIdVector:
return true;
}
zig_unreachable();
@@ -339,6 +356,28 @@ uint64_t type_size(CodeGen *g, ZigType *type_entry) {
}
}
+ return LLVMABISizeOfType(g->target_data_ref, type_entry->type_ref);
+}
+
+uint64_t type_size_store(CodeGen *g, ZigType *type_entry) {
+ assert(type_is_complete(type_entry));
+
+ if (!type_has_bits(type_entry))
+ return 0;
+
+ if (type_entry->id == ZigTypeIdStruct && type_entry->data.structure.layout == ContainerLayoutPacked) {
+ uint64_t size_in_bits = type_size_bits(g, type_entry);
+ return (size_in_bits + 7) / 8;
+ } else if (type_entry->id == ZigTypeIdArray) {
+ ZigType *child_type = type_entry->data.array.child_type;
+ if (child_type->id == ZigTypeIdStruct &&
+ child_type->data.structure.layout == ContainerLayoutPacked)
+ {
+ uint64_t size_in_bits = type_size_bits(g, type_entry);
+ return (size_in_bits + 7) / 8;
+ }
+ }
+
return LLVMStoreSizeOfType(g->target_data_ref, type_entry->type_ref);
}
@@ -400,9 +439,25 @@ ZigType *get_promise_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_pointer_to_type_extra(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 is_volatile, PtrLen ptr_len, uint32_t byte_alignment,
+ uint32_t bit_offset_in_host, uint32_t host_int_bytes)
{
+ // TODO when implementing https://github.com/ziglang/zig/issues/1953
+ // move this to a parameter
+ bool allow_zero = (ptr_len == PtrLenC);
assert(!type_is_invalid(child_type));
assert(ptr_len == PtrLenSingle || child_type->id != ZigTypeIdOpaque);
@@ -422,7 +477,7 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons
TypeId type_id = {};
ZigType **parent_pointer = nullptr;
- if (host_int_bytes != 0 || is_volatile || byte_alignment != 0 || ptr_len != PtrLenSingle) {
+ if (host_int_bytes != 0 || is_volatile || byte_alignment != 0 || ptr_len != PtrLenSingle || allow_zero) {
type_id.id = ZigTypeIdPointer;
type_id.data.pointer.child_type = child_type;
type_id.data.pointer.is_const = is_const;
@@ -431,6 +486,7 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons
type_id.data.pointer.bit_offset_in_host = bit_offset_in_host;
type_id.data.pointer.host_int_bytes = host_int_bytes;
type_id.data.pointer.ptr_len = ptr_len;
+ type_id.data.pointer.allow_zero = allow_zero;
auto existing_entry = g->type_table.maybe_get(type_id);
if (existing_entry)
@@ -448,21 +504,31 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons
ZigType *entry = new_type_table_entry(ZigTypeIdPointer);
- const char *star_str = ptr_len == PtrLenSingle ? "*" : "[*]";
+ 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) {
- buf_appendf(&entry->name, "%s%s%s%s", star_str, const_str, volatile_str, buf_ptr(&child_type->name));
+ buf_appendf(&entry->name, "%s%s%s%s%s",
+ star_str, const_str, volatile_str, allow_zero_str, buf_ptr(&child_type->name));
} else if (host_int_bytes == 0) {
- buf_appendf(&entry->name, "%salign(%" PRIu32 ") %s%s%s", star_str, byte_alignment,
- const_str, volatile_str, buf_ptr(&child_type->name));
+ 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) {
- buf_appendf(&entry->name, "%salign(:%" PRIu32 ":%" PRIu32 ") %s%s%s", star_str,
- bit_offset_in_host, host_int_bytes, const_str, volatile_str, buf_ptr(&child_type->name));
+ 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 {
- buf_appendf(&entry->name, "%salign(%" PRIu32 ":%" PRIu32 ":%" PRIu32 ") %s%s%s", star_str, byte_alignment,
- bit_offset_in_host, host_int_bytes, const_str, volatile_str, buf_ptr(&child_type->name));
+ 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));
}
assert(child_type->id != ZigTypeIdInvalid);
@@ -470,7 +536,9 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons
entry->zero_bits = !type_has_bits(child_type);
if (!entry->zero_bits) {
- if (is_const || is_volatile || byte_alignment != 0 || ptr_len != PtrLenSingle || bit_offset_in_host != 0) {
+ if (is_const || is_volatile || byte_alignment != 0 || ptr_len != PtrLenSingle ||
+ bit_offset_in_host != 0 || allow_zero)
+ {
ZigType *peer_type = get_pointer_to_type_extra(g, child_type, false, false,
PtrLenSingle, 0, 0, host_int_bytes);
entry->type_ref = peer_type->type_ref;
@@ -504,6 +572,7 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons
entry->data.pointer.explicit_alignment = byte_alignment;
entry->data.pointer.bit_offset_in_host = bit_offset_in_host;
entry->data.pointer.host_int_bytes = host_int_bytes;
+ entry->data.pointer.allow_zero = allow_zero;
if (parent_pointer) {
*parent_pointer = entry;
@@ -569,13 +638,16 @@ ZigType *get_optional_type(CodeGen *g, ZigType *child_type) {
if (child_type->zero_bits) {
entry->type_ref = LLVMInt1Type();
entry->di_type = g->builtin_types.entry_bool->di_type;
- } else if (type_is_codegen_pointer(child_type)) {
+ } else if (type_is_codegen_pointer(child_type) || child_type->id == ZigTypeIdErrorSet) {
assert(child_type->di_type);
// this is an optimization but also is necessary for calling C
// functions where all pointers are maybe pointers
// function types are technically pointers
entry->type_ref = child_type->type_ref;
entry->di_type = child_type->di_type;
+ if (entry->di_type == g->builtin_types.entry_global_error_set->di_type) {
+ g->error_di_types.append(&entry->di_type);
+ }
} else {
assert(child_type->di_type);
// create a struct with a boolean whether this is the null value
@@ -817,7 +889,7 @@ ZigType *get_slice_type(CodeGen *g, ZigType *ptr_type) {
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.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);
@@ -840,7 +912,7 @@ ZigType *get_slice_type(CodeGen *g, ZigType *ptr_type) {
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.explicit_alignment != 0 || child_ptr_type->data.pointer.allow_zero)
{
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,
@@ -1054,11 +1126,7 @@ bool want_first_arg_sret(CodeGen *g, FnTypeId *fn_type_id) {
}
if (g->zig_target.arch.arch == ZigLLVM_x86_64) {
X64CABIClass abi_class = type_c_abi_x86_64_class(g, fn_type_id->return_type);
- if (abi_class == X64CABIClass_MEMORY) {
- return true;
- }
- zig_panic("TODO implement C ABI for x86_64 return types. type '%s'\nSee https://github.com/ziglang/zig/issues/1481",
- buf_ptr(&fn_type_id->return_type->name));
+ return abi_class == X64CABIClass_MEMORY;
} else if (target_is_arm(&g->zig_target)) {
return type_size(g, fn_type_id->return_type) > 16;
}
@@ -1219,7 +1287,10 @@ ZigType *get_fn_type(CodeGen *g, FnTypeId *fn_type_id) {
fn_type->data.fn.raw_type_ref = LLVMFunctionType(gen_return_type->type_ref,
gen_param_types.items, (unsigned int)gen_param_types.length, fn_type_id->is_var_args);
fn_type->type_ref = LLVMPointerType(fn_type->data.fn.raw_type_ref, 0);
- fn_type->di_type = ZigLLVMCreateSubroutineType(g->dbuilder, param_di_types.items, (int)param_di_types.length, 0);
+ fn_type->data.fn.raw_di_type = ZigLLVMCreateSubroutineType(g->dbuilder, param_di_types.items, (int)param_di_types.length, 0);
+ fn_type->di_type = ZigLLVMCreateDebugPointerType(g->dbuilder, fn_type->data.fn.raw_di_type,
+ LLVMStoreSizeOfType(g->target_data_ref, fn_type->type_ref),
+ LLVMABIAlignmentOfType(g->target_data_ref, fn_type->type_ref), "");
}
g->fn_type_table.put(&fn_type->data.fn.fn_type_id, fn_type);
@@ -1274,20 +1345,22 @@ ZigType *get_partial_container_type(CodeGen *g, Scope *scope, ContainerKind kind
return entry;
}
-static IrInstruction *analyze_const_value(CodeGen *g, Scope *scope, AstNode *node, ZigType *type_entry, Buf *type_name) {
+static ConstExprValue *analyze_const_value(CodeGen *g, Scope *scope, AstNode *node, ZigType *type_entry,
+ Buf *type_name)
+{
size_t backward_branch_count = 0;
return ir_eval_const_value(g, scope, node, type_entry,
&backward_branch_count, default_backward_branch_quota,
- nullptr, nullptr, node, type_name, nullptr);
+ nullptr, nullptr, node, type_name, nullptr, nullptr);
}
ZigType *analyze_type_expr(CodeGen *g, Scope *scope, AstNode *node) {
- IrInstruction *result = analyze_const_value(g, scope, node, g->builtin_types.entry_type, nullptr);
- if (result->value.type->id == ZigTypeIdInvalid)
+ ConstExprValue *result = analyze_const_value(g, scope, node, g->builtin_types.entry_type, nullptr);
+ if (type_is_invalid(result->type))
return g->builtin_types.entry_invalid;
- assert(result->value.special != ConstValSpecialRuntime);
- return result->value.data.x_type;
+ assert(result->special != ConstValSpecialRuntime);
+ return result->data.x_type;
}
ZigType *get_generic_fn_type(CodeGen *g, FnTypeId *fn_type_id) {
@@ -1338,11 +1411,11 @@ void init_fn_type_id(FnTypeId *fn_type_id, AstNode *proto_node, size_t param_cou
}
static bool analyze_const_align(CodeGen *g, Scope *scope, AstNode *node, uint32_t *result) {
- IrInstruction *align_result = analyze_const_value(g, scope, node, get_align_amt_type(g), nullptr);
- if (type_is_invalid(align_result->value.type))
+ ConstExprValue *align_result = analyze_const_value(g, scope, node, get_align_amt_type(g), nullptr);
+ if (type_is_invalid(align_result->type))
return false;
- uint32_t align_bytes = bigint_as_unsigned(&align_result->value.data.x_bigint);
+ uint32_t align_bytes = bigint_as_unsigned(&align_result->data.x_bigint);
if (align_bytes == 0) {
add_node_error(g, node, buf_sprintf("alignment must be >= 1"));
return false;
@@ -1360,12 +1433,12 @@ static bool analyze_const_string(CodeGen *g, Scope *scope, AstNode *node, Buf **
ZigType *ptr_type = get_pointer_to_type_extra(g, g->builtin_types.entry_u8, true, false,
PtrLenUnknown, 0, 0, 0);
ZigType *str_type = get_slice_type(g, ptr_type);
- IrInstruction *instr = analyze_const_value(g, scope, node, str_type, nullptr);
- if (type_is_invalid(instr->value.type))
+ ConstExprValue *result_val = analyze_const_value(g, scope, node, str_type, nullptr);
+ if (type_is_invalid(result_val->type))
return false;
- ConstExprValue *ptr_field = &instr->value.data.x_struct.fields[slice_ptr_index];
- ConstExprValue *len_field = &instr->value.data.x_struct.fields[slice_len_index];
+ ConstExprValue *ptr_field = &result_val->data.x_struct.fields[slice_ptr_index];
+ ConstExprValue *len_field = &result_val->data.x_struct.fields[slice_len_index];
assert(ptr_field->data.x_ptr.special == ConstPtrSpecialBaseArray);
ConstExprValue *array_val = ptr_field->data.x_ptr.data.base_array.array_val;
@@ -1418,6 +1491,7 @@ static bool type_allowed_in_packed_struct(ZigType *type_entry) {
case ZigTypeIdPointer:
case ZigTypeIdArray:
case ZigTypeIdFn:
+ case ZigTypeIdVector:
return true;
case ZigTypeIdStruct:
return type_entry->data.structure.layout == ContainerLayoutPacked;
@@ -1434,7 +1508,7 @@ static bool type_allowed_in_packed_struct(ZigType *type_entry) {
zig_unreachable();
}
-static bool type_allowed_in_extern(CodeGen *g, ZigType *type_entry) {
+bool type_allowed_in_extern(CodeGen *g, ZigType *type_entry) {
switch (type_entry->id) {
case ZigTypeIdInvalid:
zig_unreachable();
@@ -1466,6 +1540,8 @@ static bool type_allowed_in_extern(CodeGen *g, ZigType *type_entry) {
default:
return false;
}
+ case ZigTypeIdVector:
+ return type_allowed_in_extern(g, type_entry->data.vector.elem_type);
case ZigTypeIdFloat:
return true;
case ZigTypeIdArray:
@@ -1619,6 +1695,7 @@ static ZigType *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *child_sc
case ZigTypeIdUnion:
case ZigTypeIdFn:
case ZigTypeIdPromise:
+ case ZigTypeIdVector:
switch (type_requires_comptime(g, type_entry)) {
case ReqCompTimeNo:
break;
@@ -1714,6 +1791,7 @@ static ZigType *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *child_sc
case ZigTypeIdUnion:
case ZigTypeIdFn:
case ZigTypeIdPromise:
+ case ZigTypeIdVector:
switch (type_requires_comptime(g, fn_type_id.return_type)) {
case ReqCompTimeInvalid:
return g->builtin_types.entry_invalid;
@@ -2500,20 +2578,20 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) {
// In this first pass we resolve explicit tag values.
// In a second pass we will fill in the unspecified ones.
if (tag_value != nullptr) {
- IrInstruction *result_inst = analyze_const_value(g, scope, tag_value, tag_int_type, nullptr);
- if (result_inst->value.type->id == ZigTypeIdInvalid) {
+ ConstExprValue *result = analyze_const_value(g, scope, tag_value, tag_int_type, nullptr);
+ if (type_is_invalid(result->type)) {
enum_type->data.enumeration.is_invalid = true;
continue;
}
- assert(result_inst->value.special != ConstValSpecialRuntime);
- assert(result_inst->value.type->id == ZigTypeIdInt ||
- result_inst->value.type->id == ZigTypeIdComptimeInt);
- auto entry = occupied_tag_values.put_unique(result_inst->value.data.x_bigint, tag_value);
+ assert(result->special != ConstValSpecialRuntime);
+ assert(result->type->id == ZigTypeIdInt ||
+ result->type->id == ZigTypeIdComptimeInt);
+ auto entry = occupied_tag_values.put_unique(result->data.x_bigint, tag_value);
if (entry == nullptr) {
- bigint_init_bigint(&type_enum_field->value, &result_inst->value.data.x_bigint);
+ bigint_init_bigint(&type_enum_field->value, &result->data.x_bigint);
} else {
Buf *val_buf = buf_alloc();
- bigint_append_buf(val_buf, &result_inst->value.data.x_bigint, 10);
+ bigint_append_buf(val_buf, &result->data.x_bigint, 10);
ErrorMsg *msg = add_node_error(g, tag_value,
buf_sprintf("enum tag value %s already taken", buf_ptr(val_buf)));
@@ -2623,6 +2701,13 @@ static Error resolve_struct_zero_bits(CodeGen *g, ZigType *struct_type) {
buf_sprintf("enums, not structs, support field assignment"));
}
+ if (field_type->id == ZigTypeIdOpaque) {
+ add_node_error(g, field_node->data.struct_field.type,
+ buf_sprintf("opaque types have unknown size and therefore cannot be directly embedded in structs"));
+ struct_type->data.structure.resolve_status = ResolveStatusInvalid;
+ continue;
+ }
+
switch (type_requires_comptime(g, field_type)) {
case ReqCompTimeYes:
struct_type->data.structure.requires_comptime = true;
@@ -2680,39 +2765,50 @@ static Error resolve_struct_alignment(CodeGen *g, ZigType *struct_type) {
assert(decl_node->type == NodeTypeContainerDecl);
assert(struct_type->di_type);
+ size_t field_count = struct_type->data.structure.src_field_count;
if (struct_type->data.structure.layout == ContainerLayoutPacked) {
struct_type->data.structure.abi_alignment = 1;
- }
-
- size_t field_count = struct_type->data.structure.src_field_count;
- for (size_t i = 0; i < field_count; i += 1) {
- TypeStructField *field = &struct_type->data.structure.fields[i];
-
- // If this assertion trips, look up the call stack. Probably something is
- // calling type_resolve with ResolveStatusAlignmentKnown when it should only
- // be resolving ResolveStatusZeroBitsKnown
- assert(field->type_entry != nullptr);
-
- if (type_is_invalid(field->type_entry)) {
- struct_type->data.structure.resolve_status = ResolveStatusInvalid;
- break;
+ for (size_t i = 0; i < field_count; i += 1) {
+ TypeStructField *field = &struct_type->data.structure.fields[i];
+ if (field->type_entry != nullptr && type_is_invalid(field->type_entry)) {
+ struct_type->data.structure.resolve_status = ResolveStatusInvalid;
+ break;
+ }
}
+ } else for (size_t i = 0; i < field_count; i += 1) {
+ TypeStructField *field = &struct_type->data.structure.fields[i];
+ uint32_t this_field_align;
+
+ // TODO If we have no type_entry for the field, we've already failed to
+ // compile the program correctly. This stage1 compiler needs a deeper
+ // reworking to make this correct, or we can ignore the problem
+ // and make sure it is fixed in stage2. This workaround is for when
+ // there is a false positive of a dependency loop, of alignment depending
+ // on itself. When this false positive happens we assume a pointer-aligned
+ // field, which is usually fine but could be incorrectly over-aligned or
+ // even under-aligned. See https://github.com/ziglang/zig/issues/1512
+ if (field->type_entry == nullptr) {
+ this_field_align = LLVMABIAlignmentOfType(g->target_data_ref, LLVMPointerType(LLVMInt8Type(), 0));
+ } else {
+ if (type_is_invalid(field->type_entry)) {
+ struct_type->data.structure.resolve_status = ResolveStatusInvalid;
+ break;
+ }
- if (!type_has_bits(field->type_entry))
- continue;
+ if (!type_has_bits(field->type_entry))
+ continue;
- // alignment of structs is the alignment of the most-aligned field
- if (struct_type->data.structure.layout != ContainerLayoutPacked) {
if ((err = type_resolve(g, field->type_entry, ResolveStatusAlignmentKnown))) {
struct_type->data.structure.resolve_status = ResolveStatusInvalid;
break;
}
- uint32_t this_field_align = get_abi_alignment(g, field->type_entry);
+ this_field_align = get_abi_alignment(g, field->type_entry);
assert(this_field_align != 0);
- if (this_field_align > struct_type->data.structure.abi_alignment) {
- struct_type->data.structure.abi_alignment = this_field_align;
- }
+ }
+ // alignment of structs is the alignment of the most-aligned field
+ if (this_field_align > struct_type->data.structure.abi_alignment) {
+ struct_type->data.structure.abi_alignment = this_field_align;
}
}
@@ -2790,7 +2886,7 @@ static Error resolve_union_zero_bits(CodeGen *g, ZigType *union_type) {
union_type->data.unionation.have_explicit_tag_type = decl_node->data.container_decl.auto_enum ||
enum_type_node != nullptr;
bool auto_layout = (union_type->data.unionation.layout == ContainerLayoutAuto);
- bool want_safety = (field_count >= 2) && (auto_layout || enum_type_node != nullptr);
+ bool want_safety = (field_count >= 2) && (auto_layout || enum_type_node != nullptr) && !(g->build_mode == BuildModeFastRelease || g->build_mode == BuildModeSmallRelease);
ZigType *tag_type;
bool create_enum_type = decl_node->data.container_decl.auto_enum || (enum_type_node == nullptr && want_safety);
bool *covered_enum_fields;
@@ -2896,6 +2992,13 @@ static Error resolve_union_zero_bits(CodeGen *g, ZigType *union_type) {
}
union_field->type_entry = field_type;
+ if (field_type->id == ZigTypeIdOpaque) {
+ add_node_error(g, field_node->data.struct_field.type,
+ buf_sprintf("opaque types have unknown size and therefore cannot be directly embedded in unions"));
+ union_type->data.unionation.is_invalid = true;
+ continue;
+ }
+
switch (type_requires_comptime(g, field_type)) {
case ReqCompTimeInvalid:
union_type->data.unionation.is_invalid = true;
@@ -2929,19 +3032,19 @@ static Error resolve_union_zero_bits(CodeGen *g, ZigType *union_type) {
// In a second pass we will fill in the unspecified ones.
if (tag_value != nullptr) {
ZigType *tag_int_type = tag_type->data.enumeration.tag_int_type;
- IrInstruction *result_inst = analyze_const_value(g, scope, tag_value, tag_int_type, nullptr);
- if (result_inst->value.type->id == ZigTypeIdInvalid) {
+ ConstExprValue *result = analyze_const_value(g, scope, tag_value, tag_int_type, nullptr);
+ if (type_is_invalid(result->type)) {
union_type->data.unionation.is_invalid = true;
continue;
}
- assert(result_inst->value.special != ConstValSpecialRuntime);
- assert(result_inst->value.type->id == ZigTypeIdInt);
- auto entry = occupied_tag_values.put_unique(result_inst->value.data.x_bigint, tag_value);
+ assert(result->special != ConstValSpecialRuntime);
+ assert(result->type->id == ZigTypeIdInt);
+ auto entry = occupied_tag_values.put_unique(result->data.x_bigint, tag_value);
if (entry == nullptr) {
- bigint_init_bigint(&union_field->enum_field->value, &result_inst->value.data.x_bigint);
+ bigint_init_bigint(&union_field->enum_field->value, &result->data.x_bigint);
} else {
Buf *val_buf = buf_alloc();
- bigint_append_buf(val_buf, &result_inst->value.data.x_bigint, 10);
+ bigint_append_buf(val_buf, &result->data.x_bigint, 10);
ErrorMsg *msg = add_node_error(g, tag_value,
buf_sprintf("enum tag value %s already taken", buf_ptr(val_buf)));
@@ -3144,36 +3247,19 @@ static bool scope_is_root_decls(Scope *scope) {
zig_unreachable();
}
-static void wrong_panic_prototype(CodeGen *g, AstNode *proto_node, ZigType *fn_type) {
- add_node_error(g, proto_node,
- buf_sprintf("expected 'fn([]const u8, ?*builtin.StackTrace) noreturn', found '%s'",
- buf_ptr(&fn_type->name)));
-}
-
-static void typecheck_panic_fn(CodeGen *g, ZigFn *panic_fn) {
- AstNode *proto_node = panic_fn->proto_node;
- assert(proto_node->type == NodeTypeFnProto);
- ZigType *fn_type = panic_fn->type_entry;
- FnTypeId *fn_type_id = &fn_type->data.fn.fn_type_id;
- if (fn_type_id->param_count != 2) {
- return wrong_panic_prototype(g, proto_node, fn_type);
- }
- ZigType *const_u8_ptr = get_pointer_to_type_extra(g, g->builtin_types.entry_u8, true, false,
- PtrLenUnknown, 0, 0, 0);
- ZigType *const_u8_slice = get_slice_type(g, const_u8_ptr);
- if (fn_type_id->param_info[0].type != const_u8_slice) {
- return wrong_panic_prototype(g, proto_node, fn_type);
- }
+void typecheck_panic_fn(CodeGen *g, TldFn *tld_fn, ZigFn *panic_fn) {
+ ConstExprValue *panic_fn_type_val = get_builtin_value(g, "PanicFn");
+ assert(panic_fn_type_val != nullptr);
+ assert(panic_fn_type_val->type->id == ZigTypeIdMetaType);
+ ZigType *panic_fn_type = panic_fn_type_val->data.x_type;
- ZigType *optional_ptr_to_stack_trace_type = get_optional_type(g, get_ptr_to_stack_trace_type(g));
- if (fn_type_id->param_info[1].type != optional_ptr_to_stack_trace_type) {
- return wrong_panic_prototype(g, proto_node, fn_type);
- }
+ AstNode *fake_decl = allocate<AstNode>(1);
+ *fake_decl = *panic_fn->proto_node;
+ fake_decl->type = NodeTypeSymbol;
+ fake_decl->data.symbol_expr.symbol = &panic_fn->symbol_name;
- ZigType *actual_return_type = fn_type_id->return_type;
- if (actual_return_type != g->builtin_types.entry_unreachable) {
- return wrong_panic_prototype(g, proto_node, fn_type);
- }
+ // call this for the side effects of casting to panic_fn_type
+ analyze_const_value(g, tld_fn->base.parent_scope, fake_decl, panic_fn_type, nullptr);
}
ZigType *get_test_fn_type(CodeGen *g) {
@@ -3191,14 +3277,12 @@ void add_fn_export(CodeGen *g, ZigFn *fn_table_entry, Buf *symbol_name, GlobalLi
if (ccc) {
if (buf_eql_str(symbol_name, "main") && g->libc_link_lib != nullptr) {
g->have_c_main = true;
- g->windows_subsystem_windows = false;
- g->windows_subsystem_console = true;
+ g->subsystem = TargetSubsystemConsole;
} else if (buf_eql_str(symbol_name, "WinMain") &&
g->zig_target.os == OsWindows)
{
g->have_winmain = true;
- g->windows_subsystem_windows = true;
- g->windows_subsystem_console = false;
+ g->subsystem = TargetSubsystemWindows;
} else if (buf_eql_str(symbol_name, "WinMainCRTStartup") &&
g->zig_target.os == OsWindows)
{
@@ -3209,6 +3293,7 @@ void add_fn_export(CodeGen *g, ZigFn *fn_table_entry, Buf *symbol_name, GlobalLi
g->have_dllmain_crt_startup = true;
}
}
+
FnExport *fn_export = fn_table_entry->export_list.add_one();
memset(fn_export, 0, sizeof(FnExport));
buf_init_from_buf(&fn_export->name, symbol_name);
@@ -3269,18 +3354,18 @@ static void resolve_decl_fn(CodeGen *g, TldFn *tld_fn) {
if (!fn_table_entry->type_entry->data.fn.is_generic) {
if (fn_def_node)
g->fn_defs.append(fn_table_entry);
+ }
- if (scope_is_root_decls(tld_fn->base.parent_scope) &&
- (import == g->root_import || import->package == g->panic_package))
+ if (scope_is_root_decls(tld_fn->base.parent_scope) &&
+ (import == g->root_import || import->package == g->panic_package))
+ {
+ if (g->have_pub_main && buf_eql_str(&fn_table_entry->symbol_name, "main")) {
+ g->main_fn = fn_table_entry;
+ } else if ((import->package == g->panic_package || g->have_pub_panic) &&
+ buf_eql_str(&fn_table_entry->symbol_name, "panic"))
{
- if (g->have_pub_main && buf_eql_str(&fn_table_entry->symbol_name, "main")) {
- g->main_fn = fn_table_entry;
- } else if ((import->package == g->panic_package || g->have_pub_panic) &&
- buf_eql_str(&fn_table_entry->symbol_name, "panic"))
- {
- g->panic_fn = fn_table_entry;
- typecheck_panic_fn(g, fn_table_entry);
- }
+ g->panic_fn = fn_table_entry;
+ g->panic_tld_fn = tld_fn;
}
}
} else if (source_node->type == NodeTypeTestDecl) {
@@ -3405,7 +3490,8 @@ void update_compile_var(CodeGen *g, Buf *name, ConstExprValue *value) {
resolve_top_level_decl(g, tld, false, tld->source_node);
assert(tld->id == TldIdVar);
TldVar *tld_var = (TldVar *)tld;
- tld_var->var->value = value;
+ tld_var->var->const_value = value;
+ tld_var->var->var_type = value->type;
tld_var->var->align_bytes = get_abi_alignment(g, value->type);
}
@@ -3499,7 +3585,7 @@ void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node) {
case NodeTypeArrayType:
case NodeTypeErrorType:
case NodeTypeIfErrorExpr:
- case NodeTypeTestExpr:
+ case NodeTypeIfOptional:
case NodeTypeErrorSetDecl:
case NodeTypeCancel:
case NodeTypeResume:
@@ -3560,6 +3646,7 @@ ZigType *validate_var_type(CodeGen *g, AstNode *source_node, ZigType *type_entry
case ZigTypeIdFn:
case ZigTypeIdBoundFn:
case ZigTypeIdPromise:
+ case ZigTypeIdVector:
return type_entry;
}
zig_unreachable();
@@ -3568,13 +3655,15 @@ ZigType *validate_var_type(CodeGen *g, AstNode *source_node, ZigType *type_entry
// Set name to nullptr to make the variable anonymous (not visible to programmer).
// TODO merge with definition of add_local_var in ir.cpp
ZigVar *add_variable(CodeGen *g, AstNode *source_node, Scope *parent_scope, Buf *name,
- bool is_const, ConstExprValue *value, Tld *src_tld)
+ bool is_const, ConstExprValue *const_value, Tld *src_tld, ZigType *var_type)
{
Error err;
- assert(value);
+ assert(const_value != nullptr);
+ assert(var_type != nullptr);
ZigVar *variable_entry = allocate<ZigVar>(1);
- variable_entry->value = value;
+ variable_entry->const_value = const_value;
+ variable_entry->var_type = var_type;
variable_entry->parent_scope = parent_scope;
variable_entry->shadowable = false;
variable_entry->mem_slot_index = SIZE_MAX;
@@ -3583,23 +3672,23 @@ ZigVar *add_variable(CodeGen *g, AstNode *source_node, Scope *parent_scope, Buf
assert(name);
buf_init_from_buf(&variable_entry->name, name);
- if ((err = type_resolve(g, value->type, ResolveStatusAlignmentKnown))) {
- variable_entry->value->type = g->builtin_types.entry_invalid;
+ if ((err = type_resolve(g, var_type, ResolveStatusAlignmentKnown))) {
+ variable_entry->var_type = g->builtin_types.entry_invalid;
} else {
- variable_entry->align_bytes = get_abi_alignment(g, value->type);
+ variable_entry->align_bytes = get_abi_alignment(g, var_type);
ZigVar *existing_var = find_variable(g, parent_scope, name, nullptr);
if (existing_var && !existing_var->shadowable) {
ErrorMsg *msg = add_node_error(g, source_node,
buf_sprintf("redeclaration of variable '%s'", buf_ptr(name)));
add_error_note(g, msg, existing_var->decl_node, buf_sprintf("previous declaration is here"));
- variable_entry->value->type = g->builtin_types.entry_invalid;
+ variable_entry->var_type = g->builtin_types.entry_invalid;
} else {
ZigType *type;
if (get_primitive_type(g, name, &type) != ErrorPrimitiveTypeNotFound) {
add_node_error(g, source_node,
buf_sprintf("variable shadows primitive type '%s'", buf_ptr(name)));
- variable_entry->value->type = g->builtin_types.entry_invalid;
+ variable_entry->var_type = g->builtin_types.entry_invalid;
} else {
Scope *search_scope = nullptr;
if (src_tld == nullptr) {
@@ -3613,7 +3702,7 @@ ZigVar *add_variable(CodeGen *g, AstNode *source_node, Scope *parent_scope, Buf
ErrorMsg *msg = add_node_error(g, source_node,
buf_sprintf("redefinition of '%s'", buf_ptr(name)));
add_error_note(g, msg, tld->source_node, buf_sprintf("previous definition is here"));
- variable_entry->value->type = g->builtin_types.entry_invalid;
+ variable_entry->var_type = g->builtin_types.entry_invalid;
}
}
}
@@ -3645,6 +3734,7 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) {
bool is_const = var_decl->is_const;
bool is_extern = var_decl->is_extern;
bool is_export = var_decl->is_export;
+ bool is_thread_local = var_decl->threadlocal_tok != nullptr;
ZigType *explicit_type = nullptr;
if (var_decl->type) {
@@ -3663,7 +3753,7 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) {
linkage = VarLinkageInternal;
}
- IrInstruction *init_value = nullptr;
+ ConstExprValue *init_value = nullptr;
// TODO more validation for types that can't be used for export/extern variables
ZigType *implicit_type = nullptr;
@@ -3672,7 +3762,7 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) {
} else if (var_decl->expr) {
init_value = analyze_const_value(g, tld_var->base.parent_scope, var_decl->expr, explicit_type, var_decl->symbol);
assert(init_value);
- implicit_type = init_value->value.type;
+ implicit_type = init_value->type;
if (implicit_type->id == ZigTypeIdUnreachable) {
add_node_error(g, source_node, buf_sprintf("variable initialization is unreachable"));
@@ -3690,7 +3780,7 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) {
add_node_error(g, source_node, buf_sprintf("variable of type 'type' must be constant"));
implicit_type = g->builtin_types.entry_invalid;
}
- assert(implicit_type->id == ZigTypeIdInvalid || init_value->value.special != ConstValSpecialRuntime);
+ assert(implicit_type->id == ZigTypeIdInvalid || init_value->special != ConstValSpecialRuntime);
} else if (linkage != VarLinkageExternal) {
add_node_error(g, source_node, buf_sprintf("variables must be initialized"));
implicit_type = g->builtin_types.entry_invalid;
@@ -3699,19 +3789,20 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) {
ZigType *type = explicit_type ? explicit_type : implicit_type;
assert(type != nullptr); // should have been caught by the parser
- ConstExprValue *init_val = init_value ? &init_value->value : create_const_runtime(type);
+ ConstExprValue *init_val = (init_value != nullptr) ? init_value : create_const_runtime(type);
tld_var->var = add_variable(g, source_node, tld_var->base.parent_scope, var_decl->symbol,
- is_const, init_val, &tld_var->base);
+ is_const, init_val, &tld_var->base, type);
tld_var->var->linkage = linkage;
+ tld_var->var->is_thread_local = is_thread_local;
if (implicit_type != nullptr && type_is_invalid(implicit_type)) {
- tld_var->var->value->type = g->builtin_types.entry_invalid;
+ tld_var->var->var_type = g->builtin_types.entry_invalid;
}
if (var_decl->align_expr != nullptr) {
if (!analyze_const_align(g, tld_var->base.parent_scope, var_decl->align_expr, &tld_var->var->align_bytes)) {
- tld_var->var->value->type = g->builtin_types.entry_invalid;
+ tld_var->var->var_type = g->builtin_types.entry_invalid;
}
}
@@ -3724,6 +3815,10 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) {
}
}
+ if (is_thread_local && is_const) {
+ add_node_error(g, source_node, buf_sprintf("threadlocal variable cannot be constant"));
+ }
+
g->global_vars.append(tld_var);
}
@@ -3924,6 +4019,7 @@ static bool is_container(ZigType *type_entry) {
case ZigTypeIdArgTuple:
case ZigTypeIdOpaque:
case ZigTypeIdPromise:
+ case ZigTypeIdVector:
return false;
}
zig_unreachable();
@@ -3983,6 +4079,7 @@ void resolve_container_type(CodeGen *g, ZigType *type_entry) {
case ZigTypeIdArgTuple:
case ZigTypeIdOpaque:
case ZigTypeIdPromise:
+ case ZigTypeIdVector:
zig_unreachable();
}
}
@@ -3992,7 +4089,9 @@ ZigType *get_src_ptr_type(ZigType *type) {
if (type->id == ZigTypeIdFn) return type;
if (type->id == ZigTypeIdPromise) return type;
if (type->id == ZigTypeIdOptional) {
- if (type->data.maybe.child_type->id == ZigTypeIdPointer) return type->data.maybe.child_type;
+ if (type->data.maybe.child_type->id == ZigTypeIdPointer) {
+ return type->data.maybe.child_type->data.pointer.allow_zero ? nullptr : type->data.maybe.child_type;
+ }
if (type->data.maybe.child_type->id == ZigTypeIdFn) return type->data.maybe.child_type;
if (type->data.maybe.child_type->id == ZigTypeIdPromise) return type->data.maybe.child_type;
}
@@ -4006,6 +4105,10 @@ ZigType *get_codegen_ptr_type(ZigType *type) {
return ty;
}
+bool type_is_nonnull_ptr(ZigType *type) {
+ return type_is_codegen_pointer(type) && !ptr_allows_addr_zero(type);
+}
+
bool type_is_codegen_pointer(ZigType *type) {
return get_codegen_ptr_type(type) == type;
}
@@ -4076,7 +4179,7 @@ static void define_local_param_variables(CodeGen *g, ZigFn *fn_table_entry) {
}
ZigVar *var = add_variable(g, param_decl_node, fn_table_entry->child_scope,
- param_name, true, create_const_runtime(param_type), nullptr);
+ param_name, true, create_const_runtime(param_type), nullptr, param_type);
var->src_arg_index = i;
fn_table_entry->child_scope = var->child_scope;
var->shadowable = var->shadowable || is_var_args;
@@ -4214,18 +4317,17 @@ static void add_symbols_from_import(CodeGen *g, AstNode *src_use_node, AstNode *
preview_use_decl(g, src_use_node);
}
- IrInstruction *use_target_value = src_use_node->data.use.value;
- if (use_target_value->value.type->id == ZigTypeIdInvalid) {
+ ConstExprValue *use_target_value = src_use_node->data.use.value;
+ if (type_is_invalid(use_target_value->type)) {
dst_use_node->owner->any_imports_failed = true;
return;
}
dst_use_node->data.use.resolution = TldResolutionOk;
- ConstExprValue *const_val = &use_target_value->value;
- assert(const_val->special != ConstValSpecialRuntime);
+ assert(use_target_value->special != ConstValSpecialRuntime);
- ImportTableEntry *target_import = const_val->data.x_import;
+ ImportTableEntry *target_import = use_target_value->data.x_import;
assert(target_import);
if (target_import->any_imports_failed) {
@@ -4288,10 +4390,10 @@ void preview_use_decl(CodeGen *g, AstNode *node) {
}
node->data.use.resolution = TldResolutionResolving;
- IrInstruction *result = analyze_const_value(g, &node->owner->decls_scope->base,
+ ConstExprValue *result = analyze_const_value(g, &node->owner->decls_scope->base,
node->data.use.expr, g->builtin_types.entry_namespace, nullptr);
- if (result->value.type->id == ZigTypeIdInvalid)
+ if (type_is_invalid(result->type))
node->owner->any_imports_failed = true;
node->data.use.value = result;
@@ -4364,8 +4466,7 @@ ImportTableEntry *add_source_file(CodeGen *g, PackageTableEntry *package, Buf *r
if (is_pub && ok_cc) {
if (buf_eql_str(proto_name, "main")) {
g->have_pub_main = true;
- g->windows_subsystem_windows = false;
- g->windows_subsystem_console = true;
+ g->subsystem = TargetSubsystemConsole;
} else if (buf_eql_str(proto_name, "panic")) {
g->have_pub_panic = true;
}
@@ -4434,6 +4535,43 @@ ZigType *get_int_type(CodeGen *g, bool is_signed, uint32_t size_in_bits) {
return new_entry;
}
+bool is_valid_vector_elem_type(ZigType *elem_type) {
+ return elem_type->id == ZigTypeIdInt ||
+ elem_type->id == ZigTypeIdFloat ||
+ get_codegen_ptr_type(elem_type) != nullptr;
+}
+
+ZigType *get_vector_type(CodeGen *g, uint32_t len, ZigType *elem_type) {
+ assert(is_valid_vector_elem_type(elem_type));
+
+ TypeId type_id = {};
+ type_id.id = ZigTypeIdVector;
+ type_id.data.vector.len = len;
+ type_id.data.vector.elem_type = elem_type;
+
+ {
+ auto entry = g->type_table.maybe_get(type_id);
+ if (entry)
+ return entry->value;
+ }
+
+ ZigType *entry = new_type_table_entry(ZigTypeIdVector);
+ entry->zero_bits = (len == 0) || !type_has_bits(elem_type);
+ entry->type_ref = entry->zero_bits ? LLVMVoidType() : LLVMVectorType(elem_type->type_ref, len);
+ entry->data.vector.len = len;
+ entry->data.vector.elem_type = elem_type;
+
+ buf_resize(&entry->name, 0);
+ buf_appendf(&entry->name, "@Vector(%u, %s)", len, buf_ptr(&elem_type->name));
+
+ entry->di_type = ZigLLVMDIBuilderCreateVectorType(g->dbuilder,
+ len * type_size_bits(g, elem_type),
+ LLVMABIAlignmentOfType(g->target_data_ref, entry->type_ref), elem_type->di_type, len);
+
+ g->type_table.put(type_id, entry);
+ return entry;
+}
+
ZigType **get_c_int_type_ptr(CodeGen *g, CIntType c_int_type) {
return &g->builtin_types.entry_c_int[c_int_type];
}
@@ -4465,6 +4603,7 @@ bool handle_is_ptr(ZigType *type_entry) {
case ZigTypeIdFn:
case ZigTypeIdEnum:
case ZigTypeIdPromise:
+ case ZigTypeIdVector:
return false;
case ZigTypeIdArray:
case ZigTypeIdStruct:
@@ -4473,7 +4612,8 @@ bool handle_is_ptr(ZigType *type_entry) {
return type_has_bits(type_entry->data.error_union.payload_type);
case ZigTypeIdOptional:
return type_has_bits(type_entry->data.maybe.child_type) &&
- !type_is_codegen_pointer(type_entry->data.maybe.child_type);
+ !type_is_codegen_pointer(type_entry->data.maybe.child_type) &&
+ type_entry->data.maybe.child_type->id != ZigTypeIdErrorSet;
case ZigTypeIdUnion:
assert(type_entry->data.unionation.zero_bits_known);
if (type_entry->data.unionation.gen_field_count == 0)
@@ -4580,8 +4720,7 @@ static Buf *get_posix_libc_include_path(void) {
void find_libc_include_path(CodeGen *g) {
if (g->libc_include_dir == nullptr) {
if (!g->is_native_target) {
- fprintf(stderr, "Unable to determine libc include path. --libc-include-dir");
- exit(1);
+ return;
}
if (g->zig_target.os == OsWindows) {
@@ -4720,6 +4859,11 @@ bool fn_type_id_eql(FnTypeId *a, FnTypeId *b) {
return true;
}
+static uint32_t hash_const_val_error_set(ConstExprValue *const_val) {
+ assert(const_val->data.x_err_set != nullptr);
+ return const_val->data.x_err_set->value ^ 2630160122;
+}
+
static uint32_t hash_const_val_ptr(ConstExprValue *const_val) {
uint32_t hash_val = 0;
switch (const_val->data.x_ptr.mut) {
@@ -4751,6 +4895,18 @@ static uint32_t hash_const_val_ptr(ConstExprValue *const_val) {
hash_val += hash_ptr(const_val->data.x_ptr.data.base_struct.struct_val);
hash_val += hash_size(const_val->data.x_ptr.data.base_struct.field_index);
return hash_val;
+ case ConstPtrSpecialBaseErrorUnionCode:
+ hash_val += (uint32_t)2994743799;
+ hash_val += hash_ptr(const_val->data.x_ptr.data.base_err_union_code.err_union_val);
+ return hash_val;
+ case ConstPtrSpecialBaseErrorUnionPayload:
+ hash_val += (uint32_t)3456080131;
+ hash_val += hash_ptr(const_val->data.x_ptr.data.base_err_union_payload.err_union_val);
+ return hash_val;
+ case ConstPtrSpecialBaseOptionalPayload:
+ hash_val += (uint32_t)3163140517;
+ hash_val += hash_ptr(const_val->data.x_ptr.data.base_optional_payload.optional_val);
+ return hash_val;
case ConstPtrSpecialHardCodedAddr:
hash_val += (uint32_t)4048518294;
hash_val += hash_size(const_val->data.x_ptr.data.hard_coded_addr.addr);
@@ -4762,6 +4918,9 @@ static uint32_t hash_const_val_ptr(ConstExprValue *const_val) {
hash_val += (uint32_t)2590901619;
hash_val += hash_ptr(const_val->data.x_ptr.data.fn.fn_entry);
return hash_val;
+ case ConstPtrSpecialNull:
+ hash_val += (uint32_t)1486246455;
+ return hash_val;
}
zig_unreachable();
}
@@ -4860,7 +5019,9 @@ static uint32_t hash_const_val(ConstExprValue *const_val) {
return 2709806591;
case ZigTypeIdOptional:
if (get_codegen_ptr_type(const_val->type) != nullptr) {
- return hash_const_val(const_val) * 1992916303;
+ return hash_const_val_ptr(const_val) * 1992916303;
+ } else if (const_val->type->data.maybe.child_type->id == ZigTypeIdErrorSet) {
+ return hash_const_val_error_set(const_val) * 3147031929;
} else {
if (const_val->data.x_optional) {
return hash_const_val(const_val->data.x_optional) * 1992916303;
@@ -4872,10 +5033,12 @@ static uint32_t hash_const_val(ConstExprValue *const_val) {
// TODO better hashing algorithm
return 3415065496;
case ZigTypeIdErrorSet:
- assert(const_val->data.x_err_set != nullptr);
- return const_val->data.x_err_set->value ^ 2630160122;
+ return hash_const_val_error_set(const_val);
case ZigTypeIdNamespace:
return hash_ptr(const_val->data.x_import);
+ case ZigTypeIdVector:
+ // TODO better hashing algorithm
+ return 3647867726;
case ZigTypeIdBoundFn:
case ZigTypeIdInvalid:
case ZigTypeIdUnreachable:
@@ -4928,6 +5091,7 @@ static bool can_mutate_comptime_var_state(ConstExprValue *value) {
case ZigTypeIdBool:
case ZigTypeIdUnreachable:
case ZigTypeIdInt:
+ case ZigTypeIdVector:
case ZigTypeIdFloat:
case ZigTypeIdComptimeFloat:
case ZigTypeIdComptimeInt:
@@ -4975,7 +5139,7 @@ static bool can_mutate_comptime_var_state(ConstExprValue *value) {
return can_mutate_comptime_var_state(value->data.x_optional);
case ZigTypeIdErrorUnion:
- if (value->data.x_err_union.err != nullptr)
+ if (value->data.x_err_union.error_set->data.x_err_set != nullptr)
return false;
assert(value->data.x_err_union.payload != nullptr);
return can_mutate_comptime_var_state(value->data.x_err_union.payload);
@@ -5011,6 +5175,7 @@ static bool return_type_is_cacheable(ZigType *return_type) {
case ZigTypeIdErrorSet:
case ZigTypeIdEnum:
case ZigTypeIdPointer:
+ case ZigTypeIdVector:
return true;
case ZigTypeIdArray:
@@ -5036,9 +5201,9 @@ bool fn_eval_cacheable(Scope *scope, ZigType *return_type) {
while (scope) {
if (scope->id == ScopeIdVarDecl) {
ScopeVarDecl *var_scope = (ScopeVarDecl *)scope;
- if (type_is_invalid(var_scope->var->value->type))
+ if (type_is_invalid(var_scope->var->var_type))
return false;
- if (can_mutate_comptime_var_state(var_scope->var->value))
+ if (can_mutate_comptime_var_state(var_scope->var->const_value))
return false;
} else if (scope->id == ScopeIdFnDef) {
return true;
@@ -5056,7 +5221,7 @@ uint32_t fn_eval_hash(Scope* scope) {
while (scope) {
if (scope->id == ScopeIdVarDecl) {
ScopeVarDecl *var_scope = (ScopeVarDecl *)scope;
- result += hash_const_val(var_scope->var->value);
+ result += hash_const_val(var_scope->var->const_value);
} else if (scope->id == ScopeIdFnDef) {
ScopeFnDef *fn_scope = (ScopeFnDef *)scope;
result += hash_ptr(fn_scope->fn_entry);
@@ -5080,10 +5245,16 @@ bool fn_eval_eql(Scope *a, Scope *b) {
if (a->id == ScopeIdVarDecl) {
ScopeVarDecl *a_var_scope = (ScopeVarDecl *)a;
ScopeVarDecl *b_var_scope = (ScopeVarDecl *)b;
- if (a_var_scope->var->value->type != b_var_scope->var->value->type)
- return false;
- if (!const_values_equal(a->codegen, a_var_scope->var->value, b_var_scope->var->value))
+ if (a_var_scope->var->var_type != b_var_scope->var->var_type)
return false;
+ if (a_var_scope->var->var_type == a_var_scope->var->const_value->type &&
+ b_var_scope->var->var_type == b_var_scope->var->const_value->type)
+ {
+ if (!const_values_equal(a->codegen, a_var_scope->var->const_value, b_var_scope->var->const_value))
+ return false;
+ } else {
+ zig_panic("TODO comptime ptr reinterpret for fn_eval_eql");
+ }
} else if (a->id == ScopeIdFnDef) {
ScopeFnDef *a_fn_scope = (ScopeFnDef *)a;
ScopeFnDef *b_fn_scope = (ScopeFnDef *)b;
@@ -5101,6 +5272,7 @@ bool fn_eval_eql(Scope *a, Scope *b) {
return false;
}
+// Whether the type has bits at runtime.
bool type_has_bits(ZigType *type_entry) {
assert(type_entry);
assert(!type_is_invalid(type_entry));
@@ -5108,6 +5280,66 @@ bool type_has_bits(ZigType *type_entry) {
return !type_entry->zero_bits;
}
+// Whether you can infer the value based solely on the type.
+OnePossibleValue type_has_one_possible_value(CodeGen *g, ZigType *type_entry) {
+ assert(type_entry != nullptr);
+ Error err;
+ if ((err = type_resolve(g, type_entry, ResolveStatusZeroBitsKnown)))
+ return OnePossibleValueInvalid;
+ switch (type_entry->id) {
+ case ZigTypeIdInvalid:
+ zig_unreachable();
+ case ZigTypeIdOpaque:
+ case ZigTypeIdComptimeFloat:
+ case ZigTypeIdComptimeInt:
+ case ZigTypeIdMetaType:
+ case ZigTypeIdNamespace:
+ case ZigTypeIdBoundFn:
+ case ZigTypeIdArgTuple:
+ case ZigTypeIdOptional:
+ case ZigTypeIdFn:
+ case ZigTypeIdBool:
+ case ZigTypeIdFloat:
+ case ZigTypeIdPromise:
+ case ZigTypeIdErrorUnion:
+ return OnePossibleValueNo;
+ case ZigTypeIdUndefined:
+ case ZigTypeIdNull:
+ case ZigTypeIdVoid:
+ case ZigTypeIdUnreachable:
+ return OnePossibleValueYes;
+ case ZigTypeIdArray:
+ if (type_entry->data.array.len == 0)
+ return OnePossibleValueYes;
+ return type_has_one_possible_value(g, type_entry->data.array.child_type);
+ case ZigTypeIdStruct:
+ for (size_t i = 0; i < type_entry->data.structure.src_field_count; i += 1) {
+ TypeStructField *field = &type_entry->data.structure.fields[i];
+ switch (type_has_one_possible_value(g, field->type_entry)) {
+ case OnePossibleValueInvalid:
+ return OnePossibleValueInvalid;
+ case OnePossibleValueNo:
+ return OnePossibleValueNo;
+ case OnePossibleValueYes:
+ continue;
+ }
+ }
+ return OnePossibleValueYes;
+ case ZigTypeIdErrorSet:
+ case ZigTypeIdEnum:
+ case ZigTypeIdInt:
+ case ZigTypeIdVector:
+ return type_has_bits(type_entry) ? OnePossibleValueNo : OnePossibleValueYes;
+ case ZigTypeIdPointer:
+ return type_has_one_possible_value(g, type_entry->data.pointer.child_type);
+ case ZigTypeIdUnion:
+ if (type_entry->data.unionation.src_field_count > 1)
+ return OnePossibleValueNo;
+ return type_has_one_possible_value(g, type_entry->data.unionation.fields[0].type_entry);
+ }
+ zig_unreachable();
+}
+
ReqCompTime type_requires_comptime(CodeGen *g, ZigType *type_entry) {
Error err;
if ((err = type_resolve(g, type_entry, ResolveStatusZeroBitsKnown)))
@@ -5147,6 +5379,7 @@ ReqCompTime type_requires_comptime(CodeGen *g, ZigType *type_entry) {
case ZigTypeIdErrorSet:
case ZigTypeIdBool:
case ZigTypeIdInt:
+ case ZigTypeIdVector:
case ZigTypeIdFloat:
case ZigTypeIdVoid:
case ZigTypeIdUnreachable:
@@ -5562,6 +5795,33 @@ bool const_values_equal_ptr(ConstExprValue *a, ConstExprValue *b) {
if (a->data.x_ptr.data.base_struct.field_index != b->data.x_ptr.data.base_struct.field_index)
return false;
return true;
+ case ConstPtrSpecialBaseErrorUnionCode:
+ if (a->data.x_ptr.data.base_err_union_code.err_union_val !=
+ b->data.x_ptr.data.base_err_union_code.err_union_val &&
+ a->data.x_ptr.data.base_err_union_code.err_union_val->global_refs !=
+ b->data.x_ptr.data.base_err_union_code.err_union_val->global_refs)
+ {
+ return false;
+ }
+ return true;
+ case ConstPtrSpecialBaseErrorUnionPayload:
+ if (a->data.x_ptr.data.base_err_union_payload.err_union_val !=
+ b->data.x_ptr.data.base_err_union_payload.err_union_val &&
+ a->data.x_ptr.data.base_err_union_payload.err_union_val->global_refs !=
+ b->data.x_ptr.data.base_err_union_payload.err_union_val->global_refs)
+ {
+ return false;
+ }
+ return true;
+ case ConstPtrSpecialBaseOptionalPayload:
+ if (a->data.x_ptr.data.base_optional_payload.optional_val !=
+ b->data.x_ptr.data.base_optional_payload.optional_val &&
+ a->data.x_ptr.data.base_optional_payload.optional_val->global_refs !=
+ b->data.x_ptr.data.base_optional_payload.optional_val->global_refs)
+ {
+ return false;
+ }
+ return true;
case ConstPtrSpecialHardCodedAddr:
if (a->data.x_ptr.data.hard_coded_addr.addr != b->data.x_ptr.data.hard_coded_addr.addr)
return false;
@@ -5570,10 +5830,34 @@ bool const_values_equal_ptr(ConstExprValue *a, ConstExprValue *b) {
return true;
case ConstPtrSpecialFunction:
return a->data.x_ptr.data.fn.fn_entry == b->data.x_ptr.data.fn.fn_entry;
+ case ConstPtrSpecialNull:
+ return true;
}
zig_unreachable();
}
+static bool const_values_equal_array(CodeGen *g, ConstExprValue *a, ConstExprValue *b, size_t len) {
+ assert(a->data.x_array.special != ConstArraySpecialUndef);
+ assert(b->data.x_array.special != ConstArraySpecialUndef);
+ if (a->data.x_array.special == ConstArraySpecialBuf &&
+ b->data.x_array.special == ConstArraySpecialBuf)
+ {
+ return buf_eql_buf(a->data.x_array.data.s_buf, b->data.x_array.data.s_buf);
+ }
+ expand_undef_array(g, a);
+ expand_undef_array(g, b);
+
+ ConstExprValue *a_elems = a->data.x_array.data.s_none.elements;
+ ConstExprValue *b_elems = b->data.x_array.data.s_none.elements;
+
+ for (size_t i = 0; i < len; i += 1) {
+ if (!const_values_equal(g, &a_elems[i], &b_elems[i]))
+ return false;
+ }
+
+ return true;
+}
+
bool const_values_equal(CodeGen *g, ConstExprValue *a, ConstExprValue *b) {
assert(a->type->id == b->type->id);
assert(a->special == ConstValSpecialStatic);
@@ -5628,28 +5912,12 @@ bool const_values_equal(CodeGen *g, ConstExprValue *a, ConstExprValue *b) {
case ZigTypeIdPointer:
case ZigTypeIdFn:
return const_values_equal_ptr(a, b);
+ case ZigTypeIdVector:
+ assert(a->type->data.vector.len == b->type->data.vector.len);
+ return const_values_equal_array(g, a, b, a->type->data.vector.len);
case ZigTypeIdArray: {
assert(a->type->data.array.len == b->type->data.array.len);
- assert(a->data.x_array.special != ConstArraySpecialUndef);
- assert(b->data.x_array.special != ConstArraySpecialUndef);
- if (a->data.x_array.special == ConstArraySpecialBuf &&
- b->data.x_array.special == ConstArraySpecialBuf)
- {
- return buf_eql_buf(a->data.x_array.data.s_buf, b->data.x_array.data.s_buf);
- }
- expand_undef_array(g, a);
- expand_undef_array(g, b);
-
- size_t len = a->type->data.array.len;
- ConstExprValue *a_elems = a->data.x_array.data.s_none.elements;
- ConstExprValue *b_elems = b->data.x_array.data.s_none.elements;
-
- for (size_t i = 0; i < len; ++i) {
- if (!const_values_equal(g, &a_elems[i], &b_elems[i]))
- return false;
- }
-
- return true;
+ return const_values_equal_array(g, a, b, a->type->data.array.len);
}
case ZigTypeIdStruct:
for (size_t i = 0; i < a->type->data.structure.src_field_count; i += 1) {
@@ -5738,14 +6006,25 @@ void eval_min_max_value(CodeGen *g, ZigType *type_entry, ConstExprValue *const_v
}
}
-void render_const_val_ptr(CodeGen *g, Buf *buf, ConstExprValue *const_val, ZigType *type_entry) {
+static void render_const_val_ptr(CodeGen *g, Buf *buf, ConstExprValue *const_val, ZigType *type_entry) {
+ assert(type_entry->id == ZigTypeIdPointer);
+
+ if (type_entry->data.pointer.child_type->id == ZigTypeIdOpaque) {
+ buf_append_buf(buf, &type_entry->name);
+ return;
+ }
+
switch (const_val->data.x_ptr.special) {
case ConstPtrSpecialInvalid:
zig_unreachable();
case ConstPtrSpecialRef:
case ConstPtrSpecialBaseStruct:
+ case ConstPtrSpecialBaseErrorUnionCode:
+ case ConstPtrSpecialBaseErrorUnionPayload:
+ case ConstPtrSpecialBaseOptionalPayload:
buf_appendf(buf, "*");
- render_const_value(g, buf, const_ptr_pointee(g, const_val));
+ // 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 ConstPtrSpecialBaseArray:
if (const_val->data.x_ptr.data.base_array.is_cstr) {
@@ -5753,7 +6032,8 @@ void render_const_val_ptr(CodeGen *g, Buf *buf, ConstExprValue *const_val, ZigTy
return;
} else {
buf_appendf(buf, "*");
- render_const_value(g, buf, const_ptr_pointee(g, const_val));
+ // 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:
@@ -5769,6 +6049,56 @@ void render_const_val_ptr(CodeGen *g, Buf *buf, ConstExprValue *const_val, ZigTy
buf_appendf(buf, "@ptrCast(%s, %s)", buf_ptr(&const_val->type->name), buf_ptr(&fn_entry->symbol_name));
return;
}
+ case ConstPtrSpecialNull:
+ buf_append_str(buf, "null");
+ return;
+ }
+ zig_unreachable();
+}
+
+static void render_const_val_err_set(CodeGen *g, Buf *buf, ConstExprValue *const_val, ZigType *type_entry) {
+ if (const_val->data.x_err_set == nullptr) {
+ buf_append_str(buf, "null");
+ } else {
+ buf_appendf(buf, "%s.%s", buf_ptr(&type_entry->name), buf_ptr(&const_val->data.x_err_set->name));
+ }
+}
+
+static void render_const_val_array(CodeGen *g, Buf *buf, Buf *type_name, ConstExprValue *const_val, uint64_t start, uint64_t len) {
+ ConstArrayValue *array = &const_val->data.x_array;
+ switch (array->special) {
+ case ConstArraySpecialUndef:
+ buf_append_str(buf, "undefined");
+ return;
+ case ConstArraySpecialBuf: {
+ Buf *array_buf = array->data.s_buf;
+ const char *base = &buf_ptr(array_buf)[start];
+ assert(start + len <= buf_len(array_buf));
+
+ buf_append_char(buf, '"');
+ for (size_t i = 0; i < len; i += 1) {
+ uint8_t c = base[i];
+ if (c == '"') {
+ buf_append_str(buf, "\\\"");
+ } else {
+ buf_append_char(buf, c);
+ }
+ }
+ buf_append_char(buf, '"');
+ return;
+ }
+ case ConstArraySpecialNone: {
+ ConstExprValue *base = &array->data.s_none.elements[start];
+ assert(start + len <= const_val->type->data.array.len);
+
+ buf_appendf(buf, "%s{", buf_ptr(type_name));
+ for (uint64_t i = 0; i < len; i += 1) {
+ if (i != 0) buf_appendf(buf, ",");
+ render_const_value(g, buf, &base[i]);
+ }
+ buf_appendf(buf, "}");
+ return;
+ }
}
zig_unreachable();
}
@@ -5853,39 +6183,16 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) {
}
case ZigTypeIdPointer:
return render_const_val_ptr(g, buf, const_val, type_entry);
- case ZigTypeIdArray:
- switch (const_val->data.x_array.special) {
- case ConstArraySpecialUndef:
- buf_append_str(buf, "undefined");
- return;
- case ConstArraySpecialBuf: {
- Buf *array_buf = const_val->data.x_array.data.s_buf;
- buf_append_char(buf, '"');
- for (size_t i = 0; i < buf_len(array_buf); i += 1) {
- uint8_t c = buf_ptr(array_buf)[i];
- if (c == '"') {
- buf_append_str(buf, "\\\"");
- } else {
- buf_append_char(buf, c);
- }
- }
- buf_append_char(buf, '"');
- return;
- }
- case ConstArraySpecialNone: {
- buf_appendf(buf, "%s{", buf_ptr(&type_entry->name));
- uint64_t len = type_entry->data.array.len;
- for (uint64_t i = 0; i < len; i += 1) {
- if (i != 0)
- buf_appendf(buf, ",");
- ConstExprValue *child_value = &const_val->data.x_array.data.s_none.elements[i];
- render_const_value(g, buf, child_value);
- }
- buf_appendf(buf, "}");
- return;
- }
- }
- zig_unreachable();
+ case ZigTypeIdArray: {
+ uint64_t len = type_entry->data.array.len;
+ render_const_val_array(g, buf, &type_entry->name, const_val, 0, len);
+ return;
+ }
+ case ZigTypeIdVector: {
+ uint32_t len = type_entry->data.vector.len;
+ render_const_val_array(g, buf, &type_entry->name, const_val, 0, len);
+ return;
+ }
case ZigTypeIdNull:
{
buf_appendf(buf, "null");
@@ -5900,6 +6207,8 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) {
{
if (get_codegen_ptr_type(const_val->type) != nullptr)
return render_const_val_ptr(g, buf, const_val, type_entry->data.maybe.child_type);
+ if (type_entry->data.maybe.child_type->id == ZigTypeIdErrorSet)
+ return render_const_val_err_set(g, buf, const_val, type_entry->data.maybe.child_type);
if (const_val->data.x_optional) {
render_const_value(g, buf, const_val->data.x_optional);
} else {
@@ -5925,7 +6234,24 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) {
}
case ZigTypeIdStruct:
{
- buf_appendf(buf, "(struct %s constant)", buf_ptr(&type_entry->name));
+ if (is_slice(type_entry)) {
+ ConstExprValue *len_val = &const_val->data.x_struct.fields[slice_len_index];
+ size_t len = bigint_as_unsigned(&len_val->data.x_bigint);
+
+ ConstExprValue *ptr_val = &const_val->data.x_struct.fields[slice_ptr_index];
+ if (ptr_val->special == ConstValSpecialUndef) {
+ assert(len == 0);
+ buf_appendf(buf, "((%s)(undefined))[0..0]", buf_ptr(&type_entry->name));
+ return;
+ }
+ assert(ptr_val->data.x_ptr.special == ConstPtrSpecialBaseArray);
+ ConstExprValue *array = ptr_val->data.x_ptr.data.base_array.array_val;
+ size_t start = ptr_val->data.x_ptr.data.base_array.elem_index;
+
+ render_const_val_array(g, buf, &type_entry->name, array, start, len);
+ } else {
+ buf_appendf(buf, "(struct %s constant)", buf_ptr(&type_entry->name));
+ }
return;
}
case ZigTypeIdEnum:
@@ -5937,11 +6263,12 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) {
case ZigTypeIdErrorUnion:
{
buf_appendf(buf, "%s(", buf_ptr(&type_entry->name));
- if (const_val->data.x_err_union.err == nullptr) {
+ ErrorTableEntry *err_set = const_val->data.x_err_union.error_set->data.x_err_set;
+ if (err_set == nullptr) {
render_const_value(g, buf, const_val->data.x_err_union.payload);
} else {
buf_appendf(buf, "%s.%s", buf_ptr(&type_entry->data.error_union.err_set_type->name),
- buf_ptr(&const_val->data.x_err_union.err->name));
+ buf_ptr(&err_set->name));
}
buf_appendf(buf, ")");
return;
@@ -5956,10 +6283,7 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) {
return;
}
case ZigTypeIdErrorSet:
- {
- buf_appendf(buf, "%s.%s", buf_ptr(&type_entry->name), buf_ptr(&const_val->data.x_err_set->name));
- return;
- }
+ return render_const_val_err_set(g, buf, const_val, type_entry);
case ZigTypeIdArgTuple:
{
buf_appendf(buf, "(args value)");
@@ -6035,6 +6359,7 @@ uint32_t type_id_hash(TypeId x) {
((x.data.pointer.ptr_len == PtrLenSingle) ? (uint32_t)1120226602 : (uint32_t)3200913342) +
(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.host_int_bytes) ^ (uint32_t)529908881);
@@ -6044,6 +6369,8 @@ uint32_t type_id_hash(TypeId x) {
case ZigTypeIdInt:
return (x.data.integer.is_signed ? (uint32_t)2652528194 : (uint32_t)163929201) +
(((uint32_t)x.data.integer.bit_count) ^ (uint32_t)2998081557);
+ case ZigTypeIdVector:
+ return hash_ptr(x.data.vector.elem_type) * (x.data.vector.len * 526582681);
}
zig_unreachable();
}
@@ -6083,6 +6410,7 @@ bool type_id_eql(TypeId a, TypeId b) {
a.data.pointer.ptr_len == b.data.pointer.ptr_len &&
a.data.pointer.is_const == b.data.pointer.is_const &&
a.data.pointer.is_volatile == b.data.pointer.is_volatile &&
+ a.data.pointer.allow_zero == b.data.pointer.allow_zero &&
a.data.pointer.alignment == b.data.pointer.alignment &&
a.data.pointer.bit_offset_in_host == b.data.pointer.bit_offset_in_host &&
a.data.pointer.host_int_bytes == b.data.pointer.host_int_bytes;
@@ -6092,6 +6420,9 @@ bool type_id_eql(TypeId a, TypeId b) {
case ZigTypeIdInt:
return a.data.integer.is_signed == b.data.integer.is_signed &&
a.data.integer.bit_count == b.data.integer.bit_count;
+ case ZigTypeIdVector:
+ return a.data.vector.elem_type == b.data.vector.elem_type &&
+ a.data.vector.len == b.data.vector.len;
}
zig_unreachable();
}
@@ -6110,10 +6441,15 @@ uint32_t zig_llvm_fn_key_hash(ZigLLVMFnKey x) {
return (uint32_t)(x.data.floating.bit_count) * (uint32_t)1953839089;
case ZigLLVMFnIdSqrt:
return (uint32_t)(x.data.floating.bit_count) * (uint32_t)2225366385;
+ case ZigLLVMFnIdBswap:
+ return (uint32_t)(x.data.bswap.bit_count) * (uint32_t)3661994335;
+ case ZigLLVMFnIdBitReverse:
+ return (uint32_t)(x.data.bit_reverse.bit_count) * (uint32_t)2621398431;
case ZigLLVMFnIdOverflowArithmetic:
return ((uint32_t)(x.data.overflow_arithmetic.bit_count) * 87135777) +
((uint32_t)(x.data.overflow_arithmetic.add_sub_mul) * 31640542) +
- ((uint32_t)(x.data.overflow_arithmetic.is_signed) ? 1062315172 : 314955820);
+ ((uint32_t)(x.data.overflow_arithmetic.is_signed) ? 1062315172 : 314955820) +
+ x.data.overflow_arithmetic.vector_len * 1435156945;
}
zig_unreachable();
}
@@ -6128,6 +6464,10 @@ bool zig_llvm_fn_key_eql(ZigLLVMFnKey a, ZigLLVMFnKey b) {
return a.data.clz.bit_count == b.data.clz.bit_count;
case ZigLLVMFnIdPopCount:
return a.data.pop_count.bit_count == b.data.pop_count.bit_count;
+ case ZigLLVMFnIdBswap:
+ return a.data.bswap.bit_count == b.data.bswap.bit_count;
+ case ZigLLVMFnIdBitReverse:
+ return a.data.bit_reverse.bit_count == b.data.bit_reverse.bit_count;
case ZigLLVMFnIdFloor:
case ZigLLVMFnIdCeil:
case ZigLLVMFnIdSqrt:
@@ -6135,31 +6475,42 @@ bool zig_llvm_fn_key_eql(ZigLLVMFnKey a, ZigLLVMFnKey b) {
case ZigLLVMFnIdOverflowArithmetic:
return (a.data.overflow_arithmetic.bit_count == b.data.overflow_arithmetic.bit_count) &&
(a.data.overflow_arithmetic.add_sub_mul == b.data.overflow_arithmetic.add_sub_mul) &&
- (a.data.overflow_arithmetic.is_signed == b.data.overflow_arithmetic.is_signed);
+ (a.data.overflow_arithmetic.is_signed == b.data.overflow_arithmetic.is_signed) &&
+ (a.data.overflow_arithmetic.vector_len == b.data.overflow_arithmetic.vector_len);
}
zig_unreachable();
}
// Canonicalize the array value as ConstArraySpecialNone
void expand_undef_array(CodeGen *g, ConstExprValue *const_val) {
- assert(const_val->type->id == ZigTypeIdArray);
+ size_t elem_count;
+ ZigType *elem_type;
+ if (const_val->type->id == ZigTypeIdArray) {
+ elem_count = const_val->type->data.array.len;
+ elem_type = const_val->type->data.array.child_type;
+ } else if (const_val->type->id == ZigTypeIdVector) {
+ elem_count = const_val->type->data.vector.len;
+ elem_type = const_val->type->data.vector.elem_type;
+ } else {
+ zig_unreachable();
+ }
+ if (const_val->special == ConstValSpecialUndef) {
+ const_val->special = ConstValSpecialStatic;
+ const_val->data.x_array.special = ConstArraySpecialUndef;
+ }
switch (const_val->data.x_array.special) {
case ConstArraySpecialNone:
return;
case ConstArraySpecialUndef: {
const_val->data.x_array.special = ConstArraySpecialNone;
- size_t elem_count = const_val->type->data.array.len;
const_val->data.x_array.data.s_none.elements = create_const_vals(elem_count);
for (size_t i = 0; i < elem_count; i += 1) {
ConstExprValue *element_val = &const_val->data.x_array.data.s_none.elements[i];
- element_val->type = const_val->type->data.array.child_type;
+ element_val->type = elem_type;
init_const_undefined(g, element_val);
- ConstParent *parent = get_const_val_parent(g, element_val);
- if (parent != nullptr) {
- parent->id = ConstParentIdArray;
- parent->data.p_array.array_val = const_val;
- parent->data.p_array.elem_index = i;
- }
+ element_val->parent.id = ConstParentIdArray;
+ element_val->parent.data.p_array.array_val = const_val;
+ element_val->parent.data.p_array.elem_index = i;
}
return;
}
@@ -6170,7 +6521,6 @@ void expand_undef_array(CodeGen *g, ConstExprValue *const_val) {
g->string_literals_table.maybe_remove(buf);
const_val->data.x_array.special = ConstArraySpecialNone;
- size_t elem_count = const_val->type->data.array.len;
assert(elem_count == buf_len(buf));
const_val->data.x_array.data.s_none.elements = create_const_vals(elem_count);
for (size_t i = 0; i < elem_count; i += 1) {
@@ -6178,6 +6528,9 @@ void expand_undef_array(CodeGen *g, ConstExprValue *const_val) {
this_char->special = ConstValSpecialStatic;
this_char->type = g->builtin_types.entry_u8;
bigint_init_unsigned(&this_char->data.x_bigint, (uint8_t)buf_ptr(buf)[i]);
+ this_char->parent.id = ConstParentIdArray;
+ this_char->parent.data.p_array.array_val = const_val;
+ this_char->parent.data.p_array.elem_index = i;
}
return;
}
@@ -6185,18 +6538,9 @@ void expand_undef_array(CodeGen *g, ConstExprValue *const_val) {
zig_unreachable();
}
+// Deprecated. Reference the parent field directly.
ConstParent *get_const_val_parent(CodeGen *g, ConstExprValue *value) {
- assert(value->type);
- ZigType *type_entry = value->type;
- if (type_entry->id == ZigTypeIdArray) {
- expand_undef_array(g, value);
- return &value->data.x_array.data.s_none.parent;
- } else if (type_entry->id == ZigTypeIdStruct) {
- return &value->data.x_struct.parent;
- } else if (type_entry->id == ZigTypeIdUnion) {
- return &value->data.x_union.parent;
- }
- return nullptr;
+ return &value->parent;
}
static const ZigTypeId all_type_ids[] = {
@@ -6224,6 +6568,7 @@ static const ZigTypeId all_type_ids[] = {
ZigTypeIdArgTuple,
ZigTypeIdOpaque,
ZigTypeIdPromise,
+ ZigTypeIdVector,
};
ZigTypeId type_id_at_index(size_t index) {
@@ -6289,6 +6634,8 @@ size_t type_id_index(ZigType *entry) {
return 22;
case ZigTypeIdPromise:
return 23;
+ case ZigTypeIdVector:
+ return 24;
}
zig_unreachable();
}
@@ -6345,6 +6692,8 @@ const char *type_id_name(ZigTypeId id) {
return "Opaque";
case ZigTypeIdPromise:
return "Promise";
+ case ZigTypeIdVector:
+ return "Vector";
}
zig_unreachable();
}
@@ -6361,7 +6710,7 @@ LinkLib *add_link_lib(CodeGen *g, Buf *name) {
if (is_libc && g->libc_link_lib != nullptr)
return g->libc_link_lib;
- if (g->enable_cache && is_libc && g->zig_target.os != OsMacOSX && g->zig_target.os != OsIOS) {
+ if (g->enable_cache && is_libc && g->zig_target.os != OsMacOSX && g->zig_target.os != OsIOS && g->zig_target.os != OsFreeBSD) {
fprintf(stderr, "TODO linking against libc is currently incompatible with `--cache on`.\n"
"Zig is not yet capable of determining whether the libc installation has changed on subsequent builds.\n");
exit(1);
@@ -6424,7 +6773,7 @@ ConstExprValue *get_builtin_value(CodeGen *codegen, const char *name) {
resolve_top_level_decl(codegen, tld, false, nullptr);
assert(tld->id == TldIdVar);
TldVar *tld_var = (TldVar *)tld;
- ConstExprValue *var_value = tld_var->var->value;
+ ConstExprValue *var_value = tld_var->var->const_value;
assert(var_value != nullptr);
return var_value;
}
@@ -6500,6 +6849,7 @@ X64CABIClass type_c_abi_x86_64_class(CodeGen *g, ZigType *ty) {
case ZigTypeIdBool:
return X64CABIClass_INTEGER;
case ZigTypeIdFloat:
+ case ZigTypeIdVector:
return X64CABIClass_SSE;
case ZigTypeIdStruct: {
// "If the size of an object is larger than four eightbytes, or it contains unaligned
@@ -6579,3 +6929,36 @@ uint32_t get_host_int_bytes(CodeGen *g, ZigType *struct_type, TypeStructField *f
LLVMTypeRef field_type = LLVMStructGetTypeAtIndex(struct_type->type_ref, field->gen_index);
return LLVMStoreSizeOfType(g->target_data_ref, field_type);
}
+
+Error ensure_const_val_repr(IrAnalyze *ira, CodeGen *codegen, AstNode *source_node,
+ ConstExprValue *const_val, ZigType *wanted_type)
+{
+ ConstExprValue ptr_val = {};
+ ptr_val.special = ConstValSpecialStatic;
+ ptr_val.type = get_pointer_to_type(codegen, wanted_type, true);
+ ptr_val.data.x_ptr.mut = ConstPtrMutComptimeConst;
+ ptr_val.data.x_ptr.special = ConstPtrSpecialRef;
+ ptr_val.data.x_ptr.data.ref.pointee = const_val;
+ if (const_ptr_pointee(ira, codegen, &ptr_val, source_node) == nullptr)
+ return ErrorSemanticAnalyzeFail;
+
+ return ErrorNone;
+}
+
+const char *container_string(ContainerKind kind) {
+ switch (kind) {
+ case ContainerKindEnum: return "enum";
+ case ContainerKindStruct: return "struct";
+ case ContainerKindUnion: return "union";
+ }
+ zig_unreachable();
+}
+
+bool ptr_allows_addr_zero(ZigType *ptr_type) {
+ if (ptr_type->id == ZigTypeIdPointer) {
+ return ptr_type->data.pointer.allow_zero;
+ } else if (ptr_type->id == ZigTypeIdOptional) {
+ return true;
+ }
+ return false;
+}