authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-08-14 12:52:20-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-08-14 12:52:20-04:00
log64c293f8a4ce5fcbb506c32b989a88d982f005ce
treed3f8332a227ddd4a316bd08ca93ba1d8624b4b6a
parentf3f838cc016fd8190a9bba46fa495fbc27325492
signaturelock-open Commit is signed but in an unrecognized format.

codegen for async call of blocking function


2 files changed, 151 insertions(+), 90 deletions(-)

src/analyze.cpp+44-10
...@@ -3831,7 +3831,7 @@ static void add_async_error_notes(CodeGen *g, ErrorMsg *msg, ZigFn *fn) {...@@ -3831,7 +3831,7 @@ static void add_async_error_notes(CodeGen *g, ErrorMsg *msg, ZigFn *fn) {
3831}3831}
38323832
3833// This function resolves functions being inferred async.3833// This function resolves functions being inferred async.
3834static void analyze_fn_async(CodeGen *g, ZigFn *fn) {3834static void analyze_fn_async(CodeGen *g, ZigFn *fn, bool resolve_frame) {
3835 if (fn->inferred_async_node == inferred_async_checking) {3835 if (fn->inferred_async_node == inferred_async_checking) {
3836 // TODO call graph cycle detected, disallow the recursion3836 // TODO call graph cycle detected, disallow the recursion
3837 fn->inferred_async_node = inferred_async_none;3837 fn->inferred_async_node = inferred_async_none;
...@@ -3841,7 +3841,9 @@ static void analyze_fn_async(CodeGen *g, ZigFn *fn) {...@@ -3841,7 +3841,9 @@ static void analyze_fn_async(CodeGen *g, ZigFn *fn) {
3841 return;3841 return;
3842 }3842 }
3843 if (fn->inferred_async_node != nullptr) {3843 if (fn->inferred_async_node != nullptr) {
3844 resolve_async_fn_frame(g, fn);3844 if (resolve_frame) {
3845 resolve_async_fn_frame(g, fn);
3846 }
3845 return;3847 return;
3846 }3848 }
3847 fn->inferred_async_node = inferred_async_checking;3849 fn->inferred_async_node = inferred_async_checking;
...@@ -3870,7 +3872,7 @@ static void analyze_fn_async(CodeGen *g, ZigFn *fn) {...@@ -3870,7 +3872,7 @@ static void analyze_fn_async(CodeGen *g, ZigFn *fn) {
3870 }3872 }
3871 }3873 }
3872 assert(callee->anal_state == FnAnalStateComplete);3874 assert(callee->anal_state == FnAnalStateComplete);
3873 analyze_fn_async(g, callee);3875 analyze_fn_async(g, callee, true);
3874 if (callee->anal_state == FnAnalStateInvalid) {3876 if (callee->anal_state == FnAnalStateInvalid) {
3875 fn->anal_state = FnAnalStateInvalid;3877 fn->anal_state = FnAnalStateInvalid;
3876 return;3878 return;
...@@ -3886,7 +3888,9 @@ static void analyze_fn_async(CodeGen *g, ZigFn *fn) {...@@ -3886,7 +3888,9 @@ static void analyze_fn_async(CodeGen *g, ZigFn *fn) {
3886 fn->anal_state = FnAnalStateInvalid;3888 fn->anal_state = FnAnalStateInvalid;
3887 return;3889 return;
3888 }3890 }
3889 resolve_async_fn_frame(g, fn);3891 if (resolve_frame) {
3892 resolve_async_fn_frame(g, fn);
3893 }
3890 return;3894 return;
3891 }3895 }
3892 }3896 }
...@@ -4141,7 +4145,7 @@ void semantic_analyze(CodeGen *g) {...@@ -4141,7 +4145,7 @@ void semantic_analyze(CodeGen *g) {
4141 // second pass over functions for detecting async4145 // second pass over functions for detecting async
4142 for (g->fn_defs_index = 0; g->fn_defs_index < g->fn_defs.length; g->fn_defs_index += 1) {4146 for (g->fn_defs_index = 0; g->fn_defs_index < g->fn_defs.length; g->fn_defs_index += 1) {
4143 ZigFn *fn_entry = g->fn_defs.at(g->fn_defs_index);4147 ZigFn *fn_entry = g->fn_defs.at(g->fn_defs_index);
4144 analyze_fn_async(g, fn_entry);4148 analyze_fn_async(g, fn_entry, true);
4145 }4149 }
4146}4150}
41474151
...@@ -5212,6 +5216,36 @@ static Error resolve_async_frame(CodeGen *g, ZigType *frame_type) {...@@ -5212,6 +5216,36 @@ static Error resolve_async_frame(CodeGen *g, ZigType *frame_type) {
5212 return ErrorSemanticAnalyzeFail;5216 return ErrorSemanticAnalyzeFail;
5213 }5217 }
5214 }5218 }
5219 analyze_fn_async(g, fn, false);
5220 if (fn->anal_state == FnAnalStateInvalid)
5221 return ErrorSemanticAnalyzeFail;
5222
5223 if (!fn_is_async(fn)) {
5224 ZigType *fn_type = fn->type_entry;
5225 FnTypeId *fn_type_id = &fn_type->data.fn.fn_type_id;
5226 ZigType *ptr_return_type = get_pointer_to_type(g, fn_type_id->return_type, false);
5227
5228 // label (grep this): [fn_frame_struct_layout]
5229 ZigList<SrcField> fields = {};
5230
5231 fields.append({"@fn_ptr", g->builtin_types.entry_usize, 0});
5232 fields.append({"@resume_index", g->builtin_types.entry_usize, 0});
5233 fields.append({"@awaiter", g->builtin_types.entry_usize, 0});
5234 fields.append({"@prev_val", g->builtin_types.entry_usize, 0});
5235
5236 fields.append({"@result_ptr_callee", ptr_return_type, 0});
5237 fields.append({"@result_ptr_awaiter", ptr_return_type, 0});
5238 fields.append({"@result", fn_type_id->return_type, 0});
5239
5240 frame_type->data.frame.locals_struct = get_struct_type(g, buf_ptr(&frame_type->name),
5241 fields.items, fields.length, target_fn_align(g->zig_target));
5242 frame_type->abi_size = frame_type->data.frame.locals_struct->abi_size;
5243 frame_type->abi_align = frame_type->data.frame.locals_struct->abi_align;
5244 frame_type->size_in_bits = frame_type->data.frame.locals_struct->size_in_bits;
5245
5246 return ErrorNone;
5247 }
5248
5215 ZigType *fn_type = get_async_fn_type(g, fn->type_entry);5249 ZigType *fn_type = get_async_fn_type(g, fn->type_entry);
52165250
5217 if (fn->analyzed_executable.need_err_code_spill) {5251 if (fn->analyzed_executable.need_err_code_spill) {
...@@ -5252,7 +5286,7 @@ static Error resolve_async_frame(CodeGen *g, ZigType *frame_type) {...@@ -5252,7 +5286,7 @@ static Error resolve_async_frame(CodeGen *g, ZigType *frame_type) {
5252 frame_type->data.frame.locals_struct = g->builtin_types.entry_invalid;5286 frame_type->data.frame.locals_struct = g->builtin_types.entry_invalid;
5253 return ErrorSemanticAnalyzeFail;5287 return ErrorSemanticAnalyzeFail;
5254 }5288 }
5255 analyze_fn_async(g, callee);5289 analyze_fn_async(g, callee, true);
5256 if (!fn_is_async(callee))5290 if (!fn_is_async(callee))
5257 continue;5291 continue;
52585292
...@@ -5268,6 +5302,8 @@ static Error resolve_async_frame(CodeGen *g, ZigType *frame_type) {...@@ -5268,6 +5302,8 @@ static Error resolve_async_frame(CodeGen *g, ZigType *frame_type) {
5268 fn->alloca_gen_list.append(alloca_gen);5302 fn->alloca_gen_list.append(alloca_gen);
5269 call->frame_result_loc = &alloca_gen->base;5303 call->frame_result_loc = &alloca_gen->base;
5270 }5304 }
5305 FnTypeId *fn_type_id = &fn_type->data.fn.fn_type_id;
5306 ZigType *ptr_return_type = get_pointer_to_type(g, fn_type_id->return_type, false);
52715307
5272 // label (grep this): [fn_frame_struct_layout]5308 // label (grep this): [fn_frame_struct_layout]
5273 ZigList<SrcField> fields = {};5309 ZigList<SrcField> fields = {};
...@@ -5277,9 +5313,6 @@ static Error resolve_async_frame(CodeGen *g, ZigType *frame_type) {...@@ -5277,9 +5313,6 @@ static Error resolve_async_frame(CodeGen *g, ZigType *frame_type) {
5277 fields.append({"@awaiter", g->builtin_types.entry_usize, 0});5313 fields.append({"@awaiter", g->builtin_types.entry_usize, 0});
5278 fields.append({"@prev_val", g->builtin_types.entry_usize, 0});5314 fields.append({"@prev_val", g->builtin_types.entry_usize, 0});
52795315
5280 FnTypeId *fn_type_id = &fn_type->data.fn.fn_type_id;
5281 ZigType *ptr_return_type = get_pointer_to_type(g, fn_type_id->return_type, false);
5282
5283 fields.append({"@result_ptr_callee", ptr_return_type, 0});5316 fields.append({"@result_ptr_callee", ptr_return_type, 0});
5284 fields.append({"@result_ptr_awaiter", ptr_return_type, 0});5317 fields.append({"@result_ptr_awaiter", ptr_return_type, 0});
5285 fields.append({"@result", fn_type_id->return_type, 0});5318 fields.append({"@result", fn_type_id->return_type, 0});
...@@ -7651,7 +7684,8 @@ static void resolve_llvm_types_anyerror(CodeGen *g) {...@@ -7651,7 +7684,8 @@ static void resolve_llvm_types_anyerror(CodeGen *g) {
7651}7684}
76527685
7653static void resolve_llvm_types_async_frame(CodeGen *g, ZigType *frame_type, ResolveStatus wanted_resolve_status) {7686static void resolve_llvm_types_async_frame(CodeGen *g, ZigType *frame_type, ResolveStatus wanted_resolve_status) {
7654 resolve_llvm_types_struct(g, frame_type->data.frame.locals_struct, wanted_resolve_status, frame_type);7687 ZigType *passed_frame_type = fn_is_async(frame_type->data.frame.fn) ? frame_type : nullptr;
7688 resolve_llvm_types_struct(g, frame_type->data.frame.locals_struct, wanted_resolve_status, passed_frame_type);
7655 frame_type->llvm_type = frame_type->data.frame.locals_struct->llvm_type;7689 frame_type->llvm_type = frame_type->data.frame.locals_struct->llvm_type;
7656 frame_type->llvm_di_type = frame_type->data.frame.locals_struct->llvm_di_type;7690 frame_type->llvm_di_type = frame_type->data.frame.locals_struct->llvm_di_type;
7657}7691}
src/codegen.cpp+107-80
...@@ -3850,73 +3850,74 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr...@@ -3850,73 +3850,74 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr
3850 LLVMValueRef frame_result_loc;3850 LLVMValueRef frame_result_loc;
3851 LLVMValueRef awaiter_init_val;3851 LLVMValueRef awaiter_init_val;
3852 LLVMValueRef ret_ptr;3852 LLVMValueRef ret_ptr;
3853 if (instruction->is_async) {3853 if (callee_is_async) {
3854 awaiter_init_val = zero;3854 if (instruction->is_async) {
38553855 if (instruction->new_stack == nullptr) {
3856 if (instruction->new_stack == nullptr) {3856 awaiter_init_val = zero;
3857 frame_result_loc = result_loc;3857 frame_result_loc = result_loc;
38583858
3859 if (ret_has_bits) {3859 if (ret_has_bits) {
3860 // Use the result location which is inside the frame if this is an async call.3860 // Use the result location which is inside the frame if this is an async call.
3861 ret_ptr = LLVMBuildStructGEP(g->builder, frame_result_loc, frame_ret_start + 2, "");3861 ret_ptr = LLVMBuildStructGEP(g->builder, frame_result_loc, frame_ret_start + 2, "");
3862 }3862 }
3863 } else {3863 } else if (cc == CallingConventionAsync) {
3864 LLVMValueRef frame_slice_ptr = ir_llvm_value(g, instruction->new_stack);3864 awaiter_init_val = zero;
3865 if (ir_want_runtime_safety(g, &instruction->base)) {3865 LLVMValueRef frame_slice_ptr = ir_llvm_value(g, instruction->new_stack);
3866 LLVMValueRef given_len_ptr = LLVMBuildStructGEP(g->builder, frame_slice_ptr, slice_len_index, "");3866 if (ir_want_runtime_safety(g, &instruction->base)) {
3867 LLVMValueRef given_frame_len = LLVMBuildLoad(g->builder, given_len_ptr, "");3867 LLVMValueRef given_len_ptr = LLVMBuildStructGEP(g->builder, frame_slice_ptr, slice_len_index, "");
3868 LLVMValueRef actual_frame_len = gen_frame_size(g, fn_val);3868 LLVMValueRef given_frame_len = LLVMBuildLoad(g->builder, given_len_ptr, "");
38693869 LLVMValueRef actual_frame_len = gen_frame_size(g, fn_val);
3870 LLVMBasicBlockRef fail_block = LLVMAppendBasicBlock(g->cur_fn_val, "FrameSizeCheckFail");3870
3871 LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn_val, "FrameSizeCheckOk");3871 LLVMBasicBlockRef fail_block = LLVMAppendBasicBlock(g->cur_fn_val, "FrameSizeCheckFail");
38723872 LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn_val, "FrameSizeCheckOk");
3873 LLVMValueRef ok_bit = LLVMBuildICmp(g->builder, LLVMIntUGE, given_frame_len, actual_frame_len, "");3873
3874 LLVMBuildCondBr(g->builder, ok_bit, ok_block, fail_block);3874 LLVMValueRef ok_bit = LLVMBuildICmp(g->builder, LLVMIntUGE, given_frame_len, actual_frame_len, "");
3875 LLVMBuildCondBr(g->builder, ok_bit, ok_block, fail_block);
38753876
3876 LLVMPositionBuilderAtEnd(g->builder, fail_block);3877 LLVMPositionBuilderAtEnd(g->builder, fail_block);
3877 gen_safety_crash(g, PanicMsgIdFrameTooSmall);3878 gen_safety_crash(g, PanicMsgIdFrameTooSmall);
38783879
3879 LLVMPositionBuilderAtEnd(g->builder, ok_block);3880 LLVMPositionBuilderAtEnd(g->builder, ok_block);
3881 }
3882 LLVMValueRef frame_ptr_ptr = LLVMBuildStructGEP(g->builder, frame_slice_ptr, slice_ptr_index, "");
3883 LLVMValueRef frame_ptr = LLVMBuildLoad(g->builder, frame_ptr_ptr, "");
3884 frame_result_loc = LLVMBuildBitCast(g->builder, frame_ptr,
3885 get_llvm_type(g, instruction->base.value.type), "");
3886
3887 if (ret_has_bits) {
3888 // Use the result location provided to the @asyncCall builtin
3889 ret_ptr = result_loc;
3890 }
3880 }3891 }
3881 LLVMValueRef frame_ptr_ptr = LLVMBuildStructGEP(g->builder, frame_slice_ptr, slice_ptr_index, "");
3882 LLVMValueRef frame_ptr = LLVMBuildLoad(g->builder, frame_ptr_ptr, "");
3883 frame_result_loc = LLVMBuildBitCast(g->builder, frame_ptr,
3884 get_llvm_type(g, instruction->base.value.type), "");
38853892
3893 // even if prefix_arg_err_ret_stack is true, let the async function do its own
3894 // initialization.
3895 } else {
3896 frame_result_loc = ir_llvm_value(g, instruction->frame_result_loc);
3897 awaiter_init_val = LLVMBuildPtrToInt(g->builder, g->cur_frame_ptr, usize_type_ref, ""); // caller's own frame pointer
3886 if (ret_has_bits) {3898 if (ret_has_bits) {
3887 // Use the result location provided to the @asyncCall builtin3899 if (result_loc == nullptr) {
3888 ret_ptr = result_loc;3900 // return type is a scalar, but we still need a pointer to it. Use the async fn frame.
3889 }3901 ret_ptr = LLVMBuildStructGEP(g->builder, frame_result_loc, frame_ret_start + 2, "");
3890 }3902 } else {
3903 // Use the call instruction's result location.
3904 ret_ptr = result_loc;
3905 }
38913906
3892 // even if prefix_arg_err_ret_stack is true, let the async function do its own3907 // Store a zero in the awaiter's result ptr to indicate we do not need a copy made.
3893 // initialization.3908 LLVMValueRef awaiter_ret_ptr = LLVMBuildStructGEP(g->builder, frame_result_loc, frame_ret_start + 1, "");
3894 } else if (callee_is_async) {3909 LLVMValueRef zero_ptr = LLVMConstNull(LLVMGetElementType(LLVMTypeOf(awaiter_ret_ptr)));
3895 frame_result_loc = ir_llvm_value(g, instruction->frame_result_loc);3910 LLVMBuildStore(g->builder, zero_ptr, awaiter_ret_ptr);
3896 awaiter_init_val = LLVMBuildPtrToInt(g->builder, g->cur_frame_ptr, usize_type_ref, ""); // caller's own frame pointer
3897 if (ret_has_bits) {
3898 if (result_loc == nullptr) {
3899 // return type is a scalar, but we still need a pointer to it. Use the async fn frame.
3900 ret_ptr = LLVMBuildStructGEP(g->builder, frame_result_loc, frame_ret_start + 2, "");
3901 } else {
3902 // Use the call instruction's result location.
3903 ret_ptr = result_loc;
3904 }3911 }
39053912
3906 // Store a zero in the awaiter's result ptr to indicate we do not need a copy made.3913 if (prefix_arg_err_ret_stack) {
3907 LLVMValueRef awaiter_ret_ptr = LLVMBuildStructGEP(g->builder, frame_result_loc, frame_ret_start + 1, "");3914 LLVMValueRef err_ret_trace_ptr_ptr = LLVMBuildStructGEP(g->builder, frame_result_loc,
3908 LLVMValueRef zero_ptr = LLVMConstNull(LLVMGetElementType(LLVMTypeOf(awaiter_ret_ptr)));3915 frame_index_trace_arg(g, src_return_type), "");
3909 LLVMBuildStore(g->builder, zero_ptr, awaiter_ret_ptr);3916 LLVMValueRef my_err_ret_trace_val = get_cur_err_ret_trace_val(g, instruction->base.scope);
3917 LLVMBuildStore(g->builder, my_err_ret_trace_val, err_ret_trace_ptr_ptr);
3918 }
3910 }3919 }
39113920
3912 if (prefix_arg_err_ret_stack) {
3913 LLVMValueRef err_ret_trace_ptr_ptr = LLVMBuildStructGEP(g->builder, frame_result_loc,
3914 frame_index_trace_arg(g, src_return_type), "");
3915 LLVMValueRef my_err_ret_trace_val = get_cur_err_ret_trace_val(g, instruction->base.scope);
3916 LLVMBuildStore(g->builder, my_err_ret_trace_val, err_ret_trace_ptr_ptr);
3917 }
3918 }
3919 if (instruction->is_async || callee_is_async) {
3920 assert(frame_result_loc != nullptr);3921 assert(frame_result_loc != nullptr);
39213922
3922 LLVMValueRef fn_ptr_ptr = LLVMBuildStructGEP(g->builder, frame_result_loc, frame_fn_ptr_index, "");3923 LLVMValueRef fn_ptr_ptr = LLVMBuildStructGEP(g->builder, frame_result_loc, frame_fn_ptr_index, "");
...@@ -3934,6 +3935,29 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr...@@ -3934,6 +3935,29 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr
3934 LLVMValueRef ret_ptr_ptr = LLVMBuildStructGEP(g->builder, frame_result_loc, frame_ret_start, "");3935 LLVMValueRef ret_ptr_ptr = LLVMBuildStructGEP(g->builder, frame_result_loc, frame_ret_start, "");
3935 LLVMBuildStore(g->builder, ret_ptr, ret_ptr_ptr);3936 LLVMBuildStore(g->builder, ret_ptr, ret_ptr_ptr);
3936 }3937 }
3938 } else if (instruction->is_async) {
3939 // Async call of blocking function
3940 if (instruction->new_stack != nullptr) {
3941 zig_panic("TODO @asyncCall of non-async function");
3942 }
3943 frame_result_loc = result_loc;
3944 awaiter_init_val = LLVMConstAllOnes(usize_type_ref);
3945
3946 LLVMValueRef awaiter_ptr = LLVMBuildStructGEP(g->builder, frame_result_loc, frame_awaiter_index, "");
3947 LLVMBuildStore(g->builder, awaiter_init_val, awaiter_ptr);
3948
3949 if (ret_has_bits) {
3950 LLVMValueRef ret_ptr = LLVMBuildStructGEP(g->builder, frame_result_loc, frame_ret_start + 2, "");
3951 LLVMValueRef ret_ptr_ptr = LLVMBuildStructGEP(g->builder, frame_result_loc, frame_ret_start, "");
3952 LLVMBuildStore(g->builder, ret_ptr, ret_ptr_ptr);
3953
3954 if (first_arg_ret) {
3955 gen_param_values.append(ret_ptr);
3956 }
3957 }
3958 if (prefix_arg_err_ret_stack) {
3959 gen_param_values.append(get_cur_err_ret_trace_val(g, instruction->base.scope));
3960 }
3937 } else {3961 } else {
3938 if (first_arg_ret) {3962 if (first_arg_ret) {
3939 gen_param_values.append(result_loc);3963 gen_param_values.append(result_loc);
...@@ -3966,7 +3990,7 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr...@@ -3966,7 +3990,7 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr
3966 LLVMCallConv llvm_cc = get_llvm_cc(g, cc);3990 LLVMCallConv llvm_cc = get_llvm_cc(g, cc);
3967 LLVMValueRef result;3991 LLVMValueRef result;
39683992
3969 if (instruction->is_async || callee_is_async) {3993 if (callee_is_async) {
3970 uint32_t arg_start_i = frame_index_arg(g, fn_type->data.fn.fn_type_id.return_type);3994 uint32_t arg_start_i = frame_index_arg(g, fn_type->data.fn.fn_type_id.return_type);
39713995
3972 LLVMValueRef casted_frame;3996 LLVMValueRef casted_frame;
...@@ -3992,39 +4016,42 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr...@@ -3992,39 +4016,42 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr
3992 gen_assign_raw(g, arg_ptr, get_pointer_to_type(g, gen_param_types.at(arg_i), true),4016 gen_assign_raw(g, arg_ptr, get_pointer_to_type(g, gen_param_types.at(arg_i), true),
3993 gen_param_values.at(arg_i));4017 gen_param_values.at(arg_i));
3994 }4018 }
3995 }
3996 if (instruction->is_async) {
3997 gen_resume(g, fn_val, frame_result_loc, ResumeIdCall, nullptr);
3998 if (instruction->new_stack != nullptr) {
3999 return frame_result_loc;
4000 }
4001 return nullptr;
4002 } else if (callee_is_async) {
4003 ZigType *ptr_result_type = get_pointer_to_type(g, src_return_type, true);
40044019
4005 LLVMBasicBlockRef call_bb = gen_suspend_begin(g, "CallResume");4020 if (instruction->is_async) {
4021 gen_resume(g, fn_val, frame_result_loc, ResumeIdCall, nullptr);
4022 if (instruction->new_stack != nullptr) {
4023 return frame_result_loc;
4024 }
4025 return nullptr;
4026 } else {
4027 ZigType *ptr_result_type = get_pointer_to_type(g, src_return_type, true);
40064028
4007 LLVMValueRef call_inst = gen_resume(g, fn_val, frame_result_loc, ResumeIdCall, nullptr);4029 LLVMBasicBlockRef call_bb = gen_suspend_begin(g, "CallResume");
4008 set_tail_call_if_appropriate(g, call_inst);4030
4009 LLVMBuildRetVoid(g->builder);4031 LLVMValueRef call_inst = gen_resume(g, fn_val, frame_result_loc, ResumeIdCall, nullptr);
4032 set_tail_call_if_appropriate(g, call_inst);
4033 LLVMBuildRetVoid(g->builder);
40104034
4011 LLVMPositionBuilderAtEnd(g->builder, call_bb);4035 LLVMPositionBuilderAtEnd(g->builder, call_bb);
4012 gen_assert_resume_id(g, &instruction->base, ResumeIdReturn, PanicMsgIdResumedAnAwaitingFn, nullptr);4036 gen_assert_resume_id(g, &instruction->base, ResumeIdReturn, PanicMsgIdResumedAnAwaitingFn, nullptr);
4013 render_async_var_decls(g, instruction->base.scope);4037 render_async_var_decls(g, instruction->base.scope);
40144038
4015 if (!type_has_bits(src_return_type))4039 if (!type_has_bits(src_return_type))
4016 return nullptr;4040 return nullptr;
40174041
4018 if (result_loc != nullptr) 4042 if (result_loc != nullptr)
4019 return get_handle_value(g, result_loc, src_return_type, ptr_result_type);4043 return get_handle_value(g, result_loc, src_return_type, ptr_result_type);
40204044
4021 LLVMValueRef result_ptr = LLVMBuildStructGEP(g->builder, frame_result_loc, frame_ret_start + 2, "");4045 LLVMValueRef result_ptr = LLVMBuildStructGEP(g->builder, frame_result_loc, frame_ret_start + 2, "");
4022 return LLVMBuildLoad(g->builder, result_ptr, "");4046 return LLVMBuildLoad(g->builder, result_ptr, "");
4047 }
4023 }4048 }
40244049
4025 if (instruction->new_stack == nullptr) {4050 if (instruction->new_stack == nullptr) {
4026 result = ZigLLVMBuildCall(g->builder, fn_val,4051 result = ZigLLVMBuildCall(g->builder, fn_val,
4027 gen_param_values.items, (unsigned)gen_param_values.length, llvm_cc, fn_inline, "");4052 gen_param_values.items, (unsigned)gen_param_values.length, llvm_cc, fn_inline, "");
4053 } else if (instruction->is_async) {
4054 zig_panic("TODO @asyncCall of non-async function");
4028 } else {4055 } else {
4029 LLVMValueRef stacksave_fn_val = get_stacksave_fn_val(g);4056 LLVMValueRef stacksave_fn_val = get_stacksave_fn_val(g);
4030 LLVMValueRef stackrestore_fn_val = get_stackrestore_fn_val(g);4057 LLVMValueRef stackrestore_fn_val = get_stackrestore_fn_val(g);