| ... | @@ -1857,14 +1857,17 @@ static IrInstruction *ir_build_unwrap_err_payload_from(IrBuilder *irb, IrInstruc | ... | @@ -1857,14 +1857,17 @@ static IrInstruction *ir_build_unwrap_err_payload_from(IrBuilder *irb, IrInstruc |
| 1857 | } | 1857 | } |
| 1858 | | 1858 | |
| 1859 | static IrInstruction *ir_build_fn_proto(IrBuilder *irb, Scope *scope, AstNode *source_node, | 1859 | static IrInstruction *ir_build_fn_proto(IrBuilder *irb, Scope *scope, AstNode *source_node, |
| 1860 | IrInstruction **param_types, IrInstruction *return_type) | 1860 | IrInstruction **param_types, IrInstruction *return_type, bool is_var_args) |
| 1861 | { | 1861 | { |
| 1862 | IrInstructionFnProto *instruction = ir_build_instruction<IrInstructionFnProto>(irb, scope, source_node); | 1862 | IrInstructionFnProto *instruction = ir_build_instruction<IrInstructionFnProto>(irb, scope, source_node); |
| 1863 | instruction->param_types = param_types; | 1863 | instruction->param_types = param_types; |
| 1864 | instruction->return_type = return_type; | 1864 | instruction->return_type = return_type; |
| | 1865 | instruction->is_var_args = is_var_args; |
| 1865 | | 1866 | |
| 1866 | assert(source_node->type == NodeTypeFnProto); | 1867 | assert(source_node->type == NodeTypeFnProto); |
| 1867 | for (size_t i = 0; i < source_node->data.fn_proto.params.length; i += 1) { | 1868 | size_t param_count = source_node->data.fn_proto.params.length; |
| | 1869 | if (is_var_args) param_count -= 1; |
| | 1870 | for (size_t i = 0; i < param_count; i += 1) { |
| 1868 | ir_ref_instruction(param_types[i], irb->current_basic_block); | 1871 | ir_ref_instruction(param_types[i], irb->current_basic_block); |
| 1869 | } | 1872 | } |
| 1870 | ir_ref_instruction(return_type, irb->current_basic_block); | 1873 | ir_ref_instruction(return_type, irb->current_basic_block); |
| ... | @@ -5843,8 +5846,13 @@ static IrInstruction *ir_gen_fn_proto(IrBuilder *irb, Scope *parent_scope, AstNo | ... | @@ -5843,8 +5846,13 @@ static IrInstruction *ir_gen_fn_proto(IrBuilder *irb, Scope *parent_scope, AstNo |
| 5843 | size_t param_count = node->data.fn_proto.params.length; | 5846 | size_t param_count = node->data.fn_proto.params.length; |
| 5844 | IrInstruction **param_types = allocate<IrInstruction*>(param_count); | 5847 | IrInstruction **param_types = allocate<IrInstruction*>(param_count); |
| 5845 | | 5848 | |
| | 5849 | bool is_var_args = false; |
| 5846 | for (size_t i = 0; i < param_count; i += 1) { | 5850 | for (size_t i = 0; i < param_count; i += 1) { |
| 5847 | AstNode *param_node = node->data.fn_proto.params.at(i); | 5851 | AstNode *param_node = node->data.fn_proto.params.at(i); |
| | 5852 | if (param_node->data.param_decl.is_var_args) { |
| | 5853 | is_var_args = true; |
| | 5854 | break; |
| | 5855 | } |
| 5848 | AstNode *type_node = param_node->data.param_decl.type; | 5856 | AstNode *type_node = param_node->data.param_decl.type; |
| 5849 | IrInstruction *type_value = ir_gen_node(irb, type_node, parent_scope); | 5857 | IrInstruction *type_value = ir_gen_node(irb, type_node, parent_scope); |
| 5850 | if (type_value == irb->codegen->invalid_instruction) | 5858 | if (type_value == irb->codegen->invalid_instruction) |
| ... | @@ -5856,7 +5864,7 @@ static IrInstruction *ir_gen_fn_proto(IrBuilder *irb, Scope *parent_scope, AstNo | ... | @@ -5856,7 +5864,7 @@ static IrInstruction *ir_gen_fn_proto(IrBuilder *irb, Scope *parent_scope, AstNo |
| 5856 | if (return_type == irb->codegen->invalid_instruction) | 5864 | if (return_type == irb->codegen->invalid_instruction) |
| 5857 | return irb->codegen->invalid_instruction; | 5865 | return irb->codegen->invalid_instruction; |
| 5858 | | 5866 | |
| 5859 | return ir_build_fn_proto(irb, parent_scope, node, param_types, return_type); | 5867 | return ir_build_fn_proto(irb, parent_scope, node, param_types, return_type, is_var_args); |
| 5860 | } | 5868 | } |
| 5861 | | 5869 | |
| 5862 | static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scope, | 5870 | static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scope, |
| ... | @@ -9039,7 +9047,11 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal | ... | @@ -9039,7 +9047,11 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal |
| 9039 | } | 9047 | } |
| 9040 | | 9048 | |
| 9041 | if (fn_type->data.fn.is_generic) { | 9049 | if (fn_type->data.fn.is_generic) { |
| 9042 | assert(fn_entry); | 9050 | if (!fn_entry) { |
| | 9051 | ir_add_error(ira, call_instruction->fn_ref, |
| | 9052 | buf_sprintf("calling a generic function requires compile-time known function value")); |
| | 9053 | return ira->codegen->builtin_types.entry_invalid; |
| | 9054 | } |
| 9043 | | 9055 | |
| 9044 | // Count the arguments of the function type id we are creating | 9056 | // Count the arguments of the function type id we are creating |
| 9045 | size_t new_fn_arg_count = first_arg_1_or_0; | 9057 | size_t new_fn_arg_count = first_arg_1_or_0; |
| ... | @@ -13065,6 +13077,17 @@ static TypeTableEntry *ir_analyze_instruction_fn_proto(IrAnalyze *ira, IrInstruc | ... | @@ -13065,6 +13077,17 @@ static TypeTableEntry *ir_analyze_instruction_fn_proto(IrAnalyze *ira, IrInstruc |
| 13065 | AstNode *param_node = proto_node->data.fn_proto.params.at(fn_type_id.next_param_index); | 13077 | AstNode *param_node = proto_node->data.fn_proto.params.at(fn_type_id.next_param_index); |
| 13066 | assert(param_node->type == NodeTypeParamDecl); | 13078 | assert(param_node->type == NodeTypeParamDecl); |
| 13067 | | 13079 | |
| | 13080 | bool param_is_var_args = param_node->data.param_decl.is_var_args; |
| | 13081 | if (param_is_var_args) { |
| | 13082 | if (fn_type_id.is_extern) { |
| | 13083 | fn_type_id.param_count = fn_type_id.next_param_index; |
| | 13084 | continue; |
| | 13085 | } else { |
| | 13086 | ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base); |
| | 13087 | out_val->data.x_type = get_generic_fn_type(ira->codegen, &fn_type_id); |
| | 13088 | return ira->codegen->builtin_types.entry_type; |
| | 13089 | } |
| | 13090 | } |
| 13068 | IrInstruction *param_type_value = instruction->param_types[fn_type_id.next_param_index]->other; | 13091 | IrInstruction *param_type_value = instruction->param_types[fn_type_id.next_param_index]->other; |
| 13069 | | 13092 | |
| 13070 | FnTypeParamInfo *param_info = &fn_type_id.param_info[fn_type_id.next_param_index]; | 13093 | FnTypeParamInfo *param_info = &fn_type_id.param_info[fn_type_id.next_param_index]; |