mirror of
https://github.com/ziglang/zig.git
synced 2024-11-15 08:33:06 +00:00
parent
639c381128
commit
3f776af3fa
@ -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 {
|
||||
|
449
src/analyze.cpp
449
src/analyze.cpp
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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[] = {
|
||||
|
378
src/ir.cpp
378
src/ir.cpp
@ -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;
|
||||
|
@ -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)
|
||||
|
@ -212,3 +212,10 @@ fn fnWithAlignedStack() i32 {
|
||||
@setAlignStack(256);
|
||||
return 1234;
|
||||
}
|
||||
|
||||
test "alignment of structs" {
|
||||
assert(@alignOf(struct {
|
||||
a: i32,
|
||||
b: *i32,
|
||||
}) == @alignOf(usize));
|
||||
}
|
||||
|
@ -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(
|
||||
|
Loading…
Reference in New Issue
Block a user