diff options
| author | Andrew Kelley <andrew@ziglang.org> | 2019-04-01 12:53:57 -0400 |
|---|---|---|
| committer | Andrew Kelley <andrew@ziglang.org> | 2019-04-02 18:31:18 -0400 |
| commit | 3dc8448680cfea2b55a6064c655e400e31e5d3dd (patch) | |
| tree | b8fc52931b21831c5346a956824abcf52011519f /src/ir.cpp | |
| parent | ee5064c053526e9e6a0a94d835cd334eea2e5823 (diff) | |
| download | zig-3dc8448680cfea2b55a6064c655e400e31e5d3dd.tar.gz zig-3dc8448680cfea2b55a6064c655e400e31e5d3dd.zip | |
introduce lazy values
but I think it's a bad idea, so I'm going to back out the change
Diffstat (limited to 'src/ir.cpp')
| -rw-r--r-- | src/ir.cpp | 478 |
1 files changed, 335 insertions, 143 deletions
diff --git a/src/ir.cpp b/src/ir.cpp index 872a943814..a4d7cf271b 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -154,6 +154,7 @@ struct ConstCastBadAllowsZero { enum UndefAllowed { UndefOk, UndefBad, + LazyOk, }; 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; } +static Error ir_resolve_const_val(CodeGen *codegen, IrExecutable *exec, AstNode *source_node, + ConstExprValue *val, UndefAllowed undef_allowed) +{ + Error err; + for (;;) { + switch (val->special) { + case ConstValSpecialStatic: + return ErrorNone; + case ConstValSpecialRuntime: + if (!type_has_bits(val->type)) + return ErrorNone; + + exec_add_error_node(codegen, exec, source_node, + buf_sprintf("unable to evaluate constant expression")); + return ErrorSemanticAnalyzeFail; + 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; + } + } +} + static ConstExprValue *ir_resolve_const(IrAnalyze *ira, IrInstruction *value, UndefAllowed undef_allowed) { - switch (value->value.special) { - case ConstValSpecialStatic: - return &value->value; - case ConstValSpecialRuntime: - if (!type_has_bits(value->value.type)) { - return &value->value; - } - ir_add_error(ira, value, buf_sprintf("unable to evaluate constant expression")); - return nullptr; - case ConstValSpecialUndef: - if (undef_allowed == UndefOk) { - return &value->value; - } else { - ir_add_error(ira, value, buf_sprintf("use of undefined value here causes undefined behavior")); - return nullptr; - } + Error err; + if ((err = ir_resolve_const_val(ira->codegen, ira->new_irb.exec, value->source_node, + &value->value, undef_allowed))) + { + return nullptr; } - zig_unreachable(); + return &value->value; } ConstExprValue *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node, 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, - 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)) return &codegen->invalid_instruction->value; @@ -10326,7 +10352,24 @@ ConstExprValue *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *nod 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) { @@ -10339,12 +10382,7 @@ static ZigType *ir_resolve_type(IrAnalyze *ira, IrInstruction *type_value) { return ira->codegen->builtin_types.entry_invalid; } - ConstExprValue *const_val = ir_resolve_const(ira, type_value, UndefBad); - if (!const_val) - return ira->codegen->builtin_types.entry_invalid; - - assert(const_val->data.x_type != nullptr); - return const_val->data.x_type; + return ir_resolve_const_type(ira->codegen, ira->new_irb.exec, type_value->source_node, &type_value->value); } static ZigType *ir_resolve_error_set_type(IrAnalyze *ira, IrInstruction *op_source, IrInstruction *type_value) { @@ -11835,33 +11873,38 @@ static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruc } } -static bool ir_resolve_align(IrAnalyze *ira, IrInstruction *value, uint32_t *out) { - if (type_is_invalid(value->value.type)) - return false; - - IrInstruction *casted_value = ir_implicit_cast(ira, value, get_align_amt_type(ira->codegen)); - if (type_is_invalid(casted_value->value.type)) - return false; - - ConstExprValue *const_val = ir_resolve_const(ira, casted_value, UndefBad); - if (!const_val) +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) { - ir_add_error(ira, value, buf_sprintf("alignment must be >= 1")); + exec_add_error_node(codegen, exec, source_node, 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)); + 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) { + if (type_is_invalid(value->value.type)) + return false; + + IrInstruction *casted_value = ir_implicit_cast(ira, value, get_align_amt_type(ira->codegen)); + if (type_is_invalid(casted_value->value.type)) + return false; + + return ir_resolve_const_align(ira->codegen, ira->new_irb.exec, value->source_node, &casted_value->value, out); +} + static bool ir_resolve_unsigned(IrAnalyze *ira, IrInstruction *value, ZigType *int_type, uint64_t *out) { if (type_is_invalid(value->value.type)) return false; @@ -12029,6 +12072,140 @@ static Buf *ir_resolve_str(IrAnalyze *ira, IrInstruction *value) { 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(¶m_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(¶m_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, 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) { + 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; - 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) { - FnGenParamInfo *info = &gen_param_info[param_i]; - if (info->gen_index == SIZE_MAX) + FnTypeParamInfo *src_param_info = &fn_entry->type_entry->data.fn.fn_type_id.param_info[param_i]; + if (!type_has_bits(src_param_info->type)) { continue; + } 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); } @@ -14003,7 +14179,7 @@ static IrInstruction *ir_get_var_ptr(IrAnalyze *ira, IrInstruction *instruction, if (linkage_makes_it_runtime) goto no_mem_slot; - if (var->const_value->special == ConstValSpecialStatic) { + if (value_is_comptime(var->const_value)) { mem_slot = var->const_value; } else { 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: goto no_mem_slot; case ConstValSpecialStatic: // fallthrough + case ConstValSpecialLazy: // fallthrough case ConstValSpecialUndef: { ConstPtrMut ptr_mut; 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; 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, - 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) { 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, 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, - 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, impl_fn->child_scope, fn_proto_node->data.fn_proto.align_expr); 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); Tld *tld = entry ? entry->value : nullptr; 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) return ira->codegen->invalid_instruction; 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) { - 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) 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, IrInstructionSliceType *slice_type_instruction) { - Error err; - uint32_t align_bytes = 0; + IrInstruction *result = ir_const(ira, &slice_type_instruction->base, ira->codegen->builtin_types.entry_type); + 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 (!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; } - ZigType *child_type = ir_resolve_type(ira, slice_type_instruction->child_type->child); - if (type_is_invalid(child_type)) + lazy_slice_type->elem_type = ir_resolve_type(ira, slice_type_instruction->child_type->child); + if (type_is_invalid(lazy_slice_type->elem_type)) return ira->codegen->invalid_instruction; - bool is_const = slice_type_instruction->is_const; - bool is_volatile = slice_type_instruction->is_volatile; - bool is_allow_zero = slice_type_instruction->is_allow_zero; + lazy_slice_type->is_const = slice_type_instruction->is_const; + lazy_slice_type->is_volatile = slice_type_instruction->is_volatile; + 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 zig_unreachable(); case ZigTypeIdUnreachable: @@ -16501,7 +16686,7 @@ static IrInstruction *ir_analyze_instruction_slice_type(IrAnalyze *ira, case ZigTypeIdArgTuple: case ZigTypeIdOpaque: 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; case ZigTypeIdMetaType: case ZigTypeIdVoid: @@ -16523,14 +16708,7 @@ static IrInstruction *ir_analyze_instruction_slice_type(IrAnalyze *ira, case ZigTypeIdBoundFn: case ZigTypeIdPromise: case ZigTypeIdVector: - { - 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); - } + return result; } zig_unreachable(); } @@ -16637,7 +16815,7 @@ static IrInstruction *ir_analyze_instruction_array_type(IrAnalyze *ira, case ZigTypeIdPromise: 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; ZigType *result_type = get_array_type(ira->codegen, child_type, size); 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, IrInstructionContainerInitList *instruction) { + Error err; + ZigType *container_type = ir_resolve_type(ira, instruction->container_type->child); if (type_is_invalid(container_type)) 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; } + 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); ConstExprValue const_val = {}; @@ -17923,10 +18107,11 @@ static ZigType *ir_type_info_get_type(IrAnalyze *ira, const char *type_name, Zig Error err; ConstExprValue *type_info_var = get_builtin_value(ira->codegen, "TypeInfo"); 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; assert(type_info_type->id == ZigTypeIdUnion); + if ((err = type_resolve(ira->codegen, type_info_type, ResolveStatusSizeKnown))) { + zig_unreachable(); + } if (type_name == nullptr && root == nullptr) return type_info_type; @@ -17960,7 +18145,7 @@ static Error ir_make_type_info_defs(IrAnalyze *ira, IrInstruction *source_instr, { Error err; 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; 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) { // If the definition is unresolved, force it to be resolved again. 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) { 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); 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; 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; break; } + if ((err = type_resolve(ira->codegen, type_info_error_type, ResolveStatusSizeKnown))) { + zig_unreachable(); + } ConstExprValue *slice_val = create_const_vals(1); 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); 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; 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); 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; 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 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 - (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; 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, - &cimport_scope->buf, block_node, nullptr, nullptr, nullptr); + &cimport_scope->buf, block_node, nullptr, nullptr, nullptr, false); if (type_is_invalid(cimport_result->type)) 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) { - Error err; IrInstruction *type_value = instruction->type_value->child; if (type_is_invalid(type_value->value.type)) return ira->codegen->invalid_instruction; 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) { case ZigTypeIdInvalid: zig_unreachable(); @@ -20549,12 +20744,25 @@ static IrInstruction *ir_analyze_instruction_align_of(IrAnalyze *ira, IrInstruct case ZigTypeIdUnion: case ZigTypeIdFn: case ZigTypeIdVector: - { - uint64_t align_in_bytes = get_abi_alignment(ira->codegen, type_entry); - return ir_const_unsigned(ira, &instruction->base, align_in_bytes); - } + break; } - 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) { @@ -20809,96 +21017,77 @@ static IrInstruction *ir_analyze_instruction_fn_proto(IrAnalyze *ira, IrInstruct AstNode *proto_node = instruction->base.source_node; 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) { ir_add_error(ira, &instruction->base, buf_sprintf("inferring error set of return type valid only for function definitions")); return ira->codegen->invalid_instruction; } - FnTypeId fn_type_id = {0}; - init_fn_type_id(&fn_type_id, proto_node, proto_node->data.fn_proto.params.length); + size_t param_count = 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) { - AstNode *param_node = proto_node->data.fn_proto.params.at(fn_type_id.next_param_index); + for (size_t i = 0; i < param_count; i += 1) { + AstNode *param_node = proto_node->data.fn_proto.params.at(i); assert(param_node->type == NodeTypeParamDecl); 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 (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 ir_const_type(ira, &instruction->base, get_generic_fn_type(ira->codegen, &fn_type_id)); + if (proto_node->data.fn_proto.cc == CallingConventionC) { + break; + } else if (proto_node->data.fn_proto.cc == CallingConventionUnspecified) { + lazy_fn_type->is_generic = true; + return result; } 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 (instruction->param_types[fn_type_id.next_param_index] == nullptr) { - param_info->type = nullptr; - return ir_const_type(ira, &instruction->base, get_generic_fn_type(ira->codegen, &fn_type_id)); - } 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(¶m_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(¶m_type->name), calling_convention_name(fn_type_id.cc))); - return ira->codegen->invalid_instruction; - } - param_info->type = param_type; + if (instruction->param_types[i] == nullptr) { + lazy_fn_type->is_generic = true; + return result; } + 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 (!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; } - IrInstruction *return_type_value = instruction->return_type->child; - fn_type_id.return_type = ir_resolve_type(ira, return_type_value); - if (type_is_invalid(fn_type_id.return_type)) - 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")); + lazy_fn_type->return_type = ir_resolve_const(ira, instruction->return_type->child, LazyOk); + if (lazy_fn_type->return_type == nullptr) 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) { ir_add_error(ira, &instruction->base, buf_sprintf("async fn proto missing allocator type")); return ira->codegen->invalid_instruction; } - IrInstruction *async_allocator_type_value = instruction->async_allocator_type_value->child; - fn_type_id.async_allocator_type = ir_resolve_type(ira, async_allocator_type_value); - if (type_is_invalid(fn_type_id.async_allocator_type)) + lazy_fn_type->async_allocator_type = ir_resolve_const(ira, instruction->async_allocator_type_value->child, LazyOk); + if (lazy_fn_type->async_allocator_type == nullptr) 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) { @@ -21567,8 +21756,11 @@ static Error buf_read_value_bytes(IrAnalyze *ira, CodeGen *codegen, AstNode *sou val->type->data.vector.len); case ZigTypeIdEnum: switch (val->type->data.enumeration.layout) { - case ContainerLayoutAuto: - zig_panic("TODO buf_read_value_bytes enum auto"); + case ContainerLayoutAuto: { + opt_ir_add_error_node(ira, codegen, source_node, + buf_sprintf("compiler bug: TODO: implement enum byte reinterpretation")); + return ErrorSemanticAnalyzeFail; + } case ContainerLayoutPacked: zig_panic("TODO buf_read_value_bytes enum packed"); case ContainerLayoutExtern: { @@ -21864,7 +22056,7 @@ static IrInstruction *ir_analyze_instruction_decl_ref(IrAnalyze *ira, Tld *tld = instruction->tld; 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) return ira->codegen->invalid_instruction; |
