| author | |
| committer | |
| log | 0a3c6dbda92931eba055c2c6447b7a4412408f17 |
| tree | 86d98cd519e628c28efe2fe9e2ff3ec86f55246d |
| parent | ca70ca7e26aaae3425dad3a2b179f544bacf45e3 |
| signature |
See #315713 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 | }; |
| 760 | 760 | ||
| 761 | enum CallModifier { | ||
| 762 | CallModifierNone, | ||
| 763 | CallModifierAsync, | ||
| 764 | CallModifierNoAsync, | ||
| 765 | CallModifierBuiltin, | ||
| 766 | }; | ||
| 767 | |||
| 761 | struct AstNodeFnCallExpr { | 768 | struct 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 @compileLog | 772 | bool seen; // used by @compileLog |
| 767 | }; | 773 | }; |
| 768 | 774 | ||
| ... | @@ -2730,8 +2736,10 @@ struct IrInstructionCallSrc { | ... | @@ -2730,8 +2736,10 @@ struct IrInstructionCallSrc { |
| 2730 | ResultLoc *result_loc; | 2736 | ResultLoc *result_loc; |
| 2731 | 2737 | ||
| 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 | }; |
| 2754 | 2763 |
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 async | 4228 | // ErrorIsAsync - yes async |
| 4229 | // ErrorSemanticAnalyzeFail - compile error emitted result is invalid | 4229 | // ErrorSemanticAnalyzeFail - compile error emitted result is invalid |
| 4230 | static Error analyze_callee_async(CodeGen *g, ZigFn *fn, ZigFn *callee, AstNode *call_node, | 4230 | static 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 anything | 4314 | // 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); |
| 186 | static bool value_is_all_undef(CodeGen *g, ConstExprValue *const_val); | 186 | static bool value_is_all_undef(CodeGen *g, ConstExprValue *const_val); |
| 187 | static void gen_undef_init(CodeGen *g, uint32_t ptr_align_bytes, ZigType *value_type, LLVMValueRef ptr); | 187 | static void gen_undef_init(CodeGen *g, uint32_t ptr_align_bytes, ZigType *value_type, LLVMValueRef ptr); |
| 188 | static LLVMValueRef build_alloca(CodeGen *g, ZigType *type_entry, const char *name, uint32_t alignment); | 188 | static LLVMValueRef build_alloca(CodeGen *g, ZigType *type_entry, const char *name, uint32_t alignment); |
| 189 | static 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); | ||
| 189 | 192 | ||
| 190 | static void addLLVMAttr(LLVMValueRef val, LLVMAttributeIndex attr_index, const char *attr_name) { | 193 | static 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; |
| 3889 | 3892 | ||
| ... | @@ -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 own | 3911 | // 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 function | 3914 | if (instruction->modifier == CallModifierNoAsync && !fn_is_async(g->cur_fn)) { |
| 3912 | 3915 | // 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 pointer | 3916 | // 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 function | 3964 | // 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 | } |
| 4050 | 4059 | ||
| 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); |
| 4060 | 4076 | ||
| ... | @@ -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 | } |
| 7105 | 7121 | ||
| 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 data | 7145 | // 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 |
| 1389 | 1389 | ||
| 1390 | static IrInstruction *ir_build_call_src(IrBuilder *irb, Scope *scope, AstNode *source_node, | 1390 | static 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 pointer | 1411 | // 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 |
| 1418 | 1418 | ||
| 1419 | static IrInstructionCallGen *ir_build_call_gen(IrAnalyze *ira, IrInstruction *source_instruction, | 1419 | static 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 |
| 4412 | 4412 | ||
| 4413 | args[arg_count] = ret_ptr; | 4413 | args[arg_count] = ret_ptr; |
| 4414 | 4414 | ||
| 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 | } |
| 4421 | 4421 | ||
| ... | @@ -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; |
| 5303 | 5303 | ||
| 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 | } |
| 5336 | 5336 | ||
| 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); |
| 5626 | 5626 | ||
| 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); |
| 5629 | 5629 | ||
| 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 | } |
| 5643 | 5643 | ||
| 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 | } |
| 5649 | 5648 | ||
| ... | @@ -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); |
| 7938 | 7937 | ||
| 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); |
| 15409 | 15408 | ||
| 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 | } |
| 15429 | static bool ir_analyze_fn_call_inline_arg(IrAnalyze *ira, AstNode *fn_proto_node, | 15428 | static 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; |
| 16175 | 16174 | ||
| 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 | } |
| 16203 | 16202 | ||
| 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 | } |
| 16208 | 16210 | ||
| 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); |
| 16213 | 16215 | ||
| 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; |
| 16327 | 16329 | ||
| 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 | } |
| 16333 | 16335 | ||
| 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 | } |
| 16359 | 16364 | ||
| 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 | } |
| 609 | 609 | ||
| 610 | static void ir_print_call_src(IrPrint *irp, IrInstructionCallSrc *call_instruction) { | 610 | static 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 | } |
| 630 | 639 | ||
| 631 | static void ir_print_call_gen(IrPrint *irp, IrInstructionCallGen *call_instruction) { | 640 | static 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); |
| 113 | static AstNode *ast_parse_prefix_op(ParseContext *pc); | 113 | static AstNode *ast_parse_prefix_op(ParseContext *pc); |
| 114 | static AstNode *ast_parse_prefix_type_op(ParseContext *pc); | 114 | static AstNode *ast_parse_prefix_type_op(ParseContext *pc); |
| 115 | static AstNode *ast_parse_suffix_op(ParseContext *pc); | 115 | static AstNode *ast_parse_suffix_op(ParseContext *pc); |
| 116 | static AstNode *ast_parse_fn_call_argumnets(ParseContext *pc); | 116 | static AstNode *ast_parse_fn_call_arguments(ParseContext *pc); |
| 117 | static AstNode *ast_parse_array_type_start(ParseContext *pc); | 117 | static AstNode *ast_parse_array_type_start(ParseContext *pc); |
| 118 | static AstNode *ast_parse_ptr_type_start(ParseContext *pc); | 118 | static AstNode *ast_parse_ptr_type_start(ParseContext *pc); |
| 119 | static AstNode *ast_parse_container_decl_auto(ParseContext *pc); | 119 | static 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 | } |
| 1404 | 1404 | ||
| 1405 | // SuffixExpr | 1405 | // SuffixExpr |
| 1406 | // <- KEYWORD_async PrimaryTypeExpr SuffixOp* FnCallArguments | 1406 | // <- KEYWORD_async PrimaryTypeExpr SuffixOp* FnCallArguments |
| 1407 | // / KEYWORD_noasync PrimaryTypeExpr SuffixOp* FnCallArguments | ||
| 1407 | // / PrimaryTypeExpr (SuffixOp / FnCallArguments)* | 1408 | // / PrimaryTypeExpr (SuffixOp / FnCallArguments)* |
| 1408 | static AstNode *ast_parse_suffix_expr(ParseContext *pc) { | 1409 | static 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 that | 1414 | // 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 async | 1416 | // 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 | } |
| 1449 | 1451 | ||
| 1450 | // TODO: Both *_async_prefix and *_fn_call_argumnets returns an | 1452 | // TODO: Both *_async_prefix and *_fn_call_arguments returns an |
| 1451 | // AstNode *. All we really want here is the arguments of | 1453 | // 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)); |
| 1457 | 1459 | ||
| 1458 | assert(args->type == NodeTypeFnCallExpr); | 1460 | assert(args->type == NodeTypeFnCallExpr); |
| 1459 | 1461 | ||
| 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); | ||
| 1468 | 1470 | ||
| 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 | } |
| 1498 | 1500 | ||
| 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 | } |
| 1554 | 1556 | ||
| 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; |
| 1558 | 1560 | ||
| ... | @@ -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 | } |
| 1566 | 1568 | ||
| ... | @@ -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 | } |
| 2673 | 2675 | ||
| 2674 | // FnCallArguments <- LPAREN ExprList RPAREN | 2676 | // FnCallArguments <- LPAREN ExprList RPAREN |
| 2675 | static AstNode *ast_parse_fn_call_argumnets(ParseContext *pc) { | 2677 | static 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) { |
| 253 | static AstNode *trans_create_node_builtin_fn_call(Context *c, Buf *name) { | 253 | static 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 | } |
| 259 | 259 |
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 | |||
| 1096 | test "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 | } |