get_codegen_ptr_type returns possible error

And fix most of the fallout. This also makes optional pointers not
require resolving zero bits, because the comptime value struct layout no
longer depends on whether the type has zero bits.

Thanks to @LemonBoy for the behavior test case

Closes #4357
Closes #4359
This commit is contained in:
Andrew Kelley 2020-03-04 16:46:24 -05:00
parent 6cbd1ac51a
commit f247a90541
No known key found for this signature in database
GPG Key ID: 7C5F548F728501A9
5 changed files with 439 additions and 300 deletions

View File

@ -597,7 +597,7 @@ ZigType *get_pointer_to_type_extra2(CodeGen *g, ZigType *child_type, bool is_con
entry->size_in_bits = SIZE_MAX; entry->size_in_bits = SIZE_MAX;
entry->abi_align = UINT32_MAX; entry->abi_align = UINT32_MAX;
} else if (type_is_resolved(child_type, ResolveStatusZeroBitsKnown)) { } else if (type_is_resolved(child_type, ResolveStatusZeroBitsKnown)) {
if (type_has_bits(child_type)) { if (type_has_bits(g, child_type)) {
entry->abi_size = g->builtin_types.entry_usize->abi_size; entry->abi_size = g->builtin_types.entry_usize->abi_size;
entry->size_in_bits = g->builtin_types.entry_usize->size_in_bits; entry->size_in_bits = g->builtin_types.entry_usize->size_in_bits;
entry->abi_align = g->builtin_types.entry_usize->abi_align; entry->abi_align = g->builtin_types.entry_usize->abi_align;
@ -660,11 +660,11 @@ ZigType *get_optional_type(CodeGen *g, ZigType *child_type) {
buf_resize(&entry->name, 0); buf_resize(&entry->name, 0);
buf_appendf(&entry->name, "?%s", buf_ptr(&child_type->name)); buf_appendf(&entry->name, "?%s", buf_ptr(&child_type->name));
if (!type_has_bits(child_type)) { if (!type_has_bits(g, child_type)) {
entry->size_in_bits = g->builtin_types.entry_bool->size_in_bits; entry->size_in_bits = g->builtin_types.entry_bool->size_in_bits;
entry->abi_size = g->builtin_types.entry_bool->abi_size; entry->abi_size = g->builtin_types.entry_bool->abi_size;
entry->abi_align = g->builtin_types.entry_bool->abi_align; entry->abi_align = g->builtin_types.entry_bool->abi_align;
} else if (type_is_nonnull_ptr(child_type) || child_type->id == ZigTypeIdErrorSet) { } else if (type_is_nonnull_ptr(g, child_type) || child_type->id == ZigTypeIdErrorSet) {
// This is an optimization but also is necessary for calling C // This is an optimization but also is necessary for calling C
// functions where all pointers are optional pointers. // functions where all pointers are optional pointers.
// Function types are technically pointers. // Function types are technically pointers.
@ -729,8 +729,8 @@ ZigType *get_error_union_type(CodeGen *g, ZigType *err_set_type, ZigType *payloa
entry->data.error_union.err_set_type = err_set_type; entry->data.error_union.err_set_type = err_set_type;
entry->data.error_union.payload_type = payload_type; entry->data.error_union.payload_type = payload_type;
if (!type_has_bits(payload_type)) { if (!type_has_bits(g, payload_type)) {
if (type_has_bits(err_set_type)) { if (type_has_bits(g, err_set_type)) {
entry->size_in_bits = err_set_type->size_in_bits; entry->size_in_bits = err_set_type->size_in_bits;
entry->abi_size = err_set_type->abi_size; entry->abi_size = err_set_type->abi_size;
entry->abi_align = err_set_type->abi_align; entry->abi_align = err_set_type->abi_align;
@ -739,7 +739,7 @@ ZigType *get_error_union_type(CodeGen *g, ZigType *err_set_type, ZigType *payloa
entry->abi_size = 0; entry->abi_size = 0;
entry->abi_align = 0; entry->abi_align = 0;
} }
} else if (!type_has_bits(err_set_type)) { } else if (!type_has_bits(g, err_set_type)) {
entry->size_in_bits = payload_type->size_in_bits; entry->size_in_bits = payload_type->size_in_bits;
entry->abi_size = payload_type->abi_size; entry->abi_size = payload_type->abi_size;
entry->abi_align = payload_type->abi_align; entry->abi_align = payload_type->abi_align;
@ -856,13 +856,13 @@ ZigType *get_slice_type(CodeGen *g, ZigType *ptr_type) {
entry->data.structure.requires_comptime = true; entry->data.structure.requires_comptime = true;
} }
if (!type_has_bits(ptr_type)) { if (!type_has_bits(g, ptr_type)) {
entry->data.structure.gen_field_count = 1; entry->data.structure.gen_field_count = 1;
entry->data.structure.fields[slice_ptr_index]->gen_index = SIZE_MAX; entry->data.structure.fields[slice_ptr_index]->gen_index = SIZE_MAX;
entry->data.structure.fields[slice_len_index]->gen_index = 0; entry->data.structure.fields[slice_len_index]->gen_index = 0;
} }
if (type_has_bits(ptr_type)) { if (type_has_bits(g, ptr_type)) {
entry->size_in_bits = ptr_type->size_in_bits + g->builtin_types.entry_usize->size_in_bits; 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; entry->abi_size = ptr_type->abi_size + g->builtin_types.entry_usize->abi_size;
entry->abi_align = ptr_type->abi_align; entry->abi_align = ptr_type->abi_align;
@ -969,12 +969,12 @@ ZigType *get_stack_trace_type(CodeGen *g) {
bool want_first_arg_sret(CodeGen *g, FnTypeId *fn_type_id) { bool want_first_arg_sret(CodeGen *g, FnTypeId *fn_type_id) {
if (fn_type_id->cc == CallingConventionUnspecified) { if (fn_type_id->cc == CallingConventionUnspecified) {
return handle_is_ptr(fn_type_id->return_type); return handle_is_ptr(g, fn_type_id->return_type);
} }
if (fn_type_id->cc != CallingConventionC) { if (fn_type_id->cc != CallingConventionC) {
return false; return false;
} }
if (type_is_c_abi_int(g, fn_type_id->return_type)) { if (type_is_c_abi_int_bail(g, fn_type_id->return_type)) {
return false; return false;
} }
if (g->zig_target->arch == ZigLLVM_x86 || if (g->zig_target->arch == ZigLLVM_x86 ||
@ -1650,15 +1650,16 @@ static Error emit_error_unless_type_allowed_in_packed_container(CodeGen *g, ZigT
return ErrorSemanticAnalyzeFail; return ErrorSemanticAnalyzeFail;
} }
zig_unreachable(); zig_unreachable();
case ZigTypeIdOptional: case ZigTypeIdOptional: {
if (get_codegen_ptr_type(type_entry) != nullptr) { ZigType *ptr_type;
return ErrorNone; if ((err = get_codegen_ptr_type(g, type_entry, &ptr_type))) return err;
} else { if (ptr_type != nullptr) return ErrorNone;
add_node_error(g, source_node,
buf_sprintf("type '%s' not allowed in packed %s; no guaranteed in-memory representation", add_node_error(g, source_node,
buf_ptr(&type_entry->name), container_name)); buf_sprintf("type '%s' not allowed in packed %s; no guaranteed in-memory representation",
return ErrorSemanticAnalyzeFail; buf_ptr(&type_entry->name), container_name));
} return ErrorSemanticAnalyzeFail;
}
case ZigTypeIdEnum: { case ZigTypeIdEnum: {
AstNode *decl_node = type_entry->data.enumeration.decl_node; AstNode *decl_node = type_entry->data.enumeration.decl_node;
if (decl_node->data.container_decl.init_arg_expr != nullptr) { if (decl_node->data.container_decl.init_arg_expr != nullptr) {
@ -1737,7 +1738,7 @@ Error type_allowed_in_extern(CodeGen *g, ZigType *type_entry, bool *result) {
case ZigTypeIdPointer: case ZigTypeIdPointer:
if ((err = type_resolve(g, type_entry, ResolveStatusZeroBitsKnown))) if ((err = type_resolve(g, type_entry, ResolveStatusZeroBitsKnown)))
return err; return err;
if (!type_has_bits(type_entry)) { if (!type_has_bits(g, type_entry)) {
*result = false; *result = false;
return ErrorNone; return ErrorNone;
} }
@ -1753,7 +1754,7 @@ Error type_allowed_in_extern(CodeGen *g, ZigType *type_entry, bool *result) {
*result = false; *result = false;
return ErrorNone; return ErrorNone;
} }
if (!type_is_nonnull_ptr(child_type)) { if (!type_is_nonnull_ptr(g, child_type)) {
*result = false; *result = false;
return ErrorNone; return ErrorNone;
} }
@ -1848,7 +1849,7 @@ static ZigType *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *child_sc
if (!calling_convention_allows_zig_types(fn_type_id.cc)) { if (!calling_convention_allows_zig_types(fn_type_id.cc)) {
if ((err = type_resolve(g, type_entry, ResolveStatusZeroBitsKnown))) if ((err = type_resolve(g, type_entry, ResolveStatusZeroBitsKnown)))
return g->builtin_types.entry_invalid; return g->builtin_types.entry_invalid;
if (!type_has_bits(type_entry)) { if (!type_has_bits(g, type_entry)) {
add_node_error(g, param_node->data.param_decl.type, add_node_error(g, param_node->data.param_decl.type,
buf_sprintf("parameter of type '%s' has 0 bits; not allowed in function with calling convention '%s'", buf_sprintf("parameter of type '%s' has 0 bits; not allowed in function with calling convention '%s'",
buf_ptr(&type_entry->name), calling_convention_name(fn_type_id.cc))); buf_ptr(&type_entry->name), calling_convention_name(fn_type_id.cc)));
@ -2082,7 +2083,7 @@ static ZigType *get_struct_type(CodeGen *g, const char *type_name, SrcField fiel
field->src_index = i; field->src_index = i;
field->align = fields[i].align; field->align = fields[i].align;
if (type_has_bits(field->type_entry)) { if (type_has_bits(g, field->type_entry)) {
assert(type_is_resolved(field->type_entry, ResolveStatusSizeKnown)); assert(type_is_resolved(field->type_entry, ResolveStatusSizeKnown));
unsigned field_abi_align = max(field->align, field->type_entry->abi_align); unsigned field_abi_align = max(field->align, field->type_entry->abi_align);
if (field_abi_align > abi_align) { if (field_abi_align > abi_align) {
@ -2097,7 +2098,7 @@ static ZigType *get_struct_type(CodeGen *g, const char *type_name, SrcField fiel
size_t next_offset = 0; size_t next_offset = 0;
for (size_t i = 0; i < field_count; i += 1) { for (size_t i = 0; i < field_count; i += 1) {
TypeStructField *field = struct_type->data.structure.fields[i]; TypeStructField *field = struct_type->data.structure.fields[i];
if (!type_has_bits(field->type_entry)) if (!type_has_bits(g, field->type_entry))
continue; continue;
field->offset = next_offset; field->offset = next_offset;
@ -2105,7 +2106,7 @@ static ZigType *get_struct_type(CodeGen *g, const char *type_name, SrcField fiel
// find the next non-zero-byte field for offset calculations // find the next non-zero-byte field for offset calculations
size_t next_src_field_index = i + 1; size_t next_src_field_index = i + 1;
for (; next_src_field_index < field_count; next_src_field_index += 1) { for (; next_src_field_index < field_count; next_src_field_index += 1) {
if (type_has_bits(struct_type->data.structure.fields[next_src_field_index]->type_entry)) if (type_has_bits(g, struct_type->data.structure.fields[next_src_field_index]->type_entry))
break; break;
} }
size_t next_abi_align; size_t next_abi_align;
@ -2402,7 +2403,7 @@ static Error resolve_union_alignment(CodeGen *g, ZigType *union_type) {
union_type->data.unionation.most_aligned_union_member = most_aligned_union_member; union_type->data.unionation.most_aligned_union_member = most_aligned_union_member;
ZigType *tag_type = union_type->data.unionation.tag_type; ZigType *tag_type = union_type->data.unionation.tag_type;
if (tag_type != nullptr && type_has_bits(tag_type)) { if (tag_type != nullptr && type_has_bits(g, tag_type)) {
if ((err = type_resolve(g, tag_type, ResolveStatusAlignmentKnown))) { if ((err = type_resolve(g, tag_type, ResolveStatusAlignmentKnown))) {
union_type->data.unionation.resolve_status = ResolveStatusInvalid; union_type->data.unionation.resolve_status = ResolveStatusInvalid;
return ErrorSemanticAnalyzeFail; return ErrorSemanticAnalyzeFail;
@ -2504,7 +2505,7 @@ static Error resolve_union_type(CodeGen *g, ZigType *union_type) {
if (type_is_invalid(union_type)) if (type_is_invalid(union_type))
return ErrorSemanticAnalyzeFail; return ErrorSemanticAnalyzeFail;
if (!type_has_bits(field_type)) if (!type_has_bits(g, field_type))
continue; continue;
union_abi_size = max(union_abi_size, field_type->abi_size); union_abi_size = max(union_abi_size, field_type->abi_size);
@ -2523,7 +2524,7 @@ static Error resolve_union_type(CodeGen *g, ZigType *union_type) {
union_type->data.unionation.union_abi_size = union_abi_size; union_type->data.unionation.union_abi_size = union_abi_size;
ZigType *tag_type = union_type->data.unionation.tag_type; ZigType *tag_type = union_type->data.unionation.tag_type;
if (tag_type != nullptr && type_has_bits(tag_type)) { if (tag_type != nullptr && type_has_bits(g, tag_type)) {
if ((err = type_resolve(g, tag_type, ResolveStatusSizeKnown))) { if ((err = type_resolve(g, tag_type, ResolveStatusSizeKnown))) {
union_type->data.unionation.resolve_status = ResolveStatusInvalid; union_type->data.unionation.resolve_status = ResolveStatusInvalid;
return ErrorSemanticAnalyzeFail; return ErrorSemanticAnalyzeFail;
@ -2998,7 +2999,7 @@ static Error resolve_struct_alignment(CodeGen *g, ZigType *struct_type) {
} }
} }
if (!type_has_bits(struct_type)) { if (!type_has_bits(g, struct_type)) {
assert(struct_type->abi_align == 0); assert(struct_type->abi_align == 0);
} }
@ -4416,15 +4417,50 @@ ZigType *get_src_ptr_type(ZigType *type) {
return nullptr; return nullptr;
} }
ZigType *get_codegen_ptr_type(ZigType *type) { Error get_codegen_ptr_type(CodeGen *g, ZigType *type, ZigType **result) {
Error err;
ZigType *ty = get_src_ptr_type(type); ZigType *ty = get_src_ptr_type(type);
if (ty == nullptr || !type_has_bits(ty)) if (ty == nullptr) {
return nullptr; *result = nullptr;
return ty; return ErrorNone;
}
bool has_bits;
if ((err = type_has_bits2(g, ty, &has_bits))) return err;
if (!has_bits) {
*result = nullptr;
return ErrorNone;
}
*result = ty;
return ErrorNone;
} }
bool type_is_nonnull_ptr(ZigType *type) { ZigType *get_codegen_ptr_type_bail(CodeGen *g, ZigType *type) {
return get_codegen_ptr_type(type) == type && !ptr_allows_addr_zero(type); Error err;
ZigType *result;
if ((err = get_codegen_ptr_type(g, type, &result))) {
codegen_report_errors_and_exit(g);
}
return result;
}
bool type_is_nonnull_ptr(CodeGen *g, ZigType *type) {
Error err;
bool result;
if ((err = type_is_nonnull_ptr2(g, type, &result))) {
codegen_report_errors_and_exit(g);
}
return result;
}
Error type_is_nonnull_ptr2(CodeGen *g, ZigType *type, bool *result) {
Error err;
ZigType *ptr_type;
if ((err = get_codegen_ptr_type(g, type, &ptr_type))) return err;
*result = ptr_type == type && !ptr_allows_addr_zero(type);
return ErrorNone;
} }
static uint32_t get_async_frame_align_bytes(CodeGen *g) { static uint32_t get_async_frame_align_bytes(CodeGen *g) {
@ -4499,8 +4535,12 @@ static Error define_local_param_variables(CodeGen *g, ZigFn *fn_table_entry) {
} }
bool is_noalias = param_info->is_noalias; bool is_noalias = param_info->is_noalias;
if (is_noalias && get_codegen_ptr_type(param_type) == nullptr) { if (is_noalias) {
add_node_error(g, param_decl_node, buf_sprintf("noalias on non-pointer parameter")); ZigType *ptr_type;
if ((err = get_codegen_ptr_type(g, param_type, &ptr_type))) return err;
if (ptr_type == nullptr) {
add_node_error(g, param_decl_node, buf_sprintf("noalias on non-pointer parameter"));
}
} }
ZigVar *var = add_variable(g, param_decl_node, fn_table_entry->child_scope, ZigVar *var = add_variable(g, param_decl_node, fn_table_entry->child_scope,
@ -4509,7 +4549,7 @@ static Error define_local_param_variables(CodeGen *g, ZigFn *fn_table_entry) {
fn_table_entry->child_scope = var->child_scope; fn_table_entry->child_scope = var->child_scope;
var->shadowable = var->shadowable || is_var_args; var->shadowable = var->shadowable || is_var_args;
if (type_has_bits(param_type)) { if (type_has_bits(g, param_type)) {
fn_table_entry->variable_list.append(var); fn_table_entry->variable_list.append(var);
} }
} }
@ -5027,15 +5067,35 @@ ZigType *get_int_type(CodeGen *g, bool is_signed, uint32_t size_in_bits) {
return new_entry; return new_entry;
} }
bool is_valid_vector_elem_type(ZigType *elem_type) { Error is_valid_vector_elem_type(CodeGen *g, ZigType *elem_type, bool *result) {
return elem_type->id == ZigTypeIdInt || if (elem_type->id == ZigTypeIdInt ||
elem_type->id == ZigTypeIdFloat || elem_type->id == ZigTypeIdFloat ||
elem_type->id == ZigTypeIdBool || elem_type->id == ZigTypeIdBool)
get_codegen_ptr_type(elem_type) != nullptr; {
*result = true;
return ErrorNone;
}
Error err;
ZigType *ptr_type;
if ((err = get_codegen_ptr_type(g, elem_type, &ptr_type))) return err;
if (ptr_type != nullptr) {
*result = true;
return ErrorNone;
}
*result = false;
return ErrorNone;
} }
ZigType *get_vector_type(CodeGen *g, uint32_t len, ZigType *elem_type) { ZigType *get_vector_type(CodeGen *g, uint32_t len, ZigType *elem_type) {
assert(is_valid_vector_elem_type(elem_type)); Error err;
bool valid_vector_elem;
if ((err = is_valid_vector_elem_type(g, elem_type, &valid_vector_elem))) {
codegen_report_errors_and_exit(g);
}
assert(valid_vector_elem);
TypeId type_id = {}; TypeId type_id = {};
type_id.id = ZigTypeIdVector; type_id.id = ZigTypeIdVector;
@ -5049,7 +5109,7 @@ ZigType *get_vector_type(CodeGen *g, uint32_t len, ZigType *elem_type) {
} }
ZigType *entry = new_type_table_entry(ZigTypeIdVector); ZigType *entry = new_type_table_entry(ZigTypeIdVector);
if ((len != 0) && type_has_bits(elem_type)) { if ((len != 0) && type_has_bits(g, elem_type)) {
// Vectors can only be ints, floats, bools, or pointers. ints (inc. bools) and floats have trivially resolvable // Vectors can only be ints, floats, bools, or pointers. ints (inc. bools) and floats have trivially resolvable
// llvm type refs. pointers we will use usize instead. // llvm type refs. pointers we will use usize instead.
LLVMTypeRef example_vector_llvm_type; LLVMTypeRef example_vector_llvm_type;
@ -5081,7 +5141,7 @@ ZigType *get_c_int_type(CodeGen *g, CIntType c_int_type) {
return *get_c_int_type_ptr(g, c_int_type); return *get_c_int_type_ptr(g, c_int_type);
} }
bool handle_is_ptr(ZigType *type_entry) { bool handle_is_ptr(CodeGen *g, ZigType *type_entry) {
switch (type_entry->id) { switch (type_entry->id) {
case ZigTypeIdInvalid: case ZigTypeIdInvalid:
case ZigTypeIdMetaType: case ZigTypeIdMetaType:
@ -5108,15 +5168,15 @@ bool handle_is_ptr(ZigType *type_entry) {
case ZigTypeIdArray: case ZigTypeIdArray:
case ZigTypeIdStruct: case ZigTypeIdStruct:
case ZigTypeIdFnFrame: case ZigTypeIdFnFrame:
return type_has_bits(type_entry); return type_has_bits(g, type_entry);
case ZigTypeIdErrorUnion: case ZigTypeIdErrorUnion:
return type_has_bits(type_entry->data.error_union.payload_type); return type_has_bits(g, type_entry->data.error_union.payload_type);
case ZigTypeIdOptional: case ZigTypeIdOptional:
return type_has_bits(type_entry->data.maybe.child_type) && return type_has_bits(g, type_entry->data.maybe.child_type) &&
!type_is_nonnull_ptr(type_entry->data.maybe.child_type) && !type_is_nonnull_ptr(g, type_entry->data.maybe.child_type) &&
type_entry->data.maybe.child_type->id != ZigTypeIdErrorSet; type_entry->data.maybe.child_type->id != ZigTypeIdErrorSet;
case ZigTypeIdUnion: case ZigTypeIdUnion:
return type_has_bits(type_entry) && type_entry->data.unionation.gen_field_count != 0; return type_has_bits(g, type_entry) && type_entry->data.unionation.gen_field_count != 0;
} }
zig_unreachable(); zig_unreachable();
@ -5329,7 +5389,7 @@ static uint32_t hash_const_val(ZigValue *const_val) {
// TODO better hashing algorithm // TODO better hashing algorithm
return 2709806591; return 2709806591;
case ZigTypeIdOptional: case ZigTypeIdOptional:
if (get_codegen_ptr_type(const_val->type) != nullptr) { if (get_src_ptr_type(const_val->type) != nullptr) {
return hash_const_val_ptr(const_val) * 1992916303; return hash_const_val_ptr(const_val) * 1992916303;
} else if (const_val->type->data.maybe.child_type->id == ZigTypeIdErrorSet) { } else if (const_val->type->data.maybe.child_type->id == ZigTypeIdErrorSet) {
return hash_const_val_error_set(const_val) * 3147031929; return hash_const_val_error_set(const_val) * 3147031929;
@ -5455,7 +5515,7 @@ static bool can_mutate_comptime_var_state(ZigValue *value) {
return false; return false;
case ZigTypeIdOptional: case ZigTypeIdOptional:
if (get_codegen_ptr_type(value->type) != nullptr) if (get_src_ptr_type(value->type) != nullptr)
return value->data.x_ptr.mut == ConstPtrMutComptimeVar; return value->data.x_ptr.mut == ConstPtrMutComptimeVar;
if (value->data.x_optional == nullptr) if (value->data.x_optional == nullptr)
return false; return false;
@ -5593,11 +5653,13 @@ bool fn_eval_eql(Scope *a, Scope *b) {
} }
// Deprecated. Use type_has_bits2. // Deprecated. Use type_has_bits2.
bool type_has_bits(ZigType *type_entry) { bool type_has_bits(CodeGen *g, ZigType *type_entry) {
assert(type_entry != nullptr); Error err;
assert(!type_is_invalid(type_entry)); bool result;
assert(type_is_resolved(type_entry, ResolveStatusZeroBitsKnown)); if ((err = type_has_bits2(g, type_entry, &result))) {
return type_entry->abi_size != 0; codegen_report_errors_and_exit(g);
}
return result;
} }
// Whether the type has bits at runtime. // Whether the type has bits at runtime.
@ -5687,7 +5749,7 @@ OnePossibleValue type_has_one_possible_value(CodeGen *g, ZigType *type_entry) {
case ZigTypeIdEnum: case ZigTypeIdEnum:
case ZigTypeIdInt: case ZigTypeIdInt:
case ZigTypeIdVector: case ZigTypeIdVector:
return type_has_bits(type_entry) ? OnePossibleValueNo : OnePossibleValueYes; return type_has_bits(g, type_entry) ? OnePossibleValueNo : OnePossibleValueYes;
case ZigTypeIdPointer: { case ZigTypeIdPointer: {
ZigType *elem_type = type_entry->data.pointer.child_type; ZigType *elem_type = type_entry->data.pointer.child_type;
// If the recursive function call asks, then we are not one possible value. // If the recursive function call asks, then we are not one possible value.
@ -6365,7 +6427,7 @@ static Error resolve_async_frame(CodeGen *g, ZigType *frame_type) {
} }
if (await->base.base.ref_count == 0) if (await->base.base.ref_count == 0)
continue; continue;
if (!type_has_bits(await->base.value->type)) if (!type_has_bits(g, await->base.value->type))
continue; continue;
await->result_loc = ir_create_alloca(g, await->base.base.scope, await->base.base.source_node, fn, await->result_loc = ir_create_alloca(g, await->base.base.scope, await->base.base.source_node, fn,
await->base.value->type, ""); await->base.value->type, "");
@ -6406,7 +6468,7 @@ static Error resolve_async_frame(CodeGen *g, ZigType *frame_type) {
continue; continue;
if ((err = type_resolve(g, instruction->value->type, ResolveStatusZeroBitsKnown))) if ((err = type_resolve(g, instruction->value->type, ResolveStatusZeroBitsKnown)))
return ErrorSemanticAnalyzeFail; return ErrorSemanticAnalyzeFail;
if (!type_has_bits(instruction->value->type)) if (!type_has_bits(g, instruction->value->type))
continue; continue;
if (scope_needs_spill(instruction->base.scope)) { if (scope_needs_spill(instruction->base.scope)) {
instruction->spill = ir_create_alloca(g, instruction->base.scope, instruction->base.source_node, instruction->spill = ir_create_alloca(g, instruction->base.scope, instruction->base.source_node,
@ -6465,7 +6527,7 @@ static Error resolve_async_frame(CodeGen *g, ZigType *frame_type) {
ZigType *ptr_type = instruction->base.value->type; ZigType *ptr_type = instruction->base.value->type;
assert(ptr_type->id == ZigTypeIdPointer); assert(ptr_type->id == ZigTypeIdPointer);
ZigType *child_type = resolve_type_isf(ptr_type->data.pointer.child_type); ZigType *child_type = resolve_type_isf(ptr_type->data.pointer.child_type);
if (!type_has_bits(child_type)) if (!type_has_bits(g, child_type))
continue; continue;
if (instruction->base.base.ref_count == 0) if (instruction->base.base.ref_count == 0)
continue; continue;
@ -6763,7 +6825,7 @@ bool const_values_equal(CodeGen *g, ZigValue *a, ZigValue *b) {
if (bigint_cmp(&union1->tag, &union2->tag) == CmpEQ) { if (bigint_cmp(&union1->tag, &union2->tag) == CmpEQ) {
TypeUnionField *field = find_union_field_by_tag(a->type, &union1->tag); TypeUnionField *field = find_union_field_by_tag(a->type, &union1->tag);
assert(field != nullptr); assert(field != nullptr);
if (!type_has_bits(field->type_entry)) if (!type_has_bits(g, field->type_entry))
return true; return true;
assert(find_union_field_by_tag(a->type, &union2->tag) != nullptr); assert(find_union_field_by_tag(a->type, &union2->tag) != nullptr);
return const_values_equal(g, union1->payload, union2->payload); return const_values_equal(g, union1->payload, union2->payload);
@ -6826,7 +6888,7 @@ bool const_values_equal(CodeGen *g, ZigValue *a, ZigValue *b) {
case ZigTypeIdNull: case ZigTypeIdNull:
zig_panic("TODO"); zig_panic("TODO");
case ZigTypeIdOptional: case ZigTypeIdOptional:
if (get_codegen_ptr_type(a->type) != nullptr) if (get_src_ptr_type(a->type) != nullptr)
return const_values_equal_ptr(a, b); return const_values_equal_ptr(a, b);
if (a->data.x_optional == nullptr || b->data.x_optional == nullptr) { if (a->data.x_optional == nullptr || b->data.x_optional == nullptr) {
return (a->data.x_optional == nullptr && b->data.x_optional == nullptr); return (a->data.x_optional == nullptr && b->data.x_optional == nullptr);
@ -7097,7 +7159,7 @@ void render_const_value(CodeGen *g, Buf *buf, ZigValue *const_val) {
} }
case ZigTypeIdOptional: case ZigTypeIdOptional:
{ {
if (get_codegen_ptr_type(const_val->type) != nullptr) if (get_src_ptr_type(const_val->type) != nullptr)
return render_const_val_ptr(g, buf, const_val, type_entry->data.maybe.child_type); return render_const_val_ptr(g, buf, const_val, type_entry->data.maybe.child_type);
if (type_entry->data.maybe.child_type->id == ZigTypeIdErrorSet) 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); return render_const_val_err_set(g, buf, const_val, type_entry->data.maybe.child_type);
@ -7881,8 +7943,12 @@ static X64CABIClass type_system_V_abi_x86_64_class(CodeGen *g, ZigType *ty, size
} }
X64CABIClass type_c_abi_x86_64_class(CodeGen *g, ZigType *ty) { X64CABIClass type_c_abi_x86_64_class(CodeGen *g, ZigType *ty) {
Error err;
const size_t ty_size = type_size(g, ty); const size_t ty_size = type_size(g, ty);
if (get_codegen_ptr_type(ty) != nullptr) ZigType *ptr_type;
if ((err = get_codegen_ptr_type(g, ty, &ptr_type))) return X64CABIClass_Unknown;
if (ptr_type != nullptr)
return X64CABIClass_INTEGER; return X64CABIClass_INTEGER;
if (g->zig_target->os == OsWindows || g->zig_target->os == OsUefi) { if (g->zig_target->os == OsWindows || g->zig_target->os == OsUefi) {
@ -7898,14 +7964,32 @@ X64CABIClass type_c_abi_x86_64_class(CodeGen *g, ZigType *ty) {
} }
// NOTE this does not depend on x86_64 // NOTE this does not depend on x86_64
bool type_is_c_abi_int(CodeGen *g, ZigType *ty) { Error type_is_c_abi_int(CodeGen *g, ZigType *ty, bool *result) {
return (ty->id == ZigTypeIdInt || if (ty->id == ZigTypeIdInt ||
ty->id == ZigTypeIdFloat || ty->id == ZigTypeIdFloat ||
ty->id == ZigTypeIdBool || ty->id == ZigTypeIdBool ||
ty->id == ZigTypeIdEnum || ty->id == ZigTypeIdEnum ||
ty->id == ZigTypeIdVoid || ty->id == ZigTypeIdVoid ||
ty->id == ZigTypeIdUnreachable || ty->id == ZigTypeIdUnreachable)
get_codegen_ptr_type(ty) != nullptr); {
*result = true;
return ErrorNone;
}
Error err;
ZigType *ptr_type;
if ((err = get_codegen_ptr_type(g, ty, &ptr_type))) return err;
*result = ptr_type != nullptr;
return ErrorNone;
}
bool type_is_c_abi_int_bail(CodeGen *g, ZigType *ty) {
Error err;
bool result;
if ((err = type_is_c_abi_int(g, ty, &result)))
codegen_report_errors_and_exit(g);
return result;
} }
uint32_t get_host_int_bytes(CodeGen *g, ZigType *struct_type, TypeStructField *field) { uint32_t get_host_int_bytes(CodeGen *g, ZigType *struct_type, TypeStructField *field) {
@ -8036,7 +8120,7 @@ static void resolve_llvm_types_slice(CodeGen *g, ZigType *type, ResolveStatus wa
if (ResolveStatusLLVMFwdDecl >= wanted_resolve_status) return; if (ResolveStatusLLVMFwdDecl >= wanted_resolve_status) return;
} }
if (!type_has_bits(child_type)) { if (!type_has_bits(g, child_type)) {
LLVMTypeRef element_types[] = { LLVMTypeRef element_types[] = {
usize_llvm_type, usize_llvm_type,
}; };
@ -8145,7 +8229,7 @@ static void resolve_llvm_types_struct(CodeGen *g, ZigType *struct_type, ResolveS
} }
if (struct_type->data.structure.resolve_status < ResolveStatusLLVMFwdDecl) { if (struct_type->data.structure.resolve_status < ResolveStatusLLVMFwdDecl) {
struct_type->llvm_type = type_has_bits(struct_type) ? struct_type->llvm_type = type_has_bits(g, struct_type) ?
LLVMStructCreateNamed(LLVMGetGlobalContext(), buf_ptr(&struct_type->name)) : LLVMVoidType(); LLVMStructCreateNamed(LLVMGetGlobalContext(), buf_ptr(&struct_type->name)) : LLVMVoidType();
unsigned dwarf_kind = ZigLLVMTag_DW_structure_type(); unsigned dwarf_kind = ZigLLVMTag_DW_structure_type();
struct_type->llvm_di_type = ZigLLVMCreateReplaceableCompositeType(g->dbuilder, struct_type->llvm_di_type = ZigLLVMCreateReplaceableCompositeType(g->dbuilder,
@ -8175,7 +8259,7 @@ static void resolve_llvm_types_struct(CodeGen *g, ZigType *struct_type, ResolveS
for (size_t i = 0; i < field_count; i += 1) { for (size_t i = 0; i < field_count; i += 1) {
TypeStructField *field = struct_type->data.structure.fields[i]; TypeStructField *field = struct_type->data.structure.fields[i];
ZigType *field_type = field->type_entry; ZigType *field_type = field->type_entry;
if (!type_has_bits(field_type)) if (!type_has_bits(g, field_type))
continue; continue;
(void)get_llvm_type(g, field_type); (void)get_llvm_type(g, field_type);
if (struct_type->data.structure.resolve_status >= wanted_resolve_status) return; if (struct_type->data.structure.resolve_status >= wanted_resolve_status) return;
@ -8189,7 +8273,7 @@ static void resolve_llvm_types_struct(CodeGen *g, ZigType *struct_type, ResolveS
for (size_t i = 0; i < field_count; i += 1) { for (size_t i = 0; i < field_count; i += 1) {
TypeStructField *field = struct_type->data.structure.fields[i]; TypeStructField *field = struct_type->data.structure.fields[i];
ZigType *field_type = field->type_entry; ZigType *field_type = field->type_entry;
if (field->is_comptime || !type_has_bits(field_type)) if (field->is_comptime || !type_has_bits(g, field_type))
continue; continue;
LLVMTypeRef field_llvm_type = get_llvm_type(g, field_type); LLVMTypeRef field_llvm_type = get_llvm_type(g, field_type);
size_t llvm_field_abi_align = LLVMABIAlignmentOfType(g->target_data_ref, field_llvm_type); size_t llvm_field_abi_align = LLVMABIAlignmentOfType(g->target_data_ref, field_llvm_type);
@ -8200,7 +8284,7 @@ static void resolve_llvm_types_struct(CodeGen *g, ZigType *struct_type, ResolveS
TypeStructField *field = struct_type->data.structure.fields[i]; TypeStructField *field = struct_type->data.structure.fields[i];
ZigType *field_type = field->type_entry; ZigType *field_type = field->type_entry;
if (field->is_comptime || !type_has_bits(field_type)) { if (field->is_comptime || !type_has_bits(g, field_type)) {
field->gen_index = SIZE_MAX; field->gen_index = SIZE_MAX;
continue; continue;
} }
@ -8247,7 +8331,7 @@ static void resolve_llvm_types_struct(CodeGen *g, ZigType *struct_type, ResolveS
// find the next non-zero-byte field for offset calculations // find the next non-zero-byte field for offset calculations
size_t next_src_field_index = i + 1; size_t next_src_field_index = i + 1;
for (; next_src_field_index < field_count; next_src_field_index += 1) { for (; next_src_field_index < field_count; next_src_field_index += 1) {
if (type_has_bits(struct_type->data.structure.fields[next_src_field_index]->type_entry)) if (type_has_bits(g, struct_type->data.structure.fields[next_src_field_index]->type_entry))
break; break;
} }
size_t next_abi_align; size_t next_abi_align;
@ -8293,7 +8377,7 @@ static void resolve_llvm_types_struct(CodeGen *g, ZigType *struct_type, ResolveS
gen_field_index += 1; gen_field_index += 1;
} }
if (type_has_bits(struct_type)) { if (type_has_bits(g, struct_type)) {
assert(struct_type->data.structure.gen_field_count == gen_field_index); assert(struct_type->data.structure.gen_field_count == gen_field_index);
LLVMStructSetBody(struct_type->llvm_type, element_types, LLVMStructSetBody(struct_type->llvm_type, element_types,
(unsigned)struct_type->data.structure.gen_field_count, packed); (unsigned)struct_type->data.structure.gen_field_count, packed);
@ -8405,7 +8489,7 @@ static void resolve_llvm_types_enum(CodeGen *g, ZigType *enum_type, ResolveStatu
ZigType *import = get_scope_import(scope); ZigType *import = get_scope_import(scope);
AstNode *decl_node = enum_type->data.enumeration.decl_node; AstNode *decl_node = enum_type->data.enumeration.decl_node;
if (!type_has_bits(enum_type)) { if (!type_has_bits(g, enum_type)) {
enum_type->llvm_type = g->builtin_types.entry_void->llvm_type; enum_type->llvm_type = g->builtin_types.entry_void->llvm_type;
enum_type->llvm_di_type = make_empty_namespace_llvm_di_type(g, import, buf_ptr(&enum_type->name), enum_type->llvm_di_type = make_empty_namespace_llvm_di_type(g, import, buf_ptr(&enum_type->name),
decl_node); decl_node);
@ -8487,7 +8571,7 @@ static void resolve_llvm_types_union(CodeGen *g, ZigType *union_type, ResolveSta
uint32_t field_count = union_type->data.unionation.src_field_count; uint32_t field_count = union_type->data.unionation.src_field_count;
for (uint32_t i = 0; i < field_count; i += 1) { for (uint32_t i = 0; i < field_count; i += 1) {
TypeUnionField *union_field = &union_type->data.unionation.fields[i]; TypeUnionField *union_field = &union_type->data.unionation.fields[i];
if (!type_has_bits(union_field->type_entry)) if (!type_has_bits(g, union_field->type_entry))
continue; continue;
ZigLLVMDIType *field_di_type = get_llvm_di_type(g, union_field->type_entry); ZigLLVMDIType *field_di_type = get_llvm_di_type(g, union_field->type_entry);
@ -8506,7 +8590,7 @@ static void resolve_llvm_types_union(CodeGen *g, ZigType *union_type, ResolveSta
} }
if (tag_type == nullptr || !type_has_bits(tag_type)) { if (tag_type == nullptr || !type_has_bits(g, tag_type)) {
assert(most_aligned_union_member != nullptr); assert(most_aligned_union_member != nullptr);
size_t padding_bytes = union_type->data.unionation.union_abi_size - most_aligned_union_member->type_entry->abi_size; size_t padding_bytes = union_type->data.unionation.union_abi_size - most_aligned_union_member->type_entry->abi_size;
@ -8616,7 +8700,7 @@ static void resolve_llvm_types_pointer(CodeGen *g, ZigType *type, ResolveStatus
if (resolve_pointer_zero_bits(g, type) != ErrorNone) if (resolve_pointer_zero_bits(g, type) != ErrorNone)
zig_unreachable(); zig_unreachable();
if (!type_has_bits(type)) { if (!type_has_bits(g, type)) {
type->llvm_type = g->builtin_types.entry_void->llvm_type; type->llvm_type = g->builtin_types.entry_void->llvm_type;
type->llvm_di_type = g->builtin_types.entry_void->llvm_di_type; type->llvm_di_type = g->builtin_types.entry_void->llvm_di_type;
return; return;
@ -8669,7 +8753,7 @@ static void resolve_llvm_types_pointer(CodeGen *g, ZigType *type, ResolveStatus
static void resolve_llvm_types_integer(CodeGen *g, ZigType *type) { static void resolve_llvm_types_integer(CodeGen *g, ZigType *type) {
if (type->llvm_di_type != nullptr) return; if (type->llvm_di_type != nullptr) return;
if (!type_has_bits(type)) { if (!type_has_bits(g, type)) {
type->llvm_type = g->builtin_types.entry_void->llvm_type; type->llvm_type = g->builtin_types.entry_void->llvm_type;
type->llvm_di_type = g->builtin_types.entry_void->llvm_di_type; type->llvm_di_type = g->builtin_types.entry_void->llvm_di_type;
return; return;
@ -8705,14 +8789,14 @@ static void resolve_llvm_types_optional(CodeGen *g, ZigType *type, ResolveStatus
ZigLLVMDIType *bool_llvm_di_type = get_llvm_di_type(g, g->builtin_types.entry_bool); ZigLLVMDIType *bool_llvm_di_type = get_llvm_di_type(g, g->builtin_types.entry_bool);
ZigType *child_type = type->data.maybe.child_type; ZigType *child_type = type->data.maybe.child_type;
if (!type_has_bits(child_type)) { if (!type_has_bits(g, child_type)) {
type->llvm_type = bool_llvm_type; type->llvm_type = bool_llvm_type;
type->llvm_di_type = bool_llvm_di_type; type->llvm_di_type = bool_llvm_di_type;
type->data.maybe.resolve_status = ResolveStatusLLVMFull; type->data.maybe.resolve_status = ResolveStatusLLVMFull;
return; return;
} }
if (type_is_nonnull_ptr(child_type) || child_type->id == ZigTypeIdErrorSet) { if (type_is_nonnull_ptr(g, child_type) || child_type->id == ZigTypeIdErrorSet) {
type->llvm_type = get_llvm_type(g, child_type); type->llvm_type = get_llvm_type(g, child_type);
type->llvm_di_type = get_llvm_di_type(g, child_type); type->llvm_di_type = get_llvm_di_type(g, child_type);
type->data.maybe.resolve_status = ResolveStatusLLVMFull; type->data.maybe.resolve_status = ResolveStatusLLVMFull;
@ -8778,11 +8862,11 @@ static void resolve_llvm_types_error_union(CodeGen *g, ZigType *type) {
ZigType *payload_type = type->data.error_union.payload_type; ZigType *payload_type = type->data.error_union.payload_type;
ZigType *err_set_type = type->data.error_union.err_set_type; ZigType *err_set_type = type->data.error_union.err_set_type;
if (!type_has_bits(payload_type)) { if (!type_has_bits(g, payload_type)) {
assert(type_has_bits(err_set_type)); assert(type_has_bits(g, err_set_type));
type->llvm_type = get_llvm_type(g, err_set_type); type->llvm_type = get_llvm_type(g, err_set_type);
type->llvm_di_type = get_llvm_di_type(g, err_set_type); type->llvm_di_type = get_llvm_di_type(g, err_set_type);
} else if (!type_has_bits(err_set_type)) { } else if (!type_has_bits(g, err_set_type)) {
type->llvm_type = get_llvm_type(g, payload_type); type->llvm_type = get_llvm_type(g, payload_type);
type->llvm_di_type = get_llvm_di_type(g, payload_type); type->llvm_di_type = get_llvm_di_type(g, payload_type);
} else { } else {
@ -8852,7 +8936,7 @@ static void resolve_llvm_types_error_union(CodeGen *g, ZigType *type) {
static void resolve_llvm_types_array(CodeGen *g, ZigType *type) { static void resolve_llvm_types_array(CodeGen *g, ZigType *type) {
if (type->llvm_di_type != nullptr) return; if (type->llvm_di_type != nullptr) return;
if (!type_has_bits(type)) { if (!type_has_bits(g, type)) {
type->llvm_type = g->builtin_types.entry_void->llvm_type; type->llvm_type = g->builtin_types.entry_void->llvm_type;
type->llvm_di_type = g->builtin_types.entry_void->llvm_di_type; type->llvm_di_type = g->builtin_types.entry_void->llvm_di_type;
return; return;
@ -8893,7 +8977,7 @@ static void resolve_llvm_types_fn_type(CodeGen *g, ZigType *fn_type) {
if (is_async) { if (is_async) {
gen_return_type = g->builtin_types.entry_void; gen_return_type = g->builtin_types.entry_void;
param_di_types.append(nullptr); param_di_types.append(nullptr);
} else if (!type_has_bits(fn_type_id->return_type)) { } else if (!type_has_bits(g, fn_type_id->return_type)) {
gen_return_type = g->builtin_types.entry_void; gen_return_type = g->builtin_types.entry_void;
param_di_types.append(nullptr); param_di_types.append(nullptr);
} else if (first_arg_return) { } else if (first_arg_return) {
@ -8940,11 +9024,11 @@ static void resolve_llvm_types_fn_type(CodeGen *g, ZigType *fn_type) {
gen_param_info->src_index = i; gen_param_info->src_index = i;
gen_param_info->gen_index = SIZE_MAX; gen_param_info->gen_index = SIZE_MAX;
if (is_c_abi || !type_has_bits(type_entry)) if (is_c_abi || !type_has_bits(g, type_entry))
continue; continue;
ZigType *gen_type; ZigType *gen_type;
if (handle_is_ptr(type_entry)) { if (handle_is_ptr(g, type_entry)) {
gen_type = get_pointer_to_type(g, type_entry, true); gen_type = get_pointer_to_type(g, type_entry, true);
gen_param_info->is_byval = true; gen_param_info->is_byval = true;
} else { } else {
@ -9098,7 +9182,7 @@ static void resolve_llvm_types_any_frame(CodeGen *g, ZigType *any_frame_type, Re
field_types.append(usize_type_ref); // resume_index field_types.append(usize_type_ref); // resume_index
field_types.append(usize_type_ref); // awaiter field_types.append(usize_type_ref); // awaiter
bool have_result_type = result_type != nullptr && type_has_bits(result_type); bool have_result_type = result_type != nullptr && type_has_bits(g, result_type);
if (have_result_type) { if (have_result_type) {
field_types.append(get_llvm_type(g, ptr_result_type)); // result_ptr_callee field_types.append(get_llvm_type(g, ptr_result_type)); // result_ptr_callee
field_types.append(get_llvm_type(g, ptr_result_type)); // result_ptr_awaiter field_types.append(get_llvm_type(g, ptr_result_type)); // result_ptr_awaiter
@ -9379,7 +9463,7 @@ bool is_opt_err_set(ZigType *ty) {
bool type_has_optional_repr(ZigType *ty) { bool type_has_optional_repr(ZigType *ty) {
if (ty->id != ZigTypeIdOptional) { if (ty->id != ZigTypeIdOptional) {
return false; return false;
} else if (get_codegen_ptr_type(ty) != nullptr) { } else if (get_src_ptr_type(ty) != nullptr) {
return false; return false;
} else if (is_opt_err_set(ty)) { } else if (is_opt_err_set(ty)) {
return false; return false;
@ -9471,6 +9555,58 @@ bool type_is_numeric(ZigType *ty) {
zig_unreachable(); zig_unreachable();
} }
static void dump_value_indent_error_set(ZigValue *val, int indent) {
fprintf(stderr, "<TODO dump value>\n");
}
static void dump_value_indent(ZigValue *val, int indent);
static void dump_value_indent_ptr(ZigValue *val, int indent) {
switch (val->data.x_ptr.special) {
case ConstPtrSpecialInvalid:
fprintf(stderr, "<!invalid ptr!>\n");
return;
case ConstPtrSpecialNull:
fprintf(stderr, "<null>\n");
return;
case ConstPtrSpecialRef:
fprintf(stderr, "<ref\n");
dump_value_indent(val->data.x_ptr.data.ref.pointee, indent + 1);
break;
case ConstPtrSpecialBaseStruct: {
ZigValue *struct_val = val->data.x_ptr.data.base_struct.struct_val;
size_t field_index = val->data.x_ptr.data.base_struct.field_index;
fprintf(stderr, "<struct %p field %zu\n", struct_val, field_index);
if (struct_val != nullptr) {
ZigValue *field_val = struct_val->data.x_struct.fields[field_index];
if (field_val != nullptr) {
dump_value_indent(field_val, indent + 1);
} else {
for (int i = 0; i < indent; i += 1) {
fprintf(stderr, " ");
}
fprintf(stderr, "(invalid null field)\n");
}
}
break;
}
case ConstPtrSpecialBaseOptionalPayload: {
ZigValue *optional_val = val->data.x_ptr.data.base_optional_payload.optional_val;
fprintf(stderr, "<optional %p payload\n", optional_val);
if (optional_val != nullptr) {
dump_value_indent(optional_val, indent + 1);
}
break;
}
default:
fprintf(stderr, "TODO dump more pointer things\n");
}
for (int i = 0; i < indent; i += 1) {
fprintf(stderr, " ");
}
fprintf(stderr, ">\n");
}
static void dump_value_indent(ZigValue *val, int indent) { static void dump_value_indent(ZigValue *val, int indent) {
for (int i = 0; i < indent; i += 1) { for (int i = 0; i < indent; i += 1) {
fprintf(stderr, " "); fprintf(stderr, " ");
@ -9548,15 +9684,20 @@ static void dump_value_indent(ZigValue *val, int indent) {
return; return;
case ZigTypeIdOptional: case ZigTypeIdOptional:
fprintf(stderr, "<\n"); if (get_src_ptr_type(val->type) != nullptr) {
dump_value_indent(val->data.x_optional, indent + 1); return dump_value_indent_ptr(val, indent);
} else if (val->type->data.maybe.child_type->id == ZigTypeIdErrorSet) {
return dump_value_indent_error_set(val, indent);
} else {
fprintf(stderr, "<\n");
dump_value_indent(val->data.x_optional, indent + 1);
for (int i = 0; i < indent; i += 1) { for (int i = 0; i < indent; i += 1) {
fprintf(stderr, " "); fprintf(stderr, " ");
}
fprintf(stderr, ">\n");
return;
} }
fprintf(stderr, ">\n");
return;
case ZigTypeIdErrorUnion: case ZigTypeIdErrorUnion:
if (val->data.x_err_union.payload != nullptr) { if (val->data.x_err_union.payload != nullptr) {
fprintf(stderr, "<\n"); fprintf(stderr, "<\n");
@ -9572,52 +9713,14 @@ static void dump_value_indent(ZigValue *val, int indent) {
return; return;
case ZigTypeIdPointer: case ZigTypeIdPointer:
switch (val->data.x_ptr.special) { return dump_value_indent_ptr(val, indent);
case ConstPtrSpecialInvalid:
fprintf(stderr, "<!invalid ptr!>\n"); case ZigTypeIdErrorSet:
return; return dump_value_indent_error_set(val, indent);
case ConstPtrSpecialRef:
fprintf(stderr, "<ref\n");
dump_value_indent(val->data.x_ptr.data.ref.pointee, indent + 1);
break;
case ConstPtrSpecialBaseStruct: {
ZigValue *struct_val = val->data.x_ptr.data.base_struct.struct_val;
size_t field_index = val->data.x_ptr.data.base_struct.field_index;
fprintf(stderr, "<struct %p field %zu\n", struct_val, field_index);
if (struct_val != nullptr) {
ZigValue *field_val = struct_val->data.x_struct.fields[field_index];
if (field_val != nullptr) {
dump_value_indent(field_val, indent + 1);
} else {
for (int i = 0; i < indent; i += 1) {
fprintf(stderr, " ");
}
fprintf(stderr, "(invalid null field)\n");
}
}
break;
}
case ConstPtrSpecialBaseOptionalPayload: {
ZigValue *optional_val = val->data.x_ptr.data.base_optional_payload.optional_val;
fprintf(stderr, "<optional %p payload\n", optional_val);
if (optional_val != nullptr) {
dump_value_indent(optional_val, indent + 1);
}
break;
}
default:
fprintf(stderr, "TODO dump more pointer things\n");
}
for (int i = 0; i < indent; i += 1) {
fprintf(stderr, " ");
}
fprintf(stderr, ">\n");
return;
case ZigTypeIdVector: case ZigTypeIdVector:
case ZigTypeIdArray: case ZigTypeIdArray:
case ZigTypeIdNull: case ZigTypeIdNull:
case ZigTypeIdErrorSet:
case ZigTypeIdEnum: case ZigTypeIdEnum:
case ZigTypeIdUnion: case ZigTypeIdUnion:
case ZigTypeIdFn: case ZigTypeIdFn:

View File

@ -44,14 +44,20 @@ ZigType *get_bound_fn_type(CodeGen *g, ZigFn *fn_entry);
ZigType *get_opaque_type(CodeGen *g, Scope *scope, AstNode *source_node, const char *full_name, Buf *bare_name); ZigType *get_opaque_type(CodeGen *g, Scope *scope, AstNode *source_node, const char *full_name, Buf *bare_name);
ZigType *get_test_fn_type(CodeGen *g); ZigType *get_test_fn_type(CodeGen *g);
ZigType *get_any_frame_type(CodeGen *g, ZigType *result_type); ZigType *get_any_frame_type(CodeGen *g, ZigType *result_type);
bool handle_is_ptr(ZigType *type_entry); bool handle_is_ptr(CodeGen *g, ZigType *type_entry);
bool type_has_bits(ZigType *type_entry); bool type_has_bits(CodeGen *g, ZigType *type_entry);
Error type_has_bits2(CodeGen *g, ZigType *type_entry, bool *result); Error type_has_bits2(CodeGen *g, ZigType *type_entry, bool *result);
Error type_allowed_in_extern(CodeGen *g, ZigType *type_entry, bool *result); Error type_allowed_in_extern(CodeGen *g, ZigType *type_entry, bool *result);
bool ptr_allows_addr_zero(ZigType *ptr_type); bool ptr_allows_addr_zero(ZigType *ptr_type);
bool type_is_nonnull_ptr(ZigType *type);
// Deprecated, use `type_is_nonnull_ptr2`
bool type_is_nonnull_ptr(CodeGen *g, ZigType *type);
Error type_is_nonnull_ptr2(CodeGen *g, ZigType *type, bool *result);
ZigType *get_codegen_ptr_type_bail(CodeGen *g, ZigType *type);
Error get_codegen_ptr_type(CodeGen *g, ZigType *type, ZigType **result);
enum SourceKind { enum SourceKind {
SourceKindRoot, SourceKindRoot,
@ -68,7 +74,6 @@ Tld *find_container_decl(CodeGen *g, ScopeDecls *decls_scope, Buf *name);
void resolve_top_level_decl(CodeGen *g, Tld *tld, AstNode *source_node, bool allow_lazy); void resolve_top_level_decl(CodeGen *g, Tld *tld, AstNode *source_node, bool allow_lazy);
ZigType *get_src_ptr_type(ZigType *type); ZigType *get_src_ptr_type(ZigType *type);
ZigType *get_codegen_ptr_type(ZigType *type);
uint32_t get_ptr_align(CodeGen *g, ZigType *type); uint32_t get_ptr_align(CodeGen *g, ZigType *type);
bool get_ptr_const(ZigType *type); bool get_ptr_const(ZigType *type);
ZigType *validate_var_type(CodeGen *g, AstNode *source_node, ZigType *type_entry); ZigType *validate_var_type(CodeGen *g, AstNode *source_node, ZigType *type_entry);
@ -87,7 +92,7 @@ TypeUnionField *find_union_field_by_tag(ZigType *type_entry, const BigInt *tag);
bool is_ref(ZigType *type_entry); bool is_ref(ZigType *type_entry);
bool is_array_ref(ZigType *type_entry); bool is_array_ref(ZigType *type_entry);
bool is_container_ref(ZigType *type_entry); bool is_container_ref(ZigType *type_entry);
bool is_valid_vector_elem_type(ZigType *elem_type); Error is_valid_vector_elem_type(CodeGen *g, ZigType *elem_type, bool *result);
void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node); void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node);
ZigFn *scope_fn_entry(Scope *scope); ZigFn *scope_fn_entry(Scope *scope);
ZigPackage *scope_package(Scope *scope); ZigPackage *scope_package(Scope *scope);
@ -223,7 +228,8 @@ Error ATTRIBUTE_MUST_USE file_fetch(CodeGen *g, Buf *resolved_path, Buf *content
void walk_function_params(CodeGen *g, ZigType *fn_type, FnWalk *fn_walk); void walk_function_params(CodeGen *g, ZigType *fn_type, FnWalk *fn_walk);
X64CABIClass type_c_abi_x86_64_class(CodeGen *g, ZigType *ty); X64CABIClass type_c_abi_x86_64_class(CodeGen *g, ZigType *ty);
bool type_is_c_abi_int(CodeGen *g, ZigType *ty); bool type_is_c_abi_int_bail(CodeGen *g, ZigType *ty);
Error type_is_c_abi_int(CodeGen *g, ZigType *ty, bool *result);
bool want_first_arg_sret(CodeGen *g, FnTypeId *fn_type_id); bool want_first_arg_sret(CodeGen *g, FnTypeId *fn_type_id);
const char *container_string(ContainerKind kind); const char *container_string(ContainerKind kind);

View File

@ -313,7 +313,7 @@ struct CalcLLVMFieldIndex {
}; };
static void calc_llvm_field_index_add(CodeGen *g, CalcLLVMFieldIndex *calc, ZigType *ty) { static void calc_llvm_field_index_add(CodeGen *g, CalcLLVMFieldIndex *calc, ZigType *ty) {
if (!type_has_bits(ty)) return; if (!type_has_bits(g, ty)) return;
uint32_t ty_align = get_abi_alignment(g, ty); uint32_t ty_align = get_abi_alignment(g, ty);
if (calc->offset % ty_align != 0) { if (calc->offset % ty_align != 0) {
uint32_t llvm_align = LLVMABIAlignmentOfType(g->target_data_ref, get_llvm_type(g, ty)); uint32_t llvm_align = LLVMABIAlignmentOfType(g->target_data_ref, get_llvm_type(g, ty));
@ -334,7 +334,7 @@ static void frame_index_trace_arg_calc(CodeGen *g, CalcLLVMFieldIndex *calc, Zig
calc_llvm_field_index_add(g, calc, g->builtin_types.entry_usize); // resume index calc_llvm_field_index_add(g, calc, g->builtin_types.entry_usize); // resume index
calc_llvm_field_index_add(g, calc, g->builtin_types.entry_usize); // awaiter index calc_llvm_field_index_add(g, calc, g->builtin_types.entry_usize); // awaiter index
if (type_has_bits(return_type)) { if (type_has_bits(g, return_type)) {
calc_llvm_field_index_add(g, calc, g->builtin_types.entry_usize); // *ReturnType (callee's) calc_llvm_field_index_add(g, calc, g->builtin_types.entry_usize); // *ReturnType (callee's)
calc_llvm_field_index_add(g, calc, g->builtin_types.entry_usize); // *ReturnType (awaiter's) calc_llvm_field_index_add(g, calc, g->builtin_types.entry_usize); // *ReturnType (awaiter's)
calc_llvm_field_index_add(g, calc, return_type); // ReturnType calc_llvm_field_index_add(g, calc, return_type); // ReturnType
@ -383,7 +383,7 @@ static uint32_t get_err_ret_trace_arg_index(CodeGen *g, ZigFn *fn_table_entry) {
return UINT32_MAX; return UINT32_MAX;
} }
ZigType *return_type = fn_type->data.fn.fn_type_id.return_type; ZigType *return_type = fn_type->data.fn.fn_type_id.return_type;
bool first_arg_ret = type_has_bits(return_type) && handle_is_ptr(return_type); bool first_arg_ret = type_has_bits(g, return_type) && handle_is_ptr(g, return_type);
return first_arg_ret ? 1 : 0; return first_arg_ret ? 1 : 0;
} }
@ -581,9 +581,9 @@ static LLVMValueRef make_fn_llvm_value(CodeGen *g, ZigFn *fn) {
addLLVMArgAttr(llvm_fn, 0, "nonnull"); addLLVMArgAttr(llvm_fn, 0, "nonnull");
} else { } else {
unsigned init_gen_i = 0; unsigned init_gen_i = 0;
if (!type_has_bits(return_type)) { if (!type_has_bits(g, return_type)) {
// nothing to do // nothing to do
} else if (type_is_nonnull_ptr(return_type)) { } else if (type_is_nonnull_ptr(g, return_type)) {
addLLVMAttr(llvm_fn, 0, "nonnull"); addLLVMAttr(llvm_fn, 0, "nonnull");
} else if (want_first_arg_sret(g, &fn_type->data.fn.fn_type_id)) { } else if (want_first_arg_sret(g, &fn_type->data.fn.fn_type_id)) {
// Sret pointers must not be address 0 // Sret pointers must not be address 0
@ -859,8 +859,8 @@ static LLVMValueRef gen_load(CodeGen *g, LLVMValueRef ptr, ZigType *ptr_type, co
} }
static LLVMValueRef get_handle_value(CodeGen *g, LLVMValueRef ptr, ZigType *type, ZigType *ptr_type) { static LLVMValueRef get_handle_value(CodeGen *g, LLVMValueRef ptr, ZigType *type, ZigType *ptr_type) {
if (type_has_bits(type)) { if (type_has_bits(g, type)) {
if (handle_is_ptr(type)) { if (handle_is_ptr(g, type)) {
return ptr; return ptr;
} else { } else {
assert(ptr_type->id == ZigTypeIdPointer); assert(ptr_type->id == ZigTypeIdPointer);
@ -1671,10 +1671,10 @@ static void gen_assign_raw(CodeGen *g, LLVMValueRef ptr, ZigType *ptr_type,
assert(ptr_type->id == ZigTypeIdPointer); assert(ptr_type->id == ZigTypeIdPointer);
ZigType *child_type = ptr_type->data.pointer.child_type; ZigType *child_type = ptr_type->data.pointer.child_type;
if (!type_has_bits(child_type)) if (!type_has_bits(g, child_type))
return; return;
if (handle_is_ptr(child_type)) { if (handle_is_ptr(g, child_type)) {
assert(LLVMGetTypeKind(LLVMTypeOf(value)) == LLVMPointerTypeKind); assert(LLVMGetTypeKind(LLVMTypeOf(value)) == LLVMPointerTypeKind);
assert(LLVMGetTypeKind(LLVMTypeOf(ptr)) == LLVMPointerTypeKind); assert(LLVMGetTypeKind(LLVMTypeOf(ptr)) == LLVMPointerTypeKind);
@ -1782,7 +1782,7 @@ static LLVMValueRef ir_llvm_value(CodeGen *g, IrInstGen *instruction) {
render_const_val(g, instruction->value, ""); render_const_val(g, instruction->value, "");
// we might have to do some pointer casting here due to the way union // we might have to do some pointer casting here due to the way union
// values are rendered with a type other than the one we expect // values are rendered with a type other than the one we expect
if (handle_is_ptr(instruction->value->type)) { if (handle_is_ptr(g, instruction->value->type)) {
render_const_val_global(g, instruction->value, ""); render_const_val_global(g, instruction->value, "");
ZigType *ptr_type = get_pointer_to_type(g, instruction->value->type, true); ZigType *ptr_type = get_pointer_to_type(g, instruction->value->type, true);
instruction->llvm_value = LLVMBuildBitCast(g->builder, instruction->value->llvm_global, get_llvm_type(g, ptr_type), ""); instruction->llvm_value = LLVMBuildBitCast(g->builder, instruction->value->llvm_global, get_llvm_type(g, ptr_type), "");
@ -1879,14 +1879,14 @@ static bool iter_function_params_c_abi(CodeGen *g, ZigType *fn_type, FnWalk *fn_
break; break;
} }
if (type_is_c_abi_int(g, ty) || ty->id == ZigTypeIdFloat || ty->id == ZigTypeIdVector || if (type_is_c_abi_int_bail(g, ty) || ty->id == ZigTypeIdFloat || ty->id == ZigTypeIdVector ||
ty->id == ZigTypeIdInt // TODO investigate if we need to change this ty->id == ZigTypeIdInt // TODO investigate if we need to change this
) { ) {
switch (fn_walk->id) { switch (fn_walk->id) {
case FnWalkIdAttrs: { case FnWalkIdAttrs: {
ZigType *ptr_type = get_codegen_ptr_type(ty); ZigType *ptr_type = get_codegen_ptr_type_bail(g, ty);
if (ptr_type != nullptr) { if (ptr_type != nullptr) {
if (type_is_nonnull_ptr(ty)) { if (type_is_nonnull_ptr(g, ty)) {
addLLVMArgAttr(llvm_fn, fn_walk->data.attrs.gen_i, "nonnull"); addLLVMArgAttr(llvm_fn, fn_walk->data.attrs.gen_i, "nonnull");
} }
if (ptr_type->data.pointer.is_const) { if (ptr_type->data.pointer.is_const) {
@ -1928,7 +1928,7 @@ static bool iter_function_params_c_abi(CodeGen *g, ZigType *fn_type, FnWalk *fn_
{ {
// Arrays are just pointers // Arrays are just pointers
if (ty->id == ZigTypeIdArray) { if (ty->id == ZigTypeIdArray) {
assert(handle_is_ptr(ty)); assert(handle_is_ptr(g, ty));
switch (fn_walk->id) { switch (fn_walk->id) {
case FnWalkIdAttrs: case FnWalkIdAttrs:
// arrays passed to C ABI functions may not be at address 0 // arrays passed to C ABI functions may not be at address 0
@ -1965,7 +1965,7 @@ static bool iter_function_params_c_abi(CodeGen *g, ZigType *fn_type, FnWalk *fn_
X64CABIClass abi_class = type_c_abi_x86_64_class(g, ty); X64CABIClass abi_class = type_c_abi_x86_64_class(g, ty);
size_t ty_size = type_size(g, ty); size_t ty_size = type_size(g, ty);
if (abi_class == X64CABIClass_MEMORY || abi_class == X64CABIClass_MEMORY_nobyval) { if (abi_class == X64CABIClass_MEMORY || abi_class == X64CABIClass_MEMORY_nobyval) {
assert(handle_is_ptr(ty)); assert(handle_is_ptr(g, ty));
switch (fn_walk->id) { switch (fn_walk->id) {
case FnWalkIdAttrs: case FnWalkIdAttrs:
if (abi_class != X64CABIClass_MEMORY_nobyval) { if (abi_class != X64CABIClass_MEMORY_nobyval) {
@ -2088,7 +2088,7 @@ void walk_function_params(CodeGen *g, ZigType *fn_type, FnWalk *fn_walk) {
for (size_t call_i = 0; call_i < instruction->arg_count; call_i += 1) { for (size_t call_i = 0; call_i < instruction->arg_count; call_i += 1) {
IrInstGen *param_instruction = instruction->args[call_i]; IrInstGen *param_instruction = instruction->args[call_i];
ZigType *param_type = param_instruction->value->type; ZigType *param_type = param_instruction->value->type;
if (is_var_args || type_has_bits(param_type)) { if (is_var_args || type_has_bits(g, param_type)) {
LLVMValueRef param_value = ir_llvm_value(g, param_instruction); LLVMValueRef param_value = ir_llvm_value(g, param_instruction);
assert(param_value); assert(param_value);
fn_walk->data.call.gen_param_values->append(param_value); fn_walk->data.call.gen_param_values->append(param_value);
@ -2119,10 +2119,10 @@ void walk_function_params(CodeGen *g, ZigType *fn_type, FnWalk *fn_walk) {
if ((param_type->id == ZigTypeIdPointer && param_type->data.pointer.is_const) || is_byval) { if ((param_type->id == ZigTypeIdPointer && param_type->data.pointer.is_const) || is_byval) {
addLLVMArgAttr(llvm_fn, (unsigned)gen_index, "readonly"); addLLVMArgAttr(llvm_fn, (unsigned)gen_index, "readonly");
} }
if (get_codegen_ptr_type(param_type) != nullptr) { if (get_codegen_ptr_type_bail(g, param_type) != nullptr) {
addLLVMArgAttrInt(llvm_fn, (unsigned)gen_index, "align", get_ptr_align(g, param_type)); addLLVMArgAttrInt(llvm_fn, (unsigned)gen_index, "align", get_ptr_align(g, param_type));
} }
if (type_is_nonnull_ptr(param_type)) { if (type_is_nonnull_ptr(g, param_type)) {
addLLVMArgAttr(llvm_fn, (unsigned)gen_index, "nonnull"); addLLVMArgAttr(llvm_fn, (unsigned)gen_index, "nonnull");
} }
break; break;
@ -2137,7 +2137,7 @@ void walk_function_params(CodeGen *g, ZigType *fn_type, FnWalk *fn_walk) {
assert(variable); assert(variable);
assert(variable->value_ref); assert(variable->value_ref);
if (!handle_is_ptr(variable->var_type) && !fn_is_async(fn_walk->data.inits.fn)) { if (!handle_is_ptr(g, variable->var_type) && !fn_is_async(fn_walk->data.inits.fn)) {
clear_debug_source_node(g); clear_debug_source_node(g);
ZigType *fn_type = fn_table_entry->type_entry; ZigType *fn_type = fn_table_entry->type_entry;
unsigned gen_arg_index = fn_type->data.fn.gen_param_info[variable->src_arg_index].gen_index; unsigned gen_arg_index = fn_type->data.fn.gen_param_info[variable->src_arg_index].gen_index;
@ -2404,12 +2404,12 @@ static void gen_async_return(CodeGen *g, IrInstGenReturn *instruction) {
LLVMTypeRef usize_type_ref = g->builtin_types.entry_usize->llvm_type; LLVMTypeRef usize_type_ref = g->builtin_types.entry_usize->llvm_type;
ZigType *operand_type = (instruction->operand != nullptr) ? instruction->operand->value->type : nullptr; ZigType *operand_type = (instruction->operand != nullptr) ? instruction->operand->value->type : nullptr;
bool operand_has_bits = (operand_type != nullptr) && type_has_bits(operand_type); bool operand_has_bits = (operand_type != nullptr) && type_has_bits(g, operand_type);
ZigType *ret_type = g->cur_fn->type_entry->data.fn.fn_type_id.return_type; ZigType *ret_type = g->cur_fn->type_entry->data.fn.fn_type_id.return_type;
bool ret_type_has_bits = type_has_bits(ret_type); bool ret_type_has_bits = type_has_bits(g, ret_type);
if (operand_has_bits && instruction->operand != nullptr) { if (operand_has_bits && instruction->operand != nullptr) {
bool need_store = instruction->operand->value->special != ConstValSpecialRuntime || !handle_is_ptr(ret_type); bool need_store = instruction->operand->value->special != ConstValSpecialRuntime || !handle_is_ptr(g, ret_type);
if (need_store) { if (need_store) {
// It didn't get written to the result ptr. We do that now. // It didn't get written to the result ptr. We do that now.
ZigType *ret_ptr_type = get_pointer_to_type(g, ret_type, true); ZigType *ret_ptr_type = get_pointer_to_type(g, ret_type, true);
@ -2512,7 +2512,7 @@ static LLVMValueRef ir_render_return(CodeGen *g, IrExecutableGen *executable, Ir
gen_assign_raw(g, g->cur_ret_ptr, get_pointer_to_type(g, return_type, false), value); gen_assign_raw(g, g->cur_ret_ptr, get_pointer_to_type(g, return_type, false), value);
LLVMBuildRetVoid(g->builder); LLVMBuildRetVoid(g->builder);
} else if (g->cur_fn->type_entry->data.fn.fn_type_id.cc != CallingConventionAsync && } else if (g->cur_fn->type_entry->data.fn.fn_type_id.cc != CallingConventionAsync &&
handle_is_ptr(g->cur_fn->type_entry->data.fn.fn_type_id.return_type)) handle_is_ptr(g, g->cur_fn->type_entry->data.fn.fn_type_id.return_type))
{ {
if (instruction->operand == nullptr) { if (instruction->operand == nullptr) {
LLVMValueRef by_val_value = gen_load_untyped(g, g->cur_ret_ptr, 0, false, ""); LLVMValueRef by_val_value = gen_load_untyped(g, g->cur_ret_ptr, 0, false, "");
@ -2883,7 +2883,7 @@ static LLVMValueRef ir_render_bin_op(CodeGen *g, IrExecutableGen *executable,
} else if (scalar_type->id == ZigTypeIdEnum || } else if (scalar_type->id == ZigTypeIdEnum ||
scalar_type->id == ZigTypeIdErrorSet || scalar_type->id == ZigTypeIdErrorSet ||
scalar_type->id == ZigTypeIdBool || scalar_type->id == ZigTypeIdBool ||
get_codegen_ptr_type(scalar_type) != nullptr) get_codegen_ptr_type_bail(g, scalar_type) != nullptr)
{ {
LLVMIntPredicate pred = cmp_op_to_int_predicate(op_id, false); LLVMIntPredicate pred = cmp_op_to_int_predicate(op_id, false);
return LLVMBuildICmp(g->builder, pred, op1_value, op2_value, ""); return LLVMBuildICmp(g->builder, pred, op1_value, op2_value, "");
@ -3149,7 +3149,7 @@ static LLVMValueRef ir_render_ptr_of_array_to_slice(CodeGen *g, IrExecutableGen
ZigType *array_type = actual_type->data.pointer.child_type; ZigType *array_type = actual_type->data.pointer.child_type;
assert(array_type->id == ZigTypeIdArray); assert(array_type->id == ZigTypeIdArray);
if (type_has_bits(actual_type)) { if (type_has_bits(g, actual_type)) {
LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP(g->builder, result_loc, ptr_index, ""); LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP(g->builder, result_loc, ptr_index, "");
LLVMValueRef indices[] = { LLVMValueRef indices[] = {
LLVMConstNull(g->builtin_types.entry_usize->llvm_type), LLVMConstNull(g->builtin_types.entry_usize->llvm_type),
@ -3175,7 +3175,7 @@ static LLVMValueRef ir_render_ptr_cast(CodeGen *g, IrExecutableGen *executable,
IrInstGenPtrCast *instruction) IrInstGenPtrCast *instruction)
{ {
ZigType *wanted_type = instruction->base.value->type; ZigType *wanted_type = instruction->base.value->type;
if (!type_has_bits(wanted_type)) { if (!type_has_bits(g, wanted_type)) {
return nullptr; return nullptr;
} }
LLVMValueRef ptr = ir_llvm_value(g, instruction->ptr); LLVMValueRef ptr = ir_llvm_value(g, instruction->ptr);
@ -3204,8 +3204,8 @@ static LLVMValueRef ir_render_bit_cast(CodeGen *g, IrExecutableGen *executable,
ZigType *actual_type = instruction->operand->value->type; ZigType *actual_type = instruction->operand->value->type;
LLVMValueRef value = ir_llvm_value(g, instruction->operand); LLVMValueRef value = ir_llvm_value(g, instruction->operand);
bool wanted_is_ptr = handle_is_ptr(wanted_type); bool wanted_is_ptr = handle_is_ptr(g, wanted_type);
bool actual_is_ptr = handle_is_ptr(actual_type); bool actual_is_ptr = handle_is_ptr(g, actual_type);
if (wanted_is_ptr == actual_is_ptr) { if (wanted_is_ptr == actual_is_ptr) {
// We either bitcast the value directly or bitcast the pointer which does a pointer cast // We either bitcast the value directly or bitcast the pointer which does a pointer cast
LLVMTypeRef wanted_type_ref = wanted_is_ptr ? LLVMTypeRef wanted_type_ref = wanted_is_ptr ?
@ -3352,9 +3352,9 @@ static LLVMValueRef ir_render_err_to_int(CodeGen *g, IrExecutableGen *executable
g->err_tag_type, wanted_type, target_val); g->err_tag_type, wanted_type, target_val);
} else if (actual_type->id == ZigTypeIdErrorUnion) { } else if (actual_type->id == ZigTypeIdErrorUnion) {
// this should have been a compile time constant // this should have been a compile time constant
assert(type_has_bits(actual_type->data.error_union.err_set_type)); assert(type_has_bits(g, actual_type->data.error_union.err_set_type));
if (!type_has_bits(actual_type->data.error_union.payload_type)) { if (!type_has_bits(g, actual_type->data.error_union.payload_type)) {
return gen_widen_or_shorten(g, ir_want_runtime_safety(g, &instruction->base), return gen_widen_or_shorten(g, ir_want_runtime_safety(g, &instruction->base),
g->err_tag_type, wanted_type, target_val); g->err_tag_type, wanted_type, target_val);
} else { } else {
@ -3442,7 +3442,7 @@ static LLVMValueRef ir_render_bool_not(CodeGen *g, IrExecutableGen *executable,
} }
static void render_decl_var(CodeGen *g, ZigVar *var) { static void render_decl_var(CodeGen *g, ZigVar *var) {
if (!type_has_bits(var->var_type)) if (!type_has_bits(g, var->var_type))
return; return;
var->value_ref = ir_llvm_value(g, var->ptr_instruction); var->value_ref = ir_llvm_value(g, var->ptr_instruction);
@ -3460,7 +3460,7 @@ static LLVMValueRef ir_render_load_ptr(CodeGen *g, IrExecutableGen *executable,
IrInstGenLoadPtr *instruction) IrInstGenLoadPtr *instruction)
{ {
ZigType *child_type = instruction->base.value->type; ZigType *child_type = instruction->base.value->type;
if (!type_has_bits(child_type)) if (!type_has_bits(g, child_type))
return nullptr; return nullptr;
LLVMValueRef ptr = ir_llvm_value(g, instruction->ptr); LLVMValueRef ptr = ir_llvm_value(g, instruction->ptr);
@ -3495,7 +3495,7 @@ static LLVMValueRef ir_render_load_ptr(CodeGen *g, IrExecutableGen *executable,
LLVMValueRef shift_amt_val = LLVMConstInt(LLVMTypeOf(containing_int), shift_amt, false); LLVMValueRef shift_amt_val = LLVMConstInt(LLVMTypeOf(containing_int), shift_amt, false);
LLVMValueRef shifted_value = LLVMBuildLShr(g->builder, containing_int, shift_amt_val, ""); LLVMValueRef shifted_value = LLVMBuildLShr(g->builder, containing_int, shift_amt_val, "");
if (handle_is_ptr(child_type)) { if (handle_is_ptr(g, child_type)) {
LLVMValueRef result_loc = ir_llvm_value(g, instruction->result_loc); LLVMValueRef result_loc = ir_llvm_value(g, instruction->result_loc);
LLVMTypeRef same_size_int = LLVMIntType(size_in_bits); LLVMTypeRef same_size_int = LLVMIntType(size_in_bits);
LLVMValueRef truncated_int = LLVMBuildTrunc(g->builder, shifted_value, same_size_int, ""); LLVMValueRef truncated_int = LLVMBuildTrunc(g->builder, shifted_value, same_size_int, "");
@ -3642,7 +3642,7 @@ static void gen_valgrind_undef(CodeGen *g, LLVMValueRef dest_ptr, LLVMValueRef b
} }
static void gen_undef_init(CodeGen *g, uint32_t ptr_align_bytes, ZigType *value_type, LLVMValueRef ptr) { static void gen_undef_init(CodeGen *g, uint32_t ptr_align_bytes, ZigType *value_type, LLVMValueRef ptr) {
assert(type_has_bits(value_type)); assert(type_has_bits(g, value_type));
uint64_t size_bytes = LLVMStoreSizeOfType(g->target_data_ref, get_llvm_type(g, value_type)); uint64_t size_bytes = LLVMStoreSizeOfType(g->target_data_ref, get_llvm_type(g, value_type));
assert(size_bytes > 0); assert(size_bytes > 0);
assert(ptr_align_bytes > 0); assert(ptr_align_bytes > 0);
@ -3708,7 +3708,7 @@ static LLVMValueRef ir_render_var_ptr(CodeGen *g, IrExecutableGen *executable, I
if (instruction->base.value->special != ConstValSpecialRuntime) if (instruction->base.value->special != ConstValSpecialRuntime)
return ir_llvm_value(g, &instruction->base); return ir_llvm_value(g, &instruction->base);
ZigVar *var = instruction->var; ZigVar *var = instruction->var;
if (type_has_bits(var->var_type)) { if (type_has_bits(g, var->var_type)) {
assert(var->value_ref); assert(var->value_ref);
return var->value_ref; return var->value_ref;
} else { } else {
@ -3719,7 +3719,7 @@ static LLVMValueRef ir_render_var_ptr(CodeGen *g, IrExecutableGen *executable, I
static LLVMValueRef ir_render_return_ptr(CodeGen *g, IrExecutableGen *executable, static LLVMValueRef ir_render_return_ptr(CodeGen *g, IrExecutableGen *executable,
IrInstGenReturnPtr *instruction) IrInstGenReturnPtr *instruction)
{ {
if (!type_has_bits(instruction->base.value->type)) if (!type_has_bits(g, instruction->base.value->type))
return nullptr; return nullptr;
ir_assert(g->cur_ret_ptr != nullptr, &instruction->base); ir_assert(g->cur_ret_ptr != nullptr, &instruction->base);
return g->cur_ret_ptr; return g->cur_ret_ptr;
@ -3733,7 +3733,7 @@ static LLVMValueRef ir_render_elem_ptr(CodeGen *g, IrExecutableGen *executable,
LLVMValueRef subscript_value = ir_llvm_value(g, instruction->elem_index); LLVMValueRef subscript_value = ir_llvm_value(g, instruction->elem_index);
assert(subscript_value); assert(subscript_value);
if (!type_has_bits(array_type)) if (!type_has_bits(g, array_type))
return nullptr; return nullptr;
bool safety_check_on = ir_want_runtime_safety(g, &instruction->base) && instruction->safety_check_on; bool safety_check_on = ir_want_runtime_safety(g, &instruction->base) && instruction->safety_check_on;
@ -3793,7 +3793,7 @@ static LLVMValueRef ir_render_elem_ptr(CodeGen *g, IrExecutableGen *executable,
assert(array_type->data.structure.special == StructSpecialSlice); assert(array_type->data.structure.special == StructSpecialSlice);
ZigType *ptr_type = array_type->data.structure.fields[slice_ptr_index]->type_entry; ZigType *ptr_type = array_type->data.structure.fields[slice_ptr_index]->type_entry;
if (!type_has_bits(ptr_type)) { if (!type_has_bits(g, ptr_type)) {
if (safety_check_on) { if (safety_check_on) {
assert(LLVMGetTypeKind(LLVMTypeOf(array_ptr)) == LLVMIntegerTypeKind); assert(LLVMGetTypeKind(LLVMTypeOf(array_ptr)) == LLVMIntegerTypeKind);
add_bounds_check(g, subscript_value, LLVMIntEQ, nullptr, LLVMIntULT, array_ptr); add_bounds_check(g, subscript_value, LLVMIntEQ, nullptr, LLVMIntULT, array_ptr);
@ -3872,7 +3872,7 @@ static void render_async_spills(CodeGen *g) {
for (size_t var_i = 0; var_i < g->cur_fn->variable_list.length; var_i += 1) { for (size_t var_i = 0; var_i < g->cur_fn->variable_list.length; var_i += 1) {
ZigVar *var = g->cur_fn->variable_list.at(var_i); ZigVar *var = g->cur_fn->variable_list.at(var_i);
if (!type_has_bits(var->var_type)) { if (!type_has_bits(g, var->var_type)) {
continue; continue;
} }
if (ir_get_var_is_comptime(var)) if (ir_get_var_is_comptime(var))
@ -3992,7 +3992,7 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutableGen *executable, IrIn
FnTypeId *fn_type_id = &fn_type->data.fn.fn_type_id; FnTypeId *fn_type_id = &fn_type->data.fn.fn_type_id;
ZigType *src_return_type = fn_type_id->return_type; ZigType *src_return_type = fn_type_id->return_type;
bool ret_has_bits = type_has_bits(src_return_type); bool ret_has_bits = type_has_bits(g, src_return_type);
CallingConvention cc = fn_type->data.fn.fn_type_id.cc; CallingConvention cc = fn_type->data.fn.fn_type_id.cc;
@ -4312,7 +4312,7 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutableGen *executable, IrIn
gen_assert_resume_id(g, &instruction->base, ResumeIdReturn, PanicMsgIdResumedAnAwaitingFn, nullptr); gen_assert_resume_id(g, &instruction->base, ResumeIdReturn, PanicMsgIdResumedAnAwaitingFn, nullptr);
render_async_var_decls(g, instruction->base.base.scope); render_async_var_decls(g, instruction->base.base.scope);
if (!type_has_bits(src_return_type)) if (!type_has_bits(g, src_return_type))
return nullptr; return nullptr;
if (result_loc != nullptr) { if (result_loc != nullptr) {
@ -4372,7 +4372,7 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutableGen *executable, IrIn
} else if (first_arg_ret) { } else if (first_arg_ret) {
set_call_instr_sret(g, result); set_call_instr_sret(g, result);
return result_loc; return result_loc;
} else if (handle_is_ptr(src_return_type)) { } else if (handle_is_ptr(g, src_return_type)) {
LLVMValueRef store_instr = LLVMBuildStore(g->builder, result, result_loc); LLVMValueRef store_instr = LLVMBuildStore(g->builder, result, result_loc);
LLVMSetAlignment(store_instr, get_ptr_align(g, instruction->result_loc->value->type)); LLVMSetAlignment(store_instr, get_ptr_align(g, instruction->result_loc->value->type));
return result_loc; return result_loc;
@ -4397,7 +4397,7 @@ static LLVMValueRef ir_render_struct_field_ptr(CodeGen *g, IrExecutableGen *exec
ZigType *struct_ptr_type = instruction->struct_ptr->value->type; ZigType *struct_ptr_type = instruction->struct_ptr->value->type;
TypeStructField *field = instruction->field; TypeStructField *field = instruction->field;
if (!type_has_bits(field->type_entry)) if (!type_has_bits(g, field->type_entry))
return nullptr; return nullptr;
if (struct_ptr_type->id == ZigTypeIdPointer && if (struct_ptr_type->id == ZigTypeIdPointer &&
@ -4448,9 +4448,9 @@ static LLVMValueRef ir_render_union_field_ptr(CodeGen *g, IrExecutableGen *execu
TypeUnionField *field = instruction->field; TypeUnionField *field = instruction->field;
if (!type_has_bits(field->type_entry)) { if (!type_has_bits(g, field->type_entry)) {
ZigType *tag_type = union_type->data.unionation.tag_type; ZigType *tag_type = union_type->data.unionation.tag_type;
if (!instruction->initializing || tag_type == nullptr || !type_has_bits(tag_type)) if (!instruction->initializing || tag_type == nullptr || !type_has_bits(g, tag_type))
return nullptr; return nullptr;
// The field has no bits but we still have to change the discriminant // The field has no bits but we still have to change the discriminant
@ -4672,10 +4672,10 @@ static LLVMValueRef gen_non_null_bit(CodeGen *g, ZigType *maybe_type, LLVMValueR
(maybe_type->id == ZigTypeIdPointer && maybe_type->data.pointer.allow_zero)); (maybe_type->id == ZigTypeIdPointer && maybe_type->data.pointer.allow_zero));
ZigType *child_type = maybe_type->data.maybe.child_type; ZigType *child_type = maybe_type->data.maybe.child_type;
if (!type_has_bits(child_type)) if (!type_has_bits(g, child_type))
return maybe_handle; return maybe_handle;
bool is_scalar = !handle_is_ptr(maybe_type); bool is_scalar = !handle_is_ptr(g, maybe_type);
if (is_scalar) if (is_scalar)
return LLVMBuildICmp(g->builder, LLVMIntNE, maybe_handle, LLVMConstNull(get_llvm_type(g, maybe_type)), ""); return LLVMBuildICmp(g->builder, LLVMIntNE, maybe_handle, LLVMConstNull(get_llvm_type(g, maybe_type)), "");
@ -4713,14 +4713,14 @@ static LLVMValueRef ir_render_optional_unwrap_ptr(CodeGen *g, IrExecutableGen *e
LLVMPositionBuilderAtEnd(g->builder, ok_block); LLVMPositionBuilderAtEnd(g->builder, ok_block);
} }
if (!type_has_bits(child_type)) { if (!type_has_bits(g, child_type)) {
if (instruction->initializing) { if (instruction->initializing) {
LLVMValueRef non_null_bit = LLVMConstInt(LLVMInt1Type(), 1, false); LLVMValueRef non_null_bit = LLVMConstInt(LLVMInt1Type(), 1, false);
gen_store_untyped(g, non_null_bit, base_ptr, 0, false); gen_store_untyped(g, non_null_bit, base_ptr, 0, false);
} }
return nullptr; return nullptr;
} else { } else {
bool is_scalar = !handle_is_ptr(maybe_type); bool is_scalar = !handle_is_ptr(g, maybe_type);
if (is_scalar) { if (is_scalar) {
return base_ptr; return base_ptr;
} else { } else {
@ -4899,11 +4899,11 @@ static LLVMValueRef ir_render_switch_br(CodeGen *g, IrExecutableGen *executable,
} }
static LLVMValueRef ir_render_phi(CodeGen *g, IrExecutableGen *executable, IrInstGenPhi *instruction) { static LLVMValueRef ir_render_phi(CodeGen *g, IrExecutableGen *executable, IrInstGenPhi *instruction) {
if (!type_has_bits(instruction->base.value->type)) if (!type_has_bits(g, instruction->base.value->type))
return nullptr; return nullptr;
LLVMTypeRef phi_type; LLVMTypeRef phi_type;
if (handle_is_ptr(instruction->base.value->type)) { if (handle_is_ptr(g, instruction->base.value->type)) {
phi_type = LLVMPointerType(get_llvm_type(g,instruction->base.value->type), 0); phi_type = LLVMPointerType(get_llvm_type(g,instruction->base.value->type), 0);
} else { } else {
phi_type = get_llvm_type(g, instruction->base.value->type); phi_type = get_llvm_type(g, instruction->base.value->type);
@ -4921,7 +4921,7 @@ static LLVMValueRef ir_render_phi(CodeGen *g, IrExecutableGen *executable, IrIns
} }
static LLVMValueRef ir_render_ref(CodeGen *g, IrExecutableGen *executable, IrInstGenRef *instruction) { static LLVMValueRef ir_render_ref(CodeGen *g, IrExecutableGen *executable, IrInstGenRef *instruction) {
if (!type_has_bits(instruction->base.value->type)) { if (!type_has_bits(g, instruction->base.value->type)) {
return nullptr; return nullptr;
} }
if (instruction->operand->id == IrInstGenIdCall) { if (instruction->operand->id == IrInstGenIdCall) {
@ -4931,7 +4931,7 @@ static LLVMValueRef ir_render_ref(CodeGen *g, IrExecutableGen *executable, IrIns
} }
} }
LLVMValueRef value = ir_llvm_value(g, instruction->operand); LLVMValueRef value = ir_llvm_value(g, instruction->operand);
if (handle_is_ptr(instruction->operand->value->type)) { if (handle_is_ptr(g, instruction->operand->value->type)) {
return value; return value;
} else { } else {
LLVMValueRef result_loc = ir_llvm_value(g, instruction->result_loc); LLVMValueRef result_loc = ir_llvm_value(g, instruction->result_loc);
@ -5232,20 +5232,20 @@ static LLVMValueRef ir_render_cmpxchg(CodeGen *g, IrExecutableGen *executable, I
assert(optional_type->id == ZigTypeIdOptional); assert(optional_type->id == ZigTypeIdOptional);
ZigType *child_type = optional_type->data.maybe.child_type; ZigType *child_type = optional_type->data.maybe.child_type;
if (!handle_is_ptr(optional_type)) { if (!handle_is_ptr(g, optional_type)) {
LLVMValueRef payload_val = LLVMBuildExtractValue(g->builder, result_val, 0, ""); LLVMValueRef payload_val = LLVMBuildExtractValue(g->builder, result_val, 0, "");
LLVMValueRef success_bit = LLVMBuildExtractValue(g->builder, result_val, 1, ""); LLVMValueRef success_bit = LLVMBuildExtractValue(g->builder, result_val, 1, "");
return LLVMBuildSelect(g->builder, success_bit, LLVMConstNull(get_llvm_type(g, child_type)), payload_val, ""); return LLVMBuildSelect(g->builder, success_bit, LLVMConstNull(get_llvm_type(g, child_type)), payload_val, "");
} }
// When the cmpxchg is discarded, the result location will have no bits. // When the cmpxchg is discarded, the result location will have no bits.
if (!type_has_bits(instruction->result_loc->value->type)) { if (!type_has_bits(g, instruction->result_loc->value->type)) {
return nullptr; return nullptr;
} }
LLVMValueRef result_loc = ir_llvm_value(g, instruction->result_loc); LLVMValueRef result_loc = ir_llvm_value(g, instruction->result_loc);
ir_assert(result_loc != nullptr, &instruction->base); ir_assert(result_loc != nullptr, &instruction->base);
ir_assert(type_has_bits(child_type), &instruction->base); ir_assert(type_has_bits(g, child_type), &instruction->base);
LLVMValueRef payload_val = LLVMBuildExtractValue(g->builder, result_val, 0, ""); LLVMValueRef payload_val = LLVMBuildExtractValue(g->builder, result_val, 0, "");
LLVMValueRef val_ptr = LLVMBuildStructGEP(g->builder, result_loc, maybe_child_index, ""); LLVMValueRef val_ptr = LLVMBuildStructGEP(g->builder, result_loc, maybe_child_index, "");
@ -5373,7 +5373,7 @@ static LLVMValueRef ir_render_slice(CodeGen *g, IrExecutableGen *executable, IrI
} }
} }
} }
if (!type_has_bits(array_type)) { if (!type_has_bits(g, array_type)) {
LLVMValueRef len_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, slice_len_index, ""); LLVMValueRef len_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, slice_len_index, "");
// TODO if runtime safety is on, store 0xaaaaaaa in ptr field // TODO if runtime safety is on, store 0xaaaaaaa in ptr field
@ -5409,7 +5409,7 @@ static LLVMValueRef ir_render_slice(CodeGen *g, IrExecutableGen *executable, IrI
} }
} }
if (type_has_bits(array_type)) { if (type_has_bits(g, array_type)) {
size_t gen_ptr_index = instruction->base.value->type->data.structure.fields[slice_ptr_index]->gen_index; size_t gen_ptr_index = instruction->base.value->type->data.structure.fields[slice_ptr_index]->gen_index;
LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, gen_ptr_index, ""); LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, gen_ptr_index, "");
LLVMValueRef slice_start_ptr = LLVMBuildInBoundsGEP(g->builder, array_ptr, &start_val, 1, ""); LLVMValueRef slice_start_ptr = LLVMBuildInBoundsGEP(g->builder, array_ptr, &start_val, 1, "");
@ -5597,7 +5597,7 @@ static LLVMValueRef ir_render_test_err(CodeGen *g, IrExecutableGen *executable,
LLVMValueRef err_union_handle = ir_llvm_value(g, instruction->err_union); LLVMValueRef err_union_handle = ir_llvm_value(g, instruction->err_union);
LLVMValueRef err_val; LLVMValueRef err_val;
if (type_has_bits(payload_type)) { if (type_has_bits(g, payload_type)) {
LLVMValueRef err_val_ptr = LLVMBuildStructGEP(g->builder, err_union_handle, err_union_err_index, ""); LLVMValueRef err_val_ptr = LLVMBuildStructGEP(g->builder, err_union_handle, err_union_err_index, "");
err_val = gen_load_untyped(g, err_val_ptr, 0, false, ""); err_val = gen_load_untyped(g, err_val_ptr, 0, false, "");
} else { } else {
@ -5619,7 +5619,7 @@ static LLVMValueRef ir_render_unwrap_err_code(CodeGen *g, IrExecutableGen *execu
ZigType *err_union_type = ptr_type->data.pointer.child_type; ZigType *err_union_type = ptr_type->data.pointer.child_type;
ZigType *payload_type = err_union_type->data.error_union.payload_type; ZigType *payload_type = err_union_type->data.error_union.payload_type;
LLVMValueRef err_union_ptr = ir_llvm_value(g, instruction->err_union_ptr); LLVMValueRef err_union_ptr = ir_llvm_value(g, instruction->err_union_ptr);
if (!type_has_bits(payload_type)) { if (!type_has_bits(g, payload_type)) {
return err_union_ptr; return err_union_ptr;
} else { } else {
// TODO assign undef to the payload // TODO assign undef to the payload
@ -5659,13 +5659,13 @@ static LLVMValueRef ir_render_unwrap_err_payload(CodeGen *g, IrExecutableGen *ex
LLVMValueRef err_union_handle = get_handle_value(g, err_union_ptr, err_union_type, ptr_type); LLVMValueRef err_union_handle = get_handle_value(g, err_union_ptr, err_union_type, ptr_type);
if (!type_has_bits(err_union_type->data.error_union.err_set_type)) { if (!type_has_bits(g, err_union_type->data.error_union.err_set_type)) {
return err_union_handle; return err_union_handle;
} }
if (want_safety) { if (want_safety) {
LLVMValueRef err_val; LLVMValueRef err_val;
if (type_has_bits(payload_type)) { if (type_has_bits(g, payload_type)) {
LLVMValueRef err_val_ptr = LLVMBuildStructGEP(g->builder, err_union_handle, err_union_err_index, ""); LLVMValueRef err_val_ptr = LLVMBuildStructGEP(g->builder, err_union_handle, err_union_err_index, "");
err_val = gen_load_untyped(g, err_val_ptr, 0, false, ""); err_val = gen_load_untyped(g, err_val_ptr, 0, false, "");
} else { } else {
@ -5682,7 +5682,7 @@ static LLVMValueRef ir_render_unwrap_err_payload(CodeGen *g, IrExecutableGen *ex
LLVMPositionBuilderAtEnd(g->builder, ok_block); LLVMPositionBuilderAtEnd(g->builder, ok_block);
} }
if (type_has_bits(payload_type)) { if (type_has_bits(g, payload_type)) {
if (instruction->initializing) { if (instruction->initializing) {
LLVMValueRef err_tag_ptr = LLVMBuildStructGEP(g->builder, err_union_handle, err_union_err_index, ""); LLVMValueRef err_tag_ptr = LLVMBuildStructGEP(g->builder, err_union_handle, err_union_err_index, "");
LLVMValueRef ok_err_val = LLVMConstNull(get_llvm_type(g, g->err_tag_type)); LLVMValueRef ok_err_val = LLVMConstNull(get_llvm_type(g, g->err_tag_type));
@ -5704,7 +5704,7 @@ static LLVMValueRef ir_render_optional_wrap(CodeGen *g, IrExecutableGen *executa
ZigType *child_type = wanted_type->data.maybe.child_type; ZigType *child_type = wanted_type->data.maybe.child_type;
if (!type_has_bits(child_type)) { if (!type_has_bits(g, child_type)) {
LLVMValueRef result = LLVMConstAllOnes(LLVMInt1Type()); LLVMValueRef result = LLVMConstAllOnes(LLVMInt1Type());
if (instruction->result_loc != nullptr) { if (instruction->result_loc != nullptr) {
LLVMValueRef result_loc = ir_llvm_value(g, instruction->result_loc); LLVMValueRef result_loc = ir_llvm_value(g, instruction->result_loc);
@ -5714,7 +5714,7 @@ static LLVMValueRef ir_render_optional_wrap(CodeGen *g, IrExecutableGen *executa
} }
LLVMValueRef payload_val = ir_llvm_value(g, instruction->operand); LLVMValueRef payload_val = ir_llvm_value(g, instruction->operand);
if (!handle_is_ptr(wanted_type)) { if (!handle_is_ptr(g, wanted_type)) {
if (instruction->result_loc != nullptr) { if (instruction->result_loc != nullptr) {
LLVMValueRef result_loc = ir_llvm_value(g, instruction->result_loc); LLVMValueRef result_loc = ir_llvm_value(g, instruction->result_loc);
gen_store_untyped(g, payload_val, result_loc, 0, false); gen_store_untyped(g, payload_val, result_loc, 0, false);
@ -5740,7 +5740,7 @@ static LLVMValueRef ir_render_err_wrap_code(CodeGen *g, IrExecutableGen *executa
LLVMValueRef err_val = ir_llvm_value(g, instruction->operand); LLVMValueRef err_val = ir_llvm_value(g, instruction->operand);
if (!handle_is_ptr(wanted_type)) if (!handle_is_ptr(g, wanted_type))
return err_val; return err_val;
LLVMValueRef result_loc = ir_llvm_value(g, instruction->result_loc); LLVMValueRef result_loc = ir_llvm_value(g, instruction->result_loc);
@ -5761,13 +5761,13 @@ static LLVMValueRef ir_render_err_wrap_payload(CodeGen *g, IrExecutableGen *exec
ZigType *payload_type = wanted_type->data.error_union.payload_type; ZigType *payload_type = wanted_type->data.error_union.payload_type;
ZigType *err_set_type = wanted_type->data.error_union.err_set_type; ZigType *err_set_type = wanted_type->data.error_union.err_set_type;
if (!type_has_bits(err_set_type)) { if (!type_has_bits(g, err_set_type)) {
return ir_llvm_value(g, instruction->operand); return ir_llvm_value(g, instruction->operand);
} }
LLVMValueRef ok_err_val = LLVMConstNull(get_llvm_type(g, g->err_tag_type)); LLVMValueRef ok_err_val = LLVMConstNull(get_llvm_type(g, g->err_tag_type));
if (!type_has_bits(payload_type)) if (!type_has_bits(g, payload_type))
return ok_err_val; return ok_err_val;
@ -5788,7 +5788,7 @@ static LLVMValueRef ir_render_union_tag(CodeGen *g, IrExecutableGen *executable,
ZigType *union_type = instruction->value->value->type; ZigType *union_type = instruction->value->value->type;
ZigType *tag_type = union_type->data.unionation.tag_type; ZigType *tag_type = union_type->data.unionation.tag_type;
if (!type_has_bits(tag_type)) if (!type_has_bits(g, tag_type))
return nullptr; return nullptr;
LLVMValueRef union_val = ir_llvm_value(g, instruction->value); LLVMValueRef union_val = ir_llvm_value(g, instruction->value);
@ -5825,7 +5825,7 @@ static LLVMValueRef ir_render_atomic_rmw(CodeGen *g, IrExecutableGen *executable
LLVMValueRef ptr = ir_llvm_value(g, instruction->ptr); LLVMValueRef ptr = ir_llvm_value(g, instruction->ptr);
LLVMValueRef operand = ir_llvm_value(g, instruction->operand); LLVMValueRef operand = ir_llvm_value(g, instruction->operand);
if (get_codegen_ptr_type(operand_type) == nullptr) { if (get_codegen_ptr_type_bail(g, operand_type) == nullptr) {
return ZigLLVMBuildAtomicRMW(g->builder, op, ptr, operand, ordering, g->is_single_threaded); return ZigLLVMBuildAtomicRMW(g->builder, op, ptr, operand, ordering, g->is_single_threaded);
} }
@ -5927,7 +5927,7 @@ static LLVMValueRef ir_render_vector_to_array(CodeGen *g, IrExecutableGen *execu
{ {
ZigType *array_type = instruction->base.value->type; ZigType *array_type = instruction->base.value->type;
assert(array_type->id == ZigTypeIdArray); assert(array_type->id == ZigTypeIdArray);
assert(handle_is_ptr(array_type)); assert(handle_is_ptr(g, array_type));
LLVMValueRef result_loc = ir_llvm_value(g, instruction->result_loc); LLVMValueRef result_loc = ir_llvm_value(g, instruction->result_loc);
LLVMValueRef vector = ir_llvm_value(g, instruction->vector); LLVMValueRef vector = ir_llvm_value(g, instruction->vector);
@ -5961,7 +5961,7 @@ static LLVMValueRef ir_render_array_to_vector(CodeGen *g, IrExecutableGen *execu
{ {
ZigType *vector_type = instruction->base.value->type; ZigType *vector_type = instruction->base.value->type;
assert(vector_type->id == ZigTypeIdVector); assert(vector_type->id == ZigTypeIdVector);
assert(!handle_is_ptr(vector_type)); assert(!handle_is_ptr(g, vector_type));
LLVMValueRef array_ptr = ir_llvm_value(g, instruction->array); LLVMValueRef array_ptr = ir_llvm_value(g, instruction->array);
LLVMTypeRef vector_type_ref = get_llvm_type(g, vector_type); LLVMTypeRef vector_type_ref = get_llvm_type(g, vector_type);
@ -6057,7 +6057,7 @@ static LLVMValueRef gen_await_early_return(CodeGen *g, IrInstGen *source_instr,
{ {
LLVMTypeRef usize_type_ref = g->builtin_types.entry_usize->llvm_type; LLVMTypeRef usize_type_ref = g->builtin_types.entry_usize->llvm_type;
LLVMValueRef their_result_ptr = nullptr; LLVMValueRef their_result_ptr = nullptr;
if (type_has_bits(result_type) && (non_async || result_loc != nullptr)) { if (type_has_bits(g, result_type) && (non_async || result_loc != nullptr)) {
LLVMValueRef their_result_ptr_ptr = LLVMBuildStructGEP(g->builder, target_frame_ptr, frame_ret_start, ""); LLVMValueRef their_result_ptr_ptr = LLVMBuildStructGEP(g->builder, target_frame_ptr, frame_ret_start, "");
their_result_ptr = LLVMBuildLoad(g->builder, their_result_ptr_ptr, ""); their_result_ptr = LLVMBuildLoad(g->builder, their_result_ptr_ptr, "");
if (result_loc != nullptr) { if (result_loc != nullptr) {
@ -6082,7 +6082,7 @@ static LLVMValueRef gen_await_early_return(CodeGen *g, IrInstGen *source_instr,
ZigLLVMBuildCall(g->builder, get_merge_err_ret_traces_fn_val(g), args, 2, ZigLLVMBuildCall(g->builder, get_merge_err_ret_traces_fn_val(g), args, 2,
get_llvm_cc(g, CallingConventionUnspecified), ZigLLVM_CallAttrAuto, ""); get_llvm_cc(g, CallingConventionUnspecified), ZigLLVM_CallAttrAuto, "");
} }
if (non_async && type_has_bits(result_type)) { if (non_async && type_has_bits(g, result_type)) {
LLVMValueRef result_ptr = (result_loc == nullptr) ? their_result_ptr : result_loc; LLVMValueRef result_ptr = (result_loc == nullptr) ? their_result_ptr : result_loc;
return get_handle_value(g, result_ptr, result_type, ptr_result_type); return get_handle_value(g, result_ptr, result_type, ptr_result_type);
} else { } else {
@ -6115,7 +6115,7 @@ static LLVMValueRef ir_render_await(CodeGen *g, IrExecutableGen *executable, IrI
// This code is as if it is running inside the suspend block. // This code is as if it is running inside the suspend block.
// supply the awaiter return pointer // supply the awaiter return pointer
if (type_has_bits(result_type)) { if (type_has_bits(g, result_type)) {
LLVMValueRef awaiter_ret_ptr_ptr = LLVMBuildStructGEP(g->builder, target_frame_ptr, frame_ret_start + 1, ""); LLVMValueRef awaiter_ret_ptr_ptr = LLVMBuildStructGEP(g->builder, target_frame_ptr, frame_ret_start + 1, "");
if (result_loc == nullptr) { if (result_loc == nullptr) {
// no copy needed // no copy needed
@ -6599,7 +6599,7 @@ static LLVMValueRef pack_const_int(CodeGen *g, LLVMTypeRef big_int_type_ref, Zig
} }
ZigType *type_entry = const_val->type; ZigType *type_entry = const_val->type;
assert(type_has_bits(type_entry)); assert(type_has_bits(g, type_entry));
switch (type_entry->id) { switch (type_entry->id) {
case ZigTypeIdInvalid: case ZigTypeIdInvalid:
case ZigTypeIdMetaType: case ZigTypeIdMetaType:
@ -6732,7 +6732,7 @@ static LLVMValueRef gen_const_val_ptr(CodeGen *g, ZigValue *const_val, const cha
{ {
ZigValue *array_const_val = const_val->data.x_ptr.data.base_array.array_val; ZigValue *array_const_val = const_val->data.x_ptr.data.base_array.array_val;
assert(array_const_val->type->id == ZigTypeIdArray); assert(array_const_val->type->id == ZigTypeIdArray);
if (!type_has_bits(array_const_val->type)) { if (!type_has_bits(g, array_const_val->type)) {
if (array_const_val->type->data.array.sentinel != nullptr) { if (array_const_val->type->data.array.sentinel != nullptr) {
ZigValue *pointee = array_const_val->type->data.array.sentinel; ZigValue *pointee = array_const_val->type->data.array.sentinel;
render_const_val(g, pointee, ""); render_const_val(g, pointee, "");
@ -6758,7 +6758,7 @@ static LLVMValueRef gen_const_val_ptr(CodeGen *g, ZigValue *const_val, const cha
{ {
ZigValue *struct_const_val = const_val->data.x_ptr.data.base_struct.struct_val; ZigValue *struct_const_val = const_val->data.x_ptr.data.base_struct.struct_val;
assert(struct_const_val->type->id == ZigTypeIdStruct); assert(struct_const_val->type->id == ZigTypeIdStruct);
if (!type_has_bits(struct_const_val->type)) { if (!type_has_bits(g, struct_const_val->type)) {
// make this a null pointer // make this a null pointer
ZigType *usize = g->builtin_types.entry_usize; ZigType *usize = g->builtin_types.entry_usize;
const_val->llvm_value = LLVMConstIntToPtr(LLVMConstNull(usize->llvm_type), const_val->llvm_value = LLVMConstIntToPtr(LLVMConstNull(usize->llvm_type),
@ -6777,7 +6777,7 @@ static LLVMValueRef gen_const_val_ptr(CodeGen *g, ZigValue *const_val, const cha
{ {
ZigValue *err_union_const_val = const_val->data.x_ptr.data.base_err_union_code.err_union_val; ZigValue *err_union_const_val = const_val->data.x_ptr.data.base_err_union_code.err_union_val;
assert(err_union_const_val->type->id == ZigTypeIdErrorUnion); assert(err_union_const_val->type->id == ZigTypeIdErrorUnion);
if (!type_has_bits(err_union_const_val->type)) { if (!type_has_bits(g, err_union_const_val->type)) {
// make this a null pointer // make this a null pointer
ZigType *usize = g->builtin_types.entry_usize; ZigType *usize = g->builtin_types.entry_usize;
const_val->llvm_value = LLVMConstIntToPtr(LLVMConstNull(usize->llvm_type), const_val->llvm_value = LLVMConstIntToPtr(LLVMConstNull(usize->llvm_type),
@ -6793,7 +6793,7 @@ static LLVMValueRef gen_const_val_ptr(CodeGen *g, ZigValue *const_val, const cha
{ {
ZigValue *err_union_const_val = const_val->data.x_ptr.data.base_err_union_payload.err_union_val; ZigValue *err_union_const_val = const_val->data.x_ptr.data.base_err_union_payload.err_union_val;
assert(err_union_const_val->type->id == ZigTypeIdErrorUnion); assert(err_union_const_val->type->id == ZigTypeIdErrorUnion);
if (!type_has_bits(err_union_const_val->type)) { if (!type_has_bits(g, err_union_const_val->type)) {
// make this a null pointer // make this a null pointer
ZigType *usize = g->builtin_types.entry_usize; ZigType *usize = g->builtin_types.entry_usize;
const_val->llvm_value = LLVMConstIntToPtr(LLVMConstNull(usize->llvm_type), const_val->llvm_value = LLVMConstIntToPtr(LLVMConstNull(usize->llvm_type),
@ -6809,7 +6809,7 @@ static LLVMValueRef gen_const_val_ptr(CodeGen *g, ZigValue *const_val, const cha
{ {
ZigValue *optional_const_val = const_val->data.x_ptr.data.base_optional_payload.optional_val; ZigValue *optional_const_val = const_val->data.x_ptr.data.base_optional_payload.optional_val;
assert(optional_const_val->type->id == ZigTypeIdOptional); assert(optional_const_val->type->id == ZigTypeIdOptional);
if (!type_has_bits(optional_const_val->type)) { if (!type_has_bits(g, optional_const_val->type)) {
// make this a null pointer // make this a null pointer
ZigType *usize = g->builtin_types.entry_usize; ZigType *usize = g->builtin_types.entry_usize;
const_val->llvm_value = LLVMConstIntToPtr(LLVMConstNull(usize->llvm_type), const_val->llvm_value = LLVMConstIntToPtr(LLVMConstNull(usize->llvm_type),
@ -6847,7 +6847,7 @@ static LLVMValueRef gen_const_val(CodeGen *g, ZigValue *const_val, const char *n
Error err; Error err;
ZigType *type_entry = const_val->type; ZigType *type_entry = const_val->type;
assert(type_has_bits(type_entry)); assert(type_has_bits(g, type_entry));
check: switch (const_val->special) { check: switch (const_val->special) {
case ConstValSpecialLazy: case ConstValSpecialLazy:
@ -6900,12 +6900,12 @@ check: switch (const_val->special) {
case ZigTypeIdOptional: case ZigTypeIdOptional:
{ {
ZigType *child_type = type_entry->data.maybe.child_type; ZigType *child_type = type_entry->data.maybe.child_type;
if (!type_has_bits(child_type)) { if (get_src_ptr_type(type_entry) != nullptr) {
return LLVMConstInt(LLVMInt1Type(), const_val->data.x_optional ? 1 : 0, false);
} else if (get_codegen_ptr_type(type_entry) != nullptr) {
return gen_const_val_ptr(g, const_val, name); return gen_const_val_ptr(g, const_val, name);
} else if (child_type->id == ZigTypeIdErrorSet) { } else if (child_type->id == ZigTypeIdErrorSet) {
return gen_const_val_err_set(g, const_val, name); return gen_const_val_err_set(g, const_val, name);
} else if (!type_has_bits(g, child_type)) {
return LLVMConstInt(LLVMInt1Type(), const_val->data.x_optional ? 1 : 0, false);
} else { } else {
LLVMValueRef child_val; LLVMValueRef child_val;
LLVMValueRef maybe_val; LLVMValueRef maybe_val;
@ -7128,7 +7128,7 @@ check: switch (const_val->special) {
LLVMValueRef union_value_ref; LLVMValueRef union_value_ref;
bool make_unnamed_struct; bool make_unnamed_struct;
ZigValue *payload_value = const_val->data.x_union.payload; ZigValue *payload_value = const_val->data.x_union.payload;
if (payload_value == nullptr || !type_has_bits(payload_value->type)) { if (payload_value == nullptr || !type_has_bits(g, payload_value->type)) {
if (type_entry->data.unionation.gen_tag_index == SIZE_MAX) if (type_entry->data.unionation.gen_tag_index == SIZE_MAX)
return LLVMGetUndef(get_llvm_type(g, type_entry)); return LLVMGetUndef(get_llvm_type(g, type_entry));
@ -7205,13 +7205,13 @@ check: switch (const_val->special) {
{ {
ZigType *payload_type = type_entry->data.error_union.payload_type; ZigType *payload_type = type_entry->data.error_union.payload_type;
ZigType *err_set_type = type_entry->data.error_union.err_set_type; ZigType *err_set_type = type_entry->data.error_union.err_set_type;
if (!type_has_bits(payload_type)) { if (!type_has_bits(g, payload_type)) {
assert(type_has_bits(err_set_type)); assert(type_has_bits(g, err_set_type));
ErrorTableEntry *err_set = const_val->data.x_err_union.error_set->data.x_err_set; ErrorTableEntry *err_set = const_val->data.x_err_union.error_set->data.x_err_set;
uint64_t value = (err_set == nullptr) ? 0 : err_set->value; uint64_t value = (err_set == nullptr) ? 0 : err_set->value;
return LLVMConstInt(get_llvm_type(g, g->err_tag_type), value, false); return LLVMConstInt(get_llvm_type(g, g->err_tag_type), value, false);
} else if (!type_has_bits(err_set_type)) { } else if (!type_has_bits(g, err_set_type)) {
assert(type_has_bits(payload_type)); assert(type_has_bits(g, payload_type));
return gen_const_val(g, const_val->data.x_err_union.payload, ""); return gen_const_val(g, const_val->data.x_err_union.payload, "");
} else { } else {
LLVMValueRef err_tag_value; LLVMValueRef err_tag_value;
@ -7445,7 +7445,7 @@ static void do_code_gen(CodeGen *g) {
continue; continue;
} }
if (!type_has_bits(var->var_type)) if (!type_has_bits(g, var->var_type))
continue; continue;
assert(var->decl_node); assert(var->decl_node);
@ -7544,7 +7544,7 @@ static void do_code_gen(CodeGen *g) {
} else { } else {
if (want_sret) { if (want_sret) {
g->cur_ret_ptr = LLVMGetParam(fn, 0); g->cur_ret_ptr = LLVMGetParam(fn, 0);
} else if (type_has_bits(fn_type_id->return_type)) { } else if (type_has_bits(g, fn_type_id->return_type)) {
g->cur_ret_ptr = build_alloca(g, fn_type_id->return_type, "result", 0); g->cur_ret_ptr = build_alloca(g, fn_type_id->return_type, "result", 0);
// TODO add debug info variable for this // TODO add debug info variable for this
} else { } else {
@ -7609,7 +7609,7 @@ static void do_code_gen(CodeGen *g) {
ZigType *child_type = ptr_type->data.pointer.child_type; ZigType *child_type = ptr_type->data.pointer.child_type;
if (type_resolve(g, child_type, ResolveStatusSizeKnown)) if (type_resolve(g, child_type, ResolveStatusSizeKnown))
zig_unreachable(); zig_unreachable();
if (!type_has_bits(child_type)) if (!type_has_bits(g, child_type))
continue; continue;
if (instruction->base.base.ref_count == 0) if (instruction->base.base.ref_count == 0)
continue; continue;
@ -7640,7 +7640,7 @@ static void do_code_gen(CodeGen *g) {
for (size_t var_i = 0; var_i < fn_table_entry->variable_list.length; var_i += 1) { for (size_t var_i = 0; var_i < fn_table_entry->variable_list.length; var_i += 1) {
ZigVar *var = fn_table_entry->variable_list.at(var_i); ZigVar *var = fn_table_entry->variable_list.at(var_i);
if (!type_has_bits(var->var_type)) { if (!type_has_bits(g, var->var_type)) {
continue; continue;
} }
if (ir_get_var_is_comptime(var)) if (ir_get_var_is_comptime(var))
@ -7667,7 +7667,7 @@ static void do_code_gen(CodeGen *g) {
FnGenParamInfo *gen_info = &fn_table_entry->type_entry->data.fn.gen_param_info[var->src_arg_index]; FnGenParamInfo *gen_info = &fn_table_entry->type_entry->data.fn.gen_param_info[var->src_arg_index];
assert(gen_info->gen_index != SIZE_MAX); assert(gen_info->gen_index != SIZE_MAX);
if (handle_is_ptr(var->var_type)) { if (handle_is_ptr(g, var->var_type)) {
if (gen_info->is_byval) { if (gen_info->is_byval) {
gen_type = var->var_type; gen_type = var->var_type;
} else { } else {
@ -7739,7 +7739,7 @@ static void do_code_gen(CodeGen *g) {
LLVMValueRef resume_index_ptr = LLVMBuildStructGEP(g->builder, g->cur_frame_ptr, frame_resume_index, ""); LLVMValueRef resume_index_ptr = LLVMBuildStructGEP(g->builder, g->cur_frame_ptr, frame_resume_index, "");
g->cur_async_resume_index_ptr = resume_index_ptr; g->cur_async_resume_index_ptr = resume_index_ptr;
if (type_has_bits(fn_type_id->return_type)) { if (type_has_bits(g, fn_type_id->return_type)) {
LLVMValueRef cur_ret_ptr_ptr = LLVMBuildStructGEP(g->builder, g->cur_frame_ptr, frame_ret_start, ""); LLVMValueRef cur_ret_ptr_ptr = LLVMBuildStructGEP(g->builder, g->cur_frame_ptr, frame_ret_start, "");
g->cur_ret_ptr = LLVMBuildLoad(g->builder, cur_ret_ptr_ptr, ""); g->cur_ret_ptr = LLVMBuildLoad(g->builder, cur_ret_ptr_ptr, "");
} }
@ -9847,10 +9847,10 @@ static void get_c_type(CodeGen *g, GenH *gen_h, ZigType *type_entry, Buf *out_bu
case ZigTypeIdOptional: case ZigTypeIdOptional:
{ {
ZigType *child_type = type_entry->data.maybe.child_type; ZigType *child_type = type_entry->data.maybe.child_type;
if (!type_has_bits(child_type)) { if (!type_has_bits(g, child_type)) {
buf_init_from_str(out_buf, "bool"); buf_init_from_str(out_buf, "bool");
return; return;
} else if (type_is_nonnull_ptr(child_type)) { } else if (type_is_nonnull_ptr(g, child_type)) {
return get_c_type(g, gen_h, child_type, out_buf); return get_c_type(g, gen_h, child_type, out_buf);
} else { } else {
zig_unreachable(); zig_unreachable();

View File

@ -860,7 +860,7 @@ static bool types_have_same_zig_comptime_repr(CodeGen *codegen, ZigType *expecte
if (expected == actual) if (expected == actual)
return true; return true;
if (get_codegen_ptr_type(expected) != nullptr && get_codegen_ptr_type(actual) != nullptr) if (get_src_ptr_type(expected) != nullptr && get_src_ptr_type(actual) != nullptr)
return true; return true;
if (is_opt_err_set(expected) && is_opt_err_set(actual)) if (is_opt_err_set(expected) && is_opt_err_set(actual))
@ -11399,7 +11399,7 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted
result.id = ConstCastResultIdInvalid; result.id = ConstCastResultIdInvalid;
return result; return result;
} }
if (type_has_bits(wanted_type) == type_has_bits(actual_type) && if (type_has_bits(g, wanted_type) == type_has_bits(g, actual_type) &&
actual_ptr_type->data.pointer.bit_offset_in_host == wanted_ptr_type->data.pointer.bit_offset_in_host && actual_ptr_type->data.pointer.bit_offset_in_host == wanted_ptr_type->data.pointer.bit_offset_in_host &&
actual_ptr_type->data.pointer.host_int_bytes == wanted_ptr_type->data.pointer.host_int_bytes && actual_ptr_type->data.pointer.host_int_bytes == wanted_ptr_type->data.pointer.host_int_bytes &&
get_ptr_align(ira->codegen, actual_ptr_type) >= get_ptr_align(ira->codegen, wanted_ptr_type)) get_ptr_align(ira->codegen, actual_ptr_type) >= get_ptr_align(ira->codegen, wanted_ptr_type))
@ -12532,7 +12532,7 @@ static IrInstGen *ir_const_move(IrAnalyze *ira, IrInst *old_instruction, ZigValu
static IrInstGen *ir_resolve_cast(IrAnalyze *ira, IrInst *source_instr, IrInstGen *value, static IrInstGen *ir_resolve_cast(IrAnalyze *ira, IrInst *source_instr, IrInstGen *value,
ZigType *wanted_type, CastOp cast_op) ZigType *wanted_type, CastOp cast_op)
{ {
if (instr_is_comptime(value) || !type_has_bits(wanted_type)) { if (instr_is_comptime(value) || !type_has_bits(ira->codegen, wanted_type)) {
IrInstGen *result = ir_const(ira, source_instr, wanted_type); IrInstGen *result = ir_const(ira, source_instr, wanted_type);
if (!eval_const_expr_implicit_cast(ira, source_instr, cast_op, value->value, value->value->type, if (!eval_const_expr_implicit_cast(ira, source_instr, cast_op, value->value, value->value->type,
result->value, wanted_type)) result->value, wanted_type))
@ -12918,7 +12918,7 @@ static Error ir_resolve_const_val(CodeGen *codegen, IrExecutableGen *exec, AstNo
case ConstValSpecialStatic: case ConstValSpecialStatic:
return ErrorNone; return ErrorNone;
case ConstValSpecialRuntime: case ConstValSpecialRuntime:
if (!type_has_bits(val->type)) if (!type_has_bits(codegen, val->type))
return ErrorNone; return ErrorNone;
exec_add_error_node_gen(codegen, exec, source_node, exec_add_error_node_gen(codegen, exec, source_node,
@ -13082,7 +13082,11 @@ static ZigType *ir_resolve_type(IrAnalyze *ira, IrInstGen *type_value) {
} }
static Error ir_validate_vector_elem_type(IrAnalyze *ira, AstNode *source_node, ZigType *elem_type) { static Error ir_validate_vector_elem_type(IrAnalyze *ira, AstNode *source_node, ZigType *elem_type) {
if (!is_valid_vector_elem_type(elem_type)) { Error err;
bool is_valid;
if ((err = is_valid_vector_elem_type(ira->codegen, elem_type, &is_valid)))
return err;
if (!is_valid) {
ir_add_error_node(ira, source_node, ir_add_error_node(ira, source_node,
buf_sprintf("vector element type must be integer, float, bool, or pointer; '%s' is invalid", buf_sprintf("vector element type must be integer, float, bool, or pointer; '%s' is invalid",
buf_ptr(&elem_type->name))); buf_ptr(&elem_type->name)));
@ -13198,7 +13202,7 @@ static IrInstGen *ir_analyze_optional_wrap(IrAnalyze *ira, IrInst* source_instr,
return &const_instruction->base; return &const_instruction->base;
} }
if (result_loc == nullptr && handle_is_ptr(wanted_type)) { if (result_loc == nullptr && handle_is_ptr(ira->codegen, wanted_type)) {
result_loc = no_result_loc(); result_loc = no_result_loc();
} }
IrInstGen *result_loc_inst = nullptr; IrInstGen *result_loc_inst = nullptr;
@ -13246,7 +13250,7 @@ static IrInstGen *ir_analyze_err_wrap_payload(IrAnalyze *ira, IrInst* source_ins
} }
IrInstGen *result_loc_inst; IrInstGen *result_loc_inst;
if (handle_is_ptr(wanted_type)) { if (handle_is_ptr(ira->codegen, wanted_type)) {
if (result_loc == nullptr) result_loc = no_result_loc(); if (result_loc == nullptr) result_loc = no_result_loc();
result_loc_inst = ir_resolve_result(ira, source_instr, result_loc, wanted_type, nullptr, true, true); result_loc_inst = ir_resolve_result(ira, source_instr, result_loc, wanted_type, nullptr, true, true);
if (type_is_invalid(result_loc_inst->value->type) || if (type_is_invalid(result_loc_inst->value->type) ||
@ -13358,7 +13362,7 @@ static IrInstGen *ir_analyze_err_wrap_code(IrAnalyze *ira, IrInst* source_instr,
} }
IrInstGen *result_loc_inst; IrInstGen *result_loc_inst;
if (handle_is_ptr(wanted_type)) { if (handle_is_ptr(ira->codegen, wanted_type)) {
if (result_loc == nullptr) result_loc = no_result_loc(); if (result_loc == nullptr) result_loc = no_result_loc();
result_loc_inst = ir_resolve_result(ira, source_instr, result_loc, wanted_type, nullptr, true, true); result_loc_inst = ir_resolve_result(ira, source_instr, result_loc, wanted_type, nullptr, true, true);
if (type_is_invalid(result_loc_inst->value->type) || if (type_is_invalid(result_loc_inst->value->type) ||
@ -13385,7 +13389,8 @@ static IrInstGen *ir_analyze_null_to_maybe(IrAnalyze *ira, IrInst *source_instr,
IrInstGen *result = ir_const(ira, source_instr, wanted_type); IrInstGen *result = ir_const(ira, source_instr, wanted_type);
result->value->special = ConstValSpecialStatic; result->value->special = ConstValSpecialStatic;
if (get_codegen_ptr_type(wanted_type) != nullptr) {
if (get_src_ptr_type(wanted_type) != nullptr) {
result->value->data.x_ptr.special = ConstPtrSpecialNull; result->value->data.x_ptr.special = ConstPtrSpecialNull;
} else if (is_opt_err_set(wanted_type)) { } else if (is_opt_err_set(wanted_type)) {
result->value->data.x_err_set = nullptr; result->value->data.x_err_set = nullptr;
@ -13434,7 +13439,7 @@ static IrInstGen *ir_get_ref2(IrAnalyze *ira, IrInst* source_instruction, IrInst
return ira->codegen->invalid_inst_gen; return ira->codegen->invalid_inst_gen;
IrInstGen *result_loc; IrInstGen *result_loc;
if (type_has_bits(ptr_type) && !handle_is_ptr(elem_type)) { if (type_has_bits(ira->codegen, ptr_type) && !handle_is_ptr(ira->codegen, elem_type)) {
result_loc = ir_resolve_result(ira, source_instruction, no_result_loc(), elem_type, nullptr, true, true); result_loc = ir_resolve_result(ira, source_instruction, no_result_loc(), elem_type, nullptr, true, true);
} else { } else {
result_loc = nullptr; result_loc = nullptr;
@ -13679,9 +13684,9 @@ static IrInstGen *ir_analyze_widen_or_shorten(IrAnalyze *ira, IrInst* source_ins
// If the destination integer type has no bits, then we can emit a comptime // If the destination integer type has no bits, then we can emit a comptime
// zero. However, we still want to emit a runtime safety check to make sure // zero. However, we still want to emit a runtime safety check to make sure
// the target is zero. // the target is zero.
if (!type_has_bits(wanted_type)) { if (!type_has_bits(ira->codegen, wanted_type)) {
assert(wanted_type->id == ZigTypeIdInt); assert(wanted_type->id == ZigTypeIdInt);
assert(type_has_bits(target->value->type)); assert(type_has_bits(ira->codegen, target->value->type));
ir_build_assert_zero(ira, source_instr, target); ir_build_assert_zero(ira, source_instr, target);
IrInstGen *result = ir_const_unsigned(ira, source_instr, 0); IrInstGen *result = ir_const_unsigned(ira, source_instr, 0);
result->value->type = wanted_type; result->value->type = wanted_type;
@ -15038,7 +15043,7 @@ static IrInstGen *ir_get_deref(IrAnalyze *ira, IrInst* source_instruction, IrIns
} }
IrInstGen *result_loc_inst; IrInstGen *result_loc_inst;
if (ptr_type->data.pointer.host_int_bytes != 0 && handle_is_ptr(child_type)) { if (ptr_type->data.pointer.host_int_bytes != 0 && handle_is_ptr(ira->codegen, child_type)) {
if (result_loc == nullptr) result_loc = no_result_loc(); if (result_loc == nullptr) result_loc = no_result_loc();
result_loc_inst = ir_resolve_result(ira, source_instruction, result_loc, child_type, nullptr, true, true); result_loc_inst = ir_resolve_result(ira, source_instruction, result_loc, child_type, nullptr, true, true);
if (type_is_invalid(result_loc_inst->value->type) || result_loc_inst->value->type->id == ZigTypeIdUnreachable) { if (type_is_invalid(result_loc_inst->value->type) || result_loc_inst->value->type->id == ZigTypeIdUnreachable) {
@ -15298,7 +15303,7 @@ static IrInstGen *ir_analyze_instruction_return(IrAnalyze *ira, IrInstSrcReturn
} }
if (!instr_is_comptime(operand) && ira->explicit_return_type != nullptr && if (!instr_is_comptime(operand) && ira->explicit_return_type != nullptr &&
handle_is_ptr(ira->explicit_return_type)) handle_is_ptr(ira->codegen, ira->explicit_return_type))
{ {
// result location mechanism took care of it. // result location mechanism took care of it.
IrInstGen *result = ir_build_return_gen(ira, &instruction->base.base, nullptr); IrInstGen *result = ir_build_return_gen(ira, &instruction->base.base, nullptr);
@ -15387,7 +15392,7 @@ static bool resolve_cmp_op_id(IrBinOp op_id, Cmp cmp) {
static bool optional_value_is_null(ZigValue *val) { static bool optional_value_is_null(ZigValue *val) {
assert(val->special == ConstValSpecialStatic); assert(val->special == ConstValSpecialStatic);
if (get_codegen_ptr_type(val->type) != nullptr) { if (get_src_ptr_type(val->type) != nullptr) {
if (val->data.x_ptr.special == ConstPtrSpecialNull) { if (val->data.x_ptr.special == ConstPtrSpecialNull) {
return true; return true;
} else if (val->data.x_ptr.special == ConstPtrSpecialHardCodedAddr) { } else if (val->data.x_ptr.special == ConstPtrSpecialHardCodedAddr) {
@ -15406,7 +15411,7 @@ static void set_optional_value_to_null(ZigValue *val) {
assert(val->special == ConstValSpecialStatic); assert(val->special == ConstValSpecialStatic);
if (val->type->id == ZigTypeIdNull) return; // nothing to do if (val->type->id == ZigTypeIdNull) return; // nothing to do
assert(val->type->id == ZigTypeIdOptional); assert(val->type->id == ZigTypeIdOptional);
if (get_codegen_ptr_type(val->type) != nullptr) { if (get_src_ptr_type(val->type) != nullptr) {
val->data.x_ptr.special = ConstPtrSpecialNull; val->data.x_ptr.special = ConstPtrSpecialNull;
} else if (is_opt_err_set(val->type)) { } else if (is_opt_err_set(val->type)) {
val->data.x_err_set = nullptr; val->data.x_err_set = nullptr;
@ -16244,7 +16249,7 @@ static IrInstGen *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstSrcBinOp *bin_op_i
operator_allowed = false; operator_allowed = false;
break; break;
case ZigTypeIdOptional: case ZigTypeIdOptional:
operator_allowed = is_equality_cmp && get_codegen_ptr_type(resolved_type) != nullptr; operator_allowed = is_equality_cmp && get_src_ptr_type(resolved_type) != nullptr;
break; break;
} }
if (!operator_allowed) { if (!operator_allowed) {
@ -17894,7 +17899,7 @@ static IrInstGen *ir_analyze_instruction_error_return_trace(IrAnalyze *ira,
if (!exec_has_err_ret_trace(ira->codegen, ira->old_irb.exec)) { if (!exec_has_err_ret_trace(ira->codegen, ira->old_irb.exec)) {
IrInstGen *result = ir_const(ira, &instruction->base.base, optional_type); IrInstGen *result = ir_const(ira, &instruction->base.base, optional_type);
ZigValue *out_val = result->value; ZigValue *out_val = result->value;
assert(get_codegen_ptr_type(optional_type) != nullptr); assert(get_src_ptr_type(optional_type) != nullptr);
out_val->data.x_ptr.special = ConstPtrSpecialHardCodedAddr; out_val->data.x_ptr.special = ConstPtrSpecialHardCodedAddr;
out_val->data.x_ptr.data.hard_coded_addr.addr = 0; out_val->data.x_ptr.data.hard_coded_addr.addr = 0;
return result; return result;
@ -18283,7 +18288,7 @@ static IrInstGen *ir_resolve_result_raw(IrAnalyze *ira, IrInst *suspend_source_i
if ((err = type_resolve(ira->codegen, value_type, ResolveStatusAlignmentKnown))) { if ((err = type_resolve(ira->codegen, value_type, ResolveStatusAlignmentKnown))) {
return ira->codegen->invalid_inst_gen; return ira->codegen->invalid_inst_gen;
} }
if (!type_has_bits(value_type)) { if (!type_has_bits(ira->codegen, value_type)) {
parent_ptr_align = 0; parent_ptr_align = 0;
} }
// If we're casting from a sentinel-terminated array to a non-sentinel-terminated array, // If we're casting from a sentinel-terminated array to a non-sentinel-terminated array,
@ -18328,7 +18333,10 @@ static IrInstGen *ir_resolve_result_raw(IrAnalyze *ira, IrInst *suspend_source_i
if (type_is_invalid(dest_type)) if (type_is_invalid(dest_type))
return ira->codegen->invalid_inst_gen; return ira->codegen->invalid_inst_gen;
if (get_codegen_ptr_type(dest_type) != nullptr) { ZigType *dest_cg_ptr_type;
if ((err = get_codegen_ptr_type(ira->codegen, dest_type, &dest_cg_ptr_type)))
return ira->codegen->invalid_inst_gen;
if (dest_cg_ptr_type != nullptr) {
ir_add_error(ira, &result_loc->source_instruction->base, ir_add_error(ira, &result_loc->source_instruction->base,
buf_sprintf("unable to @bitCast to pointer type '%s'", buf_ptr(&dest_type->name))); buf_sprintf("unable to @bitCast to pointer type '%s'", buf_ptr(&dest_type->name)));
return ira->codegen->invalid_inst_gen; return ira->codegen->invalid_inst_gen;
@ -18340,7 +18348,10 @@ static IrInstGen *ir_resolve_result_raw(IrAnalyze *ira, IrInst *suspend_source_i
return ira->codegen->invalid_inst_gen; return ira->codegen->invalid_inst_gen;
} }
if (get_codegen_ptr_type(value_type) != nullptr) { ZigType *value_cg_ptr_type;
if ((err = get_codegen_ptr_type(ira->codegen, value_type, &value_cg_ptr_type)))
return ira->codegen->invalid_inst_gen;
if (value_cg_ptr_type != nullptr) {
ir_add_error(ira, suspend_source_instr, ir_add_error(ira, suspend_source_instr,
buf_sprintf("unable to @bitCast from pointer type '%s'", buf_ptr(&value_type->name))); buf_sprintf("unable to @bitCast from pointer type '%s'", buf_ptr(&value_type->name)));
return ira->codegen->invalid_inst_gen; return ira->codegen->invalid_inst_gen;
@ -18400,7 +18411,7 @@ static IrInstGen *ir_resolve_result_raw(IrAnalyze *ira, IrInst *suspend_source_i
} }
} }
uint64_t parent_ptr_align = 0; uint64_t parent_ptr_align = 0;
if (type_has_bits(value_type)) parent_ptr_align = get_ptr_align(ira->codegen, parent_ptr_type); if (type_has_bits(ira->codegen, value_type)) parent_ptr_align = get_ptr_align(ira->codegen, parent_ptr_type);
ZigType *ptr_type = get_pointer_to_type_extra(ira->codegen, value_type, ZigType *ptr_type = get_pointer_to_type_extra(ira->codegen, value_type,
parent_ptr_type->data.pointer.is_const, parent_ptr_type->data.pointer.is_volatile, PtrLenSingle, parent_ptr_type->data.pointer.is_const, parent_ptr_type->data.pointer.is_volatile, PtrLenSingle,
parent_ptr_align, 0, 0, parent_ptr_type->data.pointer.allow_zero); parent_ptr_align, 0, 0, parent_ptr_type->data.pointer.allow_zero);
@ -19118,7 +19129,7 @@ static IrInstGen *ir_analyze_fn_call(IrAnalyze *ira, IrInst* source_instr,
} }
IrInstGen *first_arg; IrInstGen *first_arg;
if (!first_arg_known_bare && handle_is_ptr(first_arg_ptr->value->type->data.pointer.child_type)) { if (!first_arg_known_bare && handle_is_ptr(ira->codegen, first_arg_ptr->value->type->data.pointer.child_type)) {
first_arg = first_arg_ptr; first_arg = first_arg_ptr;
} else { } else {
first_arg = ir_get_deref(ira, &first_arg_ptr->base, first_arg_ptr, nullptr); first_arg = ir_get_deref(ira, &first_arg_ptr->base, first_arg_ptr, nullptr);
@ -19247,7 +19258,7 @@ static IrInstGen *ir_analyze_fn_call(IrAnalyze *ira, IrInst* source_instr,
} }
IrInstGen *first_arg; IrInstGen *first_arg;
if (!first_arg_known_bare && handle_is_ptr(first_arg_ptr->value->type->data.pointer.child_type)) { if (!first_arg_known_bare && handle_is_ptr(ira->codegen, first_arg_ptr->value->type->data.pointer.child_type)) {
first_arg = first_arg_ptr; first_arg = first_arg_ptr;
} else { } else {
first_arg = ir_get_deref(ira, &first_arg_ptr->base, first_arg_ptr, nullptr); first_arg = ir_get_deref(ira, &first_arg_ptr->base, first_arg_ptr, nullptr);
@ -19366,7 +19377,7 @@ static IrInstGen *ir_analyze_fn_call(IrAnalyze *ira, IrInst* source_instr,
} }
IrInstGen *result_loc; IrInstGen *result_loc;
if (handle_is_ptr(impl_fn_type_id->return_type)) { if (handle_is_ptr(ira->codegen, impl_fn_type_id->return_type)) {
result_loc = ir_resolve_result(ira, source_instr, call_result_loc, result_loc = ir_resolve_result(ira, source_instr, call_result_loc,
impl_fn_type_id->return_type, nullptr, true, false); impl_fn_type_id->return_type, nullptr, true, false);
if (result_loc != nullptr) { if (result_loc != nullptr) {
@ -19383,7 +19394,7 @@ static IrInstGen *ir_analyze_fn_call(IrAnalyze *ira, IrInst* source_instr,
if (res_child_type == ira->codegen->builtin_types.entry_var) { if (res_child_type == ira->codegen->builtin_types.entry_var) {
res_child_type = impl_fn_type_id->return_type; res_child_type = impl_fn_type_id->return_type;
} }
if (!handle_is_ptr(res_child_type)) { if (!handle_is_ptr(ira->codegen, res_child_type)) {
ir_reset_result(call_result_loc); ir_reset_result(call_result_loc);
result_loc = nullptr; result_loc = nullptr;
} }
@ -19435,7 +19446,7 @@ static IrInstGen *ir_analyze_fn_call(IrAnalyze *ira, IrInst* source_instr,
IrInstGen *first_arg; IrInstGen *first_arg;
if (param_type->id == ZigTypeIdPointer && if (param_type->id == ZigTypeIdPointer &&
handle_is_ptr(first_arg_ptr->value->type->data.pointer.child_type)) handle_is_ptr(ira->codegen, first_arg_ptr->value->type->data.pointer.child_type))
{ {
first_arg = first_arg_ptr; first_arg = first_arg_ptr;
} else { } else {
@ -19504,7 +19515,7 @@ static IrInstGen *ir_analyze_fn_call(IrAnalyze *ira, IrInst* source_instr,
} }
IrInstGen *result_loc; IrInstGen *result_loc;
if (handle_is_ptr(return_type)) { if (handle_is_ptr(ira->codegen, return_type)) {
result_loc = ir_resolve_result(ira, source_instr, call_result_loc, result_loc = ir_resolve_result(ira, source_instr, call_result_loc,
return_type, nullptr, true, false); return_type, nullptr, true, false);
if (result_loc != nullptr) { if (result_loc != nullptr) {
@ -19521,7 +19532,7 @@ static IrInstGen *ir_analyze_fn_call(IrAnalyze *ira, IrInst* source_instr,
if (res_child_type == ira->codegen->builtin_types.entry_var) { if (res_child_type == ira->codegen->builtin_types.entry_var) {
res_child_type = return_type; res_child_type = return_type;
} }
if (!handle_is_ptr(res_child_type)) { if (!handle_is_ptr(ira->codegen, res_child_type)) {
ir_reset_result(call_result_loc); ir_reset_result(call_result_loc);
result_loc = nullptr; result_loc = nullptr;
} }
@ -23346,7 +23357,7 @@ static TypeStructField *validate_byte_offset(IrAnalyze *ira,
return nullptr; return nullptr;
} }
if (!type_has_bits(field->type_entry)) { if (!type_has_bits(ira->codegen, field->type_entry)) {
ir_add_error(ira, &field_name_value->base, ir_add_error(ira, &field_name_value->base,
buf_sprintf("zero-bit field '%s' in struct '%s' has no offset", buf_sprintf("zero-bit field '%s' in struct '%s' has no offset",
buf_ptr(field_name), buf_ptr(&container_type->name))); buf_ptr(field_name), buf_ptr(&container_type->name)));
@ -24264,7 +24275,7 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInst* source_instr, ZigTy
return ErrorSemanticAnalyzeFail; return ErrorSemanticAnalyzeFail;
if ((err = type_resolve(ira->codegen, field_type, ResolveStatusZeroBitsKnown))) if ((err = type_resolve(ira->codegen, field_type, ResolveStatusZeroBitsKnown)))
return err; return err;
if (!type_has_bits(struct_field->type_entry)) { if (!type_has_bits(ira->codegen, struct_field->type_entry)) {
inner_fields[1]->data.x_optional = nullptr; inner_fields[1]->data.x_optional = nullptr;
} else { } else {
size_t byte_offset = struct_field->offset; size_t byte_offset = struct_field->offset;
@ -25077,7 +25088,7 @@ static IrInstGen *ir_analyze_instruction_cmpxchg(IrAnalyze *ira, IrInstSrcCmpxch
ZigType *result_type = get_optional_type(ira->codegen, operand_type); ZigType *result_type = get_optional_type(ira->codegen, operand_type);
IrInstGen *result_loc; IrInstGen *result_loc;
if (handle_is_ptr(result_type)) { if (handle_is_ptr(ira->codegen, result_type)) {
result_loc = ir_resolve_result(ira, &instruction->base.base, instruction->result_loc, result_loc = ir_resolve_result(ira, &instruction->base.base, instruction->result_loc,
result_type, nullptr, true, true); result_type, nullptr, true, true);
if (type_is_invalid(result_loc->value->type) || result_loc->value->type->id == ZigTypeIdUnreachable) { if (type_is_invalid(result_loc->value->type) || result_loc->value->type->id == ZigTypeIdUnreachable) {
@ -25396,8 +25407,11 @@ static IrInstGen *ir_analyze_instruction_vector_type(IrAnalyze *ira, IrInstSrcVe
static IrInstGen *ir_analyze_shuffle_vector(IrAnalyze *ira, IrInst* source_instr, static IrInstGen *ir_analyze_shuffle_vector(IrAnalyze *ira, IrInst* source_instr,
ZigType *scalar_type, IrInstGen *a, IrInstGen *b, IrInstGen *mask) ZigType *scalar_type, IrInstGen *a, IrInstGen *b, IrInstGen *mask)
{ {
Error err;
ir_assert(source_instr && scalar_type && a && b && mask, source_instr); ir_assert(source_instr && scalar_type && a && b && mask, source_instr);
ir_assert(is_valid_vector_elem_type(scalar_type), source_instr);
if ((err = ir_validate_vector_elem_type(ira, source_instr->source_node, scalar_type)))
return ira->codegen->invalid_inst_gen;
uint32_t len_mask; uint32_t len_mask;
if (mask->value->type->id == ZigTypeIdVector) { if (mask->value->type->id == ZigTypeIdVector) {
@ -27364,7 +27378,7 @@ static IrInstGen *ir_analyze_ptr_cast(IrAnalyze *ira, IrInst* source_instr, IrIn
if ((err = type_resolve(ira->codegen, src_type, ResolveStatusZeroBitsKnown))) if ((err = type_resolve(ira->codegen, src_type, ResolveStatusZeroBitsKnown)))
return ira->codegen->invalid_inst_gen; return ira->codegen->invalid_inst_gen;
if (type_has_bits(dest_type) && !type_has_bits(src_type) && safety_check_on) { if (type_has_bits(ira->codegen, dest_type) && !type_has_bits(ira->codegen, src_type) && safety_check_on) {
ErrorMsg *msg = ir_add_error(ira, source_instr, ErrorMsg *msg = ir_add_error(ira, source_instr,
buf_sprintf("'%s' and '%s' do not have the same in-memory representation", buf_sprintf("'%s' and '%s' do not have the same in-memory representation",
buf_ptr(&src_type->name), buf_ptr(&dest_type->name))); buf_ptr(&src_type->name), buf_ptr(&dest_type->name)));
@ -27423,7 +27437,7 @@ static IrInstGen *ir_analyze_ptr_cast(IrAnalyze *ira, IrInst* source_instr, IrIn
// Keep the bigger alignment, it can only help- // Keep the bigger alignment, it can only help-
// unless the target is zero bits. // unless the target is zero bits.
if (src_align_bytes > dest_align_bytes && type_has_bits(dest_type)) { if (src_align_bytes > dest_align_bytes && type_has_bits(ira->codegen, dest_type)) {
result = ir_align_cast(ira, result, src_align_bytes, false); result = ir_align_cast(ira, result, src_align_bytes, false);
} }
@ -27444,7 +27458,7 @@ static IrInstGen *ir_analyze_ptr_cast(IrAnalyze *ira, IrInst* source_instr, IrIn
// Keep the bigger alignment, it can only help- // Keep the bigger alignment, it can only help-
// unless the target is zero bits. // unless the target is zero bits.
IrInstGen *result; IrInstGen *result;
if (src_align_bytes > dest_align_bytes && type_has_bits(dest_type)) { if (src_align_bytes > dest_align_bytes && type_has_bits(ira->codegen, dest_type)) {
result = ir_align_cast(ira, casted_ptr, src_align_bytes, false); result = ir_align_cast(ira, casted_ptr, src_align_bytes, false);
if (type_is_invalid(result->value->type)) if (type_is_invalid(result->value->type))
return ira->codegen->invalid_inst_gen; return ira->codegen->invalid_inst_gen;
@ -27802,9 +27816,7 @@ static IrInstGen *ir_analyze_bit_cast(IrAnalyze *ira, IrInst* source_instr, IrIn
Error err; Error err;
ZigType *src_type = value->value->type; ZigType *src_type = value->value->type;
ir_assert(get_codegen_ptr_type(src_type) == nullptr, source_instr);
ir_assert(type_can_bit_cast(src_type), source_instr); ir_assert(type_can_bit_cast(src_type), source_instr);
ir_assert(get_codegen_ptr_type(dest_type) == nullptr, source_instr);
ir_assert(type_can_bit_cast(dest_type), source_instr); ir_assert(type_can_bit_cast(dest_type), source_instr);
if (dest_type->id == ZigTypeIdEnum) { if (dest_type->id == ZigTypeIdEnum) {
@ -27863,7 +27875,7 @@ static IrInstGen *ir_analyze_int_to_ptr(IrAnalyze *ira, IrInst* source_instr, Ir
Error err; Error err;
ir_assert(get_src_ptr_type(ptr_type) != nullptr, source_instr); ir_assert(get_src_ptr_type(ptr_type) != nullptr, source_instr);
ir_assert(type_has_bits(ptr_type), source_instr); ir_assert(type_has_bits(ira->codegen, ptr_type), source_instr);
IrInstGen *casted_int = ir_implicit_cast(ira, target, ira->codegen->builtin_types.entry_usize); IrInstGen *casted_int = ir_implicit_cast(ira, target, ira->codegen->builtin_types.entry_usize);
if (type_is_invalid(casted_int->value->type)) if (type_is_invalid(casted_int->value->type))
@ -27981,7 +27993,7 @@ static IrInstGen *ir_analyze_instruction_ptr_to_int(IrAnalyze *ira, IrInstSrcPtr
if (!val) if (!val)
return ira->codegen->invalid_inst_gen; return ira->codegen->invalid_inst_gen;
// Since we've already run this type trough get_codegen_ptr_type it is // Since we've already run this type trough get_src_ptr_type it is
// safe to access the x_ptr fields // safe to access the x_ptr fields
if (val->data.x_ptr.special == ConstPtrSpecialHardCodedAddr) { if (val->data.x_ptr.special == ConstPtrSpecialHardCodedAddr) {
IrInstGen *result = ir_const(ira, &instruction->base.base, usize); IrInstGen *result = ir_const(ira, &instruction->base.base, usize);
@ -28232,10 +28244,17 @@ static ZigType *ir_resolve_atomic_operand_type(IrAnalyze *ira, IrInstGen *op) {
max_atomic_bits, (uint32_t) operand_type->data.floating.bit_count)); max_atomic_bits, (uint32_t) operand_type->data.floating.bit_count));
return ira->codegen->builtin_types.entry_invalid; return ira->codegen->builtin_types.entry_invalid;
} }
} else if (get_codegen_ptr_type(operand_type) == nullptr) { } else {
ir_add_error(ira, &op->base, Error err;
buf_sprintf("expected integer, float, enum or pointer type, found '%s'", buf_ptr(&operand_type->name))); ZigType *operand_ptr_type;
return ira->codegen->builtin_types.entry_invalid; if ((err = get_codegen_ptr_type(ira->codegen, operand_type, &operand_ptr_type)))
return ira->codegen->builtin_types.entry_invalid;
if (operand_ptr_type == nullptr) {
ir_add_error(ira, &op->base,
buf_sprintf("expected integer, float, enum or pointer type, found '%s'",
buf_ptr(&operand_type->name)));
return ira->codegen->builtin_types.entry_invalid;
}
} }
return operand_type; return operand_type;
@ -28666,15 +28685,19 @@ static IrInstGen *ir_analyze_instruction_bswap(IrAnalyze *ira, IrInstSrcBswap *i
if (type_is_invalid(uncasted_op->value->type)) if (type_is_invalid(uncasted_op->value->type))
return ira->codegen->invalid_inst_gen; return ira->codegen->invalid_inst_gen;
uint32_t vector_len; // UINT32_MAX means not a vector uint32_t vector_len = UINT32_MAX; // means not a vector
if (uncasted_op->value->type->id == ZigTypeIdArray && if (uncasted_op->value->type->id == ZigTypeIdArray) {
is_valid_vector_elem_type(uncasted_op->value->type->data.array.child_type)) bool can_be_vec_elem;
{ if ((err = is_valid_vector_elem_type(ira->codegen, uncasted_op->value->type->data.array.child_type,
vector_len = uncasted_op->value->type->data.array.len; &can_be_vec_elem)))
{
return ira->codegen->invalid_inst_gen;
}
if (can_be_vec_elem) {
vector_len = uncasted_op->value->type->data.array.len;
}
} else if (uncasted_op->value->type->id == ZigTypeIdVector) { } else if (uncasted_op->value->type->id == ZigTypeIdVector) {
vector_len = uncasted_op->value->type->data.vector.len; vector_len = uncasted_op->value->type->data.vector.len;
} else {
vector_len = UINT32_MAX;
} }
bool is_vector = (vector_len != UINT32_MAX); bool is_vector = (vector_len != UINT32_MAX);
@ -29075,7 +29098,7 @@ static IrInstGen *ir_analyze_instruction_await(IrAnalyze *ira, IrInstSrcAwait *i
} }
IrInstGen *result_loc; IrInstGen *result_loc;
if (type_has_bits(result_type)) { if (type_has_bits(ira->codegen, result_type)) {
result_loc = ir_resolve_result(ira, &instruction->base.base, instruction->result_loc, result_loc = ir_resolve_result(ira, &instruction->base.base, instruction->result_loc,
result_type, nullptr, true, true); result_type, nullptr, true, true);
if (result_loc != nullptr && if (result_loc != nullptr &&
@ -29125,7 +29148,7 @@ static IrInstGen *ir_analyze_instruction_spill_begin(IrAnalyze *ira, IrInstSrcSp
if (type_is_invalid(operand->value->type)) if (type_is_invalid(operand->value->type))
return ira->codegen->invalid_inst_gen; return ira->codegen->invalid_inst_gen;
if (!type_has_bits(operand->value->type)) if (!type_has_bits(ira->codegen, operand->value->type))
return ir_const_void(ira, &instruction->base.base); return ir_const_void(ira, &instruction->base.base);
switch (instruction->spill_id) { switch (instruction->spill_id) {
@ -29145,7 +29168,7 @@ static IrInstGen *ir_analyze_instruction_spill_end(IrAnalyze *ira, IrInstSrcSpil
return ira->codegen->invalid_inst_gen; return ira->codegen->invalid_inst_gen;
if (ir_should_inline(ira->old_irb.exec, instruction->base.base.scope) || if (ir_should_inline(ira->old_irb.exec, instruction->base.base.scope) ||
!type_has_bits(operand->value->type) || !type_has_bits(ira->codegen, operand->value->type) ||
instr_is_comptime(operand)) instr_is_comptime(operand))
{ {
return operand; return operand;
@ -30188,7 +30211,7 @@ static Error ir_resolve_lazy_raw(AstNode *source_node, ZigValue *val) {
if (align_bytes != 0) { if (align_bytes != 0) {
if ((err = type_resolve(ira->codegen, elem_type, ResolveStatusAlignmentKnown))) if ((err = type_resolve(ira->codegen, elem_type, ResolveStatusAlignmentKnown)))
return err; return err;
if (!type_has_bits(elem_type)) if (!type_has_bits(ira->codegen, elem_type))
align_bytes = 0; align_bytes = 0;
} }
bool allow_zero = lazy_ptr_type->is_allowzero || lazy_ptr_type->ptr_len == PtrLenC; bool allow_zero = lazy_ptr_type->is_allowzero || lazy_ptr_type->ptr_len == PtrLenC;

View File

@ -786,3 +786,10 @@ test "cast between C pointer with different but compatible types" {
}; };
S.doTheTest(); S.doTheTest();
} }
var global_struct: struct { f0: usize } = undefined;
test "assignment to optional pointer result loc" {
var foo: struct { ptr: ?*c_void } = .{ .ptr = &global_struct };
expect(foo.ptr.? == @ptrCast(*c_void, &global_struct));
}