| ... | @@ -986,7 +986,7 @@ static IrInstruction *ir_build_union_field_ptr_from(IrBuilder *irb, IrInstructio | ... | @@ -986,7 +986,7 @@ static IrInstruction *ir_build_union_field_ptr_from(IrBuilder *irb, IrInstructio |
| 986 | | 986 | |
| 987 | static IrInstruction *ir_build_call(IrBuilder *irb, Scope *scope, AstNode *source_node, | 987 | static IrInstruction *ir_build_call(IrBuilder *irb, Scope *scope, AstNode *source_node, |
| 988 | FnTableEntry *fn_entry, IrInstruction *fn_ref, size_t arg_count, IrInstruction **args, | 988 | FnTableEntry *fn_entry, IrInstruction *fn_ref, size_t arg_count, IrInstruction **args, |
| 989 | bool is_comptime, FnInline fn_inline) | 989 | bool is_comptime, FnInline fn_inline, bool is_async, IrInstruction *async_allocator) |
| 990 | { | 990 | { |
| 991 | IrInstructionCall *call_instruction = ir_build_instruction<IrInstructionCall>(irb, scope, source_node); | 991 | IrInstructionCall *call_instruction = ir_build_instruction<IrInstructionCall>(irb, scope, source_node); |
| 992 | call_instruction->fn_entry = fn_entry; | 992 | call_instruction->fn_entry = fn_entry; |
| ... | @@ -995,21 +995,25 @@ static IrInstruction *ir_build_call(IrBuilder *irb, Scope *scope, AstNode *sourc | ... | @@ -995,21 +995,25 @@ static IrInstruction *ir_build_call(IrBuilder *irb, Scope *scope, AstNode *sourc |
| 995 | call_instruction->fn_inline = fn_inline; | 995 | call_instruction->fn_inline = fn_inline; |
| 996 | call_instruction->args = args; | 996 | call_instruction->args = args; |
| 997 | call_instruction->arg_count = arg_count; | 997 | call_instruction->arg_count = arg_count; |
| | 998 | call_instruction->is_async = is_async; |
| | 999 | call_instruction->async_allocator = async_allocator; |
| 998 | | 1000 | |
| 999 | if (fn_ref) | 1001 | if (fn_ref) |
| 1000 | ir_ref_instruction(fn_ref, irb->current_basic_block); | 1002 | ir_ref_instruction(fn_ref, irb->current_basic_block); |
| 1001 | for (size_t i = 0; i < arg_count; i += 1) | 1003 | for (size_t i = 0; i < arg_count; i += 1) |
| 1002 | ir_ref_instruction(args[i], irb->current_basic_block); | 1004 | ir_ref_instruction(args[i], irb->current_basic_block); |
| | 1005 | if (async_allocator) |
| | 1006 | ir_ref_instruction(async_allocator, irb->current_basic_block); |
| 1003 | | 1007 | |
| 1004 | return &call_instruction->base; | 1008 | return &call_instruction->base; |
| 1005 | } | 1009 | } |
| 1006 | | 1010 | |
| 1007 | static IrInstruction *ir_build_call_from(IrBuilder *irb, IrInstruction *old_instruction, | 1011 | static IrInstruction *ir_build_call_from(IrBuilder *irb, IrInstruction *old_instruction, |
| 1008 | FnTableEntry *fn_entry, IrInstruction *fn_ref, size_t arg_count, IrInstruction **args, | 1012 | FnTableEntry *fn_entry, IrInstruction *fn_ref, size_t arg_count, IrInstruction **args, |
| 1009 | bool is_comptime, FnInline fn_inline) | 1013 | bool is_comptime, FnInline fn_inline, bool is_async, IrInstruction *async_allocator) |
| 1010 | { | 1014 | { |
| 1011 | IrInstruction *new_instruction = ir_build_call(irb, old_instruction->scope, | 1015 | IrInstruction *new_instruction = ir_build_call(irb, old_instruction->scope, |
| 1012 | old_instruction->source_node, fn_entry, fn_ref, arg_count, args, is_comptime, fn_inline); | 1016 | old_instruction->source_node, fn_entry, fn_ref, arg_count, args, is_comptime, fn_inline, is_async, async_allocator); |
| 1013 | ir_link_new_instruction(new_instruction, old_instruction); | 1017 | ir_link_new_instruction(new_instruction, old_instruction); |
| 1014 | return new_instruction; | 1018 | return new_instruction; |
| 1015 | } | 1019 | } |
| ... | @@ -3754,7 +3758,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo | ... | @@ -3754,7 +3758,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo |
| 3754 | } | 3758 | } |
| 3755 | FnInline fn_inline = (builtin_fn->id == BuiltinFnIdInlineCall) ? FnInlineAlways : FnInlineNever; | 3759 | FnInline fn_inline = (builtin_fn->id == BuiltinFnIdInlineCall) ? FnInlineAlways : FnInlineNever; |
| 3756 | | 3760 | |
| 3757 | return ir_build_call(irb, scope, node, nullptr, fn_ref, arg_count, args, false, fn_inline); | 3761 | return ir_build_call(irb, scope, node, nullptr, fn_ref, arg_count, args, false, fn_inline, false, nullptr); |
| 3758 | } | 3762 | } |
| 3759 | case BuiltinFnIdTypeId: | 3763 | case BuiltinFnIdTypeId: |
| 3760 | { | 3764 | { |
| ... | @@ -3888,11 +3892,17 @@ static IrInstruction *ir_gen_fn_call(IrBuilder *irb, Scope *scope, AstNode *node | ... | @@ -3888,11 +3892,17 @@ static IrInstruction *ir_gen_fn_call(IrBuilder *irb, Scope *scope, AstNode *node |
| 3888 | return args[i]; | 3892 | return args[i]; |
| 3889 | } | 3893 | } |
| 3890 | | 3894 | |
| 3891 | if (node->data.fn_call_expr.is_async) { | 3895 | bool is_async = node->data.fn_call_expr.is_async; |
| 3892 | zig_panic("TODO ir_gen_fn_call for async fn calls"); | 3896 | IrInstruction *async_allocator = nullptr; |
| | 3897 | if (is_async) { |
| | 3898 | if (node->data.fn_call_expr.async_allocator) { |
| | 3899 | async_allocator = ir_gen_node(irb, node->data.fn_call_expr.async_allocator, scope); |
| | 3900 | if (async_allocator == irb->codegen->invalid_instruction) |
| | 3901 | return async_allocator; |
| | 3902 | } |
| 3893 | } | 3903 | } |
| 3894 | | 3904 | |
| 3895 | return ir_build_call(irb, scope, node, nullptr, fn_ref, arg_count, args, false, FnInlineAuto); | 3905 | return ir_build_call(irb, scope, node, nullptr, fn_ref, arg_count, args, false, FnInlineAuto, is_async, async_allocator); |
| 3896 | } | 3906 | } |
| 3897 | | 3907 | |
| 3898 | static IrInstruction *ir_gen_if_bool_expr(IrBuilder *irb, Scope *scope, AstNode *node) { | 3908 | static IrInstruction *ir_gen_if_bool_expr(IrBuilder *irb, Scope *scope, AstNode *node) { |
| ... | @@ -10584,6 +10594,11 @@ static TypeTableEntry *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructi | ... | @@ -10584,6 +10594,11 @@ static TypeTableEntry *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructi |
| 10584 | buf_sprintf("exported function must specify calling convention")); | 10594 | buf_sprintf("exported function must specify calling convention")); |
| 10585 | add_error_note(ira->codegen, msg, fn_entry->proto_node, buf_sprintf("declared here")); | 10595 | add_error_note(ira->codegen, msg, fn_entry->proto_node, buf_sprintf("declared here")); |
| 10586 | } break; | 10596 | } break; |
| | 10597 | case CallingConventionAsync: { |
| | 10598 | ErrorMsg *msg = ir_add_error(ira, target, |
| | 10599 | buf_sprintf("exported function cannot be async")); |
| | 10600 | add_error_note(ira->codegen, msg, fn_entry->proto_node, buf_sprintf("declared here")); |
| | 10601 | } break; |
| 10587 | case CallingConventionC: | 10602 | case CallingConventionC: |
| 10588 | case CallingConventionNaked: | 10603 | case CallingConventionNaked: |
| 10589 | case CallingConventionCold: | 10604 | case CallingConventionCold: |
| ... | @@ -10963,6 +10978,13 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal | ... | @@ -10963,6 +10978,13 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal |
| 10963 | } | 10978 | } |
| 10964 | return ira->codegen->builtin_types.entry_invalid; | 10979 | return ira->codegen->builtin_types.entry_invalid; |
| 10965 | } | 10980 | } |
| | 10981 | if (fn_type_id->cc == CallingConventionAsync && !call_instruction->is_async) { |
| | 10982 | ErrorMsg *msg = ir_add_error(ira, fn_ref, buf_sprintf("must use async keyword to call async function")); |
| | 10983 | if (fn_proto_node) { |
| | 10984 | add_error_note(ira->codegen, msg, fn_proto_node, buf_sprintf("declared here")); |
| | 10985 | } |
| | 10986 | return ira->codegen->builtin_types.entry_invalid; |
| | 10987 | } |
| 10966 | | 10988 | |
| 10967 | | 10989 | |
| 10968 | if (fn_type_id->is_var_args) { | 10990 | if (fn_type_id->is_var_args) { |
| ... | @@ -11258,7 +11280,7 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal | ... | @@ -11258,7 +11280,7 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal |
| 11258 | | 11280 | |
| 11259 | size_t impl_param_count = impl_fn->type_entry->data.fn.fn_type_id.param_count; | 11281 | size_t impl_param_count = impl_fn->type_entry->data.fn.fn_type_id.param_count; |
| 11260 | IrInstruction *new_call_instruction = ir_build_call_from(&ira->new_irb, &call_instruction->base, | 11282 | IrInstruction *new_call_instruction = ir_build_call_from(&ira->new_irb, &call_instruction->base, |
| 11261 | impl_fn, nullptr, impl_param_count, casted_args, false, fn_inline); | 11283 | impl_fn, nullptr, impl_param_count, casted_args, false, fn_inline, false, nullptr); |
| 11262 | | 11284 | |
| 11263 | TypeTableEntry *return_type = impl_fn->type_entry->data.fn.fn_type_id.return_type; | 11285 | TypeTableEntry *return_type = impl_fn->type_entry->data.fn.fn_type_id.return_type; |
| 11264 | ir_add_alloca(ira, new_call_instruction, return_type); | 11286 | ir_add_alloca(ira, new_call_instruction, return_type); |
| ... | @@ -11324,12 +11346,16 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal | ... | @@ -11324,12 +11346,16 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal |
| 11324 | | 11346 | |
| 11325 | assert(next_arg_index == call_param_count); | 11347 | assert(next_arg_index == call_param_count); |
| 11326 | | 11348 | |
| | 11349 | if (call_instruction->is_async) { |
| | 11350 | zig_panic("TODO handle async fn call"); |
| | 11351 | } |
| | 11352 | |
| 11327 | TypeTableEntry *return_type = fn_type_id->return_type; | 11353 | TypeTableEntry *return_type = fn_type_id->return_type; |
| 11328 | if (type_is_invalid(return_type)) | 11354 | if (type_is_invalid(return_type)) |
| 11329 | return ira->codegen->builtin_types.entry_invalid; | 11355 | return ira->codegen->builtin_types.entry_invalid; |
| 11330 | | 11356 | |
| 11331 | IrInstruction *new_call_instruction = ir_build_call_from(&ira->new_irb, &call_instruction->base, | 11357 | IrInstruction *new_call_instruction = ir_build_call_from(&ira->new_irb, &call_instruction->base, |
| 11332 | fn_entry, fn_ref, call_param_count, casted_args, false, fn_inline); | 11358 | fn_entry, fn_ref, call_param_count, casted_args, false, fn_inline, false, nullptr); |
| 11333 | | 11359 | |
| 11334 | ir_add_alloca(ira, new_call_instruction, return_type); | 11360 | ir_add_alloca(ira, new_call_instruction, return_type); |
| 11335 | return ir_finish_anal(ira, return_type); | 11361 | return ir_finish_anal(ira, return_type); |
| ... | @@ -16491,7 +16517,10 @@ static TypeTableEntry *ir_analyze_instruction_tag_type(IrAnalyze *ira, IrInstruc | ... | @@ -16491,7 +16517,10 @@ static TypeTableEntry *ir_analyze_instruction_tag_type(IrAnalyze *ira, IrInstruc |
| 16491 | } | 16517 | } |
| 16492 | | 16518 | |
| 16493 | static TypeTableEntry *ir_analyze_instruction_cancel(IrAnalyze *ira, IrInstructionCancel *instruction) { | 16519 | static TypeTableEntry *ir_analyze_instruction_cancel(IrAnalyze *ira, IrInstructionCancel *instruction) { |
| 16494 | IrInstruction *casted_target = ir_implicit_cast(ira, instruction->target->other, ira->codegen->builtin_types.entry_promise); | 16520 | IrInstruction *target_inst = instruction->target->other; |
| | 16521 | if (type_is_invalid(target_inst->value.type)) |
| | 16522 | return ira->codegen->builtin_types.entry_invalid; |
| | 16523 | IrInstruction *casted_target = ir_implicit_cast(ira, target_inst, ira->codegen->builtin_types.entry_promise); |
| 16495 | if (type_is_invalid(casted_target->value.type)) | 16524 | if (type_is_invalid(casted_target->value.type)) |
| 16496 | return ira->codegen->builtin_types.entry_invalid; | 16525 | return ira->codegen->builtin_types.entry_invalid; |
| 16497 | | 16526 | |