introduce lazy values

but I think it's a bad idea, so I'm going to back out the change
This commit is contained in:
Andrew Kelley 2019-04-01 12:53:57 -04:00
parent ee5064c053
commit 3dc8448680
No known key found for this signature in database
GPG Key ID: 7C5F548F728501A9
6 changed files with 686 additions and 269 deletions

View File

@ -256,6 +256,7 @@ enum ConstValSpecial {
ConstValSpecialRuntime, ConstValSpecialRuntime,
ConstValSpecialStatic, ConstValSpecialStatic,
ConstValSpecialUndef, ConstValSpecialUndef,
ConstValSpecialLazy,
}; };
enum RuntimeHintErrorUnion { enum RuntimeHintErrorUnion {
@ -291,6 +292,43 @@ struct ConstGlobalRefs {
LLVMValueRef llvm_global; LLVMValueRef llvm_global;
}; };
enum LazyValueId {
LazyValueIdInvalid,
LazyValueIdAlignOf,
LazyValueIdSliceType,
LazyValueIdFnType,
};
struct LazyValue {
LazyValueId id;
IrExecutable *exec;
};
struct LazyValueAlignOf {
LazyValue base;
ZigType *target_type;
};
struct LazyValueSliceType {
LazyValue base;
ZigType *elem_type;
ConstExprValue *align_val; // can be null
bool is_const;
bool is_volatile;
bool is_allowzero;
};
struct LazyValueFnType {
LazyValue base;
AstNode *proto_node;
ConstExprValue **param_types;
ConstExprValue *align_val; // can be null
ConstExprValue *return_type;
ConstExprValue *async_allocator_type;
bool is_generic;
bool is_var_args;
};
struct ConstExprValue { struct ConstExprValue {
ZigType *type; ZigType *type;
ConstValSpecial special; ConstValSpecial special;
@ -318,6 +356,7 @@ struct ConstExprValue {
ConstPtrValue x_ptr; ConstPtrValue x_ptr;
ConstArgTuple x_arg_tuple; ConstArgTuple x_arg_tuple;
Buf *x_enum_literal; Buf *x_enum_literal;
LazyValue *x_lazy;
// populated if special == ConstValSpecialRuntime // populated if special == ConstValSpecialRuntime
RuntimeHintErrorUnion rh_error_union; RuntimeHintErrorUnion rh_error_union;
@ -359,6 +398,7 @@ enum TldResolution {
TldResolutionUnresolved, TldResolutionUnresolved,
TldResolutionResolving, TldResolutionResolving,
TldResolutionInvalid, TldResolutionInvalid,
TldResolutionOkLazy,
TldResolutionOk, TldResolutionOk,
}; };
@ -1064,7 +1104,8 @@ struct ZigTypeArray {
struct TypeStructField { struct TypeStructField {
Buf *name; Buf *name;
ZigType *type_entry; ZigType *type_entry; // available after ResolveStatusSizeKnown
ConstExprValue *type_val; // available after ResolveStatusZeroBitsKnown
size_t src_index; size_t src_index;
size_t gen_index; size_t gen_index;
size_t offset; // byte offset from beginning of struct size_t offset; // byte offset from beginning of struct
@ -1893,7 +1934,6 @@ struct ZigVar {
AstNode *decl_node; AstNode *decl_node;
ZigLLVMDILocalVariable *di_loc_var; ZigLLVMDILocalVariable *di_loc_var;
size_t src_arg_index; size_t src_arg_index;
size_t gen_arg_index;
Scope *parent_scope; Scope *parent_scope;
Scope *child_scope; Scope *child_scope;
LLVMValueRef param_value_ref; LLVMValueRef param_value_ref;

View File

@ -19,7 +19,6 @@
static const size_t default_backward_branch_quota = 1000; static const size_t default_backward_branch_quota = 1000;
static Error resolve_enum_type(CodeGen *g, ZigType *enum_type);
static Error resolve_struct_type(CodeGen *g, ZigType *struct_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_zero_bits(CodeGen *g, ZigType *struct_type);
@ -568,12 +567,11 @@ static size_t align_forward(size_t addr, size_t alignment) {
return (addr + alignment - 1) & ~(alignment - 1); return (addr + alignment - 1) & ~(alignment - 1);
} }
static size_t next_field_offset(size_t offset, size_t align_from_zero, size_t field_size, size_t field_align) { static size_t next_field_offset(size_t offset, size_t align_from_zero, size_t field_size, size_t next_field_align) {
BREAKPOINT; // TODO test this
// Convert offset to a pretend address which has the specified alignment. // Convert offset to a pretend address which has the specified alignment.
size_t addr = offset + align_from_zero; size_t addr = offset + align_from_zero;
// March the address forward to respect the field alignment. // March the address forward to respect the field alignment.
size_t aligned_addr = align_forward(addr + field_size, field_align); size_t aligned_addr = align_forward(addr + field_size, next_field_align);
// Convert back from pretend address to offset. // Convert back from pretend address to offset.
return aligned_addr - align_from_zero; return aligned_addr - align_from_zero;
} }
@ -623,8 +621,8 @@ ZigType *get_error_union_type(CodeGen *g, ZigType *err_set_type, ZigType *payloa
field_aligns[err_union_err_index] = err_set_type->abi_align; field_aligns[err_union_err_index] = err_set_type->abi_align;
field_sizes[err_union_payload_index] = payload_type->abi_size; field_sizes[err_union_payload_index] = payload_type->abi_size;
field_aligns[err_union_payload_index] = payload_type->abi_align; field_aligns[err_union_payload_index] = payload_type->abi_align;
size_t field2_offset = next_field_offset(0, entry->abi_align, field_sizes[0], field_aligns[0]); size_t field2_offset = next_field_offset(0, entry->abi_align, field_sizes[0], field_aligns[1]);
entry->abi_size = next_field_offset(field2_offset, entry->abi_align, field_sizes[1], field_aligns[1]); entry->abi_size = next_field_offset(field2_offset, entry->abi_align, field_sizes[1], entry->abi_align);
entry->size_in_bits = entry->abi_size * 8; entry->size_in_bits = entry->abi_size * 8;
} }
@ -699,6 +697,15 @@ ZigType *get_slice_type(CodeGen *g, ZigType *ptr_type) {
entry->data.structure.fields_by_name.put(ptr_field_name, &entry->data.structure.fields[slice_ptr_index]); 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]); entry->data.structure.fields_by_name.put(len_field_name, &entry->data.structure.fields[slice_len_index]);
switch (type_requires_comptime(g, ptr_type)) {
case ReqCompTimeInvalid:
zig_unreachable();
case ReqCompTimeNo:
break;
case ReqCompTimeYes:
entry->data.structure.requires_comptime = true;
}
if (!type_has_bits(ptr_type)) { if (!type_has_bits(ptr_type)) {
entry->data.structure.gen_field_count = 1; entry->data.structure.gen_field_count = 1;
entry->data.structure.fields[slice_ptr_index].gen_index = SIZE_MAX; entry->data.structure.fields[slice_ptr_index].gen_index = SIZE_MAX;
@ -897,8 +904,8 @@ ZigType *get_fn_type(CodeGen *g, FnTypeId *fn_type_id) {
fn_type->size_in_bits = g->builtin_types.entry_usize->size_in_bits; fn_type->size_in_bits = g->builtin_types.entry_usize->size_in_bits;
fn_type->abi_size = g->builtin_types.entry_usize->abi_size; fn_type->abi_size = g->builtin_types.entry_usize->abi_size;
fn_type->abi_align = (fn_type_id->alignment == 0) ? // see also type_val_resolve_abi_align
g->builtin_types.entry_usize->abi_align : fn_type_id->alignment; fn_type->abi_align = (fn_type_id->alignment == 0) ? 1 : fn_type_id->alignment;
g->fn_type_table.put(&fn_type->data.fn.fn_type_id, fn_type); g->fn_type_table.put(&fn_type->data.fn.fn_type_id, fn_type);
@ -956,15 +963,134 @@ ZigType *get_partial_container_type(CodeGen *g, Scope *scope, ContainerKind kind
return entry; return entry;
} }
static ConstExprValue *analyze_const_value(CodeGen *g, Scope *scope, AstNode *node, ZigType *type_entry, static ConstExprValue *analyze_const_value_allow_lazy(CodeGen *g, Scope *scope, AstNode *node, ZigType *type_entry,
Buf *type_name) Buf *type_name, bool allow_lazy)
{ {
size_t backward_branch_count = 0; size_t backward_branch_count = 0;
return ir_eval_const_value(g, scope, node, type_entry, return ir_eval_const_value(g, scope, node, type_entry,
&backward_branch_count, default_backward_branch_quota, &backward_branch_count, default_backward_branch_quota,
nullptr, nullptr, node, type_name, nullptr, nullptr); nullptr, nullptr, node, type_name, nullptr, nullptr, allow_lazy);
} }
static ConstExprValue *analyze_const_value(CodeGen *g, Scope *scope, AstNode *node, ZigType *type_entry,
Buf *type_name)
{
return analyze_const_value_allow_lazy(g, scope, node, type_entry, type_name, false);
}
static Error type_val_resolve_zero_bits(CodeGen *g, ConstExprValue *type_val, bool *is_zero_bits) {
Error err;
if (type_val->special != ConstValSpecialLazy) {
assert(type_val->special == ConstValSpecialStatic);
if ((err = type_resolve(g, type_val->data.x_type, ResolveStatusZeroBitsKnown)))
return err;
*is_zero_bits = (type_val->data.x_type->abi_size == 0);
return ErrorNone;
}
switch (type_val->data.x_lazy->id) {
case LazyValueIdInvalid:
case LazyValueIdAlignOf:
zig_unreachable();
case LazyValueIdSliceType:
*is_zero_bits = false;
return ErrorNone;
case LazyValueIdFnType: {
LazyValueFnType *lazy_fn_type = reinterpret_cast<LazyValueFnType *>(type_val->data.x_lazy);
*is_zero_bits = lazy_fn_type->is_generic;
return ErrorNone;
}
}
zig_unreachable();
}
static Error type_val_resolve_is_opaque_type(CodeGen *g, ConstExprValue *type_val, bool *is_opaque_type) {
if (type_val->special != ConstValSpecialLazy) {
assert(type_val->special == ConstValSpecialStatic);
*is_opaque_type = (type_val->data.x_type->id == ZigTypeIdOpaque);
return ErrorNone;
}
switch (type_val->data.x_lazy->id) {
case LazyValueIdInvalid:
case LazyValueIdAlignOf:
zig_unreachable();
case LazyValueIdSliceType:
case LazyValueIdFnType:
*is_opaque_type = false;
return ErrorNone;
}
zig_unreachable();
}
static ReqCompTime type_val_resolve_requires_comptime(CodeGen *g, ConstExprValue *type_val) {
if (type_val->special != ConstValSpecialLazy) {
return type_requires_comptime(g, type_val->data.x_type);
}
switch (type_val->data.x_lazy->id) {
case LazyValueIdInvalid:
case LazyValueIdAlignOf:
zig_unreachable();
case LazyValueIdSliceType: {
LazyValueSliceType *lazy_slice_type = reinterpret_cast<LazyValueSliceType *>(type_val->data.x_lazy);
return type_requires_comptime(g, lazy_slice_type->elem_type);
}
case LazyValueIdFnType: {
LazyValueFnType *lazy_fn_type = reinterpret_cast<LazyValueFnType *>(type_val->data.x_lazy);
if (lazy_fn_type->is_generic)
return ReqCompTimeYes;
switch (type_val_resolve_requires_comptime(g, lazy_fn_type->return_type)) {
case ReqCompTimeInvalid:
return ReqCompTimeInvalid;
case ReqCompTimeYes:
return ReqCompTimeYes;
case ReqCompTimeNo:
break;
}
size_t param_count = lazy_fn_type->proto_node->data.fn_proto.params.length;
if (lazy_fn_type->is_var_args) param_count -= 1;
for (size_t i = 0; i < param_count; i += 1) {
switch (type_val_resolve_requires_comptime(g, lazy_fn_type->param_types[i])) {
case ReqCompTimeInvalid:
return ReqCompTimeInvalid;
case ReqCompTimeYes:
return ReqCompTimeYes;
case ReqCompTimeNo:
break;
}
}
return ReqCompTimeNo;
}
}
zig_unreachable();
}
static Error type_val_resolve_abi_align(CodeGen *g, ConstExprValue *type_val, size_t *abi_align) {
Error err;
if (type_val->special != ConstValSpecialLazy) {
assert(type_val->special == ConstValSpecialStatic);
if ((err = type_resolve(g, type_val->data.x_type, ResolveStatusAlignmentKnown)))
return err;
*abi_align = type_val->data.x_type->abi_align;
return ErrorNone;
}
switch (type_val->data.x_lazy->id) {
case LazyValueIdInvalid:
case LazyValueIdAlignOf:
zig_unreachable();
case LazyValueIdSliceType:
*abi_align = g->builtin_types.entry_usize->abi_align;
return ErrorNone;
case LazyValueIdFnType: {
LazyValueFnType *lazy_fn_type = reinterpret_cast<LazyValueFnType *>(type_val->data.x_lazy);
if (lazy_fn_type->align_val != nullptr)
return type_val_resolve_abi_align(g, lazy_fn_type->align_val, abi_align);
*abi_align = 1;
return ErrorNone;
}
}
zig_unreachable();
}
ZigType *analyze_type_expr(CodeGen *g, Scope *scope, AstNode *node) { ZigType *analyze_type_expr(CodeGen *g, Scope *scope, AstNode *node) {
ConstExprValue *result = analyze_const_value(g, scope, node, g->builtin_types.entry_type, nullptr); ConstExprValue *result = analyze_const_value(g, scope, node, g->builtin_types.entry_type, nullptr);
if (type_is_invalid(result->type)) if (type_is_invalid(result->type))
@ -1492,11 +1618,6 @@ bool type_is_invalid(ZigType *type_entry) {
} }
static Error resolve_enum_type(CodeGen *g, ZigType *enum_type) {
return resolve_enum_zero_bits(g, enum_type);
}
ZigType *get_struct_type(CodeGen *g, const char *type_name, const char *field_names[], ZigType *get_struct_type(CodeGen *g, const char *type_name, const char *field_names[],
ZigType *field_types[], size_t field_count) ZigType *field_types[], size_t field_count)
{ {
@ -1536,8 +1657,9 @@ ZigType *get_struct_type(CodeGen *g, const char *type_name, const char *field_na
for (size_t i = 0; i < field_count; i += 1) { for (size_t i = 0; i < field_count; i += 1) {
TypeStructField *field = &struct_type->data.structure.fields[i]; TypeStructField *field = &struct_type->data.structure.fields[i];
field->offset = next_offset; field->offset = next_offset;
next_offset = next_field_offset(next_offset, abi_align, size_t next_abi_align = (i + 1 == field_count) ?
field->type_entry->abi_size, field->type_entry->abi_align); abi_align : struct_type->data.structure.fields[i + 1].type_entry->abi_align;
next_offset = next_field_offset(next_offset, abi_align, field->type_entry->abi_size, next_abi_align);
} }
struct_type->abi_align = abi_align; struct_type->abi_align = abi_align;
@ -1548,7 +1670,7 @@ ZigType *get_struct_type(CodeGen *g, const char *type_name, const char *field_na
} }
static size_t get_store_size_in_bits(size_t size_in_bits) { static size_t get_store_size_in_bits(size_t size_in_bits) {
return (size_in_bits + 7) / 8; return ((size_in_bits + 7) / 8) * 8;
} }
static Error resolve_struct_type(CodeGen *g, ZigType *struct_type) { static Error resolve_struct_type(CodeGen *g, ZigType *struct_type) {
@ -1584,7 +1706,7 @@ static Error resolve_struct_type(CodeGen *g, ZigType *struct_type) {
bool packed = (struct_type->data.structure.layout == ContainerLayoutPacked); bool packed = (struct_type->data.structure.layout == ContainerLayoutPacked);
struct_type->data.structure.resolve_loop_flag = true; struct_type->data.structure.resolve_loop_flag = true;
uint32_t *host_int_bytes = allocate<uint32_t>(struct_type->data.structure.gen_field_count); uint32_t *host_int_bytes = packed ? allocate<uint32_t>(struct_type->data.structure.gen_field_count) : nullptr;
// Compute offsets for all the fields. // Compute offsets for all the fields.
size_t packed_bits_offset = 0; size_t packed_bits_offset = 0;
@ -1594,24 +1716,53 @@ static Error resolve_struct_type(CodeGen *g, ZigType *struct_type) {
size_t size_in_bits = 0; size_t size_in_bits = 0;
size_t abi_align = struct_type->abi_align; size_t abi_align = struct_type->abi_align;
// Resolve types for fields
for (size_t i = 0; i < field_count; i += 1) { for (size_t i = 0; i < field_count; i += 1) {
TypeStructField *type_struct_field = &struct_type->data.structure.fields[i]; AstNode *field_source_node = decl_node->data.container_decl.fields.at(i);
ZigType *field_type = type_struct_field->type_entry; TypeStructField *field = &struct_type->data.structure.fields[i];
if (!type_has_bits(field_type)) if ((err = ir_resolve_lazy(g, field_source_node, field->type_val))) {
continue; struct_type->data.structure.resolve_status = ResolveStatusInvalid;
return err;
}
ZigType *field_type = field->type_val->data.x_type;
field->type_entry = field_type;
if ((err = type_resolve(g, field_type, ResolveStatusSizeKnown))) { if ((err = type_resolve(g, field_type, ResolveStatusSizeKnown))) {
struct_type->data.structure.resolve_status = ResolveStatusInvalid; struct_type->data.structure.resolve_status = ResolveStatusInvalid;
return ErrorSemanticAnalyzeFail; return err;
} }
if (struct_type->data.structure.resolve_status == ResolveStatusInvalid) { if (struct_type->data.structure.resolve_status == ResolveStatusInvalid) {
return ErrorSemanticAnalyzeFail; return ErrorSemanticAnalyzeFail;
} }
type_struct_field->gen_index = gen_field_index; if (packed) {
type_struct_field->offset = next_offset; if ((err = emit_error_unless_type_allowed_in_packed_struct(g, field_type, field_source_node))) {
struct_type->data.structure.resolve_status = ResolveStatusInvalid;
return ErrorSemanticAnalyzeFail;
}
} else if (struct_type->data.structure.layout == ContainerLayoutExtern &&
!type_allowed_in_extern(g, field_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.resolve_status = ResolveStatusInvalid;
return ErrorSemanticAnalyzeFail;
}
}
// Calculate offsets
for (size_t i = 0; i < field_count; i += 1) {
TypeStructField *field = &struct_type->data.structure.fields[i];
if (field->gen_index == SIZE_MAX)
continue;
ZigType *field_type = field->type_entry;
assert(field_type != nullptr);
field->gen_index = gen_field_index;
field->offset = next_offset;
if (packed) { if (packed) {
size_t field_size_in_bits = type_size_bits(g, field_type); size_t field_size_in_bits = type_size_bits(g, field_type);
@ -1621,7 +1772,7 @@ static Error resolve_struct_type(CodeGen *g, ZigType *struct_type) {
if (first_packed_bits_offset_misalign != SIZE_MAX) { if (first_packed_bits_offset_misalign != SIZE_MAX) {
// this field is not byte-aligned; it is part of the previous field with a bit offset // this field is not byte-aligned; it is part of the previous field with a bit offset
type_struct_field->bit_offset_in_host = packed_bits_offset - first_packed_bits_offset_misalign; field->bit_offset_in_host = packed_bits_offset - first_packed_bits_offset_misalign;
size_t full_bit_count = next_packed_bits_offset - first_packed_bits_offset_misalign; size_t full_bit_count = next_packed_bits_offset - first_packed_bits_offset_misalign;
if (get_store_size_in_bits(full_bit_count) == full_bit_count) { if (get_store_size_in_bits(full_bit_count) == full_bit_count) {
@ -1636,10 +1787,10 @@ static Error resolve_struct_type(CodeGen *g, ZigType *struct_type) {
} }
} else if (get_store_size_in_bits(field_type->size_in_bits) != field_size_in_bits) { } else if (get_store_size_in_bits(field_type->size_in_bits) != field_size_in_bits) {
first_packed_bits_offset_misalign = packed_bits_offset; first_packed_bits_offset_misalign = packed_bits_offset;
type_struct_field->bit_offset_in_host = 0; field->bit_offset_in_host = 0;
} else { } else {
// This is a byte-aligned field (both start and end) in a packed struct. // This is a byte-aligned field (both start and end) in a packed struct.
type_struct_field->bit_offset_in_host = 0; field->bit_offset_in_host = 0;
gen_field_index += 1; gen_field_index += 1;
// TODO: https://github.com/ziglang/zig/issues/1512 // TODO: https://github.com/ziglang/zig/issues/1512
next_offset = next_field_offset(next_offset, abi_align, field_type->size_in_bits / 8, 1); next_offset = next_field_offset(next_offset, abi_align, field_type->size_in_bits / 8, 1);
@ -1648,7 +1799,15 @@ static Error resolve_struct_type(CodeGen *g, ZigType *struct_type) {
packed_bits_offset = next_packed_bits_offset; packed_bits_offset = next_packed_bits_offset;
} else { } else {
gen_field_index += 1; gen_field_index += 1;
next_offset = next_field_offset(next_offset, abi_align, field_type->abi_size, field_type->abi_align); size_t next_src_field_index = i + 1;
for (; next_src_field_index < field_count; next_src_field_index += 1) {
if (struct_type->data.structure.fields[next_src_field_index].gen_index != SIZE_MAX) {
break;
}
}
size_t next_abi_align = (next_src_field_index == field_count) ?
abi_align : struct_type->data.structure.fields[next_src_field_index].type_entry->abi_align;
next_offset = next_field_offset(next_offset, abi_align, field_type->abi_size, next_abi_align);
size_in_bits = next_offset * 8; size_in_bits = next_offset * 8;
} }
} }
@ -1679,9 +1838,10 @@ static Error resolve_union_alignment(CodeGen *g, ZigType *union_type) {
return ErrorSemanticAnalyzeFail; return ErrorSemanticAnalyzeFail;
if (union_type->data.unionation.resolve_status >= ResolveStatusAlignmentKnown) if (union_type->data.unionation.resolve_status >= ResolveStatusAlignmentKnown)
return ErrorNone; return ErrorNone;
if ((err = resolve_union_zero_bits(g, union_type))) if ((err = resolve_union_zero_bits(g, union_type)))
return err; return err;
if (union_type->data.unionation.resolve_status >= ResolveStatusAlignmentKnown)
return ErrorNone;
if (union_type->data.unionation.resolve_loop_flag) { if (union_type->data.unionation.resolve_loop_flag) {
if (!union_type->data.unionation.reported_infinite_err) { if (!union_type->data.unionation.reported_infinite_err) {
@ -1724,7 +1884,7 @@ static Error resolve_union_alignment(CodeGen *g, ZigType *union_type) {
} }
// unset temporary flag // unset temporary flag
union_type->data.unionation.resolve_loop_flag = true; union_type->data.unionation.resolve_loop_flag = false;
union_type->data.unionation.resolve_status = ResolveStatusAlignmentKnown; union_type->data.unionation.resolve_status = ResolveStatusAlignmentKnown;
ZigType *tag_type = union_type->data.unionation.tag_type; ZigType *tag_type = union_type->data.unionation.tag_type;
@ -1836,8 +1996,8 @@ static Error resolve_union_type(CodeGen *g, ZigType *union_type) {
field_aligns[union_type->data.unionation.gen_tag_index] = tag_type->abi_align; field_aligns[union_type->data.unionation.gen_tag_index] = tag_type->abi_align;
field_sizes[union_type->data.unionation.gen_union_index] = union_abi_size; field_sizes[union_type->data.unionation.gen_union_index] = union_abi_size;
field_aligns[union_type->data.unionation.gen_union_index] = most_aligned_union_member->abi_align; field_aligns[union_type->data.unionation.gen_union_index] = most_aligned_union_member->abi_align;
size_t field2_offset = next_field_offset(0, union_type->abi_align, field_sizes[0], field_aligns[0]); size_t field2_offset = next_field_offset(0, union_type->abi_align, field_sizes[0], field_aligns[1]);
union_type->abi_size = next_field_offset(field2_offset, union_type->abi_align, field_sizes[1], field_aligns[1]); union_type->abi_size = next_field_offset(field2_offset, union_type->abi_align, field_sizes[1], union_type->abi_align);
union_type->size_in_bits = union_type->abi_size * 8; union_type->size_in_bits = union_type->abi_size * 8;
} }
} else { } else {
@ -1928,6 +2088,9 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) {
} }
} }
enum_type->data.enumeration.tag_int_type = tag_int_type; enum_type->data.enumeration.tag_int_type = tag_int_type;
enum_type->size_in_bits = tag_int_type->size_in_bits;
enum_type->abi_size = tag_int_type->abi_size;
enum_type->abi_align = tag_int_type->abi_align;
for (uint32_t field_i = 0; field_i < field_count; field_i += 1) { for (uint32_t field_i = 0; field_i < field_count; field_i += 1) {
AstNode *field_node = decl_node->data.container_decl.fields.at(field_i); AstNode *field_node = decl_node->data.container_decl.fields.at(field_i);
@ -2012,6 +2175,7 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) {
enum_type->data.enumeration.zero_bits_loop_flag = false; enum_type->data.enumeration.zero_bits_loop_flag = false;
enum_type->data.enumeration.zero_bits_known = true; enum_type->data.enumeration.zero_bits_known = true;
enum_type->data.enumeration.complete = true;
if (enum_type->data.enumeration.is_invalid) if (enum_type->data.enumeration.is_invalid)
return ErrorSemanticAnalyzeFail; return ErrorSemanticAnalyzeFail;
@ -2022,22 +2186,28 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) {
static Error resolve_struct_zero_bits(CodeGen *g, ZigType *struct_type) { static Error resolve_struct_zero_bits(CodeGen *g, ZigType *struct_type) {
assert(struct_type->id == ZigTypeIdStruct); assert(struct_type->id == ZigTypeIdStruct);
Error err;
if (struct_type->data.structure.resolve_status == ResolveStatusInvalid) if (struct_type->data.structure.resolve_status == ResolveStatusInvalid)
return ErrorSemanticAnalyzeFail; return ErrorSemanticAnalyzeFail;
if (struct_type->data.structure.resolve_status >= ResolveStatusZeroBitsKnown) if (struct_type->data.structure.resolve_status >= ResolveStatusZeroBitsKnown)
return ErrorNone; return ErrorNone;
AstNode *decl_node = struct_type->data.structure.decl_node;
assert(decl_node->type == NodeTypeContainerDecl);
if (struct_type->data.structure.resolve_loop_flag) { if (struct_type->data.structure.resolve_loop_flag) {
struct_type->data.structure.resolve_status = ResolveStatusZeroBitsKnown; if (struct_type->data.structure.resolve_status != ResolveStatusInvalid) {
struct_type->data.structure.resolve_loop_flag = false; struct_type->data.structure.resolve_status = ResolveStatusInvalid;
return ErrorNone; ErrorMsg *msg = add_node_error(g, decl_node,
buf_sprintf("struct '%s' depends on its own size", buf_ptr(&struct_type->name)));
emit_error_notes_for_ref_stack(g, msg);
}
return ErrorSemanticAnalyzeFail;
} }
struct_type->data.structure.resolve_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);
assert(!struct_type->data.structure.fields); assert(!struct_type->data.structure.fields);
size_t field_count = decl_node->data.container_decl.fields.length; size_t field_count = decl_node->data.container_decl.fields.length;
struct_type->data.structure.src_field_count = (uint32_t)field_count; struct_type->data.structure.src_field_count = (uint32_t)field_count;
@ -2056,7 +2226,7 @@ static Error resolve_struct_zero_bits(CodeGen *g, ZigType *struct_type) {
if (field_node->data.struct_field.type == nullptr) { if (field_node->data.struct_field.type == nullptr) {
add_node_error(g, field_node, buf_sprintf("struct field missing type")); add_node_error(g, field_node, buf_sprintf("struct field missing type"));
struct_type->data.structure.resolve_status = ResolveStatusInvalid; struct_type->data.structure.resolve_status = ResolveStatusInvalid;
continue; return ErrorSemanticAnalyzeFail;
} }
auto field_entry = struct_type->data.structure.fields_by_name.put_unique(type_struct_field->name, type_struct_field); auto field_entry = struct_type->data.structure.fields_by_name.put_unique(type_struct_field->name, type_struct_field);
@ -2065,38 +2235,55 @@ static Error resolve_struct_zero_bits(CodeGen *g, ZigType *struct_type) {
buf_sprintf("duplicate struct field: '%s'", buf_ptr(type_struct_field->name))); 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")); add_error_note(g, msg, field_entry->value->decl_node, buf_sprintf("other field here"));
struct_type->data.structure.resolve_status = ResolveStatusInvalid; struct_type->data.structure.resolve_status = ResolveStatusInvalid;
continue; return ErrorSemanticAnalyzeFail;
} }
ZigType *field_type = analyze_type_expr(g, scope, field_node->data.struct_field.type); ConstExprValue *field_type_val = analyze_const_value_allow_lazy(g, scope,
type_struct_field->type_entry = field_type; field_node->data.struct_field.type, g->builtin_types.entry_type, nullptr, true);
if (type_is_invalid(field_type_val->type)) {
struct_type->data.structure.resolve_status = ResolveStatusInvalid;
return ErrorSemanticAnalyzeFail;
}
assert(field_type_val->special != ConstValSpecialRuntime);
type_struct_field->type_val = field_type_val;
type_struct_field->src_index = i; type_struct_field->src_index = i;
type_struct_field->gen_index = SIZE_MAX; type_struct_field->gen_index = SIZE_MAX;
if (struct_type->data.structure.resolve_status == ResolveStatusInvalid)
return ErrorSemanticAnalyzeFail;
if (field_node->data.struct_field.value != nullptr) { if (field_node->data.struct_field.value != nullptr) {
add_node_error(g, field_node->data.struct_field.value, add_node_error(g, field_node->data.struct_field.value,
buf_sprintf("enums, not structs, support field assignment")); buf_sprintf("enums, not structs, support field assignment"));
} }
bool field_is_opaque_type;
if (field_type->id == ZigTypeIdOpaque) { if ((err = type_val_resolve_is_opaque_type(g, field_type_val, &field_is_opaque_type))) {
struct_type->data.structure.resolve_status = ResolveStatusInvalid;
return ErrorSemanticAnalyzeFail;
}
if (field_is_opaque_type) {
add_node_error(g, field_node->data.struct_field.type, add_node_error(g, field_node->data.struct_field.type,
buf_sprintf("opaque types have unknown size and therefore cannot be directly embedded in structs")); buf_sprintf("opaque types have unknown size and therefore cannot be directly embedded in structs"));
struct_type->data.structure.resolve_status = ResolveStatusInvalid; struct_type->data.structure.resolve_status = ResolveStatusInvalid;
continue; return ErrorSemanticAnalyzeFail;
} }
switch (type_val_resolve_requires_comptime(g, field_type_val)) {
switch (type_requires_comptime(g, field_type)) {
case ReqCompTimeYes: case ReqCompTimeYes:
struct_type->data.structure.requires_comptime = true; struct_type->data.structure.requires_comptime = true;
break; break;
case ReqCompTimeInvalid: case ReqCompTimeInvalid:
struct_type->data.structure.resolve_status = ResolveStatusInvalid; struct_type->data.structure.resolve_status = ResolveStatusInvalid;
continue; return ErrorSemanticAnalyzeFail;
case ReqCompTimeNo: case ReqCompTimeNo:
break; break;
} }
if (!type_has_bits(field_type)) bool field_is_zero_bits;
if ((err = type_val_resolve_zero_bits(g, field_type_val, &field_is_zero_bits))) {
struct_type->data.structure.resolve_status = ResolveStatusInvalid;
return ErrorSemanticAnalyzeFail;
}
if (field_is_zero_bits)
continue; continue;
type_struct_field->gen_index = gen_field_index; type_struct_field->gen_index = gen_field_index;
@ -2126,9 +2313,10 @@ static Error resolve_struct_alignment(CodeGen *g, ZigType *struct_type) {
return ErrorSemanticAnalyzeFail; return ErrorSemanticAnalyzeFail;
if (struct_type->data.structure.resolve_status >= ResolveStatusAlignmentKnown) if (struct_type->data.structure.resolve_status >= ResolveStatusAlignmentKnown)
return ErrorNone; return ErrorNone;
if ((err = resolve_struct_zero_bits(g, struct_type))) if ((err = resolve_struct_zero_bits(g, struct_type)))
return err; return err;
if (struct_type->data.structure.resolve_status >= ResolveStatusAlignmentKnown)
return ErrorNone;
AstNode *decl_node = struct_type->data.structure.decl_node; AstNode *decl_node = struct_type->data.structure.decl_node;
@ -2136,7 +2324,7 @@ static Error resolve_struct_alignment(CodeGen *g, ZigType *struct_type) {
if (struct_type->data.structure.resolve_status != ResolveStatusInvalid) { if (struct_type->data.structure.resolve_status != ResolveStatusInvalid) {
struct_type->data.structure.resolve_status = ResolveStatusInvalid; struct_type->data.structure.resolve_status = ResolveStatusInvalid;
ErrorMsg *msg = add_node_error(g, decl_node, ErrorMsg *msg = add_node_error(g, decl_node,
buf_sprintf("struct '%s' contains itself", buf_ptr(&struct_type->name))); buf_sprintf("struct '%s' depends on its own alignment", buf_ptr(&struct_type->name)));
emit_error_notes_for_ref_stack(g, msg); emit_error_notes_for_ref_stack(g, msg);
} }
return ErrorSemanticAnalyzeFail; return ErrorSemanticAnalyzeFail;
@ -2151,42 +2339,23 @@ static Error resolve_struct_alignment(CodeGen *g, ZigType *struct_type) {
for (size_t i = 0; i < field_count; i += 1) { for (size_t i = 0; i < field_count; i += 1) {
TypeStructField *field = &struct_type->data.structure.fields[i]; TypeStructField *field = &struct_type->data.structure.fields[i];
ZigType *field_type = field->type_entry; if (field->gen_index == SIZE_MAX)
assert(field_type != nullptr);
if ((err = type_resolve(g, field_type, ResolveStatusAlignmentKnown))) {
struct_type->data.structure.resolve_status = ResolveStatusInvalid;
return ErrorSemanticAnalyzeFail;
}
if (struct_type->data.structure.layout == ContainerLayoutExtern &&
!type_allowed_in_extern(g, field_type))
{
AstNode *field_source_node = decl_node->data.container_decl.fields.at(i);
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.resolve_status = ResolveStatusInvalid;
return ErrorSemanticAnalyzeFail;
}
if (!type_has_bits(field_type))
continue; continue;
if (packed) { if (packed) {
AstNode *field_source_node = decl_node->data.container_decl.fields.at(i);
if ((err = emit_error_unless_type_allowed_in_packed_struct(g, field_type, field_source_node))) {
struct_type->data.structure.resolve_status = ResolveStatusInvalid;
return ErrorSemanticAnalyzeFail;
}
// TODO: https://github.com/ziglang/zig/issues/1512 // TODO: https://github.com/ziglang/zig/issues/1512
if (1 > abi_align) { if (1 > abi_align) {
abi_align = 1; abi_align = 1;
} }
} else { } else {
// TODO: https://github.com/ziglang/zig/issues/1512 // TODO: https://github.com/ziglang/zig/issues/1512
if (field_type->abi_align > abi_align) { size_t field_align;
abi_align = field_type->abi_align; if ((err = type_val_resolve_abi_align(g, field->type_val, &field_align))) {
struct_type->data.structure.resolve_status = ResolveStatusInvalid;
return err;
}
if (field_align > abi_align) {
abi_align = field_align;
} }
} }
} }
@ -2824,7 +2993,7 @@ void init_tld(Tld *tld, TldId id, Buf *name, VisibMod visib_mod, AstNode *source
void update_compile_var(CodeGen *g, Buf *name, ConstExprValue *value) { void update_compile_var(CodeGen *g, Buf *name, ConstExprValue *value) {
Tld *tld = get_container_scope(g->compile_var_import)->decl_table.get(name); Tld *tld = get_container_scope(g->compile_var_import)->decl_table.get(name);
resolve_top_level_decl(g, tld, tld->source_node); resolve_top_level_decl(g, tld, tld->source_node, false);
assert(tld->id == TldIdVar); assert(tld->id == TldIdVar);
TldVar *tld_var = (TldVar *)tld; TldVar *tld_var = (TldVar *)tld;
tld_var->var->const_value = value; tld_var->var->const_value = value;
@ -2933,20 +3102,17 @@ void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node) {
} }
} }
static void resolve_decl_container(CodeGen *g, TldContainer *tld_container) { static Error resolve_decl_container(CodeGen *g, TldContainer *tld_container) {
ZigType *type_entry = tld_container->type_entry; ZigType *type_entry = tld_container->type_entry;
assert(type_entry); assert(type_entry);
switch (type_entry->id) { switch (type_entry->id) {
case ZigTypeIdStruct: case ZigTypeIdStruct:
resolve_struct_type(g, tld_container->type_entry); return resolve_struct_type(g, tld_container->type_entry);
return;
case ZigTypeIdEnum: case ZigTypeIdEnum:
resolve_enum_type(g, tld_container->type_entry); return resolve_enum_zero_bits(g, tld_container->type_entry);
return;
case ZigTypeIdUnion: case ZigTypeIdUnion:
resolve_union_type(g, tld_container->type_entry); return resolve_union_type(g, tld_container->type_entry);
return;
default: default:
zig_unreachable(); zig_unreachable();
} }
@ -3066,7 +3232,7 @@ ZigVar *add_variable(CodeGen *g, AstNode *source_node, Scope *parent_scope, Buf
return variable_entry; return variable_entry;
} }
static void resolve_decl_var(CodeGen *g, TldVar *tld_var) { static void resolve_decl_var(CodeGen *g, TldVar *tld_var, bool allow_lazy) {
AstNode *source_node = tld_var->base.source_node; AstNode *source_node = tld_var->base.source_node;
AstNodeVariableDeclaration *var_decl = &source_node->data.variable_declaration; AstNodeVariableDeclaration *var_decl = &source_node->data.variable_declaration;
@ -3107,7 +3273,8 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) {
if (explicit_type && explicit_type->id == ZigTypeIdInvalid) { if (explicit_type && explicit_type->id == ZigTypeIdInvalid) {
implicit_type = explicit_type; implicit_type = explicit_type;
} else if (var_decl->expr) { } else if (var_decl->expr) {
init_value = analyze_const_value(g, tld_var->base.parent_scope, var_decl->expr, explicit_type, var_decl->symbol); init_value = analyze_const_value_allow_lazy(g, tld_var->base.parent_scope, var_decl->expr,
explicit_type, var_decl->symbol, allow_lazy);
assert(init_value); assert(init_value);
implicit_type = init_value->type; implicit_type = init_value->type;
@ -3170,11 +3337,11 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) {
g->global_vars.append(tld_var); g->global_vars.append(tld_var);
} }
void resolve_top_level_decl(CodeGen *g, Tld *tld, AstNode *source_node) { void resolve_top_level_decl(CodeGen *g, Tld *tld, AstNode *source_node, bool allow_lazy) {
if (tld->resolution != TldResolutionUnresolved) bool want_resolve_lazy = tld->resolution == TldResolutionOkLazy && !allow_lazy;
if (tld->resolution != TldResolutionUnresolved && !want_resolve_lazy)
return; return;
assert(tld->resolution != TldResolutionResolving);
tld->resolution = TldResolutionResolving; tld->resolution = TldResolutionResolving;
g->tld_ref_source_node_stack.append(source_node); g->tld_ref_source_node_stack.append(source_node);
@ -3182,7 +3349,11 @@ void resolve_top_level_decl(CodeGen *g, Tld *tld, AstNode *source_node) {
case TldIdVar: case TldIdVar:
{ {
TldVar *tld_var = (TldVar *)tld; TldVar *tld_var = (TldVar *)tld;
resolve_decl_var(g, tld_var); if (want_resolve_lazy) {
ir_resolve_lazy(g, source_node, tld_var->var->const_value);
} else {
resolve_decl_var(g, tld_var, allow_lazy);
}
break; break;
} }
case TldIdFn: case TldIdFn:
@ -3205,7 +3376,7 @@ void resolve_top_level_decl(CodeGen *g, Tld *tld, AstNode *source_node) {
} }
} }
tld->resolution = TldResolutionOk; tld->resolution = allow_lazy ? TldResolutionOkLazy : TldResolutionOk;
g->tld_ref_source_node_stack.pop(); g->tld_ref_source_node_stack.pop();
} }
@ -3399,17 +3570,14 @@ ZigType *container_ref_type(ZigType *type_entry) {
type_entry->data.pointer.child_type : type_entry; type_entry->data.pointer.child_type : type_entry;
} }
void resolve_container_type(CodeGen *g, ZigType *type_entry) { Error resolve_container_type(CodeGen *g, ZigType *type_entry) {
switch (type_entry->id) { switch (type_entry->id) {
case ZigTypeIdStruct: case ZigTypeIdStruct:
resolve_struct_type(g, type_entry); return resolve_struct_type(g, type_entry);
break;
case ZigTypeIdEnum: case ZigTypeIdEnum:
resolve_enum_type(g, type_entry); return resolve_enum_zero_bits(g, type_entry);
break;
case ZigTypeIdUnion: case ZigTypeIdUnion:
resolve_union_type(g, type_entry); return resolve_union_type(g, type_entry);
break;
case ZigTypeIdPointer: case ZigTypeIdPointer:
case ZigTypeIdMetaType: case ZigTypeIdMetaType:
case ZigTypeIdVoid: case ZigTypeIdVoid:
@ -3435,6 +3603,7 @@ void resolve_container_type(CodeGen *g, ZigType *type_entry) {
case ZigTypeIdVector: case ZigTypeIdVector:
zig_unreachable(); zig_unreachable();
} }
zig_unreachable();
} }
ZigType *get_src_ptr_type(ZigType *type) { ZigType *get_src_ptr_type(ZigType *type) {
@ -3536,10 +3705,6 @@ static void define_local_param_variables(CodeGen *g, ZigFn *fn_table_entry) {
if (type_has_bits(param_type)) { if (type_has_bits(param_type)) {
fn_table_entry->variable_list.append(var); fn_table_entry->variable_list.append(var);
} }
if (fn_type->data.fn.gen_param_info) {
var->gen_arg_index = fn_type->data.fn.gen_param_info[i].gen_index;
}
} }
} }
@ -3880,7 +4045,7 @@ void semantic_analyze(CodeGen *g) {
for (; g->resolve_queue_index < g->resolve_queue.length; g->resolve_queue_index += 1) { for (; g->resolve_queue_index < g->resolve_queue.length; g->resolve_queue_index += 1) {
Tld *tld = g->resolve_queue.at(g->resolve_queue_index); Tld *tld = g->resolve_queue.at(g->resolve_queue_index);
AstNode *source_node = nullptr; AstNode *source_node = nullptr;
resolve_top_level_decl(g, tld, source_node); resolve_top_level_decl(g, tld, source_node, false);
} }
for (; g->fn_defs_index < g->fn_defs.length; g->fn_defs_index += 1) { for (; g->fn_defs_index < g->fn_defs.length; g->fn_defs_index += 1) {
@ -4941,7 +5106,7 @@ Error type_resolve(CodeGen *g, ZigType *ty, ResolveStatus status) {
if (ty->id == ZigTypeIdStruct) { if (ty->id == ZigTypeIdStruct) {
return resolve_struct_type(g, ty); return resolve_struct_type(g, ty);
} else if (ty->id == ZigTypeIdEnum) { } else if (ty->id == ZigTypeIdEnum) {
return resolve_enum_type(g, ty); return resolve_enum_zero_bits(g, ty);
} else if (ty->id == ZigTypeIdUnion) { } else if (ty->id == ZigTypeIdUnion) {
return resolve_union_type(g, ty); return resolve_union_type(g, ty);
} }
@ -5314,6 +5479,9 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) {
case ConstValSpecialRuntime: case ConstValSpecialRuntime:
buf_appendf(buf, "(runtime value)"); buf_appendf(buf, "(runtime value)");
return; return;
case ConstValSpecialLazy:
buf_appendf(buf, "(lazy value)");
return;
case ConstValSpecialUndef: case ConstValSpecialUndef:
buf_appendf(buf, "undefined"); buf_appendf(buf, "undefined");
return; return;
@ -5930,7 +6098,7 @@ bool type_ptr_eql(const ZigType *a, const ZigType *b) {
ConstExprValue *get_builtin_value(CodeGen *codegen, const char *name) { ConstExprValue *get_builtin_value(CodeGen *codegen, const char *name) {
Tld *tld = get_container_scope(codegen->compile_var_import)->decl_table.get(buf_create_from_str(name)); Tld *tld = get_container_scope(codegen->compile_var_import)->decl_table.get(buf_create_from_str(name));
resolve_top_level_decl(codegen, tld, nullptr); resolve_top_level_decl(codegen, tld, nullptr, false);
assert(tld->id == TldIdVar); assert(tld->id == TldIdVar);
TldVar *tld_var = (TldVar *)tld; TldVar *tld_var = (TldVar *)tld;
ConstExprValue *var_value = tld_var->var->const_value; ConstExprValue *var_value = tld_var->var->const_value;
@ -6114,6 +6282,8 @@ bool type_is_c_abi_int(CodeGen *g, ZigType *ty) {
uint32_t get_host_int_bytes(CodeGen *g, ZigType *struct_type, TypeStructField *field) { uint32_t get_host_int_bytes(CodeGen *g, ZigType *struct_type, TypeStructField *field) {
assert(struct_type->id == ZigTypeIdStruct); assert(struct_type->id == ZigTypeIdStruct);
assert(type_is_resolved(struct_type, ResolveStatusSizeKnown)); assert(type_is_resolved(struct_type, ResolveStatusSizeKnown));
if (struct_type->data.structure.host_int_bytes == nullptr)
return 0;
return struct_type->data.structure.host_int_bytes[field->gen_index]; return struct_type->data.structure.host_int_bytes[field->gen_index];
} }
@ -6374,8 +6544,13 @@ static void resolve_llvm_types_struct(CodeGen *g, ZigType *struct_type) {
LLVMStructSetBody(struct_type->llvm_type, element_types, (unsigned)gen_field_count, packed); LLVMStructSetBody(struct_type->llvm_type, element_types, (unsigned)gen_field_count, packed);
ZigLLVMDIType **di_element_types = allocate<ZigLLVMDIType*>(debug_field_count); ZigLLVMDIType **di_element_types = allocate<ZigLLVMDIType*>(debug_field_count);
ZigType *import = get_scope_import(scope); ZigType *import = get_scope_import(scope);
unsigned dwarf_kind = ZigLLVMTag_DW_structure_type();
struct_type->llvm_di_type = ZigLLVMCreateReplaceableCompositeType(g->dbuilder,
dwarf_kind, buf_ptr(&struct_type->name),
ZigLLVMFileToScope(import->data.structure.root_struct->di_file),
import->data.structure.root_struct->di_file, (unsigned)(decl_node->line + 1));
size_t debug_field_index = 0; size_t debug_field_index = 0;
for (size_t i = 0; i < field_count; i += 1) { for (size_t i = 0; i < field_count; i += 1) {
AstNode *field_node = decl_node->data.container_decl.fields.at(i); AstNode *field_node = decl_node->data.container_decl.fields.at(i);

View File

@ -61,7 +61,7 @@ ZigType *add_source_file(CodeGen *g, ZigPackage *package, Buf *abs_full_path, Bu
ZigVar *find_variable(CodeGen *g, Scope *orig_context, Buf *name, ScopeFnDef **crossed_fndef_scope); ZigVar *find_variable(CodeGen *g, Scope *orig_context, Buf *name, ScopeFnDef **crossed_fndef_scope);
Tld *find_decl(CodeGen *g, Scope *scope, Buf *name); Tld *find_decl(CodeGen *g, Scope *scope, Buf *name);
Tld *find_container_decl(CodeGen *g, ScopeDecls *decls_scope, Buf *name); Tld *find_container_decl(CodeGen *g, ScopeDecls *decls_scope, Buf *name);
void resolve_top_level_decl(CodeGen *g, Tld *tld, AstNode *source_node); void resolve_top_level_decl(CodeGen *g, Tld *tld, AstNode *source_node, bool allow_lazy);
ZigType *get_src_ptr_type(ZigType *type); ZigType *get_src_ptr_type(ZigType *type);
ZigType *get_codegen_ptr_type(ZigType *type); ZigType *get_codegen_ptr_type(ZigType *type);
@ -73,7 +73,7 @@ bool type_is_complete(ZigType *type_entry);
bool type_is_resolved(ZigType *type_entry, ResolveStatus status); bool type_is_resolved(ZigType *type_entry, ResolveStatus status);
bool type_is_invalid(ZigType *type_entry); bool type_is_invalid(ZigType *type_entry);
bool type_is_global_error_set(ZigType *err_set_type); bool type_is_global_error_set(ZigType *err_set_type);
void resolve_container_type(CodeGen *g, ZigType *type_entry); Error resolve_container_type(CodeGen *g, ZigType *type_entry);
ScopeDecls *get_container_scope(ZigType *type_entry); ScopeDecls *get_container_scope(ZigType *type_entry);
TypeStructField *find_struct_type_field(ZigType *type_entry, Buf *name); TypeStructField *find_struct_type_field(ZigType *type_entry, Buf *name);
TypeEnumField *find_enum_type_field(ZigType *enum_type, Buf *name); TypeEnumField *find_enum_type_field(ZigType *enum_type, Buf *name);
@ -246,4 +246,5 @@ Error create_c_object_cache(CodeGen *g, CacheHash **out_cache_hash, bool verbose
LLVMTypeRef get_llvm_type(CodeGen *g, ZigType *type); LLVMTypeRef get_llvm_type(CodeGen *g, ZigType *type);
ZigLLVMDIType *get_llvm_di_type(CodeGen *g, ZigType *type); ZigLLVMDIType *get_llvm_di_type(CodeGen *g, ZigType *type);
#endif #endif

View File

@ -483,6 +483,8 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, ZigFn *fn_table_entry) {
ZigType *fn_type = fn_table_entry->type_entry; ZigType *fn_type = fn_table_entry->type_entry;
// Make the raw_type_ref populated
(void)get_llvm_type(g, fn_type);
LLVMTypeRef fn_llvm_type = fn_type->data.fn.raw_type_ref; LLVMTypeRef fn_llvm_type = fn_type->data.fn.raw_type_ref;
if (fn_table_entry->body_node == nullptr) { if (fn_table_entry->body_node == nullptr) {
LLVMValueRef existing_llvm_fn = LLVMGetNamedFunction(g->module, buf_ptr(symbol_name)); LLVMValueRef existing_llvm_fn = LLVMGetNamedFunction(g->module, buf_ptr(symbol_name));
@ -2285,7 +2287,9 @@ void walk_function_params(CodeGen *g, ZigType *fn_type, FnWalk *fn_walk) {
if (!handle_is_ptr(variable->var_type)) { if (!handle_is_ptr(variable->var_type)) {
clear_debug_source_node(g); clear_debug_source_node(g);
gen_store_untyped(g, LLVMGetParam(llvm_fn, (unsigned)variable->gen_arg_index), ZigType *fn_type = fn_table_entry->type_entry;
unsigned gen_arg_index = fn_type->data.fn.gen_param_info[variable->src_arg_index].gen_index;
gen_store_untyped(g, LLVMGetParam(llvm_fn, gen_arg_index),
variable->value_ref, variable->align_bytes, false); variable->value_ref, variable->align_bytes, false);
} }
@ -3354,6 +3358,8 @@ static bool value_is_all_undef_array(ConstExprValue *const_val, size_t len) {
static bool value_is_all_undef(ConstExprValue *const_val) { static bool value_is_all_undef(ConstExprValue *const_val) {
switch (const_val->special) { switch (const_val->special) {
case ConstValSpecialLazy:
zig_unreachable();
case ConstValSpecialRuntime: case ConstValSpecialRuntime:
return false; return false;
case ConstValSpecialUndef: case ConstValSpecialUndef:
@ -5818,6 +5824,7 @@ static LLVMValueRef gen_const_ptr_union_recursive(CodeGen *g, ConstExprValue *un
static LLVMValueRef pack_const_int(CodeGen *g, LLVMTypeRef big_int_type_ref, ConstExprValue *const_val) { static LLVMValueRef pack_const_int(CodeGen *g, LLVMTypeRef big_int_type_ref, ConstExprValue *const_val) {
switch (const_val->special) { switch (const_val->special) {
case ConstValSpecialLazy:
case ConstValSpecialRuntime: case ConstValSpecialRuntime:
zig_unreachable(); zig_unreachable();
case ConstValSpecialUndef: case ConstValSpecialUndef:
@ -6075,6 +6082,7 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c
assert(type_has_bits(type_entry)); assert(type_has_bits(type_entry));
switch (const_val->special) { switch (const_val->special) {
case ConstValSpecialLazy:
case ConstValSpecialRuntime: case ConstValSpecialRuntime:
zig_unreachable(); zig_unreachable();
case ConstValSpecialUndef: case ConstValSpecialUndef:
@ -6834,9 +6842,9 @@ static void do_code_gen(CodeGen *g) {
fn_walk_var.data.vars.var = var; fn_walk_var.data.vars.var = var;
iter_function_params_c_abi(g, fn_table_entry->type_entry, &fn_walk_var, var->src_arg_index); iter_function_params_c_abi(g, fn_table_entry->type_entry, &fn_walk_var, var->src_arg_index);
} else { } else {
assert(var->gen_arg_index != SIZE_MAX);
ZigType *gen_type; ZigType *gen_type;
FnGenParamInfo *gen_info = &fn_table_entry->type_entry->data.fn.gen_param_info[var->src_arg_index]; FnGenParamInfo *gen_info = &fn_table_entry->type_entry->data.fn.gen_param_info[var->src_arg_index];
assert(gen_info->gen_index != SIZE_MAX);
if (handle_is_ptr(var->var_type)) { if (handle_is_ptr(var->var_type)) {
if (gen_info->is_byval) { if (gen_info->is_byval) {
@ -6844,7 +6852,7 @@ static void do_code_gen(CodeGen *g) {
} else { } else {
gen_type = gen_info->type; gen_type = gen_info->type;
} }
var->value_ref = LLVMGetParam(fn, (unsigned)var->gen_arg_index); var->value_ref = LLVMGetParam(fn, gen_info->gen_index);
} else { } else {
gen_type = var->var_type; gen_type = var->var_type;
var->value_ref = build_alloca(g, var->var_type, buf_ptr(&var->name), var->align_bytes); var->value_ref = build_alloca(g, var->var_type, buf_ptr(&var->name), var->align_bytes);
@ -6853,7 +6861,7 @@ static void do_code_gen(CodeGen *g) {
var->di_loc_var = ZigLLVMCreateParameterVariable(g->dbuilder, get_di_scope(g, var->parent_scope), var->di_loc_var = ZigLLVMCreateParameterVariable(g->dbuilder, get_di_scope(g, var->parent_scope),
buf_ptr(&var->name), import->data.structure.root_struct->di_file, buf_ptr(&var->name), import->data.structure.root_struct->di_file,
(unsigned)(var->decl_node->line + 1), (unsigned)(var->decl_node->line + 1),
get_llvm_di_type(g, gen_type), !g->strip_debug_symbols, 0, (unsigned)(var->gen_arg_index + 1)); get_llvm_di_type(g, gen_type), !g->strip_debug_symbols, 0, (unsigned)(gen_info->gen_index));
} }
} }
@ -8241,7 +8249,7 @@ static void gen_root_source(CodeGen *g) {
} }
Tld *panic_tld = find_decl(g, &get_container_scope(import_with_panic)->base, buf_create_from_str("panic")); Tld *panic_tld = find_decl(g, &get_container_scope(import_with_panic)->base, buf_create_from_str("panic"));
assert(panic_tld != nullptr); assert(panic_tld != nullptr);
resolve_top_level_decl(g, panic_tld, nullptr); resolve_top_level_decl(g, panic_tld, nullptr, false);
} }

View File

@ -154,6 +154,7 @@ struct ConstCastBadAllowsZero {
enum UndefAllowed { enum UndefAllowed {
UndefOk, UndefOk,
UndefBad, UndefBad,
LazyOk,
}; };
static IrInstruction *ir_gen_node(IrBuilder *irb, AstNode *node, Scope *scope); static IrInstruction *ir_gen_node(IrBuilder *irb, AstNode *node, Scope *scope);
@ -10256,32 +10257,57 @@ static IrInstruction *ir_get_const_ptr(IrAnalyze *ira, IrInstruction *instructio
return const_instr; return const_instr;
} }
static ConstExprValue *ir_resolve_const(IrAnalyze *ira, IrInstruction *value, UndefAllowed undef_allowed) { static Error ir_resolve_const_val(CodeGen *codegen, IrExecutable *exec, AstNode *source_node,
switch (value->value.special) { ConstExprValue *val, UndefAllowed undef_allowed)
case ConstValSpecialStatic: {
return &value->value; Error err;
case ConstValSpecialRuntime: for (;;) {
if (!type_has_bits(value->value.type)) { switch (val->special) {
return &value->value; case ConstValSpecialStatic:
} return ErrorNone;
ir_add_error(ira, value, buf_sprintf("unable to evaluate constant expression")); case ConstValSpecialRuntime:
return nullptr; if (!type_has_bits(val->type))
case ConstValSpecialUndef: return ErrorNone;
if (undef_allowed == UndefOk) {
return &value->value; exec_add_error_node(codegen, exec, source_node,
} else { buf_sprintf("unable to evaluate constant expression"));
ir_add_error(ira, value, buf_sprintf("use of undefined value here causes undefined behavior")); return ErrorSemanticAnalyzeFail;
return nullptr; case ConstValSpecialUndef:
} if (undef_allowed == UndefOk)
return ErrorNone;
exec_add_error_node(codegen, exec, source_node,
buf_sprintf("use of undefined value here causes undefined behavior"));
return ErrorSemanticAnalyzeFail;
case ConstValSpecialLazy:
if (undef_allowed == LazyOk)
return ErrorNone;
if ((err = ir_resolve_lazy(codegen, source_node, val)))
return err;
continue;
}
} }
zig_unreachable(); }
static ConstExprValue *ir_resolve_const(IrAnalyze *ira, IrInstruction *value, UndefAllowed undef_allowed) {
Error err;
if ((err = ir_resolve_const_val(ira->codegen, ira->new_irb.exec, value->source_node,
&value->value, undef_allowed)))
{
return nullptr;
}
return &value->value;
} }
ConstExprValue *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node, ConstExprValue *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node,
ZigType *expected_type, size_t *backward_branch_count, size_t backward_branch_quota, ZigType *expected_type, size_t *backward_branch_count, size_t backward_branch_quota,
ZigFn *fn_entry, Buf *c_import_buf, AstNode *source_node, Buf *exec_name, ZigFn *fn_entry, Buf *c_import_buf, AstNode *source_node, Buf *exec_name,
IrExecutable *parent_exec, AstNode *expected_type_source_node) IrExecutable *parent_exec, AstNode *expected_type_source_node, bool allow_lazy)
{ {
Error err;
if (expected_type != nullptr && type_is_invalid(expected_type)) if (expected_type != nullptr && type_is_invalid(expected_type))
return &codegen->invalid_instruction->value; return &codegen->invalid_instruction->value;
@ -10326,7 +10352,24 @@ ConstExprValue *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *nod
fprintf(stderr, "}\n"); fprintf(stderr, "}\n");
} }
return ir_exec_const_result(codegen, analyzed_executable); ConstExprValue *result = ir_exec_const_result(codegen, analyzed_executable);
if (!allow_lazy) {
if ((err = ir_resolve_lazy(codegen, node, result)))
return &codegen->invalid_instruction->value;
}
return result;
}
static ZigType *ir_resolve_const_type(CodeGen *codegen, IrExecutable *exec, AstNode *source_node,
ConstExprValue *val)
{
Error err;
if ((err = ir_resolve_const_val(codegen, exec, source_node, val, UndefBad)))
return codegen->builtin_types.entry_invalid;
assert(val->data.x_type != nullptr);
return val->data.x_type;
} }
static ZigType *ir_resolve_type(IrAnalyze *ira, IrInstruction *type_value) { static ZigType *ir_resolve_type(IrAnalyze *ira, IrInstruction *type_value) {
@ -10339,12 +10382,7 @@ static ZigType *ir_resolve_type(IrAnalyze *ira, IrInstruction *type_value) {
return ira->codegen->builtin_types.entry_invalid; return ira->codegen->builtin_types.entry_invalid;
} }
ConstExprValue *const_val = ir_resolve_const(ira, type_value, UndefBad); return ir_resolve_const_type(ira->codegen, ira->new_irb.exec, type_value->source_node, &type_value->value);
if (!const_val)
return ira->codegen->builtin_types.entry_invalid;
assert(const_val->data.x_type != nullptr);
return const_val->data.x_type;
} }
static ZigType *ir_resolve_error_set_type(IrAnalyze *ira, IrInstruction *op_source, IrInstruction *type_value) { static ZigType *ir_resolve_error_set_type(IrAnalyze *ira, IrInstruction *op_source, IrInstruction *type_value) {
@ -11835,6 +11873,27 @@ static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruc
} }
} }
static bool ir_resolve_const_align(CodeGen *codegen, IrExecutable *exec, AstNode *source_node,
ConstExprValue *const_val, uint32_t *out)
{
Error err;
if ((err = ir_resolve_const_val(codegen, exec, source_node, const_val, UndefBad)))
return false;
uint32_t align_bytes = bigint_as_unsigned(&const_val->data.x_bigint);
if (align_bytes == 0) {
exec_add_error_node(codegen, exec, source_node, buf_sprintf("alignment must be >= 1"));
return false;
}
if (!is_power_of_2(align_bytes)) {
exec_add_error_node(codegen, exec, source_node, buf_sprintf("alignment value %" PRIu32 " is not a power of 2", align_bytes));
return false;
}
*out = align_bytes;
return true;
}
static bool ir_resolve_align(IrAnalyze *ira, IrInstruction *value, uint32_t *out) { static bool ir_resolve_align(IrAnalyze *ira, IrInstruction *value, uint32_t *out) {
if (type_is_invalid(value->value.type)) if (type_is_invalid(value->value.type))
return false; return false;
@ -11843,23 +11902,7 @@ static bool ir_resolve_align(IrAnalyze *ira, IrInstruction *value, uint32_t *out
if (type_is_invalid(casted_value->value.type)) if (type_is_invalid(casted_value->value.type))
return false; return false;
ConstExprValue *const_val = ir_resolve_const(ira, casted_value, UndefBad); return ir_resolve_const_align(ira->codegen, ira->new_irb.exec, value->source_node, &casted_value->value, out);
if (!const_val)
return false;
uint32_t align_bytes = bigint_as_unsigned(&const_val->data.x_bigint);
if (align_bytes == 0) {
ir_add_error(ira, value, buf_sprintf("alignment must be >= 1"));
return false;
}
if (!is_power_of_2(align_bytes)) {
ir_add_error(ira, value, buf_sprintf("alignment value %" PRIu32 " is not a power of 2", align_bytes));
return false;
}
*out = align_bytes;
return true;
} }
static bool ir_resolve_unsigned(IrAnalyze *ira, IrInstruction *value, ZigType *int_type, uint64_t *out) { static bool ir_resolve_unsigned(IrAnalyze *ira, IrInstruction *value, ZigType *int_type, uint64_t *out) {
@ -12029,6 +12072,140 @@ static Buf *ir_resolve_str(IrAnalyze *ira, IrInstruction *value) {
return result; return result;
} }
static ZigType *ir_resolve_lazy_fn_type(CodeGen *codegen, IrExecutable *exec, AstNode *source_node,
LazyValueFnType *lazy_fn_type)
{
AstNode *proto_node = lazy_fn_type->proto_node;
FnTypeId fn_type_id = {0};
init_fn_type_id(&fn_type_id, proto_node, proto_node->data.fn_proto.params.length);
for (; fn_type_id.next_param_index < fn_type_id.param_count; fn_type_id.next_param_index += 1) {
AstNode *param_node = proto_node->data.fn_proto.params.at(fn_type_id.next_param_index);
assert(param_node->type == NodeTypeParamDecl);
bool param_is_var_args = param_node->data.param_decl.is_var_args;
if (param_is_var_args) {
if (fn_type_id.cc == CallingConventionC) {
fn_type_id.param_count = fn_type_id.next_param_index;
continue;
} else if (fn_type_id.cc == CallingConventionUnspecified) {
return get_generic_fn_type(codegen, &fn_type_id);
} else {
zig_unreachable();
}
}
FnTypeParamInfo *param_info = &fn_type_id.param_info[fn_type_id.next_param_index];
param_info->is_noalias = param_node->data.param_decl.is_noalias;
if (lazy_fn_type->param_types[fn_type_id.next_param_index] == nullptr) {
param_info->type = nullptr;
return get_generic_fn_type(codegen, &fn_type_id);
} else {
ZigType *param_type = ir_resolve_const_type(codegen, exec, source_node,
lazy_fn_type->param_types[fn_type_id.next_param_index]);
if (type_is_invalid(param_type))
return nullptr;
switch (type_requires_comptime(codegen, param_type)) {
case ReqCompTimeYes:
if (!calling_convention_allows_zig_types(fn_type_id.cc)) {
exec_add_error_node(codegen, exec, source_node,
buf_sprintf("parameter of type '%s' not allowed in function with calling convention '%s'",
buf_ptr(&param_type->name), calling_convention_name(fn_type_id.cc)));
return nullptr;
}
param_info->type = param_type;
fn_type_id.next_param_index += 1;
return get_generic_fn_type(codegen, &fn_type_id);
case ReqCompTimeInvalid:
return nullptr;
case ReqCompTimeNo:
break;
}
if (!type_has_bits(param_type) && !calling_convention_allows_zig_types(fn_type_id.cc)) {
exec_add_error_node(codegen, exec, source_node,
buf_sprintf("parameter of type '%s' has 0 bits; not allowed in function with calling convention '%s'",
buf_ptr(&param_type->name), calling_convention_name(fn_type_id.cc)));
return nullptr;
}
param_info->type = param_type;
}
}
if (lazy_fn_type->align_val != nullptr) {
if (!ir_resolve_const_align(codegen, exec, source_node, lazy_fn_type->align_val, &fn_type_id.alignment))
return nullptr;
}
fn_type_id.return_type = ir_resolve_const_type(codegen, exec, source_node, lazy_fn_type->return_type);
if (type_is_invalid(fn_type_id.return_type))
return nullptr;
if (fn_type_id.return_type->id == ZigTypeIdOpaque) {
exec_add_error_node(codegen, exec, source_node,
buf_sprintf("return type cannot be opaque"));
return nullptr;
}
if (lazy_fn_type->async_allocator_type != nullptr) {
fn_type_id.async_allocator_type = ir_resolve_const_type(codegen, exec, source_node,
lazy_fn_type->async_allocator_type);
if (type_is_invalid(fn_type_id.async_allocator_type))
return nullptr;
}
return get_fn_type(codegen, &fn_type_id);
}
Error ir_resolve_lazy(CodeGen *codegen, AstNode *source_node, ConstExprValue *val) {
Error err;
if (val->special != ConstValSpecialLazy)
return ErrorNone;
IrExecutable *exec = val->data.x_lazy->exec;
switch (val->data.x_lazy->id) {
case LazyValueIdInvalid:
zig_unreachable();
case LazyValueIdAlignOf: {
LazyValueAlignOf *lazy_align_of = reinterpret_cast<LazyValueAlignOf *>(val->data.x_lazy);
if ((err = type_resolve(codegen, lazy_align_of->target_type, ResolveStatusAlignmentKnown)))
return err;
uint64_t align_in_bytes = get_abi_alignment(codegen, lazy_align_of->target_type);
val->special = ConstValSpecialStatic;
assert(val->type->id == ZigTypeIdComptimeInt);
bigint_init_unsigned(&val->data.x_bigint, align_in_bytes);
return ErrorNone;
}
case LazyValueIdSliceType: {
LazyValueSliceType *lazy_slice_type = reinterpret_cast<LazyValueSliceType *>(val->data.x_lazy);
uint32_t align_bytes = 0;
if (lazy_slice_type->align_val != nullptr) {
if (!ir_resolve_const_align(codegen, exec, source_node, lazy_slice_type->align_val, &align_bytes))
return ErrorSemanticAnalyzeFail;
}
if ((err = type_resolve(codegen, lazy_slice_type->elem_type, ResolveStatusZeroBitsKnown)))
return err;
ZigType *slice_ptr_type = get_pointer_to_type_extra(codegen, lazy_slice_type->elem_type,
lazy_slice_type->is_const, lazy_slice_type->is_volatile, PtrLenUnknown, align_bytes,
0, 0, lazy_slice_type->is_allowzero);
val->special = ConstValSpecialStatic;
assert(val->type->id == ZigTypeIdMetaType);
val->data.x_type = get_slice_type(codegen, slice_ptr_type);
return ErrorNone;
}
case LazyValueIdFnType: {
ZigType *fn_type = ir_resolve_lazy_fn_type(codegen, exec, source_node,
reinterpret_cast<LazyValueFnType *>(val->data.x_lazy));
if (fn_type == nullptr)
return ErrorSemanticAnalyzeFail;
val->special = ConstValSpecialStatic;
assert(val->type->id == ZigTypeIdMetaType);
val->data.x_type = fn_type;
return ErrorNone;
}
}
zig_unreachable();
}
static IrInstruction *ir_analyze_instruction_add_implicit_return_type(IrAnalyze *ira, static IrInstruction *ir_analyze_instruction_add_implicit_return_type(IrAnalyze *ira,
IrInstructionAddImplicitReturnType *instruction) IrInstructionAddImplicitReturnType *instruction)
{ {
@ -13964,20 +14141,19 @@ static bool ir_analyze_fn_call_generic_arg(IrAnalyze *ira, AstNode *fn_proto_nod
} }
static ZigVar *get_fn_var_by_index(ZigFn *fn_entry, size_t index) { static ZigVar *get_fn_var_by_index(ZigFn *fn_entry, size_t index) {
FnTypeParamInfo *src_param_info = &fn_entry->type_entry->data.fn.fn_type_id.param_info[index];
if (!type_has_bits(src_param_info->type))
return nullptr;
size_t next_var_i = 0; size_t next_var_i = 0;
FnGenParamInfo *gen_param_info = fn_entry->type_entry->data.fn.gen_param_info;
assert(gen_param_info != nullptr);
for (size_t param_i = 0; param_i < index; param_i += 1) { for (size_t param_i = 0; param_i < index; param_i += 1) {
FnGenParamInfo *info = &gen_param_info[param_i]; FnTypeParamInfo *src_param_info = &fn_entry->type_entry->data.fn.fn_type_id.param_info[param_i];
if (info->gen_index == SIZE_MAX) if (!type_has_bits(src_param_info->type)) {
continue; continue;
}
next_var_i += 1; next_var_i += 1;
} }
FnGenParamInfo *info = &gen_param_info[index];
if (info->gen_index == SIZE_MAX)
return nullptr;
return fn_entry->variable_list.at(next_var_i); return fn_entry->variable_list.at(next_var_i);
} }
@ -14003,7 +14179,7 @@ static IrInstruction *ir_get_var_ptr(IrAnalyze *ira, IrInstruction *instruction,
if (linkage_makes_it_runtime) if (linkage_makes_it_runtime)
goto no_mem_slot; goto no_mem_slot;
if (var->const_value->special == ConstValSpecialStatic) { if (value_is_comptime(var->const_value)) {
mem_slot = var->const_value; mem_slot = var->const_value;
} else { } else {
if (var->mem_slot_index != SIZE_MAX && (comptime_var_mem || var->gen_is_const)) { if (var->mem_slot_index != SIZE_MAX && (comptime_var_mem || var->gen_is_const)) {
@ -14021,6 +14197,7 @@ static IrInstruction *ir_get_var_ptr(IrAnalyze *ira, IrInstruction *instruction,
case ConstValSpecialRuntime: case ConstValSpecialRuntime:
goto no_mem_slot; goto no_mem_slot;
case ConstValSpecialStatic: // fallthrough case ConstValSpecialStatic: // fallthrough
case ConstValSpecialLazy: // fallthrough
case ConstValSpecialUndef: { case ConstValSpecialUndef: {
ConstPtrMut ptr_mut; ConstPtrMut ptr_mut;
if (comptime_var_mem) { if (comptime_var_mem) {
@ -14301,7 +14478,7 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call
AstNode *body_node = fn_entry->body_node; AstNode *body_node = fn_entry->body_node;
result = ir_eval_const_value(ira->codegen, exec_scope, body_node, return_type, result = ir_eval_const_value(ira->codegen, exec_scope, body_node, return_type,
ira->new_irb.exec->backward_branch_count, ira->new_irb.exec->backward_branch_quota, fn_entry, ira->new_irb.exec->backward_branch_count, ira->new_irb.exec->backward_branch_quota, fn_entry,
nullptr, call_instruction->base.source_node, nullptr, ira->new_irb.exec, return_type_node); nullptr, call_instruction->base.source_node, nullptr, ira->new_irb.exec, return_type_node, false);
if (inferred_err_set_type != nullptr) { if (inferred_err_set_type != nullptr) {
inferred_err_set_type->data.error_set.infer_fn = nullptr; inferred_err_set_type->data.error_set.infer_fn = nullptr;
@ -14497,7 +14674,8 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call
ConstExprValue *align_result = ir_eval_const_value(ira->codegen, impl_fn->child_scope, ConstExprValue *align_result = ir_eval_const_value(ira->codegen, impl_fn->child_scope,
fn_proto_node->data.fn_proto.align_expr, get_align_amt_type(ira->codegen), fn_proto_node->data.fn_proto.align_expr, get_align_amt_type(ira->codegen),
ira->new_irb.exec->backward_branch_count, ira->new_irb.exec->backward_branch_quota, ira->new_irb.exec->backward_branch_count, ira->new_irb.exec->backward_branch_quota,
nullptr, nullptr, fn_proto_node->data.fn_proto.align_expr, nullptr, ira->new_irb.exec, nullptr); nullptr, nullptr, fn_proto_node->data.fn_proto.align_expr, nullptr, ira->new_irb.exec, nullptr,
false);
IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(&ira->new_irb, IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(&ira->new_irb,
impl_fn->child_scope, fn_proto_node->data.fn_proto.align_expr); impl_fn->child_scope, fn_proto_node->data.fn_proto.align_expr);
const_instruction->base.value = *align_result; const_instruction->base.value = *align_result;
@ -15630,7 +15808,7 @@ static IrInstruction *ir_analyze_container_member_access_inner(IrAnalyze *ira,
auto entry = container_scope->decl_table.maybe_get(field_name); auto entry = container_scope->decl_table.maybe_get(field_name);
Tld *tld = entry ? entry->value : nullptr; Tld *tld = entry ? entry->value : nullptr;
if (tld && tld->id == TldIdFn) { if (tld && tld->id == TldIdFn) {
resolve_top_level_decl(ira->codegen, tld, source_instr->source_node); resolve_top_level_decl(ira->codegen, tld, source_instr->source_node, false);
if (tld->resolution == TldResolutionInvalid) if (tld->resolution == TldResolutionInvalid)
return ira->codegen->invalid_instruction; return ira->codegen->invalid_instruction;
TldFn *tld_fn = (TldFn *)tld; TldFn *tld_fn = (TldFn *)tld;
@ -15821,7 +15999,7 @@ static void add_link_lib_symbol(IrAnalyze *ira, Buf *lib_name, Buf *symbol_name,
static IrInstruction *ir_analyze_decl_ref(IrAnalyze *ira, IrInstruction *source_instruction, Tld *tld) { static IrInstruction *ir_analyze_decl_ref(IrAnalyze *ira, IrInstruction *source_instruction, Tld *tld) {
resolve_top_level_decl(ira->codegen, tld, source_instruction->source_node); resolve_top_level_decl(ira->codegen, tld, source_instruction->source_node, false);
if (tld->resolution == TldResolutionInvalid) if (tld->resolution == TldResolutionInvalid)
return ira->codegen->invalid_instruction; return ira->codegen->invalid_instruction;
@ -16477,22 +16655,29 @@ static IrInstruction *ir_analyze_instruction_set_float_mode(IrAnalyze *ira,
static IrInstruction *ir_analyze_instruction_slice_type(IrAnalyze *ira, static IrInstruction *ir_analyze_instruction_slice_type(IrAnalyze *ira,
IrInstructionSliceType *slice_type_instruction) IrInstructionSliceType *slice_type_instruction)
{ {
Error err; IrInstruction *result = ir_const(ira, &slice_type_instruction->base, ira->codegen->builtin_types.entry_type);
uint32_t align_bytes = 0; result->value.special = ConstValSpecialLazy;
LazyValueSliceType *lazy_slice_type = allocate<LazyValueSliceType>(1);
result->value.data.x_lazy = &lazy_slice_type->base;
lazy_slice_type->base.id = LazyValueIdSliceType;
lazy_slice_type->base.exec = ira->new_irb.exec;
if (slice_type_instruction->align_value != nullptr) { if (slice_type_instruction->align_value != nullptr) {
if (!ir_resolve_align(ira, slice_type_instruction->align_value->child, &align_bytes)) lazy_slice_type->align_val = ir_resolve_const(ira, slice_type_instruction->align_value->child, LazyOk);
if (lazy_slice_type->align_val == nullptr)
return ira->codegen->invalid_instruction; return ira->codegen->invalid_instruction;
} }
ZigType *child_type = ir_resolve_type(ira, slice_type_instruction->child_type->child); lazy_slice_type->elem_type = ir_resolve_type(ira, slice_type_instruction->child_type->child);
if (type_is_invalid(child_type)) if (type_is_invalid(lazy_slice_type->elem_type))
return ira->codegen->invalid_instruction; return ira->codegen->invalid_instruction;
bool is_const = slice_type_instruction->is_const; lazy_slice_type->is_const = slice_type_instruction->is_const;
bool is_volatile = slice_type_instruction->is_volatile; lazy_slice_type->is_volatile = slice_type_instruction->is_volatile;
bool is_allow_zero = slice_type_instruction->is_allow_zero; lazy_slice_type->is_allowzero = slice_type_instruction->is_allow_zero;
switch (child_type->id) { switch (lazy_slice_type->elem_type->id) {
case ZigTypeIdInvalid: // handled above case ZigTypeIdInvalid: // handled above
zig_unreachable(); zig_unreachable();
case ZigTypeIdUnreachable: case ZigTypeIdUnreachable:
@ -16501,7 +16686,7 @@ static IrInstruction *ir_analyze_instruction_slice_type(IrAnalyze *ira,
case ZigTypeIdArgTuple: case ZigTypeIdArgTuple:
case ZigTypeIdOpaque: case ZigTypeIdOpaque:
ir_add_error_node(ira, slice_type_instruction->base.source_node, ir_add_error_node(ira, slice_type_instruction->base.source_node,
buf_sprintf("slice of type '%s' not allowed", buf_ptr(&child_type->name))); buf_sprintf("slice of type '%s' not allowed", buf_ptr(&lazy_slice_type->elem_type->name)));
return ira->codegen->invalid_instruction; return ira->codegen->invalid_instruction;
case ZigTypeIdMetaType: case ZigTypeIdMetaType:
case ZigTypeIdVoid: case ZigTypeIdVoid:
@ -16523,14 +16708,7 @@ static IrInstruction *ir_analyze_instruction_slice_type(IrAnalyze *ira,
case ZigTypeIdBoundFn: case ZigTypeIdBoundFn:
case ZigTypeIdPromise: case ZigTypeIdPromise:
case ZigTypeIdVector: case ZigTypeIdVector:
{ return result;
if ((err = type_resolve(ira->codegen, child_type, ResolveStatusZeroBitsKnown)))
return ira->codegen->invalid_instruction;
ZigType *slice_ptr_type = get_pointer_to_type_extra(ira->codegen, child_type,
is_const, is_volatile, PtrLenUnknown, align_bytes, 0, 0, is_allow_zero);
ZigType *result_type = get_slice_type(ira->codegen, slice_ptr_type);
return ir_const_type(ira, &slice_type_instruction->base, result_type);
}
} }
zig_unreachable(); zig_unreachable();
} }
@ -16637,7 +16815,7 @@ static IrInstruction *ir_analyze_instruction_array_type(IrAnalyze *ira,
case ZigTypeIdPromise: case ZigTypeIdPromise:
case ZigTypeIdVector: case ZigTypeIdVector:
{ {
if ((err = ensure_complete_type(ira->codegen, child_type))) if ((err = type_resolve(ira->codegen, child_type, ResolveStatusSizeKnown)))
return ira->codegen->invalid_instruction; return ira->codegen->invalid_instruction;
ZigType *result_type = get_array_type(ira->codegen, child_type, size); ZigType *result_type = get_array_type(ira->codegen, child_type, size);
return ir_const_type(ira, &array_type_instruction->base, result_type); return ir_const_type(ira, &array_type_instruction->base, result_type);
@ -17513,6 +17691,8 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc
static IrInstruction *ir_analyze_instruction_container_init_list(IrAnalyze *ira, static IrInstruction *ir_analyze_instruction_container_init_list(IrAnalyze *ira,
IrInstructionContainerInitList *instruction) IrInstructionContainerInitList *instruction)
{ {
Error err;
ZigType *container_type = ir_resolve_type(ira, instruction->container_type->child); ZigType *container_type = ir_resolve_type(ira, instruction->container_type->child);
if (type_is_invalid(container_type)) if (type_is_invalid(container_type))
return ira->codegen->invalid_instruction; return ira->codegen->invalid_instruction;
@ -17541,6 +17721,10 @@ static IrInstruction *ir_analyze_instruction_container_init_list(IrAnalyze *ira,
child_type = pointer_type->data.pointer.child_type; child_type = pointer_type->data.pointer.child_type;
} }
if ((err = type_resolve(ira->codegen, child_type, ResolveStatusSizeKnown))) {
return ira->codegen->invalid_instruction;
}
ZigType *fixed_size_array_type = get_array_type(ira->codegen, child_type, elem_count); ZigType *fixed_size_array_type = get_array_type(ira->codegen, child_type, elem_count);
ConstExprValue const_val = {}; ConstExprValue const_val = {};
@ -17923,10 +18107,11 @@ static ZigType *ir_type_info_get_type(IrAnalyze *ira, const char *type_name, Zig
Error err; Error err;
ConstExprValue *type_info_var = get_builtin_value(ira->codegen, "TypeInfo"); ConstExprValue *type_info_var = get_builtin_value(ira->codegen, "TypeInfo");
assert(type_info_var->type->id == ZigTypeIdMetaType); assert(type_info_var->type->id == ZigTypeIdMetaType);
assertNoError(ensure_complete_type(ira->codegen, type_info_var->data.x_type));
ZigType *type_info_type = type_info_var->data.x_type; ZigType *type_info_type = type_info_var->data.x_type;
assert(type_info_type->id == ZigTypeIdUnion); assert(type_info_type->id == ZigTypeIdUnion);
if ((err = type_resolve(ira->codegen, type_info_type, ResolveStatusSizeKnown))) {
zig_unreachable();
}
if (type_name == nullptr && root == nullptr) if (type_name == nullptr && root == nullptr)
return type_info_type; return type_info_type;
@ -17960,7 +18145,7 @@ static Error ir_make_type_info_defs(IrAnalyze *ira, IrInstruction *source_instr,
{ {
Error err; Error err;
ZigType *type_info_definition_type = ir_type_info_get_type(ira, "Definition", nullptr); ZigType *type_info_definition_type = ir_type_info_get_type(ira, "Definition", nullptr);
if ((err = ensure_complete_type(ira->codegen, type_info_definition_type))) if ((err = type_resolve(ira->codegen, type_info_definition_type, ResolveStatusSizeKnown)))
return err; return err;
ensure_field_index(type_info_definition_type, "name", 0); ensure_field_index(type_info_definition_type, "name", 0);
@ -17987,7 +18172,7 @@ static Error ir_make_type_info_defs(IrAnalyze *ira, IrInstruction *source_instr,
while ((curr_entry = decl_it.next()) != nullptr) { while ((curr_entry = decl_it.next()) != nullptr) {
// If the definition is unresolved, force it to be resolved again. // If the definition is unresolved, force it to be resolved again.
if (curr_entry->value->resolution == TldResolutionUnresolved) { if (curr_entry->value->resolution == TldResolutionUnresolved) {
resolve_top_level_decl(ira->codegen, curr_entry->value, curr_entry->value->source_node); resolve_top_level_decl(ira->codegen, curr_entry->value, curr_entry->value->source_node, false);
if (curr_entry->value->resolution != TldResolutionOk) { if (curr_entry->value->resolution != TldResolutionOk) {
return ErrorSemanticAnalyzeFail; return ErrorSemanticAnalyzeFail;
} }
@ -18480,6 +18665,9 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInstruction *source_instr
ensure_field_index(result->type, "fields", 2); ensure_field_index(result->type, "fields", 2);
ZigType *type_info_enum_field_type = ir_type_info_get_type(ira, "EnumField", nullptr); ZigType *type_info_enum_field_type = ir_type_info_get_type(ira, "EnumField", nullptr);
if ((err = type_resolve(ira->codegen, type_info_enum_field_type, ResolveStatusSizeKnown))) {
zig_unreachable();
}
uint32_t enum_field_count = type_entry->data.enumeration.src_field_count; uint32_t enum_field_count = type_entry->data.enumeration.src_field_count;
ConstExprValue *enum_field_array = create_const_vals(1); ConstExprValue *enum_field_array = create_const_vals(1);
@ -18523,6 +18711,9 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInstruction *source_instr
result->data.x_optional = nullptr; result->data.x_optional = nullptr;
break; break;
} }
if ((err = type_resolve(ira->codegen, type_info_error_type, ResolveStatusSizeKnown))) {
zig_unreachable();
}
ConstExprValue *slice_val = create_const_vals(1); ConstExprValue *slice_val = create_const_vals(1);
result->data.x_optional = slice_val; result->data.x_optional = slice_val;
@ -18619,6 +18810,8 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInstruction *source_instr
ensure_field_index(result->type, "fields", 2); ensure_field_index(result->type, "fields", 2);
ZigType *type_info_union_field_type = ir_type_info_get_type(ira, "UnionField", nullptr); ZigType *type_info_union_field_type = ir_type_info_get_type(ira, "UnionField", nullptr);
if ((err = type_resolve(ira->codegen, type_info_union_field_type, ResolveStatusSizeKnown)))
zig_unreachable();
uint32_t union_field_count = type_entry->data.unionation.src_field_count; uint32_t union_field_count = type_entry->data.unionation.src_field_count;
ConstExprValue *union_field_array = create_const_vals(1); ConstExprValue *union_field_array = create_const_vals(1);
@ -18696,6 +18889,9 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInstruction *source_instr
ensure_field_index(result->type, "fields", 1); ensure_field_index(result->type, "fields", 1);
ZigType *type_info_struct_field_type = ir_type_info_get_type(ira, "StructField", nullptr); ZigType *type_info_struct_field_type = ir_type_info_get_type(ira, "StructField", nullptr);
if ((err = type_resolve(ira->codegen, type_info_struct_field_type, ResolveStatusSizeKnown))) {
zig_unreachable();
}
uint32_t struct_field_count = type_entry->data.structure.src_field_count; uint32_t struct_field_count = type_entry->data.structure.src_field_count;
ConstExprValue *struct_field_array = create_const_vals(1); ConstExprValue *struct_field_array = create_const_vals(1);
@ -18803,6 +18999,9 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInstruction *source_instr
} }
// args: []TypeInfo.FnArg // args: []TypeInfo.FnArg
ZigType *type_info_fn_arg_type = ir_type_info_get_type(ira, "FnArg", nullptr); ZigType *type_info_fn_arg_type = ir_type_info_get_type(ira, "FnArg", nullptr);
if ((err = type_resolve(ira->codegen, type_info_fn_arg_type, ResolveStatusSizeKnown))) {
zig_unreachable();
}
size_t fn_arg_count = type_entry->data.fn.fn_type_id.param_count - size_t fn_arg_count = type_entry->data.fn.fn_type_id.param_count -
(is_varargs && type_entry->data.fn.fn_type_id.cc != CallingConventionC); (is_varargs && type_entry->data.fn.fn_type_id.cc != CallingConventionC);
@ -18962,7 +19161,7 @@ static IrInstruction *ir_analyze_instruction_c_import(IrAnalyze *ira, IrInstruct
ZigType *void_type = ira->codegen->builtin_types.entry_void; ZigType *void_type = ira->codegen->builtin_types.entry_void;
ConstExprValue *cimport_result = ir_eval_const_value(ira->codegen, &cimport_scope->base, block_node, void_type, ConstExprValue *cimport_result = ir_eval_const_value(ira->codegen, &cimport_scope->base, block_node, void_type,
ira->new_irb.exec->backward_branch_count, ira->new_irb.exec->backward_branch_quota, nullptr, ira->new_irb.exec->backward_branch_count, ira->new_irb.exec->backward_branch_quota, nullptr,
&cimport_scope->buf, block_node, nullptr, nullptr, nullptr); &cimport_scope->buf, block_node, nullptr, nullptr, nullptr, false);
if (type_is_invalid(cimport_result->type)) if (type_is_invalid(cimport_result->type))
return ira->codegen->invalid_instruction; return ira->codegen->invalid_instruction;
@ -20509,15 +20708,11 @@ static IrInstruction *ir_analyze_instruction_handle(IrAnalyze *ira, IrInstructio
} }
static IrInstruction *ir_analyze_instruction_align_of(IrAnalyze *ira, IrInstructionAlignOf *instruction) { static IrInstruction *ir_analyze_instruction_align_of(IrAnalyze *ira, IrInstructionAlignOf *instruction) {
Error err;
IrInstruction *type_value = instruction->type_value->child; IrInstruction *type_value = instruction->type_value->child;
if (type_is_invalid(type_value->value.type)) if (type_is_invalid(type_value->value.type))
return ira->codegen->invalid_instruction; return ira->codegen->invalid_instruction;
ZigType *type_entry = ir_resolve_type(ira, type_value); ZigType *type_entry = ir_resolve_type(ira, type_value);
if ((err = type_resolve(ira->codegen, type_entry, ResolveStatusAlignmentKnown)))
return ira->codegen->invalid_instruction;
switch (type_entry->id) { switch (type_entry->id) {
case ZigTypeIdInvalid: case ZigTypeIdInvalid:
zig_unreachable(); zig_unreachable();
@ -20549,12 +20744,25 @@ static IrInstruction *ir_analyze_instruction_align_of(IrAnalyze *ira, IrInstruct
case ZigTypeIdUnion: case ZigTypeIdUnion:
case ZigTypeIdFn: case ZigTypeIdFn:
case ZigTypeIdVector: case ZigTypeIdVector:
{ break;
uint64_t align_in_bytes = get_abi_alignment(ira->codegen, type_entry);
return ir_const_unsigned(ira, &instruction->base, align_in_bytes);
}
} }
zig_unreachable(); if (type_is_resolved(type_entry, ResolveStatusAlignmentKnown)) {
uint64_t align_in_bytes = get_abi_alignment(ira->codegen, type_entry);
return ir_const_unsigned(ira, &instruction->base, align_in_bytes);
}
// Here we create a lazy value in order to avoid resolving the alignment of the type
// immediately. This avoids false positive dependency loops such as:
// const Node = struct {
// field: []align(@alignOf(Node)) Node,
// };
LazyValueAlignOf *lazy_align_of = allocate<LazyValueAlignOf>(1);
lazy_align_of->base.id = LazyValueIdAlignOf;
lazy_align_of->base.exec = ira->new_irb.exec;
lazy_align_of->target_type = type_entry;
IrInstruction *result = ir_const(ira, &instruction->base, ira->codegen->builtin_types.entry_num_lit_int);
result->value.special = ConstValSpecialLazy;
result->value.data.x_lazy = &lazy_align_of->base;
return result;
} }
static IrInstruction *ir_analyze_instruction_overflow_op(IrAnalyze *ira, IrInstructionOverflowOp *instruction) { static IrInstruction *ir_analyze_instruction_overflow_op(IrAnalyze *ira, IrInstructionOverflowOp *instruction) {
@ -20809,96 +21017,77 @@ static IrInstruction *ir_analyze_instruction_fn_proto(IrAnalyze *ira, IrInstruct
AstNode *proto_node = instruction->base.source_node; AstNode *proto_node = instruction->base.source_node;
assert(proto_node->type == NodeTypeFnProto); assert(proto_node->type == NodeTypeFnProto);
IrInstruction *result = ir_const(ira, &instruction->base, ira->codegen->builtin_types.entry_type);
result->value.special = ConstValSpecialLazy;
LazyValueFnType *lazy_fn_type = allocate<LazyValueFnType>(1);
result->value.data.x_lazy = &lazy_fn_type->base;
lazy_fn_type->base.id = LazyValueIdFnType;
lazy_fn_type->base.exec = ira->new_irb.exec;
if (proto_node->data.fn_proto.auto_err_set) { if (proto_node->data.fn_proto.auto_err_set) {
ir_add_error(ira, &instruction->base, ir_add_error(ira, &instruction->base,
buf_sprintf("inferring error set of return type valid only for function definitions")); buf_sprintf("inferring error set of return type valid only for function definitions"));
return ira->codegen->invalid_instruction; return ira->codegen->invalid_instruction;
} }
FnTypeId fn_type_id = {0}; size_t param_count = proto_node->data.fn_proto.params.length;
init_fn_type_id(&fn_type_id, proto_node, proto_node->data.fn_proto.params.length); lazy_fn_type->proto_node = proto_node;
lazy_fn_type->param_types = allocate<ConstExprValue *>(param_count);
for (; fn_type_id.next_param_index < fn_type_id.param_count; fn_type_id.next_param_index += 1) { for (size_t i = 0; i < param_count; i += 1) {
AstNode *param_node = proto_node->data.fn_proto.params.at(fn_type_id.next_param_index); AstNode *param_node = proto_node->data.fn_proto.params.at(i);
assert(param_node->type == NodeTypeParamDecl); assert(param_node->type == NodeTypeParamDecl);
bool param_is_var_args = param_node->data.param_decl.is_var_args; bool param_is_var_args = param_node->data.param_decl.is_var_args;
lazy_fn_type->is_var_args = true;
if (param_is_var_args) { if (param_is_var_args) {
if (fn_type_id.cc == CallingConventionC) { if (proto_node->data.fn_proto.cc == CallingConventionC) {
fn_type_id.param_count = fn_type_id.next_param_index; break;
continue; } else if (proto_node->data.fn_proto.cc == CallingConventionUnspecified) {
} else if (fn_type_id.cc == CallingConventionUnspecified) { lazy_fn_type->is_generic = true;
return ir_const_type(ira, &instruction->base, get_generic_fn_type(ira->codegen, &fn_type_id)); return result;
} else { } else {
zig_unreachable(); zig_unreachable();
} }
} }
FnTypeParamInfo *param_info = &fn_type_id.param_info[fn_type_id.next_param_index];
param_info->is_noalias = param_node->data.param_decl.is_noalias;
if (instruction->param_types[fn_type_id.next_param_index] == nullptr) { if (instruction->param_types[i] == nullptr) {
param_info->type = nullptr; lazy_fn_type->is_generic = true;
return ir_const_type(ira, &instruction->base, get_generic_fn_type(ira->codegen, &fn_type_id)); return result;
} else {
IrInstruction *param_type_value = instruction->param_types[fn_type_id.next_param_index]->child;
if (type_is_invalid(param_type_value->value.type))
return ira->codegen->invalid_instruction;
ZigType *param_type = ir_resolve_type(ira, param_type_value);
switch (type_requires_comptime(ira->codegen, param_type)) {
case ReqCompTimeYes:
if (!calling_convention_allows_zig_types(fn_type_id.cc)) {
ir_add_error(ira, param_type_value,
buf_sprintf("parameter of type '%s' not allowed in function with calling convention '%s'",
buf_ptr(&param_type->name), calling_convention_name(fn_type_id.cc)));
return ira->codegen->invalid_instruction;
}
param_info->type = param_type;
fn_type_id.next_param_index += 1;
return ir_const_type(ira, &instruction->base, get_generic_fn_type(ira->codegen, &fn_type_id));
case ReqCompTimeInvalid:
return ira->codegen->invalid_instruction;
case ReqCompTimeNo:
break;
}
if (!type_has_bits(param_type) && !calling_convention_allows_zig_types(fn_type_id.cc)) {
ir_add_error(ira, param_type_value,
buf_sprintf("parameter of type '%s' has 0 bits; not allowed in function with calling convention '%s'",
buf_ptr(&param_type->name), calling_convention_name(fn_type_id.cc)));
return ira->codegen->invalid_instruction;
}
param_info->type = param_type;
} }
IrInstruction *param_type_value = instruction->param_types[i]->child;
if (type_is_invalid(param_type_value->value.type))
return ira->codegen->invalid_instruction;
ConstExprValue *param_type_val = ir_resolve_const(ira, param_type_value, LazyOk);
if (param_type_val == nullptr)
return ira->codegen->invalid_instruction;
lazy_fn_type->param_types[i] = param_type_val;
} }
if (instruction->align_value != nullptr) { if (instruction->align_value != nullptr) {
if (!ir_resolve_align(ira, instruction->align_value->child, &fn_type_id.alignment)) lazy_fn_type->align_val = ir_resolve_const(ira, instruction->align_value->child, LazyOk);
if (lazy_fn_type->align_val == nullptr)
return ira->codegen->invalid_instruction; return ira->codegen->invalid_instruction;
} }
IrInstruction *return_type_value = instruction->return_type->child; lazy_fn_type->return_type = ir_resolve_const(ira, instruction->return_type->child, LazyOk);
fn_type_id.return_type = ir_resolve_type(ira, return_type_value); if (lazy_fn_type->return_type == nullptr)
if (type_is_invalid(fn_type_id.return_type))
return ira->codegen->invalid_instruction; return ira->codegen->invalid_instruction;
if (fn_type_id.return_type->id == ZigTypeIdOpaque) {
ir_add_error(ira, instruction->return_type,
buf_sprintf("return type cannot be opaque"));
return ira->codegen->invalid_instruction;
}
if (fn_type_id.cc == CallingConventionAsync) { if (proto_node->data.fn_proto.cc == CallingConventionAsync) {
if (instruction->async_allocator_type_value == nullptr) { if (instruction->async_allocator_type_value == nullptr) {
ir_add_error(ira, &instruction->base, ir_add_error(ira, &instruction->base,
buf_sprintf("async fn proto missing allocator type")); buf_sprintf("async fn proto missing allocator type"));
return ira->codegen->invalid_instruction; return ira->codegen->invalid_instruction;
} }
IrInstruction *async_allocator_type_value = instruction->async_allocator_type_value->child; lazy_fn_type->async_allocator_type = ir_resolve_const(ira, instruction->async_allocator_type_value->child, LazyOk);
fn_type_id.async_allocator_type = ir_resolve_type(ira, async_allocator_type_value); if (lazy_fn_type->async_allocator_type == nullptr)
if (type_is_invalid(fn_type_id.async_allocator_type))
return ira->codegen->invalid_instruction; return ira->codegen->invalid_instruction;
} }
return ir_const_type(ira, &instruction->base, get_fn_type(ira->codegen, &fn_type_id)); return result;
} }
static IrInstruction *ir_analyze_instruction_test_comptime(IrAnalyze *ira, IrInstructionTestComptime *instruction) { static IrInstruction *ir_analyze_instruction_test_comptime(IrAnalyze *ira, IrInstructionTestComptime *instruction) {
@ -21567,8 +21756,11 @@ static Error buf_read_value_bytes(IrAnalyze *ira, CodeGen *codegen, AstNode *sou
val->type->data.vector.len); val->type->data.vector.len);
case ZigTypeIdEnum: case ZigTypeIdEnum:
switch (val->type->data.enumeration.layout) { switch (val->type->data.enumeration.layout) {
case ContainerLayoutAuto: case ContainerLayoutAuto: {
zig_panic("TODO buf_read_value_bytes enum auto"); opt_ir_add_error_node(ira, codegen, source_node,
buf_sprintf("compiler bug: TODO: implement enum byte reinterpretation"));
return ErrorSemanticAnalyzeFail;
}
case ContainerLayoutPacked: case ContainerLayoutPacked:
zig_panic("TODO buf_read_value_bytes enum packed"); zig_panic("TODO buf_read_value_bytes enum packed");
case ContainerLayoutExtern: { case ContainerLayoutExtern: {
@ -21864,7 +22056,7 @@ static IrInstruction *ir_analyze_instruction_decl_ref(IrAnalyze *ira,
Tld *tld = instruction->tld; Tld *tld = instruction->tld;
LVal lval = instruction->lval; LVal lval = instruction->lval;
resolve_top_level_decl(ira->codegen, tld, instruction->base.source_node); resolve_top_level_decl(ira->codegen, tld, instruction->base.source_node, true);
if (tld->resolution == TldResolutionInvalid) if (tld->resolution == TldResolutionInvalid)
return ira->codegen->invalid_instruction; return ira->codegen->invalid_instruction;

View File

@ -16,7 +16,8 @@ bool ir_gen_fn(CodeGen *g, ZigFn *fn_entry);
ConstExprValue *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node, ConstExprValue *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node,
ZigType *expected_type, size_t *backward_branch_count, size_t backward_branch_quota, ZigType *expected_type, size_t *backward_branch_count, size_t backward_branch_quota,
ZigFn *fn_entry, Buf *c_import_buf, AstNode *source_node, Buf *exec_name, ZigFn *fn_entry, Buf *c_import_buf, AstNode *source_node, Buf *exec_name,
IrExecutable *parent_exec, AstNode *expected_type_source_node); IrExecutable *parent_exec, AstNode *expected_type_source_node, bool allow_lazy);
Error ir_resolve_lazy(CodeGen *codegen, AstNode *source_node, ConstExprValue *val);
ZigType *ir_analyze(CodeGen *g, IrExecutable *old_executable, IrExecutable *new_executable, ZigType *ir_analyze(CodeGen *g, IrExecutable *old_executable, IrExecutable *new_executable,
ZigType *expected_type, AstNode *expected_type_source_node); ZigType *expected_type, AstNode *expected_type_source_node);