authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-09-05 21:55:07-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-09-05 21:55:32-04:00
log0a3c6dbda92931eba055c2c6447b7a4412408f17
tree86d98cd519e628c28efe2fe9e2ff3ec86f55246d
parentca70ca7e26aaae3425dad3a2b179f544bacf45e3
signaturelock-open Commit is signed but in an unrecognized format.

implement `noasync` function calls

See #3157

13 files changed, 175 insertions(+), 68 deletions(-)

doc/docgen.zig+2-1
...@@ -786,9 +786,10 @@ fn tokenizeAndPrintRaw(docgen_tokenizer: *Tokenizer, out: var, source_token: Tok...@@ -786,9 +786,10 @@ fn tokenizeAndPrintRaw(docgen_tokenizer: *Tokenizer, out: var, source_token: Tok
786 .Keyword_for,786 .Keyword_for,
787 .Keyword_if,787 .Keyword_if,
788 .Keyword_inline,788 .Keyword_inline,
789 .Keyword_noinline,
790 .Keyword_nakedcc,789 .Keyword_nakedcc,
791 .Keyword_noalias,790 .Keyword_noalias,
791 .Keyword_noasync,
792 .Keyword_noinline,
792 .Keyword_or,793 .Keyword_or,
793 .Keyword_orelse,794 .Keyword_orelse,
794 .Keyword_packed,795 .Keyword_packed,
src/all_types.hpp+14-5
...@@ -758,11 +758,17 @@ struct AstNodeUnwrapOptional {...@@ -758,11 +758,17 @@ struct AstNodeUnwrapOptional {
758 AstNode *expr;758 AstNode *expr;
759};759};
760760
761enum CallModifier {
762 CallModifierNone,
763 CallModifierAsync,
764 CallModifierNoAsync,
765 CallModifierBuiltin,
766};
767
761struct AstNodeFnCallExpr {768struct AstNodeFnCallExpr {
762 AstNode *fn_ref_expr;769 AstNode *fn_ref_expr;
763 ZigList<AstNode *> params;770 ZigList<AstNode *> params;
764 bool is_builtin;771 CallModifier modifier;
765 bool is_async;
766 bool seen; // used by @compileLog772 bool seen; // used by @compileLog
767};773};
768774
...@@ -2730,8 +2736,10 @@ struct IrInstructionCallSrc {...@@ -2730,8 +2736,10 @@ struct IrInstructionCallSrc {
2730 ResultLoc *result_loc;2736 ResultLoc *result_loc;
27312737
2732 IrInstruction *new_stack;2738 IrInstruction *new_stack;
2739
2733 FnInline fn_inline;2740 FnInline fn_inline;
2734 bool is_async;2741 CallModifier modifier;
2742
2735 bool is_async_call_builtin;2743 bool is_async_call_builtin;
2736 bool is_comptime;2744 bool is_comptime;
2737};2745};
...@@ -2745,10 +2753,11 @@ struct IrInstructionCallGen {...@@ -2745,10 +2753,11 @@ struct IrInstructionCallGen {
2745 IrInstruction **args;2753 IrInstruction **args;
2746 IrInstruction *result_loc;2754 IrInstruction *result_loc;
2747 IrInstruction *frame_result_loc;2755 IrInstruction *frame_result_loc;
2748
2749 IrInstruction *new_stack;2756 IrInstruction *new_stack;
2757
2750 FnInline fn_inline;2758 FnInline fn_inline;
2751 bool is_async;2759 CallModifier modifier;
2760
2752 bool is_async_call_builtin;2761 bool is_async_call_builtin;
2753};2762};
27542763
src/analyze.cpp+10-4
...@@ -4214,7 +4214,7 @@ void add_async_error_notes(CodeGen *g, ErrorMsg *msg, ZigFn *fn) {...@@ -4214,7 +4214,7 @@ void add_async_error_notes(CodeGen *g, ErrorMsg *msg, ZigFn *fn) {
4214 add_error_note(g, msg, fn->inferred_async_node,4214 add_error_note(g, msg, fn->inferred_async_node,
4215 buf_sprintf("await here is a suspend point"));4215 buf_sprintf("await here is a suspend point"));
4216 } else if (fn->inferred_async_node->type == NodeTypeFnCallExpr &&4216 } else if (fn->inferred_async_node->type == NodeTypeFnCallExpr &&
4217 fn->inferred_async_node->data.fn_call_expr.is_builtin)4217 fn->inferred_async_node->data.fn_call_expr.modifier == CallModifierBuiltin)
4218 {4218 {
4219 add_error_note(g, msg, fn->inferred_async_node,4219 add_error_note(g, msg, fn->inferred_async_node,
4220 buf_sprintf("@frame() causes function to be async"));4220 buf_sprintf("@frame() causes function to be async"));
...@@ -4228,8 +4228,10 @@ void add_async_error_notes(CodeGen *g, ErrorMsg *msg, ZigFn *fn) {...@@ -4228,8 +4228,10 @@ void add_async_error_notes(CodeGen *g, ErrorMsg *msg, ZigFn *fn) {
4228// ErrorIsAsync - yes async4228// ErrorIsAsync - yes async
4229// ErrorSemanticAnalyzeFail - compile error emitted result is invalid4229// ErrorSemanticAnalyzeFail - compile error emitted result is invalid
4230static Error analyze_callee_async(CodeGen *g, ZigFn *fn, ZigFn *callee, AstNode *call_node,4230static Error analyze_callee_async(CodeGen *g, ZigFn *fn, ZigFn *callee, AstNode *call_node,
4231 bool must_not_be_async)4231 bool must_not_be_async, CallModifier modifier)
4232{4232{
4233 if (modifier == CallModifierNoAsync)
4234 return ErrorNone;
4233 if (callee->type_entry->data.fn.fn_type_id.cc != CallingConventionUnspecified)4235 if (callee->type_entry->data.fn.fn_type_id.cc != CallingConventionUnspecified)
4234 return ErrorNone;4236 return ErrorNone;
4235 if (callee->anal_state == FnAnalStateReady) {4237 if (callee->anal_state == FnAnalStateReady) {
...@@ -4312,7 +4314,9 @@ static void analyze_fn_async(CodeGen *g, ZigFn *fn, bool resolve_frame) {...@@ -4312,7 +4314,9 @@ static void analyze_fn_async(CodeGen *g, ZigFn *fn, bool resolve_frame) {
4312 // TODO function pointer call here, could be anything4314 // TODO function pointer call here, could be anything
4313 continue;4315 continue;
4314 }4316 }
4315 switch (analyze_callee_async(g, fn, call->fn_entry, call->base.source_node, must_not_be_async)) {4317 switch (analyze_callee_async(g, fn, call->fn_entry, call->base.source_node, must_not_be_async,
4318 call->modifier))
4319 {
4316 case ErrorSemanticAnalyzeFail:4320 case ErrorSemanticAnalyzeFail:
4317 fn->anal_state = FnAnalStateInvalid;4321 fn->anal_state = FnAnalStateInvalid;
4318 return;4322 return;
...@@ -4329,7 +4333,9 @@ static void analyze_fn_async(CodeGen *g, ZigFn *fn, bool resolve_frame) {...@@ -4329,7 +4333,9 @@ static void analyze_fn_async(CodeGen *g, ZigFn *fn, bool resolve_frame) {
4329 }4333 }
4330 for (size_t i = 0; i < fn->await_list.length; i += 1) {4334 for (size_t i = 0; i < fn->await_list.length; i += 1) {
4331 IrInstructionAwaitGen *await = fn->await_list.at(i);4335 IrInstructionAwaitGen *await = fn->await_list.at(i);
4332 switch (analyze_callee_async(g, fn, await->target_fn, await->base.source_node, must_not_be_async)) {4336 switch (analyze_callee_async(g, fn, await->target_fn, await->base.source_node, must_not_be_async,
4337 CallModifierNone))
4338 {
4333 case ErrorSemanticAnalyzeFail:4339 case ErrorSemanticAnalyzeFail:
4334 fn->anal_state = FnAnalStateInvalid;4340 fn->anal_state = FnAnalStateInvalid;
4335 return;4341 return;
src/ast_render.cpp+12-5
...@@ -698,11 +698,18 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {...@@ -698,11 +698,18 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {
698 }698 }
699 case NodeTypeFnCallExpr:699 case NodeTypeFnCallExpr:
700 {700 {
701 if (node->data.fn_call_expr.is_builtin) {701 switch (node->data.fn_call_expr.modifier) {
702 fprintf(ar->f, "@");702 case CallModifierNone:
703 }703 break;
704 if (node->data.fn_call_expr.is_async) {704 case CallModifierBuiltin:
705 fprintf(ar->f, "async ");705 fprintf(ar->f, "@");
706 break;
707 case CallModifierAsync:
708 fprintf(ar->f, "async ");
709 break;
710 case CallModifierNoAsync:
711 fprintf(ar->f, "noasync ");
712 break;
706 }713 }
707 AstNode *fn_ref_node = node->data.fn_call_expr.fn_ref_expr;714 AstNode *fn_ref_node = node->data.fn_call_expr.fn_ref_expr;
708 bool grouped = (fn_ref_node->type != NodeTypePrefixOpExpr && fn_ref_node->type != NodeTypePointerType);715 bool grouped = (fn_ref_node->type != NodeTypePrefixOpExpr && fn_ref_node->type != NodeTypePointerType);
src/codegen.cpp+47-9
...@@ -186,6 +186,9 @@ static void generate_error_name_table(CodeGen *g);...@@ -186,6 +186,9 @@ static void generate_error_name_table(CodeGen *g);
186static bool value_is_all_undef(CodeGen *g, ConstExprValue *const_val);186static bool value_is_all_undef(CodeGen *g, ConstExprValue *const_val);
187static void gen_undef_init(CodeGen *g, uint32_t ptr_align_bytes, ZigType *value_type, LLVMValueRef ptr);187static void gen_undef_init(CodeGen *g, uint32_t ptr_align_bytes, ZigType *value_type, LLVMValueRef ptr);
188static LLVMValueRef build_alloca(CodeGen *g, ZigType *type_entry, const char *name, uint32_t alignment);188static LLVMValueRef build_alloca(CodeGen *g, ZigType *type_entry, const char *name, uint32_t alignment);
189static LLVMValueRef gen_await_early_return(CodeGen *g, IrInstruction *source_instr,
190 LLVMValueRef target_frame_ptr, ZigType *result_type, ZigType *ptr_result_type,
191 LLVMValueRef result_loc, bool non_async);
189192
190static void addLLVMAttr(LLVMValueRef val, LLVMAttributeIndex attr_index, const char *attr_name) {193static void addLLVMAttr(LLVMValueRef val, LLVMAttributeIndex attr_index, const char *attr_name) {
191 unsigned kind_id = LLVMGetEnumAttributeKindForName(attr_name, strlen(attr_name));194 unsigned kind_id = LLVMGetEnumAttributeKindForName(attr_name, strlen(attr_name));
...@@ -3842,7 +3845,7 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr...@@ -3842,7 +3845,7 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr
3842 LLVMValueRef ret_ptr;3845 LLVMValueRef ret_ptr;
3843 if (callee_is_async) {3846 if (callee_is_async) {
3844 if (instruction->new_stack == nullptr) {3847 if (instruction->new_stack == nullptr) {
3845 if (instruction->is_async) {3848 if (instruction->modifier == CallModifierAsync) {
3846 frame_result_loc = result_loc;3849 frame_result_loc = result_loc;
3847 } else {3850 } else {
3848 frame_result_loc = ir_llvm_value(g, instruction->frame_result_loc);3851 frame_result_loc = ir_llvm_value(g, instruction->frame_result_loc);
...@@ -3883,7 +3886,7 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr...@@ -3883,7 +3886,7 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr
3883 }3886 }
3884 }3887 }
3885 }3888 }
3886 if (instruction->is_async) {3889 if (instruction->modifier == CallModifierAsync) {
3887 if (instruction->new_stack == nullptr) {3890 if (instruction->new_stack == nullptr) {
3888 awaiter_init_val = zero;3891 awaiter_init_val = zero;
38893892
...@@ -3908,9 +3911,15 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr...@@ -3908,9 +3911,15 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr
3908 // even if prefix_arg_err_ret_stack is true, let the async function do its own3911 // even if prefix_arg_err_ret_stack is true, let the async function do its own
3909 // initialization.3912 // initialization.
3910 } else {3913 } else {
3911 // async function called as a normal function3914 if (instruction->modifier == CallModifierNoAsync && !fn_is_async(g->cur_fn)) {
39123915 // Async function called as a normal function, and calling function is not async.
3913 awaiter_init_val = LLVMBuildPtrToInt(g->builder, g->cur_frame_ptr, usize_type_ref, ""); // caller's own frame pointer3916 // This is allowed because it was called with `noasync` which asserts that it will
3917 // never suspend.
3918 awaiter_init_val = zero;
3919 } else {
3920 // async function called as a normal function
3921 awaiter_init_val = LLVMBuildPtrToInt(g->builder, g->cur_frame_ptr, usize_type_ref, ""); // caller's own frame pointer
3922 }
3914 if (ret_has_bits) {3923 if (ret_has_bits) {
3915 if (result_loc == nullptr) {3924 if (result_loc == nullptr) {
3916 // return type is a scalar, but we still need a pointer to it. Use the async fn frame.3925 // return type is a scalar, but we still need a pointer to it. Use the async fn frame.
...@@ -3951,7 +3960,7 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr...@@ -3951,7 +3960,7 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr
3951 LLVMValueRef ret_ptr_ptr = LLVMBuildStructGEP(g->builder, frame_result_loc, frame_ret_start, "");3960 LLVMValueRef ret_ptr_ptr = LLVMBuildStructGEP(g->builder, frame_result_loc, frame_ret_start, "");
3952 LLVMBuildStore(g->builder, ret_ptr, ret_ptr_ptr);3961 LLVMBuildStore(g->builder, ret_ptr, ret_ptr_ptr);
3953 }3962 }
3954 } else if (instruction->is_async) {3963 } else if (instruction->modifier == CallModifierAsync) {
3955 // Async call of blocking function3964 // Async call of blocking function
3956 if (instruction->new_stack != nullptr) {3965 if (instruction->new_stack != nullptr) {
3957 zig_panic("TODO @asyncCall of non-async function");3966 zig_panic("TODO @asyncCall of non-async function");
...@@ -4048,13 +4057,20 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr...@@ -4048,13 +4057,20 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr
4048 gen_param_values.at(arg_i));4057 gen_param_values.at(arg_i));
4049 }4058 }
40504059
4051 if (instruction->is_async) {4060 if (instruction->modifier == CallModifierAsync) {
4052 gen_resume(g, fn_val, frame_result_loc, ResumeIdCall);4061 gen_resume(g, fn_val, frame_result_loc, ResumeIdCall);
4053 if (instruction->new_stack != nullptr) {4062 if (instruction->new_stack != nullptr) {
4054 return LLVMBuildBitCast(g->builder, frame_result_loc,4063 return LLVMBuildBitCast(g->builder, frame_result_loc,
4055 get_llvm_type(g, instruction->base.value.type), "");4064 get_llvm_type(g, instruction->base.value.type), "");
4056 }4065 }
4057 return nullptr;4066 return nullptr;
4067 } else if (instruction->modifier == CallModifierNoAsync && !fn_is_async(g->cur_fn)) {
4068 gen_resume(g, fn_val, frame_result_loc, ResumeIdCall);
4069
4070 ZigType *result_type = instruction->base.value.type;
4071 ZigType *ptr_result_type = get_pointer_to_type(g, result_type, true);
4072 return gen_await_early_return(g, &instruction->base, frame_result_loc,
4073 result_type, ptr_result_type, result_loc, true);
4058 } else {4074 } else {
4059 ZigType *ptr_result_type = get_pointer_to_type(g, src_return_type, true);4075 ZigType *ptr_result_type = get_pointer_to_type(g, src_return_type, true);
40604076
...@@ -4082,7 +4098,7 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr...@@ -4082,7 +4098,7 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr
4082 if (instruction->new_stack == nullptr || instruction->is_async_call_builtin) {4098 if (instruction->new_stack == nullptr || instruction->is_async_call_builtin) {
4083 result = ZigLLVMBuildCall(g->builder, fn_val,4099 result = ZigLLVMBuildCall(g->builder, fn_val,
4084 gen_param_values.items, (unsigned)gen_param_values.length, llvm_cc, fn_inline, "");4100 gen_param_values.items, (unsigned)gen_param_values.length, llvm_cc, fn_inline, "");
4085 } else if (instruction->is_async) {4101 } else if (instruction->modifier == CallModifierAsync) {
4086 zig_panic("TODO @asyncCall of non-async function");4102 zig_panic("TODO @asyncCall of non-async function");
4087 } else {4103 } else {
4088 LLVMValueRef stacksave_fn_val = get_stacksave_fn_val(g);4104 LLVMValueRef stacksave_fn_val = get_stacksave_fn_val(g);
...@@ -4107,7 +4123,7 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr...@@ -4107,7 +4123,7 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr
4107 LLVMValueRef store_instr = LLVMBuildStore(g->builder, result, result_loc);4123 LLVMValueRef store_instr = LLVMBuildStore(g->builder, result, result_loc);
4108 LLVMSetAlignment(store_instr, get_ptr_align(g, instruction->result_loc->value.type));4124 LLVMSetAlignment(store_instr, get_ptr_align(g, instruction->result_loc->value.type));
4109 return result_loc;4125 return result_loc;
4110 } else if (!callee_is_async && instruction->is_async) {4126 } else if (!callee_is_async && instruction->modifier == CallModifierAsync) {
4111 LLVMBuildStore(g->builder, result, ret_ptr);4127 LLVMBuildStore(g->builder, result, ret_ptr);
4112 return result_loc;4128 return result_loc;
4113 } else {4129 } else {
...@@ -7104,6 +7120,28 @@ static void do_code_gen(CodeGen *g) {...@@ -7104,6 +7120,28 @@ static void do_code_gen(CodeGen *g) {
7104 }7120 }
71057121
7106 if (!is_async) {7122 if (!is_async) {
7123 // allocate async frames for noasync calls & awaits to async functions
7124 for (size_t i = 0; i < fn_table_entry->call_list.length; i += 1) {
7125 IrInstructionCallGen *call = fn_table_entry->call_list.at(i);
7126 if (call->fn_entry == nullptr)
7127 continue;
7128 if (!fn_is_async(call->fn_entry))
7129 continue;
7130 if (call->modifier != CallModifierNoAsync)
7131 continue;
7132 if (call->frame_result_loc != nullptr)
7133 continue;
7134 ZigType *callee_frame_type = get_fn_frame_type(g, call->fn_entry);
7135 IrInstructionAllocaGen *alloca_gen = allocate<IrInstructionAllocaGen>(1);
7136 alloca_gen->base.id = IrInstructionIdAllocaGen;
7137 alloca_gen->base.source_node = call->base.source_node;
7138 alloca_gen->base.scope = call->base.scope;
7139 alloca_gen->base.value.type = get_pointer_to_type(g, callee_frame_type, false);
7140 alloca_gen->base.ref_count = 1;
7141 alloca_gen->name_hint = "";
7142 fn_table_entry->alloca_gen_list.append(alloca_gen);
7143 call->frame_result_loc = &alloca_gen->base;
7144 }
7107 // allocate temporary stack data7145 // allocate temporary stack data
7108 for (size_t alloca_i = 0; alloca_i < fn_table_entry->alloca_gen_list.length; alloca_i += 1) {7146 for (size_t alloca_i = 0; alloca_i < fn_table_entry->alloca_gen_list.length; alloca_i += 1) {
7109 IrInstructionAllocaGen *instruction = fn_table_entry->alloca_gen_list.at(alloca_i);7147 IrInstructionAllocaGen *instruction = fn_table_entry->alloca_gen_list.at(alloca_i);
src/ir.cpp+27-22
...@@ -1389,7 +1389,7 @@ static IrInstruction *ir_build_union_field_ptr(IrBuilder *irb, Scope *scope, Ast...@@ -1389,7 +1389,7 @@ static IrInstruction *ir_build_union_field_ptr(IrBuilder *irb, Scope *scope, Ast
13891389
1390static IrInstruction *ir_build_call_src(IrBuilder *irb, Scope *scope, AstNode *source_node,1390static IrInstruction *ir_build_call_src(IrBuilder *irb, Scope *scope, AstNode *source_node,
1391 ZigFn *fn_entry, IrInstruction *fn_ref, size_t arg_count, IrInstruction **args,1391 ZigFn *fn_entry, IrInstruction *fn_ref, size_t arg_count, IrInstruction **args,
1392 bool is_comptime, FnInline fn_inline, bool is_async, bool is_async_call_builtin,1392 bool is_comptime, FnInline fn_inline, CallModifier modifier, bool is_async_call_builtin,
1393 IrInstruction *new_stack, ResultLoc *result_loc)1393 IrInstruction *new_stack, ResultLoc *result_loc)
1394{1394{
1395 IrInstructionCallSrc *call_instruction = ir_build_instruction<IrInstructionCallSrc>(irb, scope, source_node);1395 IrInstructionCallSrc *call_instruction = ir_build_instruction<IrInstructionCallSrc>(irb, scope, source_node);
...@@ -1399,7 +1399,7 @@ static IrInstruction *ir_build_call_src(IrBuilder *irb, Scope *scope, AstNode *s...@@ -1399,7 +1399,7 @@ static IrInstruction *ir_build_call_src(IrBuilder *irb, Scope *scope, AstNode *s
1399 call_instruction->fn_inline = fn_inline;1399 call_instruction->fn_inline = fn_inline;
1400 call_instruction->args = args;1400 call_instruction->args = args;
1401 call_instruction->arg_count = arg_count;1401 call_instruction->arg_count = arg_count;
1402 call_instruction->is_async = is_async;1402 call_instruction->modifier = modifier;
1403 call_instruction->is_async_call_builtin = is_async_call_builtin;1403 call_instruction->is_async_call_builtin = is_async_call_builtin;
1404 call_instruction->new_stack = new_stack;1404 call_instruction->new_stack = new_stack;
1405 call_instruction->result_loc = result_loc;1405 call_instruction->result_loc = result_loc;
...@@ -1407,7 +1407,7 @@ static IrInstruction *ir_build_call_src(IrBuilder *irb, Scope *scope, AstNode *s...@@ -1407,7 +1407,7 @@ static IrInstruction *ir_build_call_src(IrBuilder *irb, Scope *scope, AstNode *s
1407 if (fn_ref != nullptr) ir_ref_instruction(fn_ref, irb->current_basic_block);1407 if (fn_ref != nullptr) ir_ref_instruction(fn_ref, irb->current_basic_block);
1408 for (size_t i = 0; i < arg_count; i += 1)1408 for (size_t i = 0; i < arg_count; i += 1)
1409 ir_ref_instruction(args[i], irb->current_basic_block);1409 ir_ref_instruction(args[i], irb->current_basic_block);
1410 if (is_async && new_stack != nullptr) {1410 if (modifier == CallModifierAsync && new_stack != nullptr) {
1411 // in this case the arg at the end is the return pointer1411 // in this case the arg at the end is the return pointer
1412 ir_ref_instruction(args[arg_count], irb->current_basic_block);1412 ir_ref_instruction(args[arg_count], irb->current_basic_block);
1413 }1413 }
...@@ -1418,7 +1418,7 @@ static IrInstruction *ir_build_call_src(IrBuilder *irb, Scope *scope, AstNode *s...@@ -1418,7 +1418,7 @@ static IrInstruction *ir_build_call_src(IrBuilder *irb, Scope *scope, AstNode *s
14181418
1419static IrInstructionCallGen *ir_build_call_gen(IrAnalyze *ira, IrInstruction *source_instruction,1419static IrInstructionCallGen *ir_build_call_gen(IrAnalyze *ira, IrInstruction *source_instruction,
1420 ZigFn *fn_entry, IrInstruction *fn_ref, size_t arg_count, IrInstruction **args,1420 ZigFn *fn_entry, IrInstruction *fn_ref, size_t arg_count, IrInstruction **args,
1421 FnInline fn_inline, bool is_async, IrInstruction *new_stack, bool is_async_call_builtin,1421 FnInline fn_inline, CallModifier modifier, IrInstruction *new_stack, bool is_async_call_builtin,
1422 IrInstruction *result_loc, ZigType *return_type)1422 IrInstruction *result_loc, ZigType *return_type)
1423{1423{
1424 IrInstructionCallGen *call_instruction = ir_build_instruction<IrInstructionCallGen>(&ira->new_irb,1424 IrInstructionCallGen *call_instruction = ir_build_instruction<IrInstructionCallGen>(&ira->new_irb,
...@@ -1429,7 +1429,7 @@ static IrInstructionCallGen *ir_build_call_gen(IrAnalyze *ira, IrInstruction *so...@@ -1429,7 +1429,7 @@ static IrInstructionCallGen *ir_build_call_gen(IrAnalyze *ira, IrInstruction *so
1429 call_instruction->fn_inline = fn_inline;1429 call_instruction->fn_inline = fn_inline;
1430 call_instruction->args = args;1430 call_instruction->args = args;
1431 call_instruction->arg_count = arg_count;1431 call_instruction->arg_count = arg_count;
1432 call_instruction->is_async = is_async;1432 call_instruction->modifier = modifier;
1433 call_instruction->is_async_call_builtin = is_async_call_builtin;1433 call_instruction->is_async_call_builtin = is_async_call_builtin;
1434 call_instruction->new_stack = new_stack;1434 call_instruction->new_stack = new_stack;
1435 call_instruction->result_loc = result_loc;1435 call_instruction->result_loc = result_loc;
...@@ -4412,10 +4412,10 @@ static IrInstruction *ir_gen_async_call(IrBuilder *irb, Scope *scope, AstNode *a...@@ -4412,10 +4412,10 @@ static IrInstruction *ir_gen_async_call(IrBuilder *irb, Scope *scope, AstNode *a
44124412
4413 args[arg_count] = ret_ptr;4413 args[arg_count] = ret_ptr;
44144414
4415 bool is_async = await_node == nullptr;4415 CallModifier modifier = (await_node == nullptr) ? CallModifierAsync : CallModifierNone;
4416 bool is_async_call_builtin = true;4416 bool is_async_call_builtin = true;
4417 IrInstruction *call = ir_build_call_src(irb, scope, call_node, nullptr, fn_ref, arg_count, args, false,4417 IrInstruction *call = ir_build_call_src(irb, scope, call_node, nullptr, fn_ref, arg_count, args, false,
4418 FnInlineAuto, is_async, is_async_call_builtin, bytes, result_loc);4418 FnInlineAuto, modifier, is_async_call_builtin, bytes, result_loc);
4419 return ir_lval_wrap(irb, scope, call, lval, result_loc);4419 return ir_lval_wrap(irb, scope, call, lval, result_loc);
4420}4420}
44214421
...@@ -5302,7 +5302,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo...@@ -5302,7 +5302,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
5302 FnInline fn_inline = (builtin_fn->id == BuiltinFnIdInlineCall) ? FnInlineAlways : FnInlineNever;5302 FnInline fn_inline = (builtin_fn->id == BuiltinFnIdInlineCall) ? FnInlineAlways : FnInlineNever;
53035303
5304 IrInstruction *call = ir_build_call_src(irb, scope, node, nullptr, fn_ref, arg_count, args, false,5304 IrInstruction *call = ir_build_call_src(irb, scope, node, nullptr, fn_ref, arg_count, args, false,
5305 fn_inline, false, false, nullptr, result_loc);5305 fn_inline, CallModifierNone, false, nullptr, result_loc);
5306 return ir_lval_wrap(irb, scope, call, lval, result_loc);5306 return ir_lval_wrap(irb, scope, call, lval, result_loc);
5307 }5307 }
5308 case BuiltinFnIdNewStackCall:5308 case BuiltinFnIdNewStackCall:
...@@ -5335,7 +5335,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo...@@ -5335,7 +5335,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
5335 }5335 }
53365336
5337 IrInstruction *call = ir_build_call_src(irb, scope, node, nullptr, fn_ref, arg_count, args, false,5337 IrInstruction *call = ir_build_call_src(irb, scope, node, nullptr, fn_ref, arg_count, args, false,
5338 FnInlineAuto, false, false, new_stack, result_loc);5338 FnInlineAuto, CallModifierNone, false, new_stack, result_loc);
5339 return ir_lval_wrap(irb, scope, call, lval, result_loc);5339 return ir_lval_wrap(irb, scope, call, lval, result_loc);
5340 }5340 }
5341 case BuiltinFnIdAsyncCall:5341 case BuiltinFnIdAsyncCall:
...@@ -5624,7 +5624,7 @@ static IrInstruction *ir_gen_fn_call(IrBuilder *irb, Scope *scope, AstNode *node...@@ -5624,7 +5624,7 @@ static IrInstruction *ir_gen_fn_call(IrBuilder *irb, Scope *scope, AstNode *node
5624{5624{
5625 assert(node->type == NodeTypeFnCallExpr);5625 assert(node->type == NodeTypeFnCallExpr);
56265626
5627 if (node->data.fn_call_expr.is_builtin)5627 if (node->data.fn_call_expr.modifier == CallModifierBuiltin)
5628 return ir_gen_builtin_fn_call(irb, scope, node, lval, result_loc);5628 return ir_gen_builtin_fn_call(irb, scope, node, lval, result_loc);
56295629
5630 AstNode *fn_ref_node = node->data.fn_call_expr.fn_ref_expr;5630 AstNode *fn_ref_node = node->data.fn_call_expr.fn_ref_expr;
...@@ -5641,9 +5641,8 @@ static IrInstruction *ir_gen_fn_call(IrBuilder *irb, Scope *scope, AstNode *node...@@ -5641,9 +5641,8 @@ static IrInstruction *ir_gen_fn_call(IrBuilder *irb, Scope *scope, AstNode *node
5641 return args[i];5641 return args[i];
5642 }5642 }
56435643
5644 bool is_async = node->data.fn_call_expr.is_async;
5645 IrInstruction *fn_call = ir_build_call_src(irb, scope, node, nullptr, fn_ref, arg_count, args, false,5644 IrInstruction *fn_call = ir_build_call_src(irb, scope, node, nullptr, fn_ref, arg_count, args, false,
5646 FnInlineAuto, is_async, false, nullptr, result_loc);5645 FnInlineAuto, node->data.fn_call_expr.modifier, false, nullptr, result_loc);
5647 return ir_lval_wrap(irb, scope, fn_call, lval, result_loc);5646 return ir_lval_wrap(irb, scope, fn_call, lval, result_loc);
5648}5647}
56495648
...@@ -7937,7 +7936,7 @@ static IrInstruction *ir_gen_await_expr(IrBuilder *irb, Scope *scope, AstNode *n...@@ -7937,7 +7936,7 @@ static IrInstruction *ir_gen_await_expr(IrBuilder *irb, Scope *scope, AstNode *n
7937 assert(node->type == NodeTypeAwaitExpr);7936 assert(node->type == NodeTypeAwaitExpr);
79387937
7939 AstNode *expr_node = node->data.await_expr.expr;7938 AstNode *expr_node = node->data.await_expr.expr;
7940 if (expr_node->type == NodeTypeFnCallExpr && expr_node->data.fn_call_expr.is_builtin) {7939 if (expr_node->type == NodeTypeFnCallExpr && expr_node->data.fn_call_expr.modifier == CallModifierBuiltin) {
7941 AstNode *fn_ref_expr = expr_node->data.fn_call_expr.fn_ref_expr;7940 AstNode *fn_ref_expr = expr_node->data.fn_call_expr.fn_ref_expr;
7942 Buf *name = fn_ref_expr->data.symbol_expr.symbol;7941 Buf *name = fn_ref_expr->data.symbol_expr.symbol;
7943 auto entry = irb->codegen->builtin_fn_table.maybe_get(name);7942 auto entry = irb->codegen->builtin_fn_table.maybe_get(name);
...@@ -15408,7 +15407,7 @@ static IrInstruction *ir_analyze_async_call(IrAnalyze *ira, IrInstructionCallSrc...@@ -15408,7 +15407,7 @@ static IrInstruction *ir_analyze_async_call(IrAnalyze *ira, IrInstructionCallSrc
15408 ZigType *anyframe_type = get_any_frame_type(ira->codegen, fn_ret_type);15407 ZigType *anyframe_type = get_any_frame_type(ira->codegen, fn_ret_type);
1540915408
15410 IrInstructionCallGen *call_gen = ir_build_call_gen(ira, &call_instruction->base, fn_entry, fn_ref,15409 IrInstructionCallGen *call_gen = ir_build_call_gen(ira, &call_instruction->base, fn_entry, fn_ref,
15411 arg_count, casted_args, FnInlineAuto, true, casted_new_stack,15410 arg_count, casted_args, FnInlineAuto, CallModifierAsync, casted_new_stack,
15412 call_instruction->is_async_call_builtin, ret_ptr, anyframe_type);15411 call_instruction->is_async_call_builtin, ret_ptr, anyframe_type);
15413 return &call_gen->base;15412 return &call_gen->base;
15414 } else {15413 } else {
...@@ -15422,8 +15421,8 @@ static IrInstruction *ir_analyze_async_call(IrAnalyze *ira, IrInstructionCallSrc...@@ -15422,8 +15421,8 @@ static IrInstruction *ir_analyze_async_call(IrAnalyze *ira, IrInstructionCallSrc
15422 if (type_is_invalid(result_loc->value.type))15421 if (type_is_invalid(result_loc->value.type))
15423 return ira->codegen->invalid_instruction;15422 return ira->codegen->invalid_instruction;
15424 return &ir_build_call_gen(ira, &call_instruction->base, fn_entry, fn_ref, arg_count,15423 return &ir_build_call_gen(ira, &call_instruction->base, fn_entry, fn_ref, arg_count,
15425 casted_args, FnInlineAuto, true, casted_new_stack, call_instruction->is_async_call_builtin,15424 casted_args, FnInlineAuto, CallModifierAsync, casted_new_stack,
15426 result_loc, frame_type)->base;15425 call_instruction->is_async_call_builtin, result_loc, frame_type)->base;
15427 }15426 }
15428}15427}
15429static bool ir_analyze_fn_call_inline_arg(IrAnalyze *ira, AstNode *fn_proto_node,15428static bool ir_analyze_fn_call_inline_arg(IrAnalyze *ira, AstNode *fn_proto_node,
...@@ -16174,7 +16173,7 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c...@@ -16174,7 +16173,7 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c
16174 return ira->codegen->invalid_instruction;16173 return ira->codegen->invalid_instruction;
1617516174
16176 size_t impl_param_count = impl_fn_type_id->param_count;16175 size_t impl_param_count = impl_fn_type_id->param_count;
16177 if (call_instruction->is_async) {16176 if (call_instruction->modifier == CallModifierAsync) {
16178 IrInstruction *result = ir_analyze_async_call(ira, call_instruction, impl_fn, impl_fn->type_entry,16177 IrInstruction *result = ir_analyze_async_call(ira, call_instruction, impl_fn, impl_fn->type_entry,
16179 nullptr, casted_args, impl_param_count, casted_new_stack);16178 nullptr, casted_args, impl_param_count, casted_new_stack);
16180 return ir_finish_anal(ira, result);16179 return ir_finish_anal(ira, result);
...@@ -16201,14 +16200,17 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c...@@ -16201,14 +16200,17 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c
16201 result_loc = nullptr;16200 result_loc = nullptr;
16202 }16201 }
1620316202
16204 if (impl_fn_type_id->cc == CallingConventionAsync && parent_fn_entry->inferred_async_node == nullptr) {16203 if (impl_fn_type_id->cc == CallingConventionAsync &&
16204 parent_fn_entry->inferred_async_node == nullptr &&
16205 call_instruction->modifier != CallModifierNoAsync)
16206 {
16205 parent_fn_entry->inferred_async_node = fn_ref->source_node;16207 parent_fn_entry->inferred_async_node = fn_ref->source_node;
16206 parent_fn_entry->inferred_async_fn = impl_fn;16208 parent_fn_entry->inferred_async_fn = impl_fn;
16207 }16209 }
1620816210
16209 IrInstructionCallGen *new_call_instruction = ir_build_call_gen(ira, &call_instruction->base,16211 IrInstructionCallGen *new_call_instruction = ir_build_call_gen(ira, &call_instruction->base,
16210 impl_fn, nullptr, impl_param_count, casted_args, fn_inline,16212 impl_fn, nullptr, impl_param_count, casted_args, fn_inline,
16211 false, casted_new_stack, call_instruction->is_async_call_builtin, result_loc,16213 call_instruction->modifier, casted_new_stack, call_instruction->is_async_call_builtin, result_loc,
16212 impl_fn_type_id->return_type);16214 impl_fn_type_id->return_type);
1621316215
16214 if (get_scope_typeof(call_instruction->base.scope) == nullptr) {16216 if (get_scope_typeof(call_instruction->base.scope) == nullptr) {
...@@ -16325,13 +16327,16 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c...@@ -16325,13 +16327,16 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c
16325 if (casted_new_stack != nullptr && type_is_invalid(casted_new_stack->value.type))16327 if (casted_new_stack != nullptr && type_is_invalid(casted_new_stack->value.type))
16326 return ira->codegen->invalid_instruction;16328 return ira->codegen->invalid_instruction;
1632716329
16328 if (call_instruction->is_async) {16330 if (call_instruction->modifier == CallModifierAsync) {
16329 IrInstruction *result = ir_analyze_async_call(ira, call_instruction, fn_entry, fn_type, fn_ref,16331 IrInstruction *result = ir_analyze_async_call(ira, call_instruction, fn_entry, fn_type, fn_ref,
16330 casted_args, call_param_count, casted_new_stack);16332 casted_args, call_param_count, casted_new_stack);
16331 return ir_finish_anal(ira, result);16333 return ir_finish_anal(ira, result);
16332 }16334 }
1633316335
16334 if (fn_type_id->cc == CallingConventionAsync && parent_fn_entry->inferred_async_node == nullptr) {16336 if (fn_type_id->cc == CallingConventionAsync &&
16337 parent_fn_entry->inferred_async_node == nullptr &&
16338 call_instruction->modifier != CallModifierNoAsync)
16339 {
16335 parent_fn_entry->inferred_async_node = fn_ref->source_node;16340 parent_fn_entry->inferred_async_node = fn_ref->source_node;
16336 parent_fn_entry->inferred_async_fn = fn_entry;16341 parent_fn_entry->inferred_async_fn = fn_entry;
16337 }16342 }
...@@ -16358,7 +16363,7 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c...@@ -16358,7 +16363,7 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c
16358 }16363 }
1635916364
16360 IrInstructionCallGen *new_call_instruction = ir_build_call_gen(ira, &call_instruction->base, fn_entry, fn_ref,16365 IrInstructionCallGen *new_call_instruction = ir_build_call_gen(ira, &call_instruction->base, fn_entry, fn_ref,
16361 call_param_count, casted_args, fn_inline, false, casted_new_stack,16366 call_param_count, casted_args, fn_inline, call_instruction->modifier, casted_new_stack,
16362 call_instruction->is_async_call_builtin, result_loc, return_type);16367 call_instruction->is_async_call_builtin, result_loc, return_type);
16363 if (get_scope_typeof(call_instruction->base.scope) == nullptr) {16368 if (get_scope_typeof(call_instruction->base.scope) == nullptr) {
16364 parent_fn_entry->call_list.append(new_call_instruction);16369 parent_fn_entry->call_list.append(new_call_instruction);
src/ir_print.cpp+22-4
...@@ -608,8 +608,17 @@ static void ir_print_result_loc(IrPrint *irp, ResultLoc *result_loc) {...@@ -608,8 +608,17 @@ static void ir_print_result_loc(IrPrint *irp, ResultLoc *result_loc) {
608}608}
609609
610static void ir_print_call_src(IrPrint *irp, IrInstructionCallSrc *call_instruction) {610static void ir_print_call_src(IrPrint *irp, IrInstructionCallSrc *call_instruction) {
611 if (call_instruction->is_async) {611 switch (call_instruction->modifier) {
612 fprintf(irp->f, "async ");612 case CallModifierNone:
613 break;
614 case CallModifierAsync:
615 fprintf(irp->f, "async ");
616 break;
617 case CallModifierNoAsync:
618 fprintf(irp->f, "noasync ");
619 break;
620 case CallModifierBuiltin:
621 zig_unreachable();
613 }622 }
614 if (call_instruction->fn_entry) {623 if (call_instruction->fn_entry) {
615 fprintf(irp->f, "%s", buf_ptr(&call_instruction->fn_entry->symbol_name));624 fprintf(irp->f, "%s", buf_ptr(&call_instruction->fn_entry->symbol_name));
...@@ -629,8 +638,17 @@ static void ir_print_call_src(IrPrint *irp, IrInstructionCallSrc *call_instructi...@@ -629,8 +638,17 @@ static void ir_print_call_src(IrPrint *irp, IrInstructionCallSrc *call_instructi
629}638}
630639
631static void ir_print_call_gen(IrPrint *irp, IrInstructionCallGen *call_instruction) {640static void ir_print_call_gen(IrPrint *irp, IrInstructionCallGen *call_instruction) {
632 if (call_instruction->is_async) {641 switch (call_instruction->modifier) {
633 fprintf(irp->f, "async ");642 case CallModifierNone:
643 break;
644 case CallModifierAsync:
645 fprintf(irp->f, "async ");
646 break;
647 case CallModifierNoAsync:
648 fprintf(irp->f, "noasync ");
649 break;
650 case CallModifierBuiltin:
651 zig_unreachable();
634 }652 }
635 if (call_instruction->fn_entry) {653 if (call_instruction->fn_entry) {
636 fprintf(irp->f, "%s", buf_ptr(&call_instruction->fn_entry->symbol_name));654 fprintf(irp->f, "%s", buf_ptr(&call_instruction->fn_entry->symbol_name));
src/parser.cpp+15-13
...@@ -113,7 +113,7 @@ static AstNode *ast_parse_multiply_op(ParseContext *pc);...@@ -113,7 +113,7 @@ static AstNode *ast_parse_multiply_op(ParseContext *pc);
113static AstNode *ast_parse_prefix_op(ParseContext *pc);113static AstNode *ast_parse_prefix_op(ParseContext *pc);
114static AstNode *ast_parse_prefix_type_op(ParseContext *pc);114static AstNode *ast_parse_prefix_type_op(ParseContext *pc);
115static AstNode *ast_parse_suffix_op(ParseContext *pc);115static AstNode *ast_parse_suffix_op(ParseContext *pc);
116static AstNode *ast_parse_fn_call_argumnets(ParseContext *pc);116static AstNode *ast_parse_fn_call_arguments(ParseContext *pc);
117static AstNode *ast_parse_array_type_start(ParseContext *pc);117static AstNode *ast_parse_array_type_start(ParseContext *pc);
118static AstNode *ast_parse_ptr_type_start(ParseContext *pc);118static AstNode *ast_parse_ptr_type_start(ParseContext *pc);
119static AstNode *ast_parse_container_decl_auto(ParseContext *pc);119static AstNode *ast_parse_container_decl_auto(ParseContext *pc);
...@@ -1403,12 +1403,14 @@ static AstNode *ast_parse_error_union_expr(ParseContext *pc) {...@@ -1403,12 +1403,14 @@ static AstNode *ast_parse_error_union_expr(ParseContext *pc) {
1403}1403}
14041404
1405// SuffixExpr1405// SuffixExpr
1406// <- KEYWORD_async PrimaryTypeExpr SuffixOp* FnCallArguments1406// <- KEYWORD_async PrimaryTypeExpr SuffixOp* FnCallArguments
1407// / KEYWORD_noasync PrimaryTypeExpr SuffixOp* FnCallArguments
1407// / PrimaryTypeExpr (SuffixOp / FnCallArguments)*1408// / PrimaryTypeExpr (SuffixOp / FnCallArguments)*
1408static AstNode *ast_parse_suffix_expr(ParseContext *pc) {1409static AstNode *ast_parse_suffix_expr(ParseContext *pc) {
1409 Token *async_token = eat_token_if(pc, TokenIdKeywordAsync);1410 Token *async_token = eat_token(pc);
1410 if (async_token != nullptr) {1411 bool is_async = async_token->id == TokenIdKeywordAsync;
1411 if (eat_token_if(pc, TokenIdKeywordFn) != nullptr) {1412 if (is_async || async_token->id == TokenIdKeywordNoAsync) {
1413 if (is_async && eat_token_if(pc, TokenIdKeywordFn) != nullptr) {
1412 // HACK: If we see the keyword `fn`, then we assume that1414 // HACK: If we see the keyword `fn`, then we assume that
1413 // we are parsing an async fn proto, and not a call.1415 // we are parsing an async fn proto, and not a call.
1414 // We therefore put back all tokens consumed by the async1416 // We therefore put back all tokens consumed by the async
...@@ -1447,24 +1449,24 @@ static AstNode *ast_parse_suffix_expr(ParseContext *pc) {...@@ -1447,24 +1449,24 @@ static AstNode *ast_parse_suffix_expr(ParseContext *pc) {
1447 child = suffix;1449 child = suffix;
1448 }1450 }
14491451
1450 // TODO: Both *_async_prefix and *_fn_call_argumnets returns an1452 // TODO: Both *_async_prefix and *_fn_call_arguments returns an
1451 // AstNode *. All we really want here is the arguments of1453 // AstNode *. All we really want here is the arguments of
1452 // the call we parse. We therefor "leak" the node for now.1454 // the call we parse. We therefor "leak" the node for now.
1453 // Wait till we get async rework to fix this.1455 // Wait till we get async rework to fix this.
1454 AstNode *args = ast_parse_fn_call_argumnets(pc);1456 AstNode *args = ast_parse_fn_call_arguments(pc);
1455 if (args == nullptr)1457 if (args == nullptr)
1456 ast_invalid_token_error(pc, peek_token(pc));1458 ast_invalid_token_error(pc, peek_token(pc));
14571459
1458 assert(args->type == NodeTypeFnCallExpr);1460 assert(args->type == NodeTypeFnCallExpr);
14591461
1460 AstNode *res = ast_create_node(pc, NodeTypeFnCallExpr, async_token);1462 AstNode *res = ast_create_node(pc, NodeTypeFnCallExpr, async_token);
1461 res->data.fn_call_expr.is_async = true;1463 res->data.fn_call_expr.modifier = is_async ? CallModifierAsync : CallModifierNoAsync;
1462 res->data.fn_call_expr.seen = false;1464 res->data.fn_call_expr.seen = false;
1463 res->data.fn_call_expr.fn_ref_expr = child;1465 res->data.fn_call_expr.fn_ref_expr = child;
1464 res->data.fn_call_expr.params = args->data.fn_call_expr.params;1466 res->data.fn_call_expr.params = args->data.fn_call_expr.params;
1465 res->data.fn_call_expr.is_builtin = false;
1466 return res;1467 return res;
1467 }1468 }
1469 put_back_token(pc);
14681470
1469 AstNode *res = ast_parse_primary_type_expr(pc);1471 AstNode *res = ast_parse_primary_type_expr(pc);
1470 if (res == nullptr)1472 if (res == nullptr)
...@@ -1496,7 +1498,7 @@ static AstNode *ast_parse_suffix_expr(ParseContext *pc) {...@@ -1496,7 +1498,7 @@ static AstNode *ast_parse_suffix_expr(ParseContext *pc) {
1496 continue;1498 continue;
1497 }1499 }
14981500
1499 AstNode * call = ast_parse_fn_call_argumnets(pc);1501 AstNode * call = ast_parse_fn_call_arguments(pc);
1500 if (call != nullptr) {1502 if (call != nullptr) {
1501 assert(call->type == NodeTypeFnCallExpr);1503 assert(call->type == NodeTypeFnCallExpr);
1502 call->data.fn_call_expr.fn_ref_expr = res;1504 call->data.fn_call_expr.fn_ref_expr = res;
...@@ -1552,7 +1554,7 @@ static AstNode *ast_parse_primary_type_expr(ParseContext *pc) {...@@ -1552,7 +1554,7 @@ static AstNode *ast_parse_primary_type_expr(ParseContext *pc) {
1552 name = buf_create_from_str("export");1554 name = buf_create_from_str("export");
1553 }1555 }
15541556
1555 AstNode *res = ast_expect(pc, ast_parse_fn_call_argumnets);1557 AstNode *res = ast_expect(pc, ast_parse_fn_call_arguments);
1556 AstNode *name_sym = ast_create_node(pc, NodeTypeSymbol, token);1558 AstNode *name_sym = ast_create_node(pc, NodeTypeSymbol, token);
1557 name_sym->data.symbol_expr.symbol = name;1559 name_sym->data.symbol_expr.symbol = name;
15581560
...@@ -1560,7 +1562,7 @@ static AstNode *ast_parse_primary_type_expr(ParseContext *pc) {...@@ -1560,7 +1562,7 @@ static AstNode *ast_parse_primary_type_expr(ParseContext *pc) {
1560 res->line = at_sign->start_line;1562 res->line = at_sign->start_line;
1561 res->column = at_sign->start_column;1563 res->column = at_sign->start_column;
1562 res->data.fn_call_expr.fn_ref_expr = name_sym;1564 res->data.fn_call_expr.fn_ref_expr = name_sym;
1563 res->data.fn_call_expr.is_builtin = true;1565 res->data.fn_call_expr.modifier = CallModifierBuiltin;
1564 return res;1566 return res;
1565 }1567 }
15661568
...@@ -2672,7 +2674,7 @@ static AstNode *ast_parse_suffix_op(ParseContext *pc) {...@@ -2672,7 +2674,7 @@ static AstNode *ast_parse_suffix_op(ParseContext *pc) {
2672}2674}
26732675
2674// FnCallArguments <- LPAREN ExprList RPAREN2676// FnCallArguments <- LPAREN ExprList RPAREN
2675static AstNode *ast_parse_fn_call_argumnets(ParseContext *pc) {2677static AstNode *ast_parse_fn_call_arguments(ParseContext *pc) {
2676 Token *paren = eat_token_if(pc, TokenIdLParen);2678 Token *paren = eat_token_if(pc, TokenIdLParen);
2677 if (paren == nullptr)2679 if (paren == nullptr)
2678 return nullptr;2680 return nullptr;
src/tokenizer.cpp+4-2
...@@ -130,9 +130,10 @@ static const struct ZigKeyword zig_keywords[] = {...@@ -130,9 +130,10 @@ static const struct ZigKeyword zig_keywords[] = {
130 {"for", TokenIdKeywordFor},130 {"for", TokenIdKeywordFor},
131 {"if", TokenIdKeywordIf},131 {"if", TokenIdKeywordIf},
132 {"inline", TokenIdKeywordInline},132 {"inline", TokenIdKeywordInline},
133 {"noinline", TokenIdKeywordNoInline},
134 {"nakedcc", TokenIdKeywordNakedCC},133 {"nakedcc", TokenIdKeywordNakedCC},
135 {"noalias", TokenIdKeywordNoAlias},134 {"noalias", TokenIdKeywordNoAlias},
135 {"noasync", TokenIdKeywordNoAsync},
136 {"noinline", TokenIdKeywordNoInline},
136 {"null", TokenIdKeywordNull},137 {"null", TokenIdKeywordNull},
137 {"or", TokenIdKeywordOr},138 {"or", TokenIdKeywordOr},
138 {"orelse", TokenIdKeywordOrElse},139 {"orelse", TokenIdKeywordOrElse},
...@@ -1552,9 +1553,10 @@ const char * token_name(TokenId id) {...@@ -1552,9 +1553,10 @@ const char * token_name(TokenId id) {
1552 case TokenIdKeywordFor: return "for";1553 case TokenIdKeywordFor: return "for";
1553 case TokenIdKeywordIf: return "if";1554 case TokenIdKeywordIf: return "if";
1554 case TokenIdKeywordInline: return "inline";1555 case TokenIdKeywordInline: return "inline";
1555 case TokenIdKeywordNoInline: return "noinline";
1556 case TokenIdKeywordNakedCC: return "nakedcc";1556 case TokenIdKeywordNakedCC: return "nakedcc";
1557 case TokenIdKeywordNoAlias: return "noalias";1557 case TokenIdKeywordNoAlias: return "noalias";
1558 case TokenIdKeywordNoAsync: return "noasync";
1559 case TokenIdKeywordNoInline: return "noinline";
1558 case TokenIdKeywordNull: return "null";1560 case TokenIdKeywordNull: return "null";
1559 case TokenIdKeywordOr: return "or";1561 case TokenIdKeywordOr: return "or";
1560 case TokenIdKeywordOrElse: return "orelse";1562 case TokenIdKeywordOrElse: return "orelse";
src/tokenizer.hpp+1
...@@ -78,6 +78,7 @@ enum TokenId {...@@ -78,6 +78,7 @@ enum TokenId {
78 TokenIdKeywordLinkSection,78 TokenIdKeywordLinkSection,
79 TokenIdKeywordNakedCC,79 TokenIdKeywordNakedCC,
80 TokenIdKeywordNoAlias,80 TokenIdKeywordNoAlias,
81 TokenIdKeywordNoAsync,
81 TokenIdKeywordNull,82 TokenIdKeywordNull,
82 TokenIdKeywordOr,83 TokenIdKeywordOr,
83 TokenIdKeywordOrElse,84 TokenIdKeywordOrElse,
src/translate_c.cpp+1-1
...@@ -253,7 +253,7 @@ static AstNode *trans_create_node_symbol_str(Context *c, const char *name) {...@@ -253,7 +253,7 @@ static AstNode *trans_create_node_symbol_str(Context *c, const char *name) {
253static AstNode *trans_create_node_builtin_fn_call(Context *c, Buf *name) {253static AstNode *trans_create_node_builtin_fn_call(Context *c, Buf *name) {
254 AstNode *node = trans_create_node(c, NodeTypeFnCallExpr);254 AstNode *node = trans_create_node(c, NodeTypeFnCallExpr);
255 node->data.fn_call_expr.fn_ref_expr = trans_create_node_symbol(c, name);255 node->data.fn_call_expr.fn_ref_expr = trans_create_node_symbol(c, name);
256 node->data.fn_call_expr.is_builtin = true;256 node->data.fn_call_expr.modifier = CallModifierBuiltin;
257 return node;257 return node;
258}258}
259259
std/zig/tokenizer.zig+4-2
...@@ -36,9 +36,10 @@ pub const Token = struct {...@@ -36,9 +36,10 @@ pub const Token = struct {
36 Keyword{ .bytes = "for", .id = Id.Keyword_for },36 Keyword{ .bytes = "for", .id = Id.Keyword_for },
37 Keyword{ .bytes = "if", .id = Id.Keyword_if },37 Keyword{ .bytes = "if", .id = Id.Keyword_if },
38 Keyword{ .bytes = "inline", .id = Id.Keyword_inline },38 Keyword{ .bytes = "inline", .id = Id.Keyword_inline },
39 Keyword{ .bytes = "noinline", .id = Id.Keyword_noinline },
40 Keyword{ .bytes = "nakedcc", .id = Id.Keyword_nakedcc },39 Keyword{ .bytes = "nakedcc", .id = Id.Keyword_nakedcc },
41 Keyword{ .bytes = "noalias", .id = Id.Keyword_noalias },40 Keyword{ .bytes = "noalias", .id = Id.Keyword_noalias },
41 Keyword{ .bytes = "noasync", .id = Id.Keyword_noasync },
42 Keyword{ .bytes = "noinline", .id = Id.Keyword_noinline },
42 Keyword{ .bytes = "null", .id = Id.Keyword_null },43 Keyword{ .bytes = "null", .id = Id.Keyword_null },
43 Keyword{ .bytes = "or", .id = Id.Keyword_or },44 Keyword{ .bytes = "or", .id = Id.Keyword_or },
44 Keyword{ .bytes = "orelse", .id = Id.Keyword_orelse },45 Keyword{ .bytes = "orelse", .id = Id.Keyword_orelse },
...@@ -167,9 +168,10 @@ pub const Token = struct {...@@ -167,9 +168,10 @@ pub const Token = struct {
167 Keyword_for,168 Keyword_for,
168 Keyword_if,169 Keyword_if,
169 Keyword_inline,170 Keyword_inline,
170 Keyword_noinline,
171 Keyword_nakedcc,171 Keyword_nakedcc,
172 Keyword_noalias,172 Keyword_noalias,
173 Keyword_noasync,
174 Keyword_noinline,
173 Keyword_null,175 Keyword_null,
174 Keyword_or,176 Keyword_or,
175 Keyword_orelse,177 Keyword_orelse,
test/stage1/behavior/async_fn.zig+16
...@@ -1092,3 +1092,19 @@ test "recursive call of await @asyncCall with struct return type" {...@@ -1092,3 +1092,19 @@ test "recursive call of await @asyncCall with struct return type" {
1092 expect(res.y == 2);1092 expect(res.y == 2);
1093 expect(res.z == 3);1093 expect(res.z == 3);
1094}1094}
1095
1096test "noasync function call" {
1097 const S = struct {
1098 fn doTheTest() void {
1099 const result = noasync add(50, 100);
1100 expect(result == 150);
1101 }
1102 fn add(a: i32, b: i32) i32 {
1103 if (a > 100) {
1104 suspend;
1105 }
1106 return a + b;
1107 }
1108 };
1109 S.doTheTest();
1110}