fix alignment of structs

closes #1248
closes #1052
closes #1154
This commit is contained in:
Andrew Kelley 2018-09-14 18:56:30 -04:00
parent 639c381128
commit 3f776af3fa
No known key found for this signature in database
GPG Key ID: 4E7CD66038A4D47C
8 changed files with 556 additions and 356 deletions

View File

@ -1012,13 +1012,13 @@ enum PtrLen {
struct ZigTypePointer {
ZigType *child_type;
ZigType *slice_parent;
PtrLen ptr_len;
bool is_const;
bool is_volatile;
uint32_t alignment;
uint32_t explicit_alignment; // 0 means use ABI alignment
uint32_t bit_offset;
uint32_t unaligned_bit_count;
ZigType *slice_parent;
bool is_const;
bool is_volatile;
};
struct ZigTypeInt {
@ -1046,32 +1046,35 @@ struct TypeStructField {
size_t unaligned_bit_count;
AstNode *decl_node;
};
enum ResolveStatus {
ResolveStatusUnstarted,
ResolveStatusInvalid,
ResolveStatusZeroBitsKnown,
ResolveStatusAlignmentKnown,
ResolveStatusSizeKnown,
};
struct ZigTypeStruct {
AstNode *decl_node;
ContainerLayout layout;
TypeStructField *fields;
ScopeDecls *decls_scope;
uint64_t size_bytes;
HashMap<Buf *, TypeStructField *, buf_hash, buf_eql_buf> fields_by_name;
uint32_t src_field_count;
uint32_t gen_field_count;
TypeStructField *fields;
uint64_t size_bytes;
bool is_invalid; // true if any fields are invalid
uint32_t abi_alignment; // known after ResolveStatusAlignmentKnown
ContainerLayout layout;
ResolveStatus resolve_status;
bool is_slice;
ScopeDecls *decls_scope;
// set this flag temporarily to detect infinite loops
bool embedded_in_current;
bool resolve_loop_flag; // set this flag temporarily to detect infinite loops
bool reported_infinite_err;
// whether we've finished resolving it
bool complete;
// whether any of the fields require comptime
// the value is not valid until zero_bits_known == true
// known after ResolveStatusZeroBitsKnown
bool requires_comptime;
bool zero_bits_loop_flag;
bool zero_bits_known;
uint32_t abi_alignment; // also figured out with zero_bits pass
HashMap<Buf *, TypeStructField *, buf_hash, buf_eql_buf> fields_by_name;
};
struct ZigTypeOptional {

View File

@ -23,6 +23,7 @@ static Error resolve_enum_type(CodeGen *g, ZigType *enum_type);
static Error resolve_struct_type(CodeGen *g, ZigType *struct_type);
static Error ATTRIBUTE_MUST_USE resolve_struct_zero_bits(CodeGen *g, ZigType *struct_type);
static Error ATTRIBUTE_MUST_USE resolve_struct_alignment(CodeGen *g, ZigType *struct_type);
static Error ATTRIBUTE_MUST_USE resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type);
static Error ATTRIBUTE_MUST_USE resolve_union_zero_bits(CodeGen *g, ZigType *union_type);
static void analyze_fn_body(CodeGen *g, ZigFn *fn_table_entry);
@ -254,80 +255,71 @@ AstNode *type_decl_node(ZigType *type_entry) {
zig_unreachable();
}
bool type_is_resolved(ZigType *type_entry, ResolveStatus status) {
switch (type_entry->id) {
case ZigTypeIdInvalid:
zig_unreachable();
case ZigTypeIdStruct:
return type_entry->data.structure.resolve_status >= status;
case ZigTypeIdEnum:
switch (status) {
case ResolveStatusUnstarted:
return true;
case ResolveStatusInvalid:
zig_unreachable();
case ResolveStatusZeroBitsKnown:
return type_entry->data.enumeration.zero_bits_known;
case ResolveStatusAlignmentKnown:
return type_entry->data.enumeration.zero_bits_known;
case ResolveStatusSizeKnown:
return type_entry->data.enumeration.complete;
}
zig_unreachable();
case ZigTypeIdUnion:
switch (status) {
case ResolveStatusUnstarted:
return true;
case ResolveStatusInvalid:
zig_unreachable();
case ResolveStatusZeroBitsKnown:
return type_entry->data.unionation.zero_bits_known;
case ResolveStatusAlignmentKnown:
return type_entry->data.unionation.zero_bits_known;
case ResolveStatusSizeKnown:
return type_entry->data.unionation.complete;
}
zig_unreachable();
case ZigTypeIdOpaque:
return status < ResolveStatusSizeKnown;
case ZigTypeIdMetaType:
case ZigTypeIdVoid:
case ZigTypeIdBool:
case ZigTypeIdUnreachable:
case ZigTypeIdInt:
case ZigTypeIdFloat:
case ZigTypeIdPointer:
case ZigTypeIdArray:
case ZigTypeIdComptimeFloat:
case ZigTypeIdComptimeInt:
case ZigTypeIdUndefined:
case ZigTypeIdNull:
case ZigTypeIdOptional:
case ZigTypeIdErrorUnion:
case ZigTypeIdErrorSet:
case ZigTypeIdFn:
case ZigTypeIdNamespace:
case ZigTypeIdBoundFn:
case ZigTypeIdArgTuple:
case ZigTypeIdPromise:
return true;
}
zig_unreachable();
}
bool type_is_complete(ZigType *type_entry) {
switch (type_entry->id) {
case ZigTypeIdInvalid:
zig_unreachable();
case ZigTypeIdStruct:
return type_entry->data.structure.complete;
case ZigTypeIdEnum:
return type_entry->data.enumeration.complete;
case ZigTypeIdUnion:
return type_entry->data.unionation.complete;
case ZigTypeIdOpaque:
return false;
case ZigTypeIdMetaType:
case ZigTypeIdVoid:
case ZigTypeIdBool:
case ZigTypeIdUnreachable:
case ZigTypeIdInt:
case ZigTypeIdFloat:
case ZigTypeIdPointer:
case ZigTypeIdArray:
case ZigTypeIdComptimeFloat:
case ZigTypeIdComptimeInt:
case ZigTypeIdUndefined:
case ZigTypeIdNull:
case ZigTypeIdOptional:
case ZigTypeIdErrorUnion:
case ZigTypeIdErrorSet:
case ZigTypeIdFn:
case ZigTypeIdNamespace:
case ZigTypeIdBoundFn:
case ZigTypeIdArgTuple:
case ZigTypeIdPromise:
return true;
}
zig_unreachable();
return type_is_resolved(type_entry, ResolveStatusSizeKnown);
}
bool type_has_zero_bits_known(ZigType *type_entry) {
switch (type_entry->id) {
case ZigTypeIdInvalid:
zig_unreachable();
case ZigTypeIdStruct:
return type_entry->data.structure.zero_bits_known;
case ZigTypeIdEnum:
return type_entry->data.enumeration.zero_bits_known;
case ZigTypeIdUnion:
return type_entry->data.unionation.zero_bits_known;
case ZigTypeIdMetaType:
case ZigTypeIdVoid:
case ZigTypeIdBool:
case ZigTypeIdUnreachable:
case ZigTypeIdInt:
case ZigTypeIdFloat:
case ZigTypeIdPointer:
case ZigTypeIdArray:
case ZigTypeIdComptimeFloat:
case ZigTypeIdComptimeInt:
case ZigTypeIdUndefined:
case ZigTypeIdNull:
case ZigTypeIdOptional:
case ZigTypeIdErrorUnion:
case ZigTypeIdErrorSet:
case ZigTypeIdFn:
case ZigTypeIdNamespace:
case ZigTypeIdBoundFn:
case ZigTypeIdArgTuple:
case ZigTypeIdOpaque:
case ZigTypeIdPromise:
return true;
}
zig_unreachable();
}
uint64_t type_size(CodeGen *g, ZigType *type_entry) {
assert(type_is_complete(type_entry));
@ -376,7 +368,7 @@ uint64_t type_size_bits(CodeGen *g, ZigType *type_entry) {
Result<bool> type_is_copyable(CodeGen *g, ZigType *type_entry) {
Error err;
if ((err = type_ensure_zero_bits_known(g, type_entry)))
if ((err = type_resolve(g, type_entry, ResolveStatusZeroBitsKnown)))
return err;
if (!type_has_bits(type_entry))
@ -431,10 +423,15 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons
assert(!type_is_invalid(child_type));
assert(ptr_len == PtrLenSingle || child_type->id != ZigTypeIdOpaque);
if (byte_alignment != 0) {
uint32_t abi_alignment = get_abi_alignment(g, child_type);
if (byte_alignment == abi_alignment)
byte_alignment = 0;
}
TypeId type_id = {};
ZigType **parent_pointer = nullptr;
uint32_t abi_alignment = get_abi_alignment(g, child_type);
if (unaligned_bit_count != 0 || is_volatile || byte_alignment != abi_alignment || ptr_len != PtrLenSingle) {
if (unaligned_bit_count != 0 || is_volatile || byte_alignment != 0 || ptr_len != PtrLenSingle) {
type_id.id = ZigTypeIdPointer;
type_id.data.pointer.child_type = child_type;
type_id.data.pointer.is_const = is_const;
@ -451,12 +448,12 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons
assert(bit_offset == 0);
parent_pointer = &child_type->pointer_parent[(is_const ? 1 : 0)];
if (*parent_pointer) {
assert((*parent_pointer)->data.pointer.alignment == byte_alignment);
assert((*parent_pointer)->data.pointer.explicit_alignment == 0);
return *parent_pointer;
}
}
assertNoError(type_ensure_zero_bits_known(g, child_type));
assert(type_is_resolved(child_type, ResolveStatusZeroBitsKnown));
ZigType *entry = new_type_table_entry(ZigTypeIdPointer);
entry->is_copyable = true;
@ -465,11 +462,14 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons
const char *const_str = is_const ? "const " : "";
const char *volatile_str = is_volatile ? "volatile " : "";
buf_resize(&entry->name, 0);
if (unaligned_bit_count == 0 && byte_alignment == abi_alignment) {
if (unaligned_bit_count == 0 && byte_alignment == 0) {
buf_appendf(&entry->name, "%s%s%s%s", star_str, const_str, volatile_str, buf_ptr(&child_type->name));
} else if (unaligned_bit_count == 0) {
buf_appendf(&entry->name, "%salign(%" PRIu32 ") %s%s%s", star_str, byte_alignment,
const_str, volatile_str, buf_ptr(&child_type->name));
} else if (byte_alignment == 0) {
buf_appendf(&entry->name, "%salign(:%" PRIu32 ":%" PRIu32 ") %s%s%s", star_str,
bit_offset, bit_offset + unaligned_bit_count, const_str, volatile_str, buf_ptr(&child_type->name));
} else {
buf_appendf(&entry->name, "%salign(%" PRIu32 ":%" PRIu32 ":%" PRIu32 ") %s%s%s", star_str, byte_alignment,
bit_offset, bit_offset + unaligned_bit_count, const_str, volatile_str, buf_ptr(&child_type->name));
@ -480,8 +480,7 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons
entry->zero_bits = !type_has_bits(child_type);
if (!entry->zero_bits) {
assert(byte_alignment > 0);
if (is_const || is_volatile || unaligned_bit_count != 0 || byte_alignment != abi_alignment ||
if (is_const || is_volatile || unaligned_bit_count != 0 || byte_alignment != 0 ||
ptr_len != PtrLenSingle)
{
ZigType *peer_type = get_pointer_to_type(g, child_type, false);
@ -505,7 +504,7 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons
entry->data.pointer.child_type = child_type;
entry->data.pointer.is_const = is_const;
entry->data.pointer.is_volatile = is_volatile;
entry->data.pointer.alignment = byte_alignment;
entry->data.pointer.explicit_alignment = byte_alignment;
entry->data.pointer.bit_offset = bit_offset;
entry->data.pointer.unaligned_bit_count = unaligned_bit_count;
@ -518,8 +517,7 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons
}
ZigType *get_pointer_to_type(CodeGen *g, ZigType *child_type, bool is_const) {
return get_pointer_to_type_extra(g, child_type, is_const, false, PtrLenSingle,
get_abi_alignment(g, child_type), 0, 0);
return get_pointer_to_type_extra(g, child_type, is_const, false, PtrLenSingle, 0, 0, 0);
}
ZigType *get_promise_frame_type(CodeGen *g, ZigType *return_type) {
@ -800,8 +798,7 @@ static void slice_type_common_init(CodeGen *g, ZigType *pointer_type, ZigType *e
entry->data.structure.fields_by_name.put(ptr_field_name, &entry->data.structure.fields[slice_ptr_index]);
entry->data.structure.fields_by_name.put(len_field_name, &entry->data.structure.fields[slice_len_index]);
assert(type_has_zero_bits_known(pointer_type->data.pointer.child_type));
if (pointer_type->data.pointer.child_type->zero_bits) {
if (!type_has_bits(pointer_type->data.pointer.child_type)) {
entry->data.structure.gen_field_count = 1;
entry->data.structure.fields[slice_ptr_index].gen_index = SIZE_MAX;
entry->data.structure.fields[slice_len_index].gen_index = 0;
@ -826,20 +823,18 @@ ZigType *get_slice_type(CodeGen *g, ZigType *ptr_type) {
buf_appendf(&entry->name, "[]%s", buf_ptr(&ptr_type->name) + name_offset);
ZigType *child_type = ptr_type->data.pointer.child_type;
uint32_t abi_alignment = get_abi_alignment(g, child_type);
if (ptr_type->data.pointer.is_const || ptr_type->data.pointer.is_volatile ||
ptr_type->data.pointer.alignment != abi_alignment)
ptr_type->data.pointer.explicit_alignment != 0)
{
ZigType *peer_ptr_type = get_pointer_to_type_extra(g, child_type, false, false,
PtrLenUnknown, abi_alignment, 0, 0);
PtrLenUnknown, 0, 0, 0);
ZigType *peer_slice_type = get_slice_type(g, peer_ptr_type);
slice_type_common_init(g, ptr_type, entry);
entry->type_ref = peer_slice_type->type_ref;
entry->di_type = peer_slice_type->di_type;
entry->data.structure.complete = true;
entry->data.structure.zero_bits_known = true;
entry->data.structure.resolve_status = ResolveStatusSizeKnown;
entry->data.structure.abi_alignment = peer_slice_type->data.structure.abi_alignment;
*parent_pointer = entry;
@ -851,15 +846,15 @@ ZigType *get_slice_type(CodeGen *g, ZigType *ptr_type) {
if (is_slice(child_type)) {
ZigType *child_ptr_type = child_type->data.structure.fields[slice_ptr_index].type_entry;
assert(child_ptr_type->id == ZigTypeIdPointer);
ZigType *grand_child_type = child_ptr_type->data.pointer.child_type;
if (child_ptr_type->data.pointer.is_const || child_ptr_type->data.pointer.is_volatile ||
child_ptr_type->data.pointer.alignment != get_abi_alignment(g, grand_child_type))
child_ptr_type->data.pointer.explicit_alignment != 0)
{
ZigType *grand_child_type = child_ptr_type->data.pointer.child_type;
ZigType *bland_child_ptr_type = get_pointer_to_type_extra(g, grand_child_type, false, false,
PtrLenUnknown, get_abi_alignment(g, grand_child_type), 0, 0);
PtrLenUnknown, 0, 0, 0);
ZigType *bland_child_slice = get_slice_type(g, bland_child_ptr_type);
ZigType *peer_ptr_type = get_pointer_to_type_extra(g, bland_child_slice, false, false,
PtrLenUnknown, get_abi_alignment(g, bland_child_slice), 0, 0);
PtrLenUnknown, 0, 0, 0);
ZigType *peer_slice_type = get_slice_type(g, peer_ptr_type);
entry->type_ref = peer_slice_type->type_ref;
@ -961,8 +956,7 @@ ZigType *get_slice_type(CodeGen *g, ZigType *ptr_type) {
}
entry->data.structure.complete = true;
entry->data.structure.zero_bits_known = true;
entry->data.structure.resolve_status = ResolveStatusSizeKnown;
*parent_pointer = entry;
return entry;
@ -1367,7 +1361,7 @@ static bool analyze_const_align(CodeGen *g, Scope *scope, AstNode *node, uint32_
static bool analyze_const_string(CodeGen *g, Scope *scope, AstNode *node, Buf **out_buffer) {
ZigType *ptr_type = get_pointer_to_type_extra(g, g->builtin_types.entry_u8, true, false,
PtrLenUnknown, get_abi_alignment(g, g->builtin_types.entry_u8), 0, 0);
PtrLenUnknown, 0, 0, 0);
ZigType *str_type = get_slice_type(g, ptr_type);
IrInstruction *instr = analyze_const_value(g, scope, node, str_type, nullptr);
if (type_is_invalid(instr->value.type))
@ -1576,7 +1570,7 @@ static ZigType *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *child_sc
return g->builtin_types.entry_invalid;
}
if (!calling_convention_allows_zig_types(fn_type_id.cc)) {
if ((err = type_ensure_zero_bits_known(g, type_entry)))
if ((err = type_resolve(g, type_entry, ResolveStatusZeroBitsKnown)))
return g->builtin_types.entry_invalid;
if (!type_has_bits(type_entry)) {
add_node_error(g, param_node->data.param_decl.type,
@ -1624,7 +1618,7 @@ static ZigType *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *child_sc
case ZigTypeIdUnion:
case ZigTypeIdFn:
case ZigTypeIdPromise:
if ((err = type_ensure_zero_bits_known(g, type_entry)))
if ((err = type_resolve(g, type_entry, ResolveStatusZeroBitsKnown)))
return g->builtin_types.entry_invalid;
if (type_requires_comptime(type_entry)) {
add_node_error(g, param_node->data.param_decl.type,
@ -1714,7 +1708,7 @@ static ZigType *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *child_sc
case ZigTypeIdUnion:
case ZigTypeIdFn:
case ZigTypeIdPromise:
if ((err = type_ensure_zero_bits_known(g, fn_type_id.return_type)))
if ((err = type_resolve(g, fn_type_id.return_type, ResolveStatusZeroBitsKnown)))
return g->builtin_types.entry_invalid;
if (type_requires_comptime(fn_type_id.return_type)) {
return get_generic_fn_type(g, &fn_type_id);
@ -1740,7 +1734,7 @@ bool type_is_invalid(ZigType *type_entry) {
case ZigTypeIdInvalid:
return true;
case ZigTypeIdStruct:
return type_entry->data.structure.is_invalid;
return type_entry->data.structure.resolve_status == ResolveStatusInvalid;
case ZigTypeIdEnum:
return type_entry->data.enumeration.is_invalid;
case ZigTypeIdUnion:
@ -1855,8 +1849,7 @@ ZigType *get_struct_type(CodeGen *g, const char *type_name, const char *field_na
struct_type->data.structure.src_field_count = field_count;
struct_type->data.structure.gen_field_count = 0;
struct_type->data.structure.zero_bits_known = true;
struct_type->data.structure.complete = true;
struct_type->data.structure.resolve_status = ResolveStatusSizeKnown;
struct_type->data.structure.fields = allocate<TypeStructField>(field_count);
struct_type->data.structure.fields_by_name.init(field_count);
@ -1928,26 +1921,29 @@ ZigType *get_struct_type(CodeGen *g, const char *type_name, const char *field_na
static Error resolve_struct_type(CodeGen *g, ZigType *struct_type) {
assert(struct_type->id == ZigTypeIdStruct);
if (struct_type->data.structure.complete)
Error err;
if (struct_type->data.structure.resolve_status == ResolveStatusInvalid)
return ErrorSemanticAnalyzeFail;
if (struct_type->data.structure.resolve_status >= ResolveStatusSizeKnown)
return ErrorNone;
Error err;
if ((err = resolve_struct_zero_bits(g, struct_type)))
if ((err = resolve_struct_alignment(g, struct_type)))
return err;
AstNode *decl_node = struct_type->data.structure.decl_node;
if (struct_type->data.structure.embedded_in_current) {
struct_type->data.structure.is_invalid = true;
if (!struct_type->data.structure.reported_infinite_err) {
struct_type->data.structure.reported_infinite_err = true;
if (struct_type->data.structure.resolve_loop_flag) {
if (struct_type->data.structure.resolve_status != ResolveStatusInvalid) {
struct_type->data.structure.resolve_status = ResolveStatusInvalid;
add_node_error(g, decl_node,
buf_sprintf("struct '%s' contains itself", buf_ptr(&struct_type->name)));
buf_sprintf("struct '%s' contains itself", buf_ptr(&struct_type->name)));
}
return ErrorSemanticAnalyzeFail;
}
assert(!struct_type->data.structure.zero_bits_loop_flag);
struct_type->data.structure.resolve_loop_flag = true;
assert(struct_type->data.structure.fields || struct_type->data.structure.src_field_count == 0);
assert(decl_node->type == NodeTypeContainerDecl);
@ -1956,9 +1952,6 @@ static Error resolve_struct_type(CodeGen *g, ZigType *struct_type) {
size_t gen_field_count = struct_type->data.structure.gen_field_count;
LLVMTypeRef *element_types = allocate<LLVMTypeRef>(gen_field_count);
// this field should be set to true only during the recursive calls to resolve_struct_type
struct_type->data.structure.embedded_in_current = true;
Scope *scope = &struct_type->data.structure.decls_scope->base;
size_t gen_field_index = 0;
@ -1972,7 +1965,7 @@ static Error resolve_struct_type(CodeGen *g, ZigType *struct_type) {
ZigType *field_type = type_struct_field->type_entry;
if ((err = ensure_complete_type(g, field_type))) {
struct_type->data.structure.is_invalid = true;
struct_type->data.structure.resolve_status = ResolveStatusInvalid;
break;
}
@ -1982,7 +1975,7 @@ static Error resolve_struct_type(CodeGen *g, ZigType *struct_type) {
add_node_error(g, field_source_node,
buf_sprintf("extern structs cannot contain fields of type '%s'",
buf_ptr(&field_type->name)));
struct_type->data.structure.is_invalid = true;
struct_type->data.structure.resolve_status = ResolveStatusInvalid;
break;
}
}
@ -1998,7 +1991,7 @@ static Error resolve_struct_type(CodeGen *g, ZigType *struct_type) {
add_node_error(g, field_source_node,
buf_sprintf("packed structs cannot contain fields of type '%s'",
buf_ptr(&field_type->name)));
struct_type->data.structure.is_invalid = true;
struct_type->data.structure.resolve_status = ResolveStatusInvalid;
break;
}
@ -2049,12 +2042,13 @@ static Error resolve_struct_type(CodeGen *g, ZigType *struct_type) {
gen_field_index += 1;
}
struct_type->data.structure.embedded_in_current = false;
struct_type->data.structure.complete = true;
struct_type->data.structure.resolve_loop_flag = false;
if (struct_type->data.structure.is_invalid)
if (struct_type->data.structure.resolve_status == ResolveStatusInvalid)
return ErrorSemanticAnalyzeFail;
struct_type->data.structure.resolve_status = ResolveStatusSizeKnown;
if (struct_type->zero_bits) {
struct_type->type_ref = LLVMVoidType();
@ -2116,7 +2110,7 @@ static Error resolve_struct_type(CodeGen *g, ZigType *struct_type) {
assert(field_type->type_ref);
assert(struct_type->type_ref);
assert(struct_type->data.structure.complete);
assert(struct_type->data.structure.resolve_status == ResolveStatusSizeKnown);
uint64_t debug_size_in_bits;
uint64_t debug_align_in_bits;
uint64_t debug_offset_in_bits;
@ -2570,30 +2564,18 @@ static Error resolve_struct_zero_bits(CodeGen *g, ZigType *struct_type) {
Error err;
if (struct_type->data.structure.is_invalid)
if (struct_type->data.structure.resolve_status == ResolveStatusInvalid)
return ErrorSemanticAnalyzeFail;
if (struct_type->data.structure.zero_bits_known)
if (struct_type->data.structure.resolve_status >= ResolveStatusZeroBitsKnown)
return ErrorNone;
if (struct_type->data.structure.zero_bits_loop_flag) {
// If we get here it's due to recursion. This is a design flaw in the compiler,
// we should be able to still figure out alignment, but here we give up and say that
// the alignment is pointer width, then assert that the first field is within that
// alignment
struct_type->data.structure.zero_bits_known = true;
struct_type->data.structure.zero_bits_loop_flag = false;
if (struct_type->data.structure.abi_alignment == 0) {
if (struct_type->data.structure.layout == ContainerLayoutPacked) {
struct_type->data.structure.abi_alignment = 1;
} else {
struct_type->data.structure.abi_alignment = LLVMABIAlignmentOfType(g->target_data_ref, LLVMPointerType(LLVMInt8Type(), 0));
}
}
if (struct_type->data.structure.resolve_loop_flag) {
struct_type->data.structure.resolve_status = ResolveStatusZeroBitsKnown;
struct_type->data.structure.resolve_loop_flag = false;
return ErrorNone;
}
struct_type->data.structure.zero_bits_loop_flag = true;
struct_type->data.structure.resolve_loop_flag = true;
AstNode *decl_node = struct_type->data.structure.decl_node;
assert(decl_node->type == NodeTypeContainerDecl);
@ -2616,7 +2598,7 @@ static Error resolve_struct_zero_bits(CodeGen *g, ZigType *struct_type) {
if (field_node->data.struct_field.type == nullptr) {
add_node_error(g, field_node, buf_sprintf("struct field missing type"));
struct_type->data.structure.is_invalid = true;
struct_type->data.structure.resolve_status = ResolveStatusInvalid;
continue;
}
@ -2625,7 +2607,7 @@ static Error resolve_struct_zero_bits(CodeGen *g, ZigType *struct_type) {
ErrorMsg *msg = add_node_error(g, field_node,
buf_sprintf("duplicate struct field: '%s'", buf_ptr(type_struct_field->name)));
add_error_note(g, msg, field_entry->value->decl_node, buf_sprintf("other field here"));
struct_type->data.structure.is_invalid = true;
struct_type->data.structure.resolve_status = ResolveStatusInvalid;
continue;
}
@ -2639,8 +2621,8 @@ static Error resolve_struct_zero_bits(CodeGen *g, ZigType *struct_type) {
buf_sprintf("enums, not structs, support field assignment"));
}
if ((err = type_ensure_zero_bits_known(g, field_type))) {
struct_type->data.structure.is_invalid = true;
if ((err = type_resolve(g, field_type, ResolveStatusZeroBitsKnown))) {
struct_type->data.structure.resolve_status = ResolveStatusInvalid;
continue;
}
@ -2651,36 +2633,87 @@ static Error resolve_struct_zero_bits(CodeGen *g, ZigType *struct_type) {
if (!type_has_bits(field_type))
continue;
if (gen_field_index == 0) {
if (struct_type->data.structure.layout == ContainerLayoutPacked) {
struct_type->data.structure.abi_alignment = 1;
} else if (struct_type->data.structure.abi_alignment == 0) {
// Alignment of structs is the alignment of the first field, for now.
// TODO change this when we re-order struct fields (issue #168)
struct_type->data.structure.abi_alignment = get_abi_alignment(g, field_type);
assert(struct_type->data.structure.abi_alignment != 0);
} else {
// due to a design flaw in the compiler we assumed that alignment was
// pointer width, so we assert that this wasn't violated.
if (get_abi_alignment(g, field_type) > struct_type->data.structure.abi_alignment) {
zig_panic("compiler design flaw: incorrect alignment assumption");
}
}
}
type_struct_field->gen_index = gen_field_index;
gen_field_index += 1;
}
struct_type->data.structure.zero_bits_loop_flag = false;
struct_type->data.structure.resolve_loop_flag = false;
struct_type->data.structure.gen_field_count = (uint32_t)gen_field_index;
struct_type->zero_bits = (gen_field_index == 0);
struct_type->data.structure.zero_bits_known = true;
if (struct_type->data.structure.is_invalid) {
if (struct_type->data.structure.resolve_status == ResolveStatusInvalid)
return ErrorSemanticAnalyzeFail;
struct_type->data.structure.resolve_status = ResolveStatusZeroBitsKnown;
return ErrorNone;
}
static Error resolve_struct_alignment(CodeGen *g, ZigType *struct_type) {
assert(struct_type->id == ZigTypeIdStruct);
Error err;
if (struct_type->data.structure.resolve_status == ResolveStatusInvalid)
return ErrorSemanticAnalyzeFail;
if (struct_type->data.structure.resolve_status >= ResolveStatusAlignmentKnown)
return ErrorNone;
if ((err = resolve_struct_zero_bits(g, struct_type)))
return err;
AstNode *decl_node = struct_type->data.structure.decl_node;
if (struct_type->data.structure.resolve_loop_flag) {
if (struct_type->data.structure.resolve_status != ResolveStatusInvalid) {
struct_type->data.structure.resolve_status = ResolveStatusInvalid;
add_node_error(g, decl_node,
buf_sprintf("struct '%s' contains itself", buf_ptr(&struct_type->name)));
}
return ErrorSemanticAnalyzeFail;
}
struct_type->data.structure.resolve_loop_flag = true;
assert(decl_node->type == NodeTypeContainerDecl);
assert(struct_type->di_type);
if (struct_type->data.structure.layout == ContainerLayoutPacked) {
struct_type->data.structure.abi_alignment = 1;
}
size_t field_count = struct_type->data.structure.src_field_count;
for (size_t i = 0; i < field_count; i += 1) {
TypeStructField *field = &struct_type->data.structure.fields[i];
// If this assertion trips, look up the call stack. Probably something is
// calling type_resolve with ResolveStatusAlignmentKnown when it should only
// be resolving ResolveStatusZeroBitsKnown
assert(field->type_entry != nullptr);
if (!type_has_bits(field->type_entry))
continue;
// alignment of structs is the alignment of the most-aligned field
if (struct_type->data.structure.layout != ContainerLayoutPacked) {
if ((err = type_resolve(g, field->type_entry, ResolveStatusAlignmentKnown))) {
struct_type->data.structure.resolve_status = ResolveStatusInvalid;
break;
}
uint32_t this_field_align = get_abi_alignment(g, field->type_entry);
assert(this_field_align != 0);
if (this_field_align > struct_type->data.structure.abi_alignment) {
struct_type->data.structure.abi_alignment = this_field_align;
}
}
}
struct_type->data.structure.resolve_loop_flag = false;
if (struct_type->data.structure.resolve_status == ResolveStatusInvalid) {
return ErrorSemanticAnalyzeFail;
}
struct_type->data.structure.resolve_status = ResolveStatusAlignmentKnown;
return ErrorNone;
}
@ -2807,7 +2840,7 @@ static Error resolve_union_zero_bits(CodeGen *g, ZigType *union_type) {
buf_sprintf("expected enum tag type, found '%s'", buf_ptr(&enum_type->name)));
return ErrorSemanticAnalyzeFail;
}
if ((err = type_ensure_zero_bits_known(g, enum_type))) {
if ((err = type_resolve(g, enum_type, ResolveStatusAlignmentKnown))) {
assert(g->errors.length != 0);
return err;
}
@ -2848,7 +2881,7 @@ static Error resolve_union_zero_bits(CodeGen *g, ZigType *union_type) {
}
} else {
field_type = analyze_type_expr(g, scope, field_node->data.struct_field.type);
if ((err = type_ensure_zero_bits_known(g, field_type))) {
if ((err = type_resolve(g, field_type, ResolveStatusAlignmentKnown))) {
union_type->data.unionation.is_invalid = true;
continue;
}
@ -3111,7 +3144,7 @@ static void typecheck_panic_fn(CodeGen *g, ZigFn *panic_fn) {
return wrong_panic_prototype(g, proto_node, fn_type);
}
ZigType *const_u8_ptr = get_pointer_to_type_extra(g, g->builtin_types.entry_u8, true, false,
PtrLenUnknown, get_abi_alignment(g, g->builtin_types.entry_u8), 0, 0);
PtrLenUnknown, 0, 0, 0);
ZigType *const_u8_slice = get_slice_type(g, const_u8_ptr);
if (fn_type_id->param_info[0].type != const_u8_slice) {
return wrong_panic_prototype(g, proto_node, fn_type);
@ -3801,7 +3834,7 @@ TypeEnumField *find_enum_type_field(ZigType *enum_type, Buf *name) {
TypeStructField *find_struct_type_field(ZigType *type_entry, Buf *name) {
assert(type_entry->id == ZigTypeIdStruct);
assert(type_entry->data.structure.complete);
assert(type_is_resolved(type_entry, ResolveStatusZeroBitsKnown));
if (type_entry->data.structure.src_field_count == 0)
return nullptr;
auto entry = type_entry->data.structure.fields_by_name.maybe_get(name);
@ -3956,9 +3989,12 @@ bool type_is_codegen_pointer(ZigType *type) {
uint32_t get_ptr_align(CodeGen *g, ZigType *type) {
ZigType *ptr_type = get_codegen_ptr_type(type);
if (ptr_type->id == ZigTypeIdPointer) {
return ptr_type->data.pointer.alignment;
return (ptr_type->data.pointer.explicit_alignment == 0) ?
get_abi_alignment(g, ptr_type->data.pointer.child_type) : ptr_type->data.pointer.explicit_alignment;
} else if (ptr_type->id == ZigTypeIdFn) {
return (ptr_type->data.fn.fn_type_id.alignment == 0) ? 1 : ptr_type->data.fn.fn_type_id.alignment;
return (ptr_type->data.fn.fn_type_id.alignment == 0) ?
LLVMABIAlignmentOfType(g->target_data_ref, ptr_type->data.fn.raw_type_ref) :
ptr_type->data.fn.fn_type_id.alignment;
} else if (ptr_type->id == ZigTypeIdPromise) {
return get_coro_frame_align_bytes(g);
} else {
@ -5023,8 +5059,8 @@ bool fn_eval_eql(Scope *a, Scope *b) {
bool type_has_bits(ZigType *type_entry) {
assert(type_entry);
assert(type_entry->id != ZigTypeIdInvalid);
assert(type_has_zero_bits_known(type_entry));
assert(!type_is_invalid(type_entry));
assert(type_is_resolved(type_entry, ResolveStatusZeroBitsKnown));
return !type_entry->zero_bits;
}
@ -5045,10 +5081,10 @@ bool type_requires_comptime(ZigType *type_entry) {
case ZigTypeIdArray:
return type_requires_comptime(type_entry->data.array.child_type);
case ZigTypeIdStruct:
assert(type_has_zero_bits_known(type_entry));
assert(type_is_resolved(type_entry, ResolveStatusZeroBitsKnown));
return type_entry->data.structure.requires_comptime;
case ZigTypeIdUnion:
assert(type_has_zero_bits_known(type_entry));
assert(type_is_resolved(type_entry, ResolveStatusZeroBitsKnown));
return type_entry->data.unionation.requires_comptime;
case ZigTypeIdOptional:
return type_requires_comptime(type_entry->data.maybe.child_type);
@ -5124,7 +5160,7 @@ void init_const_c_str_lit(CodeGen *g, ConstExprValue *const_val, Buf *str) {
const_val->special = ConstValSpecialStatic;
// TODO make this `[*]null u8` instead of `[*]u8`
const_val->type = get_pointer_to_type_extra(g, g->builtin_types.entry_u8, true, false,
PtrLenUnknown, get_abi_alignment(g, g->builtin_types.entry_u8), 0, 0);
PtrLenUnknown, 0, 0, 0);
const_val->data.x_ptr.special = ConstPtrSpecialBaseArray;
const_val->data.x_ptr.data.base_array.array_val = array_val;
const_val->data.x_ptr.data.base_array.elem_index = 0;
@ -5269,8 +5305,7 @@ void init_const_slice(CodeGen *g, ConstExprValue *const_val, ConstExprValue *arr
assert(array_val->type->id == ZigTypeIdArray);
ZigType *ptr_type = get_pointer_to_type_extra(g, array_val->type->data.array.child_type,
is_const, false, PtrLenUnknown, get_abi_alignment(g, array_val->type->data.array.child_type),
0, 0);
is_const, false, PtrLenUnknown, 0, 0, 0);
const_val->special = ConstValSpecialStatic;
const_val->type = get_slice_type(g, ptr_type);
@ -5295,7 +5330,7 @@ void init_const_ptr_array(CodeGen *g, ConstExprValue *const_val, ConstExprValue
const_val->special = ConstValSpecialStatic;
const_val->type = get_pointer_to_type_extra(g, child_type, is_const, false,
ptr_len, get_abi_alignment(g, child_type), 0, 0);
ptr_len, 0, 0, 0);
const_val->data.x_ptr.special = ConstPtrSpecialBaseArray;
const_val->data.x_ptr.data.base_array.array_val = array_val;
const_val->data.x_ptr.data.base_array.elem_index = elem_index;
@ -5394,32 +5429,46 @@ ConstExprValue *create_const_vals(size_t count) {
}
Error ensure_complete_type(CodeGen *g, ZigType *type_entry) {
if (type_is_invalid(type_entry))
return ErrorSemanticAnalyzeFail;
if (type_entry->id == ZigTypeIdStruct) {
if (!type_entry->data.structure.complete)
return resolve_struct_type(g, type_entry);
} else if (type_entry->id == ZigTypeIdEnum) {
if (!type_entry->data.enumeration.complete)
return resolve_enum_type(g, type_entry);
} else if (type_entry->id == ZigTypeIdUnion) {
if (!type_entry->data.unionation.complete)
return resolve_union_type(g, type_entry);
}
return ErrorNone;
return type_resolve(g, type_entry, ResolveStatusSizeKnown);
}
Error type_ensure_zero_bits_known(CodeGen *g, ZigType *type_entry) {
if (type_is_invalid(type_entry))
Error type_resolve(CodeGen *g, ZigType *ty, ResolveStatus status) {
if (type_is_invalid(ty))
return ErrorSemanticAnalyzeFail;
if (type_entry->id == ZigTypeIdStruct) {
return resolve_struct_zero_bits(g, type_entry);
} else if (type_entry->id == ZigTypeIdEnum) {
return resolve_enum_zero_bits(g, type_entry);
} else if (type_entry->id == ZigTypeIdUnion) {
return resolve_union_zero_bits(g, type_entry);
switch (status) {
case ResolveStatusUnstarted:
return ErrorNone;
case ResolveStatusInvalid:
zig_unreachable();
case ResolveStatusZeroBitsKnown:
if (ty->id == ZigTypeIdStruct) {
return resolve_struct_zero_bits(g, ty);
} else if (ty->id == ZigTypeIdEnum) {
return resolve_enum_zero_bits(g, ty);
} else if (ty->id == ZigTypeIdUnion) {
return resolve_union_zero_bits(g, ty);
}
return ErrorNone;
case ResolveStatusAlignmentKnown:
if (ty->id == ZigTypeIdStruct) {
return resolve_struct_alignment(g, ty);
} else if (ty->id == ZigTypeIdEnum) {
return resolve_enum_zero_bits(g, ty);
} else if (ty->id == ZigTypeIdUnion) {
return resolve_union_zero_bits(g, ty);
}
return ErrorNone;
case ResolveStatusSizeKnown:
if (ty->id == ZigTypeIdStruct) {
return resolve_struct_type(g, ty);
} else if (ty->id == ZigTypeIdEnum) {
return resolve_enum_type(g, ty);
} else if (ty->id == ZigTypeIdUnion) {
return resolve_union_type(g, ty);
}
return ErrorNone;
}
return ErrorNone;
zig_unreachable();
}
bool ir_get_var_is_comptime(ZigVar *var) {
@ -6262,7 +6311,7 @@ LinkLib *add_link_lib(CodeGen *g, Buf *name) {
}
uint32_t get_abi_alignment(CodeGen *g, ZigType *type_entry) {
assertNoError(type_ensure_zero_bits_known(g, type_entry));
assert(type_is_resolved(type_entry, ResolveStatusAlignmentKnown));
if (type_entry->zero_bits) return 0;
// We need to make this function work without requiring ensure_complete_type

View File

@ -59,9 +59,9 @@ bool get_ptr_const(ZigType *type);
ZigType *validate_var_type(CodeGen *g, AstNode *source_node, ZigType *type_entry);
ZigType *container_ref_type(ZigType *type_entry);
bool type_is_complete(ZigType *type_entry);
bool type_is_resolved(ZigType *type_entry, ResolveStatus status);
bool type_is_invalid(ZigType *type_entry);
bool type_is_global_error_set(ZigType *err_set_type);
bool type_has_zero_bits_known(ZigType *type_entry);
void resolve_container_type(CodeGen *g, ZigType *type_entry);
ScopeDecls *get_container_scope(ZigType *type_entry);
TypeStructField *find_struct_type_field(ZigType *type_entry, Buf *name);
@ -89,7 +89,7 @@ void init_fn_type_id(FnTypeId *fn_type_id, AstNode *proto_node, size_t param_cou
AstNode *get_param_decl_node(ZigFn *fn_entry, size_t index);
bool type_requires_comptime(ZigType *type_entry);
Error ATTRIBUTE_MUST_USE ensure_complete_type(CodeGen *g, ZigType *type_entry);
Error ATTRIBUTE_MUST_USE type_ensure_zero_bits_known(CodeGen *g, ZigType *type_entry);
Error ATTRIBUTE_MUST_USE type_resolve(CodeGen *g, ZigType *type_entry, ResolveStatus status);
void complete_enum(CodeGen *g, ZigType *enum_type);
bool ir_get_var_is_comptime(ZigVar *var);
bool const_values_equal(ConstExprValue *a, ConstExprValue *b);

View File

@ -775,7 +775,8 @@ static LLVMValueRef gen_store_untyped(CodeGen *g, LLVMValueRef value, LLVMValueR
static LLVMValueRef gen_store(CodeGen *g, LLVMValueRef value, LLVMValueRef ptr, ZigType *ptr_type) {
assert(ptr_type->id == ZigTypeIdPointer);
return gen_store_untyped(g, value, ptr, ptr_type->data.pointer.alignment, ptr_type->data.pointer.is_volatile);
uint32_t alignment = get_ptr_align(g, ptr_type);
return gen_store_untyped(g, value, ptr, alignment, ptr_type->data.pointer.is_volatile);
}
static LLVMValueRef gen_load_untyped(CodeGen *g, LLVMValueRef ptr, uint32_t alignment, bool is_volatile,
@ -793,7 +794,8 @@ static LLVMValueRef gen_load_untyped(CodeGen *g, LLVMValueRef ptr, uint32_t alig
static LLVMValueRef gen_load(CodeGen *g, LLVMValueRef ptr, ZigType *ptr_type, const char *name) {
assert(ptr_type->id == ZigTypeIdPointer);
return gen_load_untyped(g, ptr, ptr_type->data.pointer.alignment, ptr_type->data.pointer.is_volatile, name);
uint32_t alignment = get_ptr_align(g, ptr_type);
return gen_load_untyped(g, ptr, alignment, ptr_type->data.pointer.is_volatile, name);
}
static LLVMValueRef get_handle_value(CodeGen *g, LLVMValueRef ptr, ZigType *type, ZigType *ptr_type) {
@ -1795,7 +1797,7 @@ static LLVMValueRef gen_assign_raw(CodeGen *g, LLVMValueRef ptr, ZigType *ptr_ty
ZigType *usize = g->builtin_types.entry_usize;
uint64_t size_bytes = LLVMStoreSizeOfType(g->target_data_ref, child_type->type_ref);
uint64_t align_bytes = ptr_type->data.pointer.alignment;
uint64_t align_bytes = get_ptr_align(g, ptr_type);
assert(size_bytes > 0);
assert(align_bytes > 0);
@ -4084,7 +4086,7 @@ static LLVMValueRef ir_render_align_cast(CodeGen *g, IrExecutable *executable, I
LLVMValueRef ptr_val;
if (target_type->id == ZigTypeIdPointer) {
align_bytes = target_type->data.pointer.alignment;
align_bytes = get_ptr_align(g, target_type);
ptr_val = target_val;
} else if (target_type->id == ZigTypeIdFn) {
align_bytes = target_type->data.fn.fn_type_id.alignment;
@ -4092,7 +4094,7 @@ static LLVMValueRef ir_render_align_cast(CodeGen *g, IrExecutable *executable, I
} else if (target_type->id == ZigTypeIdOptional &&
target_type->data.maybe.child_type->id == ZigTypeIdPointer)
{
align_bytes = target_type->data.maybe.child_type->data.pointer.alignment;
align_bytes = get_ptr_align(g, target_type->data.maybe.child_type);
ptr_val = target_val;
} else if (target_type->id == ZigTypeIdOptional &&
target_type->data.maybe.child_type->id == ZigTypeIdFn)
@ -4105,7 +4107,7 @@ static LLVMValueRef ir_render_align_cast(CodeGen *g, IrExecutable *executable, I
zig_panic("TODO audit this function");
} else if (target_type->id == ZigTypeIdStruct && target_type->data.structure.is_slice) {
ZigType *slice_ptr_type = target_type->data.structure.fields[slice_ptr_index].type_entry;
align_bytes = slice_ptr_type->data.pointer.alignment;
align_bytes = get_ptr_align(g, slice_ptr_type);
size_t ptr_index = target_type->data.structure.fields[slice_ptr_index].gen_index;
LLVMValueRef ptr_val_ptr = LLVMBuildStructGEP(g->builder, target_val, (unsigned)ptr_index, "");
@ -4260,7 +4262,8 @@ static LLVMValueRef ir_render_memset(CodeGen *g, IrExecutable *executable, IrIns
LLVMValueRef is_volatile = ptr_type->data.pointer.is_volatile ?
LLVMConstAllOnes(LLVMInt1Type()) : LLVMConstNull(LLVMInt1Type());
LLVMValueRef align_val = LLVMConstInt(LLVMInt32Type(), ptr_type->data.pointer.alignment, false);
uint32_t alignment = get_ptr_align(g, ptr_type);
LLVMValueRef align_val = LLVMConstInt(LLVMInt32Type(), alignment, false);
LLVMValueRef params[] = {
dest_ptr_casted,
@ -4293,7 +4296,7 @@ static LLVMValueRef ir_render_memcpy(CodeGen *g, IrExecutable *executable, IrIns
LLVMValueRef is_volatile = (dest_ptr_type->data.pointer.is_volatile || src_ptr_type->data.pointer.is_volatile) ?
LLVMConstAllOnes(LLVMInt1Type()) : LLVMConstNull(LLVMInt1Type());
uint32_t min_align_bytes = min(src_ptr_type->data.pointer.alignment, dest_ptr_type->data.pointer.alignment);
uint32_t min_align_bytes = min(get_ptr_align(g, src_ptr_type), get_ptr_align(g, dest_ptr_type));
LLVMValueRef align_val = LLVMConstInt(LLVMInt32Type(), min_align_bytes, false);
LLVMValueRef params[] = {

View File

@ -40,6 +40,7 @@ struct IrAnalyze {
enum ConstCastResultId {
ConstCastResultIdOk,
ConstCastResultIdInvalid,
ConstCastResultIdErrSet,
ConstCastResultIdErrSetGlobal,
ConstCastResultIdPointerChild,
@ -7490,8 +7491,7 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec
if (type_has_bits(return_type)) {
IrInstruction *u8_ptr_type_unknown_len = ir_build_const_type(irb, scope, node,
get_pointer_to_type_extra(irb->codegen, irb->codegen->builtin_types.entry_u8,
false, false, PtrLenUnknown, get_abi_alignment(irb->codegen, irb->codegen->builtin_types.entry_u8),
0, 0));
false, false, PtrLenUnknown, 0, 0, 0));
IrInstruction *result_ptr = ir_build_load_ptr(irb, scope, node, irb->exec->coro_result_ptr_field_ptr);
IrInstruction *result_ptr_as_u8_ptr = ir_build_ptr_cast(irb, scope, node, u8_ptr_type_unknown_len, result_ptr);
IrInstruction *return_value_ptr_as_u8_ptr = ir_build_ptr_cast(irb, scope, node, u8_ptr_type_unknown_len,
@ -7544,8 +7544,7 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec
IrInstruction *coro_mem_ptr_maybe = ir_build_coro_free(irb, scope, node, coro_id, irb->exec->coro_handle);
IrInstruction *u8_ptr_type_unknown_len = ir_build_const_type(irb, scope, node,
get_pointer_to_type_extra(irb->codegen, irb->codegen->builtin_types.entry_u8,
false, false, PtrLenUnknown, get_abi_alignment(irb->codegen, irb->codegen->builtin_types.entry_u8),
0, 0));
false, false, PtrLenUnknown, 0, 0, 0));
IrInstruction *coro_mem_ptr = ir_build_ptr_cast(irb, scope, node, u8_ptr_type_unknown_len, coro_mem_ptr_maybe);
IrInstruction *coro_mem_ptr_ref = ir_build_ref(irb, scope, node, coro_mem_ptr, true, false);
IrInstruction *coro_size_ptr = ir_build_var_ptr(irb, scope, node, coro_size_var);
@ -8516,6 +8515,8 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted
ConstCastOnly result = {};
result.id = ConstCastResultIdOk;
Error err;
if (wanted_type == actual_type)
return result;
@ -8528,6 +8529,8 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted
{
ConstCastOnly child = types_match_const_cast_only(ira,
wanted_type->data.maybe.child_type, actual_type, source_node, wanted_is_mutable);
if (child.id == ConstCastResultIdInvalid)
return child;
if (child.id != ConstCastResultIdOk) {
result.id = ConstCastResultIdNullWrapPtr;
result.data.null_wrap_ptr_child = allocate_nonzero<ConstCastOnly>(1);
@ -8544,7 +8547,6 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted
(!actual_type->data.pointer.is_const || wanted_type->data.pointer.is_const) &&
(!actual_type->data.pointer.is_volatile || wanted_type->data.pointer.is_volatile))
{
assert(actual_type->data.pointer.alignment >= wanted_type->data.pointer.alignment);
return result;
}
@ -8552,6 +8554,8 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted
if (wanted_type->id == ZigTypeIdPointer && actual_type->id == ZigTypeIdPointer) {
ConstCastOnly child = types_match_const_cast_only(ira, wanted_type->data.pointer.child_type,
actual_type->data.pointer.child_type, source_node, !wanted_type->data.pointer.is_const);
if (child.id == ConstCastResultIdInvalid)
return child;
if (child.id != ConstCastResultIdOk) {
result.id = ConstCastResultIdPointerChild;
result.data.pointer_mismatch = allocate_nonzero<ConstCastPointerMismatch>(1);
@ -8560,12 +8564,20 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted
result.data.pointer_mismatch->actual_child = actual_type->data.pointer.child_type;
return result;
}
if ((err = type_resolve(g, actual_type->data.pointer.child_type, ResolveStatusAlignmentKnown))) {
result.id = ConstCastResultIdInvalid;
return result;
}
if ((err = type_resolve(g, wanted_type->data.pointer.child_type, ResolveStatusAlignmentKnown))) {
result.id = ConstCastResultIdInvalid;
return result;
}
if ((actual_type->data.pointer.ptr_len == wanted_type->data.pointer.ptr_len) &&
(!actual_type->data.pointer.is_const || wanted_type->data.pointer.is_const) &&
(!actual_type->data.pointer.is_volatile || wanted_type->data.pointer.is_volatile) &&
actual_type->data.pointer.bit_offset == wanted_type->data.pointer.bit_offset &&
actual_type->data.pointer.unaligned_bit_count == wanted_type->data.pointer.unaligned_bit_count &&
actual_type->data.pointer.alignment >= wanted_type->data.pointer.alignment)
get_ptr_align(ira->codegen, actual_type) >= get_ptr_align(ira->codegen, wanted_type))
{
return result;
}
@ -8575,14 +8587,24 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted
if (is_slice(wanted_type) && is_slice(actual_type)) {
ZigType *actual_ptr_type = actual_type->data.structure.fields[slice_ptr_index].type_entry;
ZigType *wanted_ptr_type = wanted_type->data.structure.fields[slice_ptr_index].type_entry;
if ((err = type_resolve(g, actual_ptr_type->data.pointer.child_type, ResolveStatusAlignmentKnown))) {
result.id = ConstCastResultIdInvalid;
return result;
}
if ((err = type_resolve(g, wanted_ptr_type->data.pointer.child_type, ResolveStatusAlignmentKnown))) {
result.id = ConstCastResultIdInvalid;
return result;
}
if ((!actual_ptr_type->data.pointer.is_const || wanted_ptr_type->data.pointer.is_const) &&
(!actual_ptr_type->data.pointer.is_volatile || wanted_ptr_type->data.pointer.is_volatile) &&
actual_ptr_type->data.pointer.bit_offset == wanted_ptr_type->data.pointer.bit_offset &&
actual_ptr_type->data.pointer.unaligned_bit_count == wanted_ptr_type->data.pointer.unaligned_bit_count &&
actual_ptr_type->data.pointer.alignment >= wanted_ptr_type->data.pointer.alignment)
get_ptr_align(g, actual_ptr_type) >= get_ptr_align(g, wanted_ptr_type))
{
ConstCastOnly child = types_match_const_cast_only(ira, wanted_ptr_type->data.pointer.child_type,
actual_ptr_type->data.pointer.child_type, source_node, !wanted_ptr_type->data.pointer.is_const);
if (child.id == ConstCastResultIdInvalid)
return child;
if (child.id != ConstCastResultIdOk) {
result.id = ConstCastResultIdSliceChild;
result.data.slice_mismatch = allocate_nonzero<ConstCastSliceMismatch>(1);
@ -8598,6 +8620,8 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted
if (wanted_type->id == ZigTypeIdOptional && actual_type->id == ZigTypeIdOptional) {
ConstCastOnly child = types_match_const_cast_only(ira, wanted_type->data.maybe.child_type,
actual_type->data.maybe.child_type, source_node, wanted_is_mutable);
if (child.id == ConstCastResultIdInvalid)
return child;
if (child.id != ConstCastResultIdOk) {
result.id = ConstCastResultIdOptionalChild;
result.data.optional = allocate_nonzero<ConstCastOptionalMismatch>(1);
@ -8612,6 +8636,8 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted
if (wanted_type->id == ZigTypeIdErrorUnion && actual_type->id == ZigTypeIdErrorUnion) {
ConstCastOnly payload_child = types_match_const_cast_only(ira, wanted_type->data.error_union.payload_type,
actual_type->data.error_union.payload_type, source_node, wanted_is_mutable);
if (payload_child.id == ConstCastResultIdInvalid)
return payload_child;
if (payload_child.id != ConstCastResultIdOk) {
result.id = ConstCastResultIdErrorUnionPayload;
result.data.error_union_payload = allocate_nonzero<ConstCastErrUnionPayloadMismatch>(1);
@ -8622,6 +8648,8 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted
}
ConstCastOnly error_set_child = types_match_const_cast_only(ira, wanted_type->data.error_union.err_set_type,
actual_type->data.error_union.err_set_type, source_node, wanted_is_mutable);
if (error_set_child.id == ConstCastResultIdInvalid)
return error_set_child;
if (error_set_child.id != ConstCastResultIdOk) {
result.id = ConstCastResultIdErrorUnionErrorSet;
result.data.error_union_error_set = allocate_nonzero<ConstCastErrUnionErrSetMismatch>(1);
@ -8709,6 +8737,8 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted
{
ConstCastOnly child = types_match_const_cast_only(ira, wanted_type->data.fn.fn_type_id.return_type,
actual_type->data.fn.fn_type_id.return_type, source_node, false);
if (child.id == ConstCastResultIdInvalid)
return child;
if (child.id != ConstCastResultIdOk) {
result.id = ConstCastResultIdFnReturnType;
result.data.return_type = allocate_nonzero<ConstCastOnly>(1);
@ -8721,6 +8751,8 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted
actual_type->data.fn.fn_type_id.async_allocator_type,
wanted_type->data.fn.fn_type_id.async_allocator_type,
source_node, false);
if (child.id == ConstCastResultIdInvalid)
return child;
if (child.id != ConstCastResultIdOk) {
result.id = ConstCastResultIdAsyncAllocatorType;
result.data.async_allocator_type = allocate_nonzero<ConstCastOnly>(1);
@ -8745,6 +8777,8 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted
ConstCastOnly arg_child = types_match_const_cast_only(ira, actual_param_info->type,
expected_param_info->type, source_node, false);
if (arg_child.id == ConstCastResultIdInvalid)
return arg_child;
if (arg_child.id != ConstCastResultIdOk) {
result.id = ConstCastResultIdFnArg;
result.data.fn_arg.arg_index = i;
@ -9238,7 +9272,7 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT
if (prev_type->id == ZigTypeIdEnum && cur_type->id == ZigTypeIdUnion &&
(cur_type->data.unionation.decl_node->data.container_decl.auto_enum || cur_type->data.unionation.decl_node->data.container_decl.init_arg_expr != nullptr))
{
if ((err = type_ensure_zero_bits_known(ira->codegen, cur_type)))
if ((err = type_resolve(ira->codegen, cur_type, ResolveStatusZeroBitsKnown)))
return ira->codegen->builtin_types.entry_invalid;
if (cur_type->data.unionation.tag_type == prev_type) {
continue;
@ -9248,7 +9282,7 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT
if (cur_type->id == ZigTypeIdEnum && prev_type->id == ZigTypeIdUnion &&
(prev_type->data.unionation.decl_node->data.container_decl.auto_enum || prev_type->data.unionation.decl_node->data.container_decl.init_arg_expr != nullptr))
{
if ((err = type_ensure_zero_bits_known(ira->codegen, prev_type)))
if ((err = type_resolve(ira->codegen, prev_type, ResolveStatusZeroBitsKnown)))
return ira->codegen->builtin_types.entry_invalid;
if (prev_type->data.unionation.tag_type == cur_type) {
prev_inst = cur_inst;
@ -9274,8 +9308,7 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT
ZigType *ptr_type = get_pointer_to_type_extra(
ira->codegen, prev_inst->value.type->data.array.child_type,
true, false, PtrLenUnknown,
get_abi_alignment(ira->codegen, prev_inst->value.type->data.array.child_type),
0, 0);
0, 0, 0);
ZigType *slice_type = get_slice_type(ira->codegen, ptr_type);
if (err_set_type != nullptr) {
return get_error_union_type(ira->codegen, err_set_type, slice_type);
@ -9472,7 +9505,16 @@ static IrInstruction *ir_resolve_ptr_of_array_to_unknown_len_ptr(IrAnalyze *ira,
IrInstruction *value, ZigType *wanted_type)
{
assert(value->value.type->id == ZigTypeIdPointer);
wanted_type = adjust_ptr_align(ira->codegen, wanted_type, value->value.type->data.pointer.alignment);
Error err;
if ((err = type_resolve(ira->codegen, value->value.type->data.pointer.child_type,
ResolveStatusAlignmentKnown)))
{
return ira->codegen->invalid_instruction;
}
wanted_type = adjust_ptr_align(ira->codegen, wanted_type, get_ptr_align(ira->codegen, value->value.type));
if (instr_is_comptime(value)) {
ConstExprValue *pointee = ir_const_ptr_pointee(ira, &value->value, source_instr->source_node);
@ -9500,7 +9542,15 @@ static IrInstruction *ir_resolve_ptr_of_array_to_unknown_len_ptr(IrAnalyze *ira,
static IrInstruction *ir_resolve_ptr_of_array_to_slice(IrAnalyze *ira, IrInstruction *source_instr,
IrInstruction *value, ZigType *wanted_type)
{
wanted_type = adjust_slice_align(ira->codegen, wanted_type, value->value.type->data.pointer.alignment);
Error err;
if ((err = type_resolve(ira->codegen, value->value.type->data.pointer.child_type,
ResolveStatusAlignmentKnown)))
{
return ira->codegen->invalid_instruction;
}
wanted_type = adjust_slice_align(ira->codegen, wanted_type, get_ptr_align(ira->codegen, value->value.type));
if (instr_is_comptime(value)) {
ConstExprValue *pointee = ir_const_ptr_pointee(ira, &value->value, source_instr->source_node);
@ -9687,8 +9737,7 @@ static ZigType *ir_analyze_const_ptr(IrAnalyze *ira, IrInstruction *instruction,
ConstPtrMut ptr_mut, bool ptr_is_const, bool ptr_is_volatile)
{
IrInstruction *const_instr = ir_get_const_ptr(ira, instruction, pointee,
pointee_type, ptr_mut, ptr_is_const, ptr_is_volatile,
get_abi_alignment(ira->codegen, pointee_type));
pointee_type, ptr_mut, ptr_is_const, ptr_is_volatile, 0);
ir_link_new_instruction(const_instr, instruction);
return const_instr->value.type;
}
@ -10005,20 +10054,24 @@ static IrInstruction *ir_analyze_null_to_maybe(IrAnalyze *ira, IrInstruction *so
static IrInstruction *ir_get_ref(IrAnalyze *ira, IrInstruction *source_instruction, IrInstruction *value,
bool is_const, bool is_volatile)
{
Error err;
if (type_is_invalid(value->value.type))
return ira->codegen->invalid_instruction;
if ((err = type_resolve(ira->codegen, value->value.type, ResolveStatusZeroBitsKnown)))
return ira->codegen->invalid_instruction;
if (instr_is_comptime(value)) {
ConstExprValue *val = ir_resolve_const(ira, value, UndefOk);
if (!val)
return ira->codegen->invalid_instruction;
return ir_get_const_ptr(ira, source_instruction, val, value->value.type,
ConstPtrMutComptimeConst, is_const, is_volatile,
get_abi_alignment(ira->codegen, value->value.type));
ConstPtrMutComptimeConst, is_const, is_volatile, 0);
}
ZigType *ptr_type = get_pointer_to_type_extra(ira->codegen, value->value.type,
is_const, is_volatile, PtrLenSingle, get_abi_alignment(ira->codegen, value->value.type), 0, 0);
is_const, is_volatile, PtrLenSingle, 0, 0, 0);
IrInstruction *new_instruction = ir_build_ref(&ira->new_irb, source_instruction->scope,
source_instruction->source_node, value, is_const, is_volatile);
new_instruction->value.type = ptr_type;
@ -10185,9 +10238,9 @@ static IrInstruction *ir_analyze_enum_to_union(IrAnalyze *ira, IrInstruction *so
return ira->codegen->invalid_instruction;
TypeUnionField *union_field = find_union_field_by_tag(wanted_type, &val->data.x_enum_tag);
assert(union_field != nullptr);
if ((err = type_ensure_zero_bits_known(ira->codegen, union_field->type_entry)))
if ((err = type_resolve(ira->codegen, union_field->type_entry, ResolveStatusZeroBitsKnown)))
return ira->codegen->invalid_instruction;
if (!union_field->type_entry->zero_bits) {
if (type_has_bits(union_field->type_entry)) {
AstNode *field_node = wanted_type->data.unionation.decl_node->data.container_decl.fields.at(
union_field->enum_field->decl_index);
ErrorMsg *msg = ir_add_error(ira, source_instr,
@ -10490,7 +10543,10 @@ static IrInstruction *ir_analyze_ptr_to_array(IrAnalyze *ira, IrInstruction *sou
ZigType *wanted_type)
{
assert(wanted_type->id == ZigTypeIdPointer);
wanted_type = adjust_ptr_align(ira->codegen, wanted_type, target->value.type->data.pointer.alignment);
Error err;
if ((err = type_resolve(ira->codegen, target->value.type->data.pointer.child_type, ResolveStatusAlignmentKnown)))
return ira->codegen->invalid_instruction;
wanted_type = adjust_ptr_align(ira->codegen, wanted_type, get_ptr_align(ira->codegen, target->value.type));
ZigType *array_type = wanted_type->data.pointer.child_type;
assert(array_type->id == ZigTypeIdArray);
assert(array_type->data.array.len == 1);
@ -10537,6 +10593,8 @@ static void report_recursive_error(IrAnalyze *ira, AstNode *source_node, ConstCa
switch (cast_result->id) {
case ConstCastResultIdOk:
zig_unreachable();
case ConstCastResultIdInvalid:
zig_unreachable();
case ConstCastResultIdOptionalChild: {
ErrorMsg *msg = add_error_note(ira->codegen, parent_msg, source_node,
buf_sprintf("optional type child '%s' cannot cast into optional type child '%s'",
@ -10636,6 +10694,8 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
// perfect match or non-const to const
ConstCastOnly const_cast_result = types_match_const_cast_only(ira, wanted_type, actual_type,
source_node, false);
if (const_cast_result.id == ConstCastResultIdInvalid)
return ira->codegen->invalid_instruction;
if (const_cast_result.id == ConstCastResultIdOk) {
return ir_resolve_cast(ira, source_instr, value, wanted_type, CastOpNoop, false);
}
@ -10751,13 +10811,19 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
wanted_type->data.pointer.ptr_len == PtrLenUnknown &&
actual_type->id == ZigTypeIdPointer &&
actual_type->data.pointer.ptr_len == PtrLenSingle &&
actual_type->data.pointer.child_type->id == ZigTypeIdArray &&
actual_type->data.pointer.alignment >= wanted_type->data.pointer.alignment &&
types_match_const_cast_only(ira, wanted_type->data.pointer.child_type,
actual_type->data.pointer.child_type->data.array.child_type, source_node,
!wanted_type->data.pointer.is_const).id == ConstCastResultIdOk)
actual_type->data.pointer.child_type->id == ZigTypeIdArray)
{
return ir_resolve_ptr_of_array_to_unknown_len_ptr(ira, source_instr, value, wanted_type);
if ((err = type_resolve(ira->codegen, actual_type->data.pointer.child_type, ResolveStatusAlignmentKnown)))
return ira->codegen->invalid_instruction;
if ((err = type_resolve(ira->codegen, wanted_type->data.pointer.child_type, ResolveStatusAlignmentKnown)))
return ira->codegen->invalid_instruction;
if (get_ptr_align(ira->codegen, actual_type) >= get_ptr_align(ira->codegen, wanted_type) &&
types_match_const_cast_only(ira, wanted_type->data.pointer.child_type,
actual_type->data.pointer.child_type->data.array.child_type, source_node,
!wanted_type->data.pointer.is_const).id == ConstCastResultIdOk)
{
return ir_resolve_ptr_of_array_to_unknown_len_ptr(ira, source_instr, value, wanted_type);
}
}
// *[N]T to []T
@ -10811,16 +10877,23 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
wanted_child_type->data.pointer.ptr_len == PtrLenUnknown &&
actual_type->id == ZigTypeIdPointer &&
actual_type->data.pointer.ptr_len == PtrLenSingle &&
actual_type->data.pointer.child_type->id == ZigTypeIdArray &&
actual_type->data.pointer.alignment >= wanted_child_type->data.pointer.alignment &&
types_match_const_cast_only(ira, wanted_child_type->data.pointer.child_type,
actual_type->data.pointer.child_type->data.array.child_type, source_node,
!wanted_child_type->data.pointer.is_const).id == ConstCastResultIdOk)
actual_type->data.pointer.child_type->id == ZigTypeIdArray)
{
IrInstruction *cast1 = ir_resolve_ptr_of_array_to_unknown_len_ptr(ira, source_instr, value, wanted_child_type);
if (type_is_invalid(cast1->value.type))
if ((err = type_resolve(ira->codegen, actual_type->data.pointer.child_type, ResolveStatusAlignmentKnown)))
return ira->codegen->invalid_instruction;
return ir_analyze_maybe_wrap(ira, source_instr, cast1, wanted_type);
if ((err = type_resolve(ira->codegen, wanted_child_type->data.pointer.child_type, ResolveStatusAlignmentKnown)))
return ira->codegen->invalid_instruction;
if (get_ptr_align(ira->codegen, actual_type) >= get_ptr_align(ira->codegen, wanted_child_type) &&
types_match_const_cast_only(ira, wanted_child_type->data.pointer.child_type,
actual_type->data.pointer.child_type->data.array.child_type, source_node,
!wanted_child_type->data.pointer.is_const).id == ConstCastResultIdOk)
{
IrInstruction *cast1 = ir_resolve_ptr_of_array_to_unknown_len_ptr(ira, source_instr, value,
wanted_child_type);
if (type_is_invalid(cast1->value.type))
return ira->codegen->invalid_instruction;
return ir_analyze_maybe_wrap(ira, source_instr, cast1, wanted_type);
}
}
}
@ -10963,7 +11036,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
// cast from union to the enum type of the union
if (actual_type->id == ZigTypeIdUnion && wanted_type->id == ZigTypeIdEnum) {
if ((err = type_ensure_zero_bits_known(ira->codegen, actual_type)))
if ((err = type_resolve(ira->codegen, actual_type, ResolveStatusZeroBitsKnown)))
return ira->codegen->invalid_instruction;
if (actual_type->data.unionation.tag_type == wanted_type) {
@ -10976,7 +11049,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
(wanted_type->data.unionation.decl_node->data.container_decl.auto_enum ||
wanted_type->data.unionation.decl_node->data.container_decl.init_arg_expr != nullptr))
{
if ((err = type_ensure_zero_bits_known(ira->codegen, wanted_type)))
if ((err = type_resolve(ira->codegen, wanted_type, ResolveStatusZeroBitsKnown)))
return ira->codegen->invalid_instruction;
if (wanted_type->data.unionation.tag_type == actual_type) {
@ -10990,7 +11063,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
if (union_type->data.unionation.decl_node->data.container_decl.auto_enum ||
union_type->data.unionation.decl_node->data.container_decl.init_arg_expr != nullptr)
{
if ((err = type_ensure_zero_bits_known(ira->codegen, union_type)))
if ((err = type_resolve(ira->codegen, union_type, ResolveStatusZeroBitsKnown)))
return ira->codegen->invalid_instruction;
if (union_type->data.unionation.tag_type == actual_type) {
@ -11017,14 +11090,24 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
actual_type->data.pointer.child_type, source_node,
!wanted_type->data.pointer.is_const).id == ConstCastResultIdOk)
{
if (wanted_type->data.pointer.alignment > actual_type->data.pointer.alignment) {
if ((err = type_resolve(ira->codegen, wanted_type->data.pointer.child_type,
ResolveStatusAlignmentKnown)))
{
return ira->codegen->invalid_instruction;
}
if ((err = type_resolve(ira->codegen, actual_type->data.pointer.child_type,
ResolveStatusAlignmentKnown)))
{
return ira->codegen->invalid_instruction;
}
uint32_t wanted_align = get_ptr_align(ira->codegen, wanted_type);
uint32_t actual_align = get_ptr_align(ira->codegen, actual_type);
if (wanted_align > actual_align) {
ErrorMsg *msg = ir_add_error(ira, source_instr, buf_sprintf("cast increases pointer alignment"));
add_error_note(ira->codegen, msg, value->source_node,
buf_sprintf("'%s' has alignment %" PRIu32, buf_ptr(&actual_type->name),
actual_type->data.pointer.alignment));
buf_sprintf("'%s' has alignment %" PRIu32, buf_ptr(&actual_type->name), actual_align));
add_error_note(ira->codegen, msg, source_instr->source_node,
buf_sprintf("'%s' has alignment %" PRIu32, buf_ptr(&wanted_type->name),
wanted_type->data.pointer.alignment));
buf_sprintf("'%s' has alignment %" PRIu32, buf_ptr(&wanted_type->name), wanted_align));
return ira->codegen->invalid_instruction;
}
return ir_analyze_ptr_to_array(ira, source_instr, value, wanted_type);
@ -11036,7 +11119,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
types_match_const_cast_only(ira, wanted_type->data.pointer.child_type,
actual_type, source_node, !wanted_type->data.pointer.is_const).id == ConstCastResultIdOk)
{
if ((err = type_ensure_zero_bits_known(ira->codegen, actual_type))) {
if ((err = type_resolve(ira->codegen, actual_type, ResolveStatusZeroBitsKnown))) {
return ira->codegen->invalid_instruction;
}
if (!type_has_bits(actual_type)) {
@ -11282,8 +11365,7 @@ static Buf *ir_resolve_str(IrAnalyze *ira, IrInstruction *value) {
return nullptr;
ZigType *ptr_type = get_pointer_to_type_extra(ira->codegen, ira->codegen->builtin_types.entry_u8,
true, false, PtrLenUnknown,
get_abi_alignment(ira->codegen, ira->codegen->builtin_types.entry_u8), 0, 0);
true, false, PtrLenUnknown, 0, 0, 0);
ZigType *str_type = get_slice_type(ira->codegen, ptr_type);
IrInstruction *casted_value = ir_implicit_cast(ira, value, str_type);
if (type_is_invalid(casted_value->value.type))
@ -11573,8 +11655,6 @@ static ZigType *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *bin_op
ZigType *resolved_type = ir_resolve_peer_types(ira, source_node, nullptr, instructions, 2);
if (type_is_invalid(resolved_type))
return resolved_type;
if ((err = type_ensure_zero_bits_known(ira->codegen, resolved_type)))
return resolved_type;
bool operator_allowed;
switch (resolved_type->id) {
@ -11630,6 +11710,9 @@ static ZigType *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *bin_op
if (casted_op2 == ira->codegen->invalid_instruction)
return ira->codegen->builtin_types.entry_invalid;
if ((err = type_resolve(ira->codegen, resolved_type, ResolveStatusZeroBitsKnown)))
return resolved_type;
bool one_possible_value = !type_requires_comptime(resolved_type) && !type_has_bits(resolved_type);
if (one_possible_value || (instr_is_comptime(casted_op1) && instr_is_comptime(casted_op2))) {
ConstExprValue *op1_val = one_possible_value ? &casted_op1->value : ir_resolve_const(ira, casted_op1, UndefBad);
@ -12316,7 +12399,7 @@ static ZigType *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *instruc
out_array_val = out_val;
} else if (is_slice(op1_type) || is_slice(op2_type)) {
ZigType *ptr_type = get_pointer_to_type_extra(ira->codegen, child_type,
true, false, PtrLenUnknown, get_abi_alignment(ira->codegen, child_type), 0, 0);
true, false, PtrLenUnknown, 0, 0, 0);
result_type = get_slice_type(ira->codegen, ptr_type);
out_array_val = create_const_vals(1);
out_array_val->special = ConstValSpecialStatic;
@ -12337,8 +12420,7 @@ static ZigType *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *instruc
new_len += 1; // null byte
// TODO make this `[*]null T` instead of `[*]T`
result_type = get_pointer_to_type_extra(ira->codegen, child_type, true, false,
PtrLenUnknown, get_abi_alignment(ira->codegen, child_type), 0, 0);
result_type = get_pointer_to_type_extra(ira->codegen, child_type, true, false, PtrLenUnknown, 0, 0, 0);
out_array_val = create_const_vals(1);
out_array_val->special = ConstValSpecialStatic;
@ -12563,7 +12645,7 @@ static ZigType *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstructionDec
if (type_is_invalid(result_type)) {
result_type = ira->codegen->builtin_types.entry_invalid;
} else {
if ((err = type_ensure_zero_bits_known(ira->codegen, result_type))) {
if ((err = type_resolve(ira->codegen, result_type, ResolveStatusZeroBitsKnown))) {
result_type = ira->codegen->builtin_types.entry_invalid;
}
}
@ -12631,6 +12713,11 @@ static ZigType *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstructionDec
}
if (decl_var_instruction->align_value == nullptr) {
if ((err = type_resolve(ira->codegen, result_type, ResolveStatusAlignmentKnown))) {
var->value->type = ira->codegen->builtin_types.entry_invalid;
decl_var_instruction->base.other = &decl_var_instruction->base;
return ira->codegen->builtin_types.entry_void;
}
var->align_bytes = get_abi_alignment(ira->codegen, result_type);
} else {
if (!ir_resolve_align(ira, decl_var_instruction->align_value->other, &var->align_bytes)) {
@ -13100,7 +13187,6 @@ static ZigVar *get_fn_var_by_index(ZigFn *fn_entry, size_t index) {
static IrInstruction *ir_get_var_ptr(IrAnalyze *ira, IrInstruction *instruction,
ZigVar *var)
{
Error err;
while (var->next_var != nullptr) {
var = var->next_var;
}
@ -13158,8 +13244,6 @@ no_mem_slot:
instruction->scope, instruction->source_node, var);
var_ptr_instruction->value.type = get_pointer_to_type_extra(ira->codegen, var->value->type,
var->src_is_const, is_volatile, PtrLenSingle, var->align_bytes, 0, 0);
if ((err = type_ensure_zero_bits_known(ira->codegen, var->value->type)))
return ira->codegen->invalid_instruction;
bool in_fn_scope = (scope_fn_entry(var->parent_scope) != nullptr);
var_ptr_instruction->value.data.rh_ptr = in_fn_scope ? RuntimeHintPtrStack : RuntimeHintPtrNonStack;
@ -13356,8 +13440,7 @@ static ZigType *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call_instr
IrInstruction *casted_new_stack = nullptr;
if (call_instruction->new_stack != nullptr) {
ZigType *u8_ptr = get_pointer_to_type_extra(ira->codegen, ira->codegen->builtin_types.entry_u8,
false, false, PtrLenUnknown,
get_abi_alignment(ira->codegen, ira->codegen->builtin_types.entry_u8), 0, 0);
false, false, PtrLenUnknown, 0, 0, 0);
ZigType *u8_slice = get_slice_type(ira->codegen, u8_ptr);
IrInstruction *new_stack = call_instruction->new_stack->other;
if (type_is_invalid(new_stack->value.type))
@ -13536,7 +13619,7 @@ static ZigType *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call_instr
inst_fn_type_id.return_type = specified_return_type;
}
if ((err = type_ensure_zero_bits_known(ira->codegen, specified_return_type)))
if ((err = type_resolve(ira->codegen, specified_return_type, ResolveStatusZeroBitsKnown)))
return ira->codegen->builtin_types.entry_invalid;
if (type_requires_comptime(specified_return_type)) {
@ -14212,7 +14295,7 @@ static ZigType *adjust_ptr_len(CodeGen *g, ZigType *ptr_type, PtrLen ptr_len) {
ptr_type->data.pointer.child_type,
ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile,
ptr_len,
ptr_type->data.pointer.alignment,
ptr_type->data.pointer.explicit_alignment,
ptr_type->data.pointer.bit_offset, ptr_type->data.pointer.unaligned_bit_count);
}
@ -14264,7 +14347,7 @@ static ZigType *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstructionEle
return_type = get_pointer_to_type_extra(ira->codegen, child_type,
ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile,
elem_ptr_instruction->ptr_len,
ptr_type->data.pointer.alignment, 0, 0);
ptr_type->data.pointer.explicit_alignment, 0, 0);
} else {
uint64_t elem_val_scalar;
if (!ir_resolve_usize(ira, elem_index, &elem_val_scalar))
@ -14336,7 +14419,7 @@ static ZigType *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstructionEle
uint64_t elem_size = type_size(ira->codegen, return_type->data.pointer.child_type);
uint64_t abi_align = get_abi_alignment(ira->codegen, return_type->data.pointer.child_type);
uint64_t ptr_align = return_type->data.pointer.alignment;
uint64_t ptr_align = get_ptr_align(ira->codegen, return_type);
if (instr_is_comptime(casted_elem_index)) {
uint64_t index = bigint_as_unsigned(&casted_elem_index->value.data.x_bigint);
if (array_type->id == ZigTypeIdArray) {
@ -14653,9 +14736,7 @@ static IrInstruction *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_
}
ZigType *ptr_type = get_pointer_to_type_extra(ira->codegen, field_type,
is_const, is_volatile,
PtrLenSingle,
get_abi_alignment(ira->codegen, field_type), 0, 0);
is_const, is_volatile, PtrLenSingle, 0, 0, 0);
IrInstruction *result = ir_get_const(ira, source_instr);
ConstExprValue *const_val = &result->value;
@ -14669,7 +14750,7 @@ static IrInstruction *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_
IrInstruction *result = ir_build_union_field_ptr(&ira->new_irb, source_instr->scope, source_instr->source_node, container_ptr, field);
result->value.type = get_pointer_to_type_extra(ira->codegen, field->type_entry, is_const, is_volatile,
PtrLenSingle, get_abi_alignment(ira->codegen, field->type_entry), 0, 0);
PtrLenSingle, 0, 0, 0);
return result;
} else {
return ir_analyze_container_member_access_inner(ira, bare_type, field_name,
@ -15002,9 +15083,14 @@ static ZigType *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstructionFi
} else if (buf_eql_str(field_name, "alignment")) {
bool ptr_is_const = true;
bool ptr_is_volatile = false;
if ((err = type_resolve(ira->codegen, child_type->data.pointer.child_type,
ResolveStatusAlignmentKnown)))
{
return ira->codegen->builtin_types.entry_invalid;
}
return ir_analyze_const_ptr(ira, &field_ptr_instruction->base,
create_const_unsigned_negative(ira->codegen->builtin_types.entry_num_lit_int,
child_type->data.pointer.alignment, false),
get_ptr_align(ira->codegen, child_type), false),
ira->codegen->builtin_types.entry_num_lit_int,
ConstPtrMutComptimeConst, ptr_is_const, ptr_is_volatile);
} else {
@ -15461,7 +15547,7 @@ static ZigType *ir_analyze_instruction_slice_type(IrAnalyze *ira,
IrInstructionSliceType *slice_type_instruction)
{
Error err;
uint32_t align_bytes;
uint32_t align_bytes = 0;
if (slice_type_instruction->align_value != nullptr) {
if (!ir_resolve_align(ira, slice_type_instruction->align_value->other, &align_bytes))
return ira->codegen->builtin_types.entry_invalid;
@ -15471,12 +15557,6 @@ static ZigType *ir_analyze_instruction_slice_type(IrAnalyze *ira,
if (type_is_invalid(child_type))
return ira->codegen->builtin_types.entry_invalid;
if (slice_type_instruction->align_value == nullptr) {
if ((err = type_ensure_zero_bits_known(ira->codegen, child_type)))
return ira->codegen->builtin_types.entry_invalid;
align_bytes = get_abi_alignment(ira->codegen, child_type);
}
bool is_const = slice_type_instruction->is_const;
bool is_volatile = slice_type_instruction->is_volatile;
@ -15511,7 +15591,7 @@ static ZigType *ir_analyze_instruction_slice_type(IrAnalyze *ira,
case ZigTypeIdBoundFn:
case ZigTypeIdPromise:
{
if ((err = type_ensure_zero_bits_known(ira->codegen, child_type)))
if ((err = type_resolve(ira->codegen, child_type, ResolveStatusZeroBitsKnown)))
return ira->codegen->builtin_types.entry_invalid;
ZigType *slice_ptr_type = get_pointer_to_type_extra(ira->codegen, child_type,
is_const, is_volatile, PtrLenUnknown, align_bytes, 0, 0);
@ -15751,9 +15831,7 @@ static ZigType *ir_analyze_instruction_unwrap_maybe(IrAnalyze *ira,
}
ZigType *child_type = type_entry->data.maybe.child_type;
ZigType *result_type = get_pointer_to_type_extra(ira->codegen, child_type,
ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile,
PtrLenSingle,
get_abi_alignment(ira->codegen, child_type), 0, 0);
ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile, PtrLenSingle, 0, 0, 0);
if (instr_is_comptime(value)) {
ConstExprValue *val = ir_resolve_const(ira, value, UndefBad);
@ -16123,7 +16201,7 @@ static ZigType *ir_analyze_instruction_switch_target(IrAnalyze *ira,
return tag_type;
}
case ZigTypeIdEnum: {
if ((err = type_ensure_zero_bits_known(ira->codegen, target_type)))
if ((err = type_resolve(ira->codegen, target_type, ResolveStatusZeroBitsKnown)))
return ira->codegen->builtin_types.entry_invalid;
if (target_type->data.enumeration.src_field_count < 2) {
TypeEnumField *only_field = &target_type->data.enumeration.fields[0];
@ -16352,7 +16430,7 @@ static ZigType *ir_analyze_container_init_fields_union(IrAnalyze *ira, IrInstruc
if (casted_field_value == ira->codegen->invalid_instruction)
return ira->codegen->builtin_types.entry_invalid;
if ((err = type_ensure_zero_bits_known(ira->codegen, casted_field_value->value.type)))
if ((err = type_resolve(ira->codegen, casted_field_value->value.type, ResolveStatusZeroBitsKnown)))
return ira->codegen->builtin_types.entry_invalid;
bool is_comptime = ir_should_inline(ira->new_irb.exec, instruction->scope);
@ -16752,7 +16830,7 @@ static ZigType *ir_analyze_instruction_err_name(IrAnalyze *ira, IrInstructionErr
return ira->codegen->builtin_types.entry_invalid;
ZigType *u8_ptr_type = get_pointer_to_type_extra(ira->codegen, ira->codegen->builtin_types.entry_u8,
true, false, PtrLenUnknown, get_abi_alignment(ira->codegen, ira->codegen->builtin_types.entry_u8), 0, 0);
true, false, PtrLenUnknown, 0, 0, 0);
ZigType *str_type = get_slice_type(ira->codegen, u8_ptr_type);
if (casted_value->value.special == ConstValSpecialStatic) {
ErrorTableEntry *err = casted_value->value.data.x_err_set;
@ -16779,7 +16857,7 @@ static ZigType *ir_analyze_instruction_enum_tag_name(IrAnalyze *ira, IrInstructi
assert(target->value.type->id == ZigTypeIdEnum);
if (instr_is_comptime(target)) {
if ((err = type_ensure_zero_bits_known(ira->codegen, target->value.type)))
if ((err = type_resolve(ira->codegen, target->value.type, ResolveStatusZeroBitsKnown)))
return ira->codegen->builtin_types.entry_invalid;
TypeEnumField *field = find_enum_field_by_tag(target->value.type, &target->value.data.x_bigint);
ConstExprValue *array_val = create_const_str_lit(ira->codegen, field->name);
@ -16794,8 +16872,7 @@ static ZigType *ir_analyze_instruction_enum_tag_name(IrAnalyze *ira, IrInstructi
ZigType *u8_ptr_type = get_pointer_to_type_extra(
ira->codegen, ira->codegen->builtin_types.entry_u8,
true, false, PtrLenUnknown,
get_abi_alignment(ira->codegen, ira->codegen->builtin_types.entry_u8),
0, 0);
0, 0, 0);
result->value.type = get_slice_type(ira->codegen, u8_ptr_type);
return result->value.type;
}
@ -17158,8 +17235,7 @@ static Error ir_make_type_info_defs(IrAnalyze *ira, ConstExprValue *out_val, Sco
ZigType *u8_ptr = get_pointer_to_type_extra(
ira->codegen, ira->codegen->builtin_types.entry_u8,
true, false, PtrLenUnknown,
get_abi_alignment(ira->codegen, ira->codegen->builtin_types.entry_u8),
0, 0);
0, 0, 0);
fn_def_fields[6].type = get_optional_type(ira->codegen, get_slice_type(ira->codegen, u8_ptr));
if (fn_node->is_extern && buf_len(fn_node->lib_name) > 0) {
fn_def_fields[6].data.x_optional = create_const_vals(1);
@ -17279,7 +17355,7 @@ static ConstExprValue *create_ptr_like_type_info(IrAnalyze *ira, ZigType *ptr_ty
ensure_field_index(result->type, "alignment", 3);
fields[3].special = ConstValSpecialStatic;
fields[3].type = get_int_type(ira->codegen, false, 29);
bigint_init_unsigned(&fields[3].data.x_bigint, attrs_type->data.pointer.alignment);
bigint_init_unsigned(&fields[3].data.x_bigint, get_ptr_align(ira->codegen, attrs_type));
// child: type
ensure_field_index(result->type, "child", 4);
fields[4].special = ConstValSpecialStatic;
@ -18369,7 +18445,21 @@ static ZigType *ir_analyze_instruction_err_set_cast(IrAnalyze *ira, IrInstructio
return dest_type;
}
static Error resolve_ptr_align(IrAnalyze *ira, ZigType *ty, uint32_t *result_align) {
Error err;
if (ty->id == ZigTypeIdPointer) {
if ((err = type_resolve(ira->codegen, ty->data.pointer.child_type, ResolveStatusAlignmentKnown)))
return err;
}
*result_align = get_ptr_align(ira->codegen, ty);
return ErrorNone;
}
static ZigType *ir_analyze_instruction_from_bytes(IrAnalyze *ira, IrInstructionFromBytes *instruction) {
Error err;
ZigType *dest_child_type = ir_resolve_type(ira, instruction->dest_child_type->other);
if (type_is_invalid(dest_child_type))
return ira->codegen->builtin_types.entry_invalid;
@ -18384,15 +18474,23 @@ static ZigType *ir_analyze_instruction_from_bytes(IrAnalyze *ira, IrInstructionF
if (target->value.type->id == ZigTypeIdPointer) {
src_ptr_const = target->value.type->data.pointer.is_const;
src_ptr_volatile = target->value.type->data.pointer.is_volatile;
src_ptr_align = target->value.type->data.pointer.alignment;
if ((err = resolve_ptr_align(ira, target->value.type, &src_ptr_align)))
return ira->codegen->builtin_types.entry_invalid;
} else if (is_slice(target->value.type)) {
ZigType *src_ptr_type = target->value.type->data.structure.fields[slice_ptr_index].type_entry;
src_ptr_const = src_ptr_type->data.pointer.is_const;
src_ptr_volatile = src_ptr_type->data.pointer.is_volatile;
src_ptr_align = src_ptr_type->data.pointer.alignment;
if ((err = resolve_ptr_align(ira, src_ptr_type, &src_ptr_align)))
return ira->codegen->builtin_types.entry_invalid;
} else {
src_ptr_const = true;
src_ptr_volatile = false;
if ((err = type_resolve(ira->codegen, target->value.type, ResolveStatusAlignmentKnown)))
return ira->codegen->builtin_types.entry_invalid;
src_ptr_align = get_abi_alignment(ira->codegen, target->value.type);
}
@ -18450,6 +18548,8 @@ static ZigType *ir_analyze_instruction_from_bytes(IrAnalyze *ira, IrInstructionF
}
static ZigType *ir_analyze_instruction_to_bytes(IrAnalyze *ira, IrInstructionToBytes *instruction) {
Error err;
IrInstruction *target = instruction->target->other;
if (type_is_invalid(target->value.type))
return ira->codegen->builtin_types.entry_invalid;
@ -18462,9 +18562,13 @@ static ZigType *ir_analyze_instruction_to_bytes(IrAnalyze *ira, IrInstructionToB
ZigType *src_ptr_type = target->value.type->data.structure.fields[slice_ptr_index].type_entry;
uint32_t alignment;
if ((err = resolve_ptr_align(ira, src_ptr_type, &alignment)))
return ira->codegen->builtin_types.entry_invalid;
ZigType *dest_ptr_type = get_pointer_to_type_extra(ira->codegen, ira->codegen->builtin_types.entry_u8,
src_ptr_type->data.pointer.is_const, src_ptr_type->data.pointer.is_volatile, PtrLenUnknown,
src_ptr_type->data.pointer.alignment, 0, 0);
alignment, 0, 0);
ZigType *dest_slice_type = get_slice_type(ira->codegen, dest_ptr_type);
IrInstruction *result = ir_resolve_cast(ira, &instruction->base, target, dest_slice_type, CastOpResizeSlice, true);
@ -18622,6 +18726,8 @@ static ZigType *ir_analyze_instruction_bool_not(IrAnalyze *ira, IrInstructionBoo
}
static ZigType *ir_analyze_instruction_memset(IrAnalyze *ira, IrInstructionMemset *instruction) {
Error err;
IrInstruction *dest_ptr = instruction->dest_ptr->other;
if (type_is_invalid(dest_ptr->value.type))
return ira->codegen->builtin_types.entry_invalid;
@ -18640,8 +18746,13 @@ static ZigType *ir_analyze_instruction_memset(IrAnalyze *ira, IrInstructionMemse
ZigType *usize = ira->codegen->builtin_types.entry_usize;
ZigType *u8 = ira->codegen->builtin_types.entry_u8;
uint32_t dest_align = (dest_uncasted_type->id == ZigTypeIdPointer) ?
dest_uncasted_type->data.pointer.alignment : get_abi_alignment(ira->codegen, u8);
uint32_t dest_align;
if (dest_uncasted_type->id == ZigTypeIdPointer) {
if ((err = resolve_ptr_align(ira, dest_uncasted_type, &dest_align)))
return ira->codegen->builtin_types.entry_invalid;
} else {
dest_align = get_abi_alignment(ira->codegen, u8);
}
ZigType *u8_ptr = get_pointer_to_type_extra(ira->codegen, u8, false, dest_is_volatile,
PtrLenUnknown, dest_align, 0, 0);
@ -18714,6 +18825,8 @@ static ZigType *ir_analyze_instruction_memset(IrAnalyze *ira, IrInstructionMemse
}
static ZigType *ir_analyze_instruction_memcpy(IrAnalyze *ira, IrInstructionMemcpy *instruction) {
Error err;
IrInstruction *dest_ptr = instruction->dest_ptr->other;
if (type_is_invalid(dest_ptr->value.type))
return ira->codegen->builtin_types.entry_invalid;
@ -18733,10 +18846,22 @@ static ZigType *ir_analyze_instruction_memcpy(IrAnalyze *ira, IrInstructionMemcp
dest_uncasted_type->data.pointer.is_volatile;
bool src_is_volatile = (src_uncasted_type->id == ZigTypeIdPointer) &&
src_uncasted_type->data.pointer.is_volatile;
uint32_t dest_align = (dest_uncasted_type->id == ZigTypeIdPointer) ?
dest_uncasted_type->data.pointer.alignment : get_abi_alignment(ira->codegen, u8);
uint32_t src_align = (src_uncasted_type->id == ZigTypeIdPointer) ?
src_uncasted_type->data.pointer.alignment : get_abi_alignment(ira->codegen, u8);
uint32_t dest_align;
if (dest_uncasted_type->id == ZigTypeIdPointer) {
if ((err = resolve_ptr_align(ira, dest_uncasted_type, &dest_align)))
return ira->codegen->builtin_types.entry_invalid;
} else {
dest_align = get_abi_alignment(ira->codegen, u8);
}
uint32_t src_align;
if (src_uncasted_type->id == ZigTypeIdPointer) {
if ((err = resolve_ptr_align(ira, src_uncasted_type, &src_align)))
return ira->codegen->builtin_types.entry_invalid;
} else {
src_align = get_abi_alignment(ira->codegen, u8);
}
ZigType *usize = ira->codegen->builtin_types.entry_usize;
ZigType *u8_ptr_mut = get_pointer_to_type_extra(ira->codegen, u8, false, dest_is_volatile,
@ -18881,17 +19006,13 @@ static ZigType *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstructionSlice
ZigType *return_type;
if (array_type->id == ZigTypeIdArray) {
uint32_t byte_alignment = ptr_type->data.pointer.alignment;
if (array_type->data.array.len == 0 && byte_alignment == 0) {
byte_alignment = get_abi_alignment(ira->codegen, array_type->data.array.child_type);
}
bool is_comptime_const = ptr_ptr->value.special == ConstValSpecialStatic &&
ptr_ptr->value.data.x_ptr.mut == ConstPtrMutComptimeConst;
ZigType *slice_ptr_type = get_pointer_to_type_extra(ira->codegen, array_type->data.array.child_type,
ptr_type->data.pointer.is_const || is_comptime_const,
ptr_type->data.pointer.is_volatile,
PtrLenUnknown,
byte_alignment, 0, 0);
ptr_type->data.pointer.explicit_alignment, 0, 0);
return_type = get_slice_type(ira->codegen, slice_ptr_type);
} else if (array_type->id == ZigTypeIdPointer) {
if (array_type->data.pointer.ptr_len == PtrLenSingle) {
@ -18901,7 +19022,7 @@ static ZigType *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstructionSlice
main_type->data.pointer.child_type,
array_type->data.pointer.is_const, array_type->data.pointer.is_volatile,
PtrLenUnknown,
array_type->data.pointer.alignment, 0, 0);
array_type->data.pointer.explicit_alignment, 0, 0);
return_type = get_slice_type(ira->codegen, slice_ptr_type);
} else {
ir_add_error(ira, &instruction->base, buf_sprintf("slice of single-item pointer"));
@ -18911,7 +19032,7 @@ static ZigType *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstructionSlice
ZigType *slice_ptr_type = get_pointer_to_type_extra(ira->codegen, array_type->data.pointer.child_type,
array_type->data.pointer.is_const, array_type->data.pointer.is_volatile,
PtrLenUnknown,
array_type->data.pointer.alignment, 0, 0);
array_type->data.pointer.explicit_alignment, 0, 0);
return_type = get_slice_type(ira->codegen, slice_ptr_type);
if (!end) {
ir_add_error(ira, &instruction->base, buf_sprintf("slice of pointer must include end value"));
@ -19292,7 +19413,7 @@ static ZigType *ir_analyze_instruction_align_of(IrAnalyze *ira, IrInstructionAli
return ira->codegen->builtin_types.entry_invalid;
ZigType *type_entry = ir_resolve_type(ira, type_value);
if ((err = type_ensure_zero_bits_known(ira->codegen, type_entry)))
if ((err = type_resolve(ira->codegen, type_entry, ResolveStatusAlignmentKnown)))
return ira->codegen->builtin_types.entry_invalid;
switch (type_entry->id) {
@ -19336,6 +19457,8 @@ static ZigType *ir_analyze_instruction_align_of(IrAnalyze *ira, IrInstructionAli
}
static ZigType *ir_analyze_instruction_overflow_op(IrAnalyze *ira, IrInstructionOverflowOp *instruction) {
Error err;
IrInstruction *type_value = instruction->type_value->other;
if (type_is_invalid(type_value->value.type))
return ira->codegen->builtin_types.entry_invalid;
@ -19379,10 +19502,13 @@ static ZigType *ir_analyze_instruction_overflow_op(IrAnalyze *ira, IrInstruction
ZigType *expected_ptr_type;
if (result_ptr->value.type->id == ZigTypeIdPointer) {
uint32_t alignment;
if ((err = resolve_ptr_align(ira, result_ptr->value.type, &alignment)))
return ira->codegen->builtin_types.entry_invalid;
expected_ptr_type = get_pointer_to_type_extra(ira->codegen, dest_type,
false, result_ptr->value.type->data.pointer.is_volatile,
PtrLenSingle,
result_ptr->value.type->data.pointer.alignment, 0, 0);
alignment, 0, 0);
} else {
expected_ptr_type = get_pointer_to_type(ira->codegen, dest_type, false);
}
@ -19544,8 +19670,7 @@ static ZigType *ir_analyze_instruction_unwrap_err_payload(IrAnalyze *ira,
}
ZigType *result_type = get_pointer_to_type_extra(ira->codegen, payload_type,
ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile,
PtrLenSingle,
get_abi_alignment(ira->codegen, payload_type), 0, 0);
PtrLenSingle, 0, 0, 0);
if (instr_is_comptime(value)) {
ConstExprValue *ptr_val = ir_resolve_const(ira, value, UndefBad);
if (!ptr_val)
@ -19624,7 +19749,7 @@ static ZigType *ir_analyze_instruction_fn_proto(IrAnalyze *ira, IrInstructionFnP
ZigType *param_type = ir_resolve_type(ira, param_type_value);
if (type_is_invalid(param_type))
return ira->codegen->builtin_types.entry_invalid;
if ((err = type_ensure_zero_bits_known(ira->codegen, param_type)))
if ((err = type_resolve(ira->codegen, param_type, ResolveStatusZeroBitsKnown)))
return ira->codegen->builtin_types.entry_invalid;
if (type_requires_comptime(param_type)) {
if (!calling_convention_allows_zig_types(fn_type_id.cc)) {
@ -19899,7 +20024,7 @@ static ZigType *ir_analyze_instruction_panic(IrAnalyze *ira, IrInstructionPanic
}
ZigType *u8_ptr_type = get_pointer_to_type_extra(ira->codegen, ira->codegen->builtin_types.entry_u8,
true, false, PtrLenUnknown, get_abi_alignment(ira->codegen, ira->codegen->builtin_types.entry_u8), 0, 0);
true, false, PtrLenUnknown, 0, 0, 0);
ZigType *str_type = get_slice_type(ira->codegen, u8_ptr_type);
IrInstruction *casted_msg = ir_implicit_cast(ira, msg, str_type);
if (type_is_invalid(casted_msg->value.type))
@ -19912,6 +20037,8 @@ static ZigType *ir_analyze_instruction_panic(IrAnalyze *ira, IrInstructionPanic
}
static IrInstruction *ir_align_cast(IrAnalyze *ira, IrInstruction *target, uint32_t align_bytes, bool safety_check_on) {
Error err;
ZigType *target_type = target->value.type;
assert(!type_is_invalid(target_type));
@ -19920,7 +20047,8 @@ static IrInstruction *ir_align_cast(IrAnalyze *ira, IrInstruction *target, uint3
if (target_type->id == ZigTypeIdPointer) {
result_type = adjust_ptr_align(ira->codegen, target_type, align_bytes);
old_align_bytes = target_type->data.pointer.alignment;
if ((err = resolve_ptr_align(ira, target_type, &old_align_bytes)))
return ira->codegen->invalid_instruction;
} else if (target_type->id == ZigTypeIdFn) {
FnTypeId fn_type_id = target_type->data.fn.fn_type_id;
old_align_bytes = fn_type_id.alignment;
@ -19930,7 +20058,8 @@ static IrInstruction *ir_align_cast(IrAnalyze *ira, IrInstruction *target, uint3
target_type->data.maybe.child_type->id == ZigTypeIdPointer)
{
ZigType *ptr_type = target_type->data.maybe.child_type;
old_align_bytes = ptr_type->data.pointer.alignment;
if ((err = resolve_ptr_align(ira, ptr_type, &old_align_bytes)))
return ira->codegen->invalid_instruction;
ZigType *better_ptr_type = adjust_ptr_align(ira->codegen, ptr_type, align_bytes);
result_type = get_optional_type(ira->codegen, better_ptr_type);
@ -19944,7 +20073,8 @@ static IrInstruction *ir_align_cast(IrAnalyze *ira, IrInstruction *target, uint3
result_type = get_optional_type(ira->codegen, fn_type);
} else if (is_slice(target_type)) {
ZigType *slice_ptr_type = target_type->data.structure.fields[slice_ptr_index].type_entry;
old_align_bytes = slice_ptr_type->data.pointer.alignment;
if ((err = resolve_ptr_align(ira, slice_ptr_type, &old_align_bytes)))
return ira->codegen->invalid_instruction;
ZigType *result_ptr_type = adjust_ptr_align(ira->codegen, slice_ptr_type, align_bytes);
result_type = get_slice_type(ira->codegen, result_ptr_type);
} else {
@ -20023,8 +20153,13 @@ static ZigType *ir_analyze_instruction_ptr_cast(IrAnalyze *ira, IrInstructionPtr
return dest_type;
}
uint32_t src_align_bytes = get_ptr_align(ira->codegen, src_type);
uint32_t dest_align_bytes = get_ptr_align(ira->codegen, dest_type);
uint32_t src_align_bytes;
if ((err = resolve_ptr_align(ira, src_type, &src_align_bytes)))
return ira->codegen->builtin_types.entry_invalid;
uint32_t dest_align_bytes;
if ((err = resolve_ptr_align(ira, dest_type, &dest_align_bytes)))
return ira->codegen->builtin_types.entry_invalid;
if (dest_align_bytes > src_align_bytes) {
ErrorMsg *msg = ir_add_error(ira, &instruction->base, buf_sprintf("cast increases pointer alignment"));
@ -20041,7 +20176,7 @@ static ZigType *ir_analyze_instruction_ptr_cast(IrAnalyze *ira, IrInstructionPtr
// Keep the bigger alignment, it can only help-
// unless the target is zero bits.
if ((err = type_ensure_zero_bits_known(ira->codegen, dest_type)))
if ((err = type_resolve(ira->codegen, dest_type, ResolveStatusZeroBitsKnown)))
return ira->codegen->builtin_types.entry_invalid;
IrInstruction *result;
@ -20289,7 +20424,7 @@ static ZigType *ir_analyze_instruction_int_to_ptr(IrAnalyze *ira, IrInstructionI
return ira->codegen->builtin_types.entry_invalid;
}
if ((err = type_ensure_zero_bits_known(ira->codegen, dest_type)))
if ((err = type_resolve(ira->codegen, dest_type, ResolveStatusZeroBitsKnown)))
return ira->codegen->builtin_types.entry_invalid;
if (!type_has_bits(dest_type)) {
ir_add_error(ira, dest_type_value,
@ -20440,12 +20575,15 @@ static ZigType *ir_analyze_instruction_ptr_type(IrAnalyze *ira, IrInstructionPtr
if (instruction->align_value != nullptr) {
if (!ir_resolve_align(ira, instruction->align_value->other, &align_bytes))
return ira->codegen->builtin_types.entry_invalid;
} else {
if ((err = type_ensure_zero_bits_known(ira->codegen, child_type)))
if ((err = type_resolve(ira->codegen, child_type, ResolveStatusAlignmentKnown)))
return ira->codegen->builtin_types.entry_invalid;
align_bytes = get_abi_alignment(ira->codegen, child_type);
} else {
if ((err = type_resolve(ira->codegen, child_type, ResolveStatusZeroBitsKnown)))
return ira->codegen->builtin_types.entry_invalid;
align_bytes = 0;
}
ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
out_val->data.x_type = get_pointer_to_type_extra(ira->codegen, child_type,
instruction->is_const, instruction->is_volatile,
@ -21089,7 +21227,7 @@ static ZigType *ir_analyze_instruction_enum_to_int(IrAnalyze *ira, IrInstruction
return ira->codegen->builtin_types.entry_invalid;
}
if ((err = type_ensure_zero_bits_known(ira->codegen, target->value.type)))
if ((err = type_resolve(ira->codegen, target->value.type, ResolveStatusZeroBitsKnown)))
return ira->codegen->builtin_types.entry_invalid;
ZigType *tag_type = target->value.type->data.enumeration.tag_int_type;
@ -21112,7 +21250,7 @@ static ZigType *ir_analyze_instruction_int_to_enum(IrAnalyze *ira, IrInstruction
return ira->codegen->builtin_types.entry_invalid;
}
if ((err = type_ensure_zero_bits_known(ira->codegen, dest_type)))
if ((err = type_resolve(ira->codegen, dest_type, ResolveStatusZeroBitsKnown)))
return ira->codegen->builtin_types.entry_invalid;
ZigType *tag_type = dest_type->data.enumeration.tag_int_type;

View File

@ -916,7 +916,7 @@ fn openSelfDebugInfoMacOs(allocator: *mem.Allocator) !DebugInfo {
} else {
return error.MissingDebugInfo;
};
const syms = @ptrCast([*]macho.nlist_64, hdr_base + symtab.symoff)[0..symtab.nsyms];
const syms = @ptrCast([*]macho.nlist_64, @alignCast(@alignOf(macho.nlist_64), hdr_base + symtab.symoff))[0..symtab.nsyms];
const strings = @ptrCast([*]u8, hdr_base + symtab.stroff)[0..symtab.strsize];
const symbols_buf = try allocator.alloc(MachoSymbol, syms.len);
@ -1497,14 +1497,14 @@ fn getLineNumberInfoMacOs(di: *DebugInfo, symbol: MachoSymbol, target_address: u
const segcmd = while (ncmd != 0) : (ncmd -= 1) {
const lc = @ptrCast(*const std.macho.load_command, ptr);
switch (lc.cmd) {
std.macho.LC_SEGMENT_64 => break @ptrCast(*const std.macho.segment_command_64, ptr),
std.macho.LC_SEGMENT_64 => break @ptrCast(*const std.macho.segment_command_64, @alignCast(@alignOf(std.macho.segment_command_64), ptr)),
else => {},
}
ptr += lc.cmdsize; // TODO https://github.com/ziglang/zig/issues/1403
} else {
return error.MissingDebugInfo;
};
const sections = @alignCast(@alignOf(macho.section_64), @ptrCast([*]const macho.section_64, ptr + @sizeOf(std.macho.segment_command_64)))[0..segcmd.nsects];
const sections = @ptrCast([*]const macho.section_64, @alignCast(@alignOf(macho.section_64), ptr + @sizeOf(std.macho.segment_command_64)))[0..segcmd.nsects];
for (sections) |*sect| {
if (sect.flags & macho.SECTION_TYPE == macho.S_REGULAR and
(sect.flags & macho.SECTION_ATTRIBUTES) & macho.S_ATTR_DEBUG == macho.S_ATTR_DEBUG)

View File

@ -212,3 +212,10 @@ fn fnWithAlignedStack() i32 {
@setAlignStack(256);
return 1234;
}
test "alignment of structs" {
assert(@alignOf(struct {
a: i32,
b: *i32,
}) == @alignOf(usize));
}

View File

@ -3444,7 +3444,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
\\
\\export fn entry() usize { return @sizeOf(@typeOf(foo)); }
,
".tmp_source.zig:8:26: error: expected type '*const u3', found '*align(1:3:6) const u3'",
".tmp_source.zig:8:26: error: expected type '*const u3', found '*align(:3:6) const u3'",
);
cases.add(