| ... | @@ -19707,25 +19707,31 @@ static IrInstGen *ir_analyze_fn_call(IrAnalyze *ira, IrInst* source_instr, | ... | @@ -19707,25 +19707,31 @@ static IrInstGen *ir_analyze_fn_call(IrAnalyze *ira, IrInst* source_instr, |
| 19707 | } | 19707 | } |
| 19708 | | 19708 | |
| 19709 | if (modifier == CallModifierCompileTime) { | 19709 | if (modifier == CallModifierCompileTime) { |
| 19710 | bool extern_fn_in_typeof = false; | 19710 | // If we are evaluating an extern function in a TypeOf call, we can return an undefined value |
| | 19711 | // of its return type. |
| | 19712 | if (fn_entry != nullptr && source_instr->scope->id == ScopeIdTypeOf && |
| | 19713 | fn_proto_node->data.fn_proto.is_extern) { |
| | 19714 | |
| | 19715 | assert(fn_entry->body_node == nullptr); |
| | 19716 | AstNode *return_type_node = fn_proto_node->data.fn_proto.return_type; |
| | 19717 | ZigType *return_type = ir_analyze_type_expr(ira, source_instr->scope, return_type_node); |
| | 19718 | if (type_is_invalid(return_type)) |
| | 19719 | return ira->codegen->invalid_inst_gen; |
| | 19720 | |
| | 19721 | return ir_const_undef(ira, source_instr, return_type); |
| | 19722 | } |
| 19711 | | 19723 | |
| 19712 | // No special handling is needed for compile time evaluation of generic functions. | 19724 | // No special handling is needed for compile time evaluation of generic functions. |
| 19713 | if (!fn_entry || fn_entry->body_node == nullptr) { | 19725 | if (!fn_entry || fn_entry->body_node == nullptr) { |
| 19714 | // We keep evaluating extern functions directly in TypeOfs | 19726 | ir_add_error(ira, &fn_ref->base, buf_sprintf("unable to evaluate constant expression")); |
| 19715 | if (fn_entry && source_instr->scope->id == ScopeIdTypeOf) { | 19727 | return ira->codegen->invalid_inst_gen; |
| 19716 | extern_fn_in_typeof = true; | | |
| 19717 | } else { | | |
| 19718 | ir_add_error(ira, &fn_ref->base, buf_sprintf("unable to evaluate constant expression")); | | |
| 19719 | return ira->codegen->invalid_inst_gen; | | |
| 19720 | } | | |
| 19721 | } | 19728 | } |
| 19722 | | 19729 | |
| 19723 | if (!ir_emit_backward_branch(ira, source_instr)) | 19730 | if (!ir_emit_backward_branch(ira, source_instr)) |
| 19724 | return ira->codegen->invalid_inst_gen; | 19731 | return ira->codegen->invalid_inst_gen; |
| 19725 | | 19732 | |
| 19726 | // Fork a scope of the function with known values for the parameters. | 19733 | // Fork a scope of the function with known values for the parameters. |
| 19727 | // If we are evaluating an extern function in a TypeOf, we use the current scope instead. | 19734 | Scope *exec_scope = &fn_entry->fndef_scope->base; |
| 19728 | Scope *exec_scope = extern_fn_in_typeof ? source_instr->scope : &fn_entry->fndef_scope->base; | | |
| 19729 | | 19735 | |
| 19730 | size_t next_proto_i = 0; | 19736 | size_t next_proto_i = 0; |
| 19731 | if (first_arg_ptr) { | 19737 | if (first_arg_ptr) { |
| ... | @@ -19752,7 +19758,7 @@ static IrInstGen *ir_analyze_fn_call(IrAnalyze *ira, IrInst* source_instr, | ... | @@ -19752,7 +19758,7 @@ static IrInstGen *ir_analyze_fn_call(IrAnalyze *ira, IrInst* source_instr, |
| 19752 | return ira->codegen->invalid_inst_gen; | 19758 | return ira->codegen->invalid_inst_gen; |
| 19753 | } | 19759 | } |
| 19754 | | 19760 | |
| 19755 | if (!extern_fn_in_typeof) for (size_t call_i = 0; call_i < args_len; call_i += 1) { | 19761 | for (size_t call_i = 0; call_i < args_len; call_i += 1) { |
| 19756 | IrInstGen *old_arg = args_ptr[call_i]; | 19762 | IrInstGen *old_arg = args_ptr[call_i]; |
| 19757 | | 19763 | |
| 19758 | if (!ir_analyze_fn_call_inline_arg(ira, fn_proto_node, old_arg, &exec_scope, &next_proto_i)) | 19764 | if (!ir_analyze_fn_call_inline_arg(ira, fn_proto_node, old_arg, &exec_scope, &next_proto_i)) |
| ... | @@ -19774,7 +19780,7 @@ static IrInstGen *ir_analyze_fn_call(IrAnalyze *ira, IrInst* source_instr, | ... | @@ -19774,7 +19780,7 @@ static IrInstGen *ir_analyze_fn_call(IrAnalyze *ira, IrInst* source_instr, |
| 19774 | return_type = specified_return_type; | 19780 | return_type = specified_return_type; |
| 19775 | } | 19781 | } |
| 19776 | | 19782 | |
| 19777 | bool cacheable = !extern_fn_in_typeof && fn_eval_cacheable(exec_scope, return_type); | 19783 | bool cacheable = fn_eval_cacheable(exec_scope, return_type); |
| 19778 | ZigValue *result = nullptr; | 19784 | ZigValue *result = nullptr; |
| 19779 | if (cacheable) { | 19785 | if (cacheable) { |
| 19780 | auto entry = ira->codegen->memoized_fn_eval_table.maybe_get(exec_scope); | 19786 | auto entry = ira->codegen->memoized_fn_eval_table.maybe_get(exec_scope); |
| ... | @@ -19788,15 +19794,12 @@ static IrInstGen *ir_analyze_fn_call(IrAnalyze *ira, IrInst* source_instr, | ... | @@ -19788,15 +19794,12 @@ static IrInstGen *ir_analyze_fn_call(IrAnalyze *ira, IrInst* source_instr, |
| 19788 | ZigValue *result_ptr; | 19794 | ZigValue *result_ptr; |
| 19789 | create_result_ptr(ira->codegen, return_type, &result, &result_ptr); | 19795 | create_result_ptr(ira->codegen, return_type, &result, &result_ptr); |
| 19790 | | 19796 | |
| 19791 | // If we are evaluating an extern function in a TypeOf, create a value and keep it undefined. | 19797 | if ((err = ir_eval_const_value(ira->codegen, exec_scope, body_node, result_ptr, |
| 19792 | if (!extern_fn_in_typeof) { | 19798 | ira->new_irb.exec->backward_branch_count, ira->new_irb.exec->backward_branch_quota, |
| 19793 | if ((err = ir_eval_const_value(ira->codegen, exec_scope, body_node, result_ptr, | 19799 | fn_entry, nullptr, source_instr->source_node, nullptr, ira->new_irb.exec, return_type_node, |
| 19794 | ira->new_irb.exec->backward_branch_count, ira->new_irb.exec->backward_branch_quota, | 19800 | UndefOk))) |
| 19795 | fn_entry, nullptr, source_instr->source_node, nullptr, ira->new_irb.exec, return_type_node, | 19801 | { |
| 19796 | UndefOk))) | 19802 | return ira->codegen->invalid_inst_gen; |
| 19797 | { | | |
| 19798 | return ira->codegen->invalid_inst_gen; | | |
| 19799 | } | | |
| 19800 | } | 19803 | } |
| 19801 | | 19804 | |
| 19802 | if (inferred_err_set_type != nullptr) { | 19805 | if (inferred_err_set_type != nullptr) { |