| ... | ... | @@ -22869,84 +22869,65 @@ static IrInstruction *ir_analyze_instruction_fn_proto(IrAnalyze *ira, IrInstruct |
| 22869 | 22869 | AstNode *proto_node = instruction->base.source_node; |
| 22870 | 22870 | assert(proto_node->type == NodeTypeFnProto); |
| 22871 | 22871 | |
| 22872 | IrInstruction *result = ir_const(ira, &instruction->base, ira->codegen->builtin_types.entry_type); |
| 22873 | result->value.special = ConstValSpecialLazy; |
| 22874 | |
| 22875 | LazyValueFnType *lazy_fn_type = allocate<LazyValueFnType>(1); |
| 22876 | result->value.data.x_lazy = &lazy_fn_type->base; |
| 22877 | lazy_fn_type->base.id = LazyValueIdFnType; |
| 22878 | lazy_fn_type->base.exec = ira->new_irb.exec; |
| 22879 | |
| 22872 | 22880 | if (proto_node->data.fn_proto.auto_err_set) { |
| 22873 | 22881 | ir_add_error(ira, &instruction->base, |
| 22874 | 22882 | buf_sprintf("inferring error set of return type valid only for function definitions")); |
| 22875 | 22883 | return ira->codegen->invalid_instruction; |
| 22876 | 22884 | } |
| 22877 | 22885 | |
| 22878 | | FnTypeId fn_type_id = {0}; |
| 22879 | | init_fn_type_id(&fn_type_id, proto_node, proto_node->data.fn_proto.params.length); |
| 22886 | size_t param_count = proto_node->data.fn_proto.params.length; |
| 22887 | lazy_fn_type->proto_node = proto_node; |
| 22888 | lazy_fn_type->param_types = allocate<ConstExprValue *>(param_count); |
| 22880 | 22889 | |
| 22881 | | for (; fn_type_id.next_param_index < fn_type_id.param_count; fn_type_id.next_param_index += 1) { |
| 22882 | | AstNode *param_node = proto_node->data.fn_proto.params.at(fn_type_id.next_param_index); |
| 22890 | for (size_t param_index = 0; param_index < param_count; param_index += 1) { |
| 22891 | AstNode *param_node = proto_node->data.fn_proto.params.at(param_index); |
| 22883 | 22892 | assert(param_node->type == NodeTypeParamDecl); |
| 22884 | 22893 | |
| 22885 | 22894 | bool param_is_var_args = param_node->data.param_decl.is_var_args; |
| 22886 | 22895 | if (param_is_var_args) { |
| 22887 | | if (fn_type_id.cc == CallingConventionC) { |
| 22888 | | fn_type_id.param_count = fn_type_id.next_param_index; |
| 22889 | | continue; |
| 22890 | | } else if (fn_type_id.cc == CallingConventionUnspecified) { |
| 22891 | | return ir_const_type(ira, &instruction->base, get_generic_fn_type(ira->codegen, &fn_type_id)); |
| 22896 | if (proto_node->data.fn_proto.cc == CallingConventionC) { |
| 22897 | break; |
| 22898 | } else if (proto_node->data.fn_proto.cc == CallingConventionUnspecified) { |
| 22899 | lazy_fn_type->is_generic = true; |
| 22900 | return result; |
| 22892 | 22901 | } else { |
| 22893 | 22902 | zig_unreachable(); |
| 22894 | 22903 | } |
| 22895 | 22904 | } |
| 22896 | | FnTypeParamInfo *param_info = &fn_type_id.param_info[fn_type_id.next_param_index]; |
| 22897 | | param_info->is_noalias = param_node->data.param_decl.is_noalias; |
| 22898 | 22905 | |
| 22899 | | if (instruction->param_types[fn_type_id.next_param_index] == nullptr) { |
| 22900 | | param_info->type = nullptr; |
| 22901 | | return ir_const_type(ira, &instruction->base, get_generic_fn_type(ira->codegen, &fn_type_id)); |
| 22902 | | } else { |
| 22903 | | IrInstruction *param_type_value = instruction->param_types[fn_type_id.next_param_index]->child; |
| 22904 | | ZigType *param_type = ir_resolve_type(ira, param_type_value); |
| 22905 | | if (type_is_invalid(param_type)) |
| 22906 | | return ira->codegen->invalid_instruction; |
| 22907 | | switch (type_requires_comptime(ira->codegen, param_type, nullptr)) { |
| 22908 | | case ReqCompTimeYes: |
| 22909 | | if (!calling_convention_allows_zig_types(fn_type_id.cc)) { |
| 22910 | | ir_add_error(ira, param_type_value, |
| 22911 | | buf_sprintf("parameter of type '%s' not allowed in function with calling convention '%s'", |
| 22912 | | buf_ptr(&param_type->name), calling_convention_name(fn_type_id.cc))); |
| 22913 | | return ira->codegen->invalid_instruction; |
| 22914 | | } |
| 22915 | | param_info->type = param_type; |
| 22916 | | fn_type_id.next_param_index += 1; |
| 22917 | | return ir_const_type(ira, &instruction->base, get_generic_fn_type(ira->codegen, &fn_type_id)); |
| 22918 | | case ReqCompTimeInvalid: |
| 22919 | | return ira->codegen->invalid_instruction; |
| 22920 | | case ReqCompTimeNo: |
| 22921 | | break; |
| 22922 | | } |
| 22923 | | if (!type_has_bits(param_type) && !calling_convention_allows_zig_types(fn_type_id.cc)) { |
| 22924 | | ir_add_error(ira, param_type_value, |
| 22925 | | buf_sprintf("parameter of type '%s' has 0 bits; not allowed in function with calling convention '%s'", |
| 22926 | | buf_ptr(&param_type->name), calling_convention_name(fn_type_id.cc))); |
| 22927 | | return ira->codegen->invalid_instruction; |
| 22928 | | } |
| 22929 | | param_info->type = param_type; |
| 22906 | if (instruction->param_types[param_index] == nullptr) { |
| 22907 | lazy_fn_type->is_generic = true; |
| 22908 | return result; |
| 22930 | 22909 | } |
| 22931 | 22910 | |
| 22911 | IrInstruction *param_type_value = instruction->param_types[param_index]->child; |
| 22912 | if (type_is_invalid(param_type_value->value.type)) |
| 22913 | return ira->codegen->invalid_instruction; |
| 22914 | ConstExprValue *param_type_val = ir_resolve_const(ira, param_type_value, LazyOk); |
| 22915 | if (param_type_val == nullptr) |
| 22916 | return ira->codegen->invalid_instruction; |
| 22917 | lazy_fn_type->param_types[param_index] = param_type_val; |
| 22932 | 22918 | } |
| 22933 | 22919 | |
| 22934 | 22920 | if (instruction->align_value != nullptr) { |
| 22935 | | if (!ir_resolve_align(ira, instruction->align_value->child, &fn_type_id.alignment)) |
| 22921 | lazy_fn_type->align_val = ir_resolve_const(ira, instruction->align_value->child, LazyOk); |
| 22922 | if (lazy_fn_type->align_val == nullptr) |
| 22936 | 22923 | return ira->codegen->invalid_instruction; |
| 22937 | 22924 | } |
| 22938 | 22925 | |
| 22939 | | IrInstruction *return_type_value = instruction->return_type->child; |
| 22940 | | fn_type_id.return_type = ir_resolve_type(ira, return_type_value); |
| 22941 | | if (type_is_invalid(fn_type_id.return_type)) |
| 22942 | | return ira->codegen->invalid_instruction; |
| 22943 | | if (fn_type_id.return_type->id == ZigTypeIdOpaque) { |
| 22944 | | ir_add_error(ira, instruction->return_type, |
| 22945 | | buf_sprintf("return type cannot be opaque")); |
| 22946 | | return ira->codegen->invalid_instruction; |
| 22947 | | } |
| 22926 | lazy_fn_type->return_type = ir_resolve_const(ira, instruction->return_type->child, LazyOk); |
| 22927 | if (lazy_fn_type->return_type == nullptr) |
| 22928 | return ira->codegen->invalid_instruction; |
| 22948 | 22929 | |
| 22949 | | return ir_const_type(ira, &instruction->base, get_fn_type(ira->codegen, &fn_type_id)); |
| 22930 | return result; |
| 22950 | 22931 | } |
| 22951 | 22932 | |
| 22952 | 22933 | static IrInstruction *ir_analyze_instruction_test_comptime(IrAnalyze *ira, IrInstructionTestComptime *instruction) { |
| ... | ... | @@ -25492,6 +25473,82 @@ bool ir_has_side_effects(IrInstruction *instruction) { |
| 25492 | 25473 | zig_unreachable(); |
| 25493 | 25474 | } |
| 25494 | 25475 | |
| 25476 | static ZigType *ir_resolve_lazy_fn_type(CodeGen *codegen, IrExecutable *exec, AstNode *source_node, |
| 25477 | LazyValueFnType *lazy_fn_type) |
| 25478 | { |
| 25479 | AstNode *proto_node = lazy_fn_type->proto_node; |
| 25480 | |
| 25481 | FnTypeId fn_type_id = {0}; |
| 25482 | init_fn_type_id(&fn_type_id, proto_node, proto_node->data.fn_proto.params.length); |
| 25483 | |
| 25484 | for (; fn_type_id.next_param_index < fn_type_id.param_count; fn_type_id.next_param_index += 1) { |
| 25485 | AstNode *param_node = proto_node->data.fn_proto.params.at(fn_type_id.next_param_index); |
| 25486 | assert(param_node->type == NodeTypeParamDecl); |
| 25487 | |
| 25488 | bool param_is_var_args = param_node->data.param_decl.is_var_args; |
| 25489 | if (param_is_var_args) { |
| 25490 | if (fn_type_id.cc == CallingConventionC) { |
| 25491 | fn_type_id.param_count = fn_type_id.next_param_index; |
| 25492 | continue; |
| 25493 | } else if (fn_type_id.cc == CallingConventionUnspecified) { |
| 25494 | return get_generic_fn_type(codegen, &fn_type_id); |
| 25495 | } else { |
| 25496 | zig_unreachable(); |
| 25497 | } |
| 25498 | } |
| 25499 | FnTypeParamInfo *param_info = &fn_type_id.param_info[fn_type_id.next_param_index]; |
| 25500 | param_info->is_noalias = param_node->data.param_decl.is_noalias; |
| 25501 | |
| 25502 | if (lazy_fn_type->param_types[fn_type_id.next_param_index] == nullptr) { |
| 25503 | param_info->type = nullptr; |
| 25504 | return get_generic_fn_type(codegen, &fn_type_id); |
| 25505 | } else { |
| 25506 | ZigType *param_type = ir_resolve_const_type(codegen, exec, source_node, |
| 25507 | lazy_fn_type->param_types[fn_type_id.next_param_index]); |
| 25508 | if (type_is_invalid(param_type)) |
| 25509 | return nullptr; |
| 25510 | switch (type_requires_comptime(codegen, param_type, nullptr)) { |
| 25511 | case ReqCompTimeYes: |
| 25512 | if (!calling_convention_allows_zig_types(fn_type_id.cc)) { |
| 25513 | exec_add_error_node(codegen, exec, source_node, |
| 25514 | buf_sprintf("parameter of type '%s' not allowed in function with calling convention '%s'", |
| 25515 | buf_ptr(&param_type->name), calling_convention_name(fn_type_id.cc))); |
| 25516 | return nullptr; |
| 25517 | } |
| 25518 | param_info->type = param_type; |
| 25519 | fn_type_id.next_param_index += 1; |
| 25520 | return get_generic_fn_type(codegen, &fn_type_id); |
| 25521 | case ReqCompTimeInvalid: |
| 25522 | return nullptr; |
| 25523 | case ReqCompTimeNo: |
| 25524 | break; |
| 25525 | } |
| 25526 | if (!type_has_bits(param_type) && !calling_convention_allows_zig_types(fn_type_id.cc)) { |
| 25527 | exec_add_error_node(codegen, exec, source_node, |
| 25528 | buf_sprintf("parameter of type '%s' has 0 bits; not allowed in function with calling convention '%s'", |
| 25529 | buf_ptr(&param_type->name), calling_convention_name(fn_type_id.cc))); |
| 25530 | return nullptr; |
| 25531 | } |
| 25532 | param_info->type = param_type; |
| 25533 | } |
| 25534 | } |
| 25535 | |
| 25536 | if (lazy_fn_type->align_val != nullptr) { |
| 25537 | if (!ir_resolve_const_align(codegen, exec, source_node, lazy_fn_type->align_val, &fn_type_id.alignment)) |
| 25538 | return nullptr; |
| 25539 | } |
| 25540 | |
| 25541 | fn_type_id.return_type = ir_resolve_const_type(codegen, exec, source_node, lazy_fn_type->return_type); |
| 25542 | if (type_is_invalid(fn_type_id.return_type)) |
| 25543 | return nullptr; |
| 25544 | if (fn_type_id.return_type->id == ZigTypeIdOpaque) { |
| 25545 | exec_add_error_node(codegen, exec, source_node, buf_create_from_str("return type cannot be opaque")); |
| 25546 | return nullptr; |
| 25547 | } |
| 25548 | |
| 25549 | return get_fn_type(codegen, &fn_type_id); |
| 25550 | } |
| 25551 | |
| 25495 | 25552 | static Error ir_resolve_lazy_raw(CodeGen *codegen, AstNode *source_node, ConstExprValue *val) { |
| 25496 | 25553 | Error err; |
| 25497 | 25554 | if (val->special != ConstValSpecialLazy) |
| ... | ... | @@ -25551,6 +25608,16 @@ static Error ir_resolve_lazy_raw(CodeGen *codegen, AstNode *source_node, ConstEx |
| 25551 | 25608 | val->special = ConstValSpecialStatic; |
| 25552 | 25609 | return ErrorNone; |
| 25553 | 25610 | } |
| 25611 | case LazyValueIdFnType: { |
| 25612 | ZigType *fn_type = ir_resolve_lazy_fn_type(codegen, exec, source_node, |
| 25613 | reinterpret_cast<LazyValueFnType *>(val->data.x_lazy)); |
| 25614 | if (fn_type == nullptr) |
| 25615 | return ErrorSemanticAnalyzeFail; |
| 25616 | val->special = ConstValSpecialStatic; |
| 25617 | assert(val->type->id == ZigTypeIdMetaType); |
| 25618 | val->data.x_type = fn_type; |
| 25619 | return ErrorNone; |
| 25620 | } |
| 25554 | 25621 | } |
| 25555 | 25622 | zig_unreachable(); |
| 25556 | 25623 | } |