authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-08-06 16:37:25-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-08-06 16:53:22-04:00
log400500a3afafca8178f13a7e4e1cd0ae7808aff2
treef6ee011721206db3cda4952dd2eccaeb71c7e632
parent20f63e588e62c4a7250bc96c9e5b54c8106ad1af
signature Commit is signed but in an unrecognized format.

improve async function semantics

* add safety panic for resuming a function which is returning, pending an await * remove IrInstructionResultPtr * add IrInstructionReturnBegin. This does the early return in async functions; does nothing in normal functions. * `await` gets a result location * `analyze_fn_async` will call `analyze_fn_body` if necessary. * async function frames have a result pointer field for themselves to access and one for the awaiter to supply before the atomic rmw. when returning, async functions copy the result to the awaiter result pointer, if it is non-null. * async function frames have a stack trace pointer which is supplied by the awaiter before the atomicrmw. Later in the frame is a stack trace struct and addresses, which is used for its own calls and awaits. * when awaiting an async function, if an early return occurred, the awaiter tail resumes the frame. * when an async function returns, early return does a suspend (in IrInstructionReturnBegin) before copying the error return trace data, result, and running the defers. After the last defer runs, the frame will no longer be accessed. * proper acquire/release atomic ordering attributes in async functions.

7 files changed, 491 insertions(+), 323 deletions(-)

BRANCH_TODO+3
...@@ -33,3 +33,6 @@...@@ -33,3 +33,6 @@
33 - anyframe, anyframe->T33 - anyframe, anyframe->T
34 * safety for double await34 * safety for double await
35 * call graph analysis to have fewer stack trace frames35 * call graph analysis to have fewer stack trace frames
36 * grep for "coroutine" and "coro" and replace all that nomenclature with "async functions"
37 * when there are multiple calls to async functions in a function, reuse the same frame buffer, so that the
38 needed bytes is equal to the largest callee's frame
src/all_types.hpp+23-4
...@@ -1557,6 +1557,7 @@ enum PanicMsgId {...@@ -1557,6 +1557,7 @@ enum PanicMsgId {
1557 PanicMsgIdBadReturn,1557 PanicMsgIdBadReturn,
1558 PanicMsgIdResumedAnAwaitingFn,1558 PanicMsgIdResumedAnAwaitingFn,
1559 PanicMsgIdFrameTooSmall,1559 PanicMsgIdFrameTooSmall,
1560 PanicMsgIdResumedFnPendingAwait,
15601561
1561 PanicMsgIdCount,1562 PanicMsgIdCount,
1562};1563};
...@@ -1717,10 +1718,12 @@ struct CodeGen {...@@ -1717,10 +1718,12 @@ struct CodeGen {
1717 LLVMTargetMachineRef target_machine;1718 LLVMTargetMachineRef target_machine;
1718 ZigLLVMDIFile *dummy_di_file;1719 ZigLLVMDIFile *dummy_di_file;
1719 LLVMValueRef cur_ret_ptr;1720 LLVMValueRef cur_ret_ptr;
1721 LLVMValueRef cur_ret_ptr_ptr;
1720 LLVMValueRef cur_fn_val;1722 LLVMValueRef cur_fn_val;
1721 LLVMValueRef cur_async_switch_instr;1723 LLVMValueRef cur_async_switch_instr;
1722 LLVMValueRef cur_async_resume_index_ptr;1724 LLVMValueRef cur_async_resume_index_ptr;
1723 LLVMValueRef cur_async_awaiter_ptr;1725 LLVMValueRef cur_async_awaiter_ptr;
1726 LLVMValueRef cur_async_prev_val;
1724 LLVMBasicBlockRef cur_preamble_llvm_block;1727 LLVMBasicBlockRef cur_preamble_llvm_block;
1725 size_t cur_resume_block_count;1728 size_t cur_resume_block_count;
1726 LLVMValueRef cur_err_ret_trace_val_arg;1729 LLVMValueRef cur_err_ret_trace_val_arg;
...@@ -2223,6 +2226,7 @@ enum IrInstructionId {...@@ -2223,6 +2226,7 @@ enum IrInstructionId {
2223 IrInstructionIdCallGen,2226 IrInstructionIdCallGen,
2224 IrInstructionIdConst,2227 IrInstructionIdConst,
2225 IrInstructionIdReturn,2228 IrInstructionIdReturn,
2229 IrInstructionIdReturnBegin,
2226 IrInstructionIdCast,2230 IrInstructionIdCast,
2227 IrInstructionIdResizeSlice,2231 IrInstructionIdResizeSlice,
2228 IrInstructionIdContainerInitList,2232 IrInstructionIdContainerInitList,
...@@ -2326,7 +2330,6 @@ enum IrInstructionId {...@@ -2326,7 +2330,6 @@ enum IrInstructionId {
2326 IrInstructionIdImplicitCast,2330 IrInstructionIdImplicitCast,
2327 IrInstructionIdResolveResult,2331 IrInstructionIdResolveResult,
2328 IrInstructionIdResetResult,2332 IrInstructionIdResetResult,
2329 IrInstructionIdResultPtr,
2330 IrInstructionIdOpaqueType,2333 IrInstructionIdOpaqueType,
2331 IrInstructionIdSetAlignStack,2334 IrInstructionIdSetAlignStack,
2332 IrInstructionIdArgType,2335 IrInstructionIdArgType,
...@@ -2355,7 +2358,8 @@ enum IrInstructionId {...@@ -2355,7 +2358,8 @@ enum IrInstructionId {
2355 IrInstructionIdUnionInitNamedField,2358 IrInstructionIdUnionInitNamedField,
2356 IrInstructionIdSuspendBegin,2359 IrInstructionIdSuspendBegin,
2357 IrInstructionIdSuspendFinish,2360 IrInstructionIdSuspendFinish,
2358 IrInstructionIdAwait,2361 IrInstructionIdAwaitSrc,
2362 IrInstructionIdAwaitGen,
2359 IrInstructionIdCoroResume,2363 IrInstructionIdCoroResume,
2360};2364};
23612365
...@@ -2630,7 +2634,13 @@ struct IrInstructionConst {...@@ -2630,7 +2634,13 @@ struct IrInstructionConst {
2630struct IrInstructionReturn {2634struct IrInstructionReturn {
2631 IrInstruction base;2635 IrInstruction base;
26322636
2633 IrInstruction *value;2637 IrInstruction *operand;
2638};
2639
2640struct IrInstructionReturnBegin {
2641 IrInstruction base;
2642
2643 IrInstruction *operand;
2634};2644};
26352645
2636enum CastOp {2646enum CastOp {
...@@ -3136,6 +3146,7 @@ struct IrInstructionTestErrSrc {...@@ -3136,6 +3146,7 @@ struct IrInstructionTestErrSrc {
3136 IrInstruction base;3146 IrInstruction base;
31373147
3138 bool resolve_err_set;3148 bool resolve_err_set;
3149 bool base_ptr_is_payload;
3139 IrInstruction *base_ptr;3150 IrInstruction *base_ptr;
3140};3151};
31413152
...@@ -3603,10 +3614,18 @@ struct IrInstructionSuspendFinish {...@@ -3603,10 +3614,18 @@ struct IrInstructionSuspendFinish {
3603 IrInstructionSuspendBegin *begin;3614 IrInstructionSuspendBegin *begin;
3604};3615};
36053616
3606struct IrInstructionAwait {3617struct IrInstructionAwaitSrc {
3607 IrInstruction base;3618 IrInstruction base;
36083619
3609 IrInstruction *frame;3620 IrInstruction *frame;
3621 ResultLoc *result_loc;
3622};
3623
3624struct IrInstructionAwaitGen {
3625 IrInstruction base;
3626
3627 IrInstruction *frame;
3628 IrInstruction *result_loc;
3610};3629};
36113630
3612struct IrInstructionCoroResume {3631struct IrInstructionCoroResume {
src/analyze.cpp+28-23
...@@ -3848,6 +3848,13 @@ static void analyze_fn_async(CodeGen *g, ZigFn *fn) {...@@ -3848,6 +3848,13 @@ static void analyze_fn_async(CodeGen *g, ZigFn *fn) {
38483848
3849 if (callee->type_entry->data.fn.fn_type_id.cc != CallingConventionUnspecified)3849 if (callee->type_entry->data.fn.fn_type_id.cc != CallingConventionUnspecified)
3850 continue;3850 continue;
3851 if (callee->anal_state == FnAnalStateReady) {
3852 analyze_fn_body(g, callee);
3853 if (callee->anal_state == FnAnalStateInvalid) {
3854 fn->anal_state = FnAnalStateInvalid;
3855 return;
3856 }
3857 }
3851 assert(callee->anal_state == FnAnalStateComplete);3858 assert(callee->anal_state == FnAnalStateComplete);
3852 analyze_fn_async(g, callee);3859 analyze_fn_async(g, callee);
3853 if (callee->anal_state == FnAnalStateInvalid) {3860 if (callee->anal_state == FnAnalStateInvalid) {
...@@ -5224,20 +5231,18 @@ static Error resolve_coro_frame(CodeGen *g, ZigType *frame_type) {...@@ -5224,20 +5231,18 @@ static Error resolve_coro_frame(CodeGen *g, ZigType *frame_type) {
52245231
5225 FnTypeId *fn_type_id = &fn_type->data.fn.fn_type_id;5232 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);5233 ZigType *ptr_return_type = get_pointer_to_type(g, fn_type_id->return_type, false);
5227 field_names.append("@ptr_result");5234 field_names.append("@result_ptr_callee");
5235 field_types.append(ptr_return_type);
5236
5237 field_names.append("@result_ptr_awaiter");
5228 field_types.append(ptr_return_type);5238 field_types.append(ptr_return_type);
52295239
5230 field_names.append("@result");5240 field_names.append("@result");
5231 field_types.append(fn_type_id->return_type);5241 field_types.append(fn_type_id->return_type);
52325242
5233 if (codegen_fn_has_err_ret_tracing_arg(g, fn_type_id->return_type)) {5243 if (codegen_fn_has_err_ret_tracing_arg(g, fn_type_id->return_type)) {
5234 (void)get_ptr_to_stack_trace_type(g); // populate g->stack_trace_type5244 field_names.append("@ptr_stack_trace");
52355245 field_types.append(get_ptr_to_stack_trace_type(g));
5236 field_names.append("@stack_trace");
5237 field_types.append(g->stack_trace_type);
5238
5239 field_names.append("@instruction_addresses");
5240 field_types.append(get_array_type(g, g->builtin_types.entry_usize, stack_trace_ptr_count));
5241 }5246 }
52425247
5243 for (size_t arg_i = 0; arg_i < fn_type_id->param_count; arg_i += 1) {5248 for (size_t arg_i = 0; arg_i < fn_type_id->param_count; arg_i += 1) {
...@@ -5255,7 +5260,7 @@ static Error resolve_coro_frame(CodeGen *g, ZigType *frame_type) {...@@ -5255,7 +5260,7 @@ static Error resolve_coro_frame(CodeGen *g, ZigType *frame_type) {
5255 field_types.append(param_type);5260 field_types.append(param_type);
5256 }5261 }
52575262
5258 if (codegen_fn_has_err_ret_tracing_stack(g, fn)) {5263 if (codegen_fn_has_err_ret_tracing_stack(g, fn, true)) {
5259 (void)get_ptr_to_stack_trace_type(g); // populate g->stack_trace_type5264 (void)get_ptr_to_stack_trace_type(g); // populate g->stack_trace_type
52605265
5261 field_names.append("@stack_trace");5266 field_names.append("@stack_trace");
...@@ -7570,11 +7575,11 @@ static void resolve_llvm_types_any_frame(CodeGen *g, ZigType *any_frame_type, Re...@@ -7570,11 +7575,11 @@ static void resolve_llvm_types_any_frame(CodeGen *g, ZigType *any_frame_type, Re
75707575
7571 bool have_result_type = result_type != nullptr && type_has_bits(result_type);7576 bool have_result_type = result_type != nullptr && type_has_bits(result_type);
7572 if (have_result_type) {7577 if (have_result_type) {
7573 field_types.append(get_llvm_type(g, ptr_result_type)); // ptr_result7578 field_types.append(get_llvm_type(g, ptr_result_type)); // result_ptr_callee
7579 field_types.append(get_llvm_type(g, ptr_result_type)); // result_ptr_awaiter
7574 field_types.append(get_llvm_type(g, result_type)); // result7580 field_types.append(get_llvm_type(g, result_type)); // result
7575 if (codegen_fn_has_err_ret_tracing_arg(g, result_type)) {7581 if (codegen_fn_has_err_ret_tracing_arg(g, result_type)) {
7576 field_types.append(get_llvm_type(g, g->stack_trace_type)); // stack_trace7582 field_types.append(get_llvm_type(g, get_ptr_to_stack_trace_type(g))); // ptr_stack_trace
7577 field_types.append(get_llvm_type(g, get_array_type(g, g->builtin_types.entry_usize, stack_trace_ptr_count))); // instruction_addresses
7578 }7583 }
7579 }7584 }
7580 LLVMStructSetBody(frame_header_type, field_types.items, field_types.length, false);7585 LLVMStructSetBody(frame_header_type, field_types.items, field_types.length, false);
...@@ -7607,7 +7612,15 @@ static void resolve_llvm_types_any_frame(CodeGen *g, ZigType *any_frame_type, Re...@@ -7607,7 +7612,15 @@ static void resolve_llvm_types_any_frame(CodeGen *g, ZigType *any_frame_type, Re
7607 if (have_result_type) {7612 if (have_result_type) {
7608 di_element_types.append(7613 di_element_types.append(
7609 ZigLLVMCreateDebugMemberType(g->dbuilder,7614 ZigLLVMCreateDebugMemberType(g->dbuilder,
7610 ZigLLVMTypeToScope(any_frame_type->llvm_di_type), "ptr_result",7615 ZigLLVMTypeToScope(any_frame_type->llvm_di_type), "result_ptr_callee",
7616 di_file, line,
7617 8*LLVMABISizeOfType(g->target_data_ref, field_types.at(di_element_types.length)),
7618 8*LLVMABIAlignmentOfType(g->target_data_ref, field_types.at(di_element_types.length)),
7619 8*LLVMOffsetOfElement(g->target_data_ref, frame_header_type, di_element_types.length),
7620 ZigLLVM_DIFlags_Zero, get_llvm_di_type(g, ptr_result_type)));
7621 di_element_types.append(
7622 ZigLLVMCreateDebugMemberType(g->dbuilder,
7623 ZigLLVMTypeToScope(any_frame_type->llvm_di_type), "result_ptr_awaiter",
7611 di_file, line,7624 di_file, line,
7612 8*LLVMABISizeOfType(g->target_data_ref, field_types.at(di_element_types.length)),7625 8*LLVMABISizeOfType(g->target_data_ref, field_types.at(di_element_types.length)),
7613 8*LLVMABIAlignmentOfType(g->target_data_ref, field_types.at(di_element_types.length)),7626 8*LLVMABIAlignmentOfType(g->target_data_ref, field_types.at(di_element_types.length)),
...@@ -7625,20 +7638,12 @@ static void resolve_llvm_types_any_frame(CodeGen *g, ZigType *any_frame_type, Re...@@ -7625,20 +7638,12 @@ static void resolve_llvm_types_any_frame(CodeGen *g, ZigType *any_frame_type, Re
7625 if (codegen_fn_has_err_ret_tracing_arg(g, result_type)) {7638 if (codegen_fn_has_err_ret_tracing_arg(g, result_type)) {
7626 di_element_types.append(7639 di_element_types.append(
7627 ZigLLVMCreateDebugMemberType(g->dbuilder,7640 ZigLLVMCreateDebugMemberType(g->dbuilder,
7628 ZigLLVMTypeToScope(any_frame_type->llvm_di_type), "stack_trace",7641 ZigLLVMTypeToScope(any_frame_type->llvm_di_type), "ptr_stack_trace",
7629 di_file, line,
7630 8*LLVMABISizeOfType(g->target_data_ref, field_types.at(di_element_types.length)),
7631 8*LLVMABIAlignmentOfType(g->target_data_ref, field_types.at(di_element_types.length)),
7632 8*LLVMOffsetOfElement(g->target_data_ref, frame_header_type, di_element_types.length),
7633 ZigLLVM_DIFlags_Zero, get_llvm_di_type(g, g->stack_trace_type)));
7634 di_element_types.append(
7635 ZigLLVMCreateDebugMemberType(g->dbuilder,
7636 ZigLLVMTypeToScope(any_frame_type->llvm_di_type), "instruction_addresses",
7637 di_file, line,7642 di_file, line,
7638 8*LLVMABISizeOfType(g->target_data_ref, field_types.at(di_element_types.length)),7643 8*LLVMABISizeOfType(g->target_data_ref, field_types.at(di_element_types.length)),
7639 8*LLVMABIAlignmentOfType(g->target_data_ref, field_types.at(di_element_types.length)),7644 8*LLVMABIAlignmentOfType(g->target_data_ref, field_types.at(di_element_types.length)),
7640 8*LLVMOffsetOfElement(g->target_data_ref, frame_header_type, di_element_types.length),7645 8*LLVMOffsetOfElement(g->target_data_ref, frame_header_type, di_element_types.length),
7641 ZigLLVM_DIFlags_Zero, get_llvm_di_type(g, get_array_type(g, g->builtin_types.entry_usize, stack_trace_ptr_count))));7646 ZigLLVM_DIFlags_Zero, get_llvm_di_type(g, get_ptr_to_stack_trace_type(g))));
7642 }7647 }
7643 };7648 };
76447649
src/codegen.cpp+270-171
...@@ -24,6 +24,14 @@...@@ -24,6 +24,14 @@
24#include <stdio.h>24#include <stdio.h>
25#include <errno.h>25#include <errno.h>
2626
27enum ResumeId {
28 ResumeIdManual,
29 ResumeIdReturn,
30 ResumeIdCall,
31
32 ResumeIdAwaitEarlyReturn // must be last
33};
34
27static void init_darwin_native(CodeGen *g) {35static void init_darwin_native(CodeGen *g) {
28 char *osx_target = getenv("MACOSX_DEPLOYMENT_TARGET");36 char *osx_target = getenv("MACOSX_DEPLOYMENT_TARGET");
29 char *ios_target = getenv("IPHONEOS_DEPLOYMENT_TARGET");37 char *ios_target = getenv("IPHONEOS_DEPLOYMENT_TARGET");
...@@ -298,25 +306,25 @@ static LLVMLinkage to_llvm_linkage(GlobalLinkageId id) {...@@ -298,25 +306,25 @@ static LLVMLinkage to_llvm_linkage(GlobalLinkageId id) {
298}306}
299307
300// label (grep this): [coro_frame_struct_layout]308// label (grep this): [coro_frame_struct_layout]
301static uint32_t frame_index_trace_arg(CodeGen *g, FnTypeId *fn_type_id) {309static uint32_t frame_index_trace_arg(CodeGen *g, ZigType *return_type) {
302 // [0] *ReturnType310 // [0] *ReturnType (callee's)
303 // [1] ReturnType311 // [1] *ReturnType (awaiter's)
304 uint32_t return_field_count = type_has_bits(fn_type_id->return_type) ? 2 : 0;312 // [2] ReturnType
313 uint32_t return_field_count = type_has_bits(return_type) ? 3 : 0;
305 return coro_ret_start + return_field_count;314 return coro_ret_start + return_field_count;
306}315}
307316
308// label (grep this): [coro_frame_struct_layout]317// label (grep this): [coro_frame_struct_layout]
309static uint32_t frame_index_arg(CodeGen *g, FnTypeId *fn_type_id) {318static uint32_t frame_index_arg(CodeGen *g, ZigType *return_type) {
310 bool have_stack_trace = codegen_fn_has_err_ret_tracing_arg(g, fn_type_id->return_type);319 bool have_stack_trace = codegen_fn_has_err_ret_tracing_arg(g, return_type);
311 // [0] StackTrace320 // [0] *StackTrace
312 // [1] [stack_trace_ptr_count]usize321 uint32_t trace_field_count = have_stack_trace ? 1 : 0;
313 uint32_t trace_field_count = have_stack_trace ? 2 : 0;322 return frame_index_trace_arg(g, return_type) + trace_field_count;
314 return frame_index_trace_arg(g, fn_type_id) + trace_field_count;
315}323}
316324
317// label (grep this): [coro_frame_struct_layout]325// label (grep this): [coro_frame_struct_layout]
318static uint32_t frame_index_trace_stack(CodeGen *g, FnTypeId *fn_type_id) {326static uint32_t frame_index_trace_stack(CodeGen *g, FnTypeId *fn_type_id) {
319 uint32_t result = frame_index_arg(g, fn_type_id);327 uint32_t result = frame_index_arg(g, fn_type_id->return_type);
320 for (size_t i = 0; i < fn_type_id->param_count; i += 1) {328 for (size_t i = 0; i < fn_type_id->param_count; i += 1) {
321 if (type_has_bits(fn_type_id->param_info->type)) {329 if (type_has_bits(fn_type_id->param_info->type)) {
322 result += 1;330 result += 1;
...@@ -901,7 +909,7 @@ static Buf *panic_msg_buf(PanicMsgId msg_id) {...@@ -901,7 +909,7 @@ static Buf *panic_msg_buf(PanicMsgId msg_id) {
901 case PanicMsgIdPtrCastNull:909 case PanicMsgIdPtrCastNull:
902 return buf_create_from_str("cast causes pointer to be null");910 return buf_create_from_str("cast causes pointer to be null");
903 case PanicMsgIdBadResume:911 case PanicMsgIdBadResume:
904 return buf_create_from_str("invalid resume of async function");912 return buf_create_from_str("resumed an async function which already returned");
905 case PanicMsgIdBadAwait:913 case PanicMsgIdBadAwait:
906 return buf_create_from_str("async function awaited twice");914 return buf_create_from_str("async function awaited twice");
907 case PanicMsgIdBadReturn:915 case PanicMsgIdBadReturn:
...@@ -910,6 +918,8 @@ static Buf *panic_msg_buf(PanicMsgId msg_id) {...@@ -910,6 +918,8 @@ static Buf *panic_msg_buf(PanicMsgId msg_id) {
910 return buf_create_from_str("awaiting function resumed");918 return buf_create_from_str("awaiting function resumed");
911 case PanicMsgIdFrameTooSmall:919 case PanicMsgIdFrameTooSmall:
912 return buf_create_from_str("frame too small");920 return buf_create_from_str("frame too small");
921 case PanicMsgIdResumedFnPendingAwait:
922 return buf_create_from_str("resumed an async function which can only be awaited");
913 }923 }
914 zig_unreachable();924 zig_unreachable();
915}925}
...@@ -1301,7 +1311,14 @@ static LLVMValueRef get_cur_err_ret_trace_val(CodeGen *g, Scope *scope) {...@@ -1301,7 +1311,14 @@ static LLVMValueRef get_cur_err_ret_trace_val(CodeGen *g, Scope *scope) {
1301 if (g->cur_err_ret_trace_val_stack != nullptr) {1311 if (g->cur_err_ret_trace_val_stack != nullptr) {
1302 return g->cur_err_ret_trace_val_stack;1312 return g->cur_err_ret_trace_val_stack;
1303 }1313 }
1304 return g->cur_err_ret_trace_val_arg;1314 if (g->cur_err_ret_trace_val_arg != nullptr) {
1315 if (fn_is_async(g->cur_fn)) {
1316 return LLVMBuildLoad(g->builder, g->cur_err_ret_trace_val_arg, "");
1317 } else {
1318 return g->cur_err_ret_trace_val_arg;
1319 }
1320 }
1321 return nullptr;
1305}1322}
13061323
1307static void gen_safety_crash_for_err(CodeGen *g, LLVMValueRef err_val, Scope *scope) {1324static void gen_safety_crash_for_err(CodeGen *g, LLVMValueRef err_val, Scope *scope) {
...@@ -2023,99 +2040,191 @@ static LLVMValueRef ir_render_save_err_ret_addr(CodeGen *g, IrExecutable *execut...@@ -2023,99 +2040,191 @@ static LLVMValueRef ir_render_save_err_ret_addr(CodeGen *g, IrExecutable *execut
2023 return call_instruction;2040 return call_instruction;
2024}2041}
20252042
2026static LLVMValueRef ir_render_return(CodeGen *g, IrExecutable *executable,2043static void gen_assert_resume_id(CodeGen *g, IrInstruction *source_instr, ResumeId resume_id, PanicMsgId msg_id,
2027 IrInstructionReturn *return_instruction)2044 LLVMBasicBlockRef end_bb)
2045{
2046 LLVMTypeRef usize_type_ref = g->builtin_types.entry_usize->llvm_type;
2047 LLVMBasicBlockRef bad_resume_block = LLVMAppendBasicBlock(g->cur_fn_val, "BadResume");
2048 if (end_bb == nullptr) end_bb = LLVMAppendBasicBlock(g->cur_fn_val, "OkResume");
2049 LLVMValueRef ok_bit;
2050 if (resume_id == ResumeIdAwaitEarlyReturn) {
2051 LLVMValueRef last_value = LLVMBuildSub(g->builder, LLVMConstAllOnes(usize_type_ref),
2052 LLVMConstInt(usize_type_ref, ResumeIdAwaitEarlyReturn, false), "");
2053 ok_bit = LLVMBuildICmp(g->builder, LLVMIntULT, LLVMGetParam(g->cur_fn_val, 1), last_value, "");
2054 } else {
2055 LLVMValueRef expected_value = LLVMBuildSub(g->builder, LLVMConstAllOnes(usize_type_ref),
2056 LLVMConstInt(usize_type_ref, resume_id, false), "");
2057 ok_bit = LLVMBuildICmp(g->builder, LLVMIntEQ, LLVMGetParam(g->cur_fn_val, 1), expected_value, "");
2058 }
2059 LLVMBuildCondBr(g->builder, ok_bit, end_bb, bad_resume_block);
2060
2061 LLVMPositionBuilderAtEnd(g->builder, bad_resume_block);
2062 gen_assertion(g, msg_id, source_instr);
2063
2064 LLVMPositionBuilderAtEnd(g->builder, end_bb);
2065}
2066
2067static LLVMValueRef gen_resume(CodeGen *g, LLVMValueRef fn_val, LLVMValueRef target_frame_ptr,
2068 ResumeId resume_id, LLVMValueRef arg_val)
2069{
2070 LLVMTypeRef usize_type_ref = g->builtin_types.entry_usize->llvm_type;
2071 if (fn_val == nullptr) {
2072 if (g->anyframe_fn_type == nullptr) {
2073 (void)get_llvm_type(g, get_any_frame_type(g, nullptr));
2074 }
2075 LLVMValueRef fn_ptr_ptr = LLVMBuildStructGEP(g->builder, target_frame_ptr, coro_fn_ptr_index, "");
2076 fn_val = LLVMBuildLoad(g->builder, fn_ptr_ptr, "");
2077 }
2078 if (arg_val == nullptr) {
2079 arg_val = LLVMBuildSub(g->builder, LLVMConstAllOnes(usize_type_ref),
2080 LLVMConstInt(usize_type_ref, resume_id, false), "");
2081 } else {
2082 assert(resume_id == ResumeIdAwaitEarlyReturn);
2083 }
2084 LLVMValueRef args[] = {target_frame_ptr, arg_val};
2085 return ZigLLVMBuildCall(g->builder, fn_val, args, 2, LLVMFastCallConv, ZigLLVM_FnInlineAuto, "");
2086}
2087
2088static LLVMValueRef ir_render_return_begin(CodeGen *g, IrExecutable *executable,
2089 IrInstructionReturnBegin *instruction)
2028{2090{
2091 if (!fn_is_async(g->cur_fn)) return nullptr;
2092
2093 LLVMTypeRef usize_type_ref = g->builtin_types.entry_usize->llvm_type;
2094
2095 bool ret_type_has_bits = instruction->operand != nullptr &&
2096 type_has_bits(instruction->operand->value.type);
2097 ZigType *ret_type = ret_type_has_bits ? instruction->operand->value.type : nullptr;
2098 if (ret_type_has_bits && !handle_is_ptr(ret_type)) {
2099 // It's a scalar, so it didn't get written to the result ptr. Do that before the atomic rmw.
2100 LLVMValueRef result_ptr = LLVMBuildLoad(g->builder, g->cur_ret_ptr_ptr, "");
2101 LLVMBuildStore(g->builder, ir_llvm_value(g, instruction->operand), result_ptr);
2102 }
2103
2104 // Prepare to be suspended. We might end up not having to suspend though.
2105 LLVMBasicBlockRef resume_bb = LLVMAppendBasicBlock(g->cur_fn_val, "ReturnResume");
2106 size_t new_block_index = g->cur_resume_block_count;
2107 g->cur_resume_block_count += 1;
2108 LLVMValueRef new_block_index_val = LLVMConstInt(usize_type_ref, new_block_index, false);
2109 LLVMAddCase(g->cur_async_switch_instr, new_block_index_val, resume_bb);
2110 LLVMBuildStore(g->builder, new_block_index_val, g->cur_async_resume_index_ptr);
2111
2112 LLVMValueRef zero = LLVMConstNull(usize_type_ref);
2113 LLVMValueRef all_ones = LLVMConstAllOnes(usize_type_ref);
2114 LLVMValueRef prev_val = LLVMBuildAtomicRMW(g->builder, LLVMAtomicRMWBinOpXchg, g->cur_async_awaiter_ptr,
2115 all_ones, LLVMAtomicOrderingAcquire, g->is_single_threaded);
2116
2117 LLVMBasicBlockRef bad_return_block = LLVMAppendBasicBlock(g->cur_fn_val, "BadReturn");
2118 LLVMBasicBlockRef early_return_block = LLVMAppendBasicBlock(g->cur_fn_val, "EarlyReturn");
2119 LLVMBasicBlockRef resume_them_block = LLVMAppendBasicBlock(g->cur_fn_val, "ResumeThem");
2120
2121 LLVMValueRef switch_instr = LLVMBuildSwitch(g->builder, prev_val, resume_them_block, 2);
2122 LLVMBasicBlockRef switch_bb = LLVMGetInsertBlock(g->builder);
2123
2124 LLVMAddCase(switch_instr, zero, early_return_block);
2125 LLVMAddCase(switch_instr, all_ones, bad_return_block);
2126
2127 // Something has gone horribly wrong, and this is an invalid second return.
2128 LLVMPositionBuilderAtEnd(g->builder, bad_return_block);
2129 gen_assertion(g, PanicMsgIdBadReturn, &instruction->base);
2130
2131 // The caller has not done an await yet. So we suspend at the return instruction, until a
2132 // cancel or await is performed.
2133 LLVMPositionBuilderAtEnd(g->builder, early_return_block);
2134 LLVMBuildRetVoid(g->builder);
2135
2136 // Add a safety check for when getting resumed by the awaiter.
2137 LLVMPositionBuilderAtEnd(g->builder, resume_bb);
2138 LLVMBasicBlockRef after_resume_block = LLVMGetInsertBlock(g->builder);
2139 gen_assert_resume_id(g, &instruction->base, ResumeIdAwaitEarlyReturn, PanicMsgIdResumedFnPendingAwait,
2140 resume_them_block);
2141
2142 // We need to resume the caller by tail calling them.
2143 // That will happen when rendering IrInstructionReturn after running the defers/errdefers.
2144 // We either got here from Entry (function call) or from the switch above
2145 g->cur_async_prev_val = LLVMBuildPhi(g->builder, usize_type_ref, "");
2146 LLVMValueRef incoming_values[] = { LLVMGetParam(g->cur_fn_val, 1), prev_val };
2147 LLVMBasicBlockRef incoming_blocks[] = { after_resume_block, switch_bb };
2148 LLVMAddIncoming(g->cur_async_prev_val, incoming_values, incoming_blocks, 2);
2149
2150 return nullptr;
2151}
2152
2153static LLVMValueRef ir_render_return(CodeGen *g, IrExecutable *executable, IrInstructionReturn *instruction) {
2029 if (fn_is_async(g->cur_fn)) {2154 if (fn_is_async(g->cur_fn)) {
2030 LLVMTypeRef usize_type_ref = g->builtin_types.entry_usize->llvm_type;2155 LLVMTypeRef usize_type_ref = g->builtin_types.entry_usize->llvm_type;
2031 bool ret_type_has_bits = return_instruction->value != nullptr &&2156 bool ret_type_has_bits = instruction->operand != nullptr &&
2032 type_has_bits(return_instruction->value->value.type);2157 type_has_bits(instruction->operand->value.type);
2033 ZigType *ret_type = ret_type_has_bits ? return_instruction->value->value.type : nullptr;2158 ZigType *ret_type = ret_type_has_bits ? instruction->operand->value.type : nullptr;
20342159
2035 if (ir_want_runtime_safety(g, &return_instruction->base)) {2160 if (ir_want_runtime_safety(g, &instruction->base)) {
2036 LLVMValueRef new_resume_index = LLVMConstAllOnes(usize_type_ref);2161 LLVMValueRef new_resume_index = LLVMConstAllOnes(usize_type_ref);
2037 LLVMBuildStore(g->builder, new_resume_index, g->cur_async_resume_index_ptr);2162 LLVMBuildStore(g->builder, new_resume_index, g->cur_async_resume_index_ptr);
2038 }2163 }
20392164
2040 LLVMValueRef result_ptr_as_usize;
2041 if (ret_type_has_bits) {2165 if (ret_type_has_bits) {
2042 LLVMValueRef result_ptr_ptr = LLVMBuildStructGEP(g->builder, g->cur_ret_ptr, coro_ret_start, "");2166 // If the awaiter result pointer is non-null, we need to copy the result to there.
2043 LLVMValueRef result_ptr = LLVMBuildLoad(g->builder, result_ptr_ptr, "");2167 LLVMBasicBlockRef copy_block = LLVMAppendBasicBlock(g->cur_fn_val, "CopyResult");
2044 if (!handle_is_ptr(ret_type)) {2168 LLVMBasicBlockRef copy_end_block = LLVMAppendBasicBlock(g->cur_fn_val, "CopyResultEnd");
2045 // It's a scalar, so it didn't get written to the result ptr. Do that now.2169 LLVMValueRef awaiter_ret_ptr_ptr = LLVMBuildStructGEP(g->builder, g->cur_ret_ptr, coro_ret_start + 1, "");
2046 LLVMBuildStore(g->builder, ir_llvm_value(g, return_instruction->value), result_ptr);2170 LLVMValueRef awaiter_ret_ptr = LLVMBuildLoad(g->builder, awaiter_ret_ptr_ptr, "");
2047 }2171 LLVMValueRef zero_ptr = LLVMConstNull(LLVMTypeOf(awaiter_ret_ptr));
2048 result_ptr_as_usize = LLVMBuildPtrToInt(g->builder, result_ptr, usize_type_ref, "");2172 LLVMValueRef need_copy_bit = LLVMBuildICmp(g->builder, LLVMIntNE, awaiter_ret_ptr, zero_ptr, "");
2049 } else {2173 LLVMBuildCondBr(g->builder, need_copy_bit, copy_block, copy_end_block);
2050 // For debug safety, this value has to be anything other than all 1's, which signals2174
2051 // that it is being resumed. 0 is a bad choice since null pointers are special.2175 LLVMPositionBuilderAtEnd(g->builder, copy_block);
2052 result_ptr_as_usize = ir_want_runtime_safety(g, &return_instruction->base) ?2176 LLVMValueRef ret_ptr = LLVMBuildLoad(g->builder, g->cur_ret_ptr_ptr, "");
2053 LLVMConstInt(usize_type_ref, 1, false) : LLVMGetUndef(usize_type_ref);2177 LLVMTypeRef ptr_u8 = LLVMPointerType(LLVMInt8Type(), 0);
2178 LLVMValueRef dest_ptr_casted = LLVMBuildBitCast(g->builder, awaiter_ret_ptr, ptr_u8, "");
2179 LLVMValueRef src_ptr_casted = LLVMBuildBitCast(g->builder, ret_ptr, ptr_u8, "");
2180 bool is_volatile = false;
2181 uint32_t abi_align = get_abi_alignment(g, ret_type);
2182 LLVMValueRef byte_count_val = LLVMConstInt(usize_type_ref, type_size(g, ret_type), false);
2183 ZigLLVMBuildMemCpy(g->builder,
2184 dest_ptr_casted, abi_align,
2185 src_ptr_casted, abi_align, byte_count_val, is_volatile);
2186 LLVMBuildBr(g->builder, copy_end_block);
2187
2188 LLVMPositionBuilderAtEnd(g->builder, copy_end_block);
2054 }2189 }
2055 LLVMValueRef zero = LLVMConstNull(usize_type_ref);
2056 LLVMValueRef all_ones = LLVMConstAllOnes(usize_type_ref);
2057 LLVMValueRef prev_val = LLVMBuildAtomicRMW(g->builder, LLVMAtomicRMWBinOpXchg, g->cur_async_awaiter_ptr,
2058 all_ones, LLVMAtomicOrderingMonotonic, g->is_single_threaded);
2059
2060 LLVMBasicBlockRef bad_return_block = LLVMAppendBasicBlock(g->cur_fn_val, "BadReturn");
2061 LLVMBasicBlockRef early_return_block = LLVMAppendBasicBlock(g->cur_fn_val, "EarlyReturn");
2062 LLVMBasicBlockRef resume_them_block = LLVMAppendBasicBlock(g->cur_fn_val, "ResumeThem");
2063
2064 LLVMValueRef switch_instr = LLVMBuildSwitch(g->builder, prev_val, resume_them_block, 2);
2065
2066 LLVMAddCase(switch_instr, zero, early_return_block);
2067 LLVMAddCase(switch_instr, all_ones, bad_return_block);
2068
2069 // Something has gone horribly wrong, and this is an invalid second return.
2070 LLVMPositionBuilderAtEnd(g->builder, bad_return_block);
2071 gen_assertion(g, PanicMsgIdBadReturn, &return_instruction->base);
2072
2073 // The caller will deal with fetching the result - we're done.
2074 LLVMPositionBuilderAtEnd(g->builder, early_return_block);
2075 LLVMBuildRetVoid(g->builder);
20762190
2077 // We need to resume the caller by tail calling them.2191 // We need to resume the caller by tail calling them.
2078 LLVMPositionBuilderAtEnd(g->builder, resume_them_block);
2079 ZigType *any_frame_type = get_any_frame_type(g, ret_type);2192 ZigType *any_frame_type = get_any_frame_type(g, ret_type);
2080 LLVMValueRef their_frame_ptr = LLVMBuildIntToPtr(g->builder, prev_val,2193 LLVMValueRef their_frame_ptr = LLVMBuildIntToPtr(g->builder, g->cur_async_prev_val,
2081 get_llvm_type(g, any_frame_type), "");2194 get_llvm_type(g, any_frame_type), "");
2082 LLVMValueRef fn_ptr_ptr = LLVMBuildStructGEP(g->builder, their_frame_ptr, coro_fn_ptr_index, "");2195 LLVMValueRef call_inst = gen_resume(g, nullptr, their_frame_ptr, ResumeIdReturn, nullptr);
2083 LLVMValueRef awaiter_fn = LLVMBuildLoad(g->builder, fn_ptr_ptr, "");
2084 LLVMValueRef args[] = {their_frame_ptr, result_ptr_as_usize};
2085 LLVMValueRef call_inst = ZigLLVMBuildCall(g->builder, awaiter_fn, args, 2, LLVMFastCallConv,
2086 ZigLLVM_FnInlineAuto, "");
2087 ZigLLVMSetTailCall(call_inst);2196 ZigLLVMSetTailCall(call_inst);
2088 LLVMBuildRetVoid(g->builder);2197 LLVMBuildRetVoid(g->builder);
20892198
2090 return nullptr;2199 return nullptr;
2091 }2200 }
2092 if (want_first_arg_sret(g, &g->cur_fn->type_entry->data.fn.fn_type_id)) {2201 if (want_first_arg_sret(g, &g->cur_fn->type_entry->data.fn.fn_type_id)) {
2093 if (return_instruction->value == nullptr) {2202 if (instruction->operand == nullptr) {
2094 LLVMBuildRetVoid(g->builder);2203 LLVMBuildRetVoid(g->builder);
2095 return nullptr;2204 return nullptr;
2096 }2205 }
2097 assert(g->cur_ret_ptr);2206 assert(g->cur_ret_ptr);
2098 src_assert(return_instruction->value->value.special != ConstValSpecialRuntime,2207 src_assert(instruction->operand->value.special != ConstValSpecialRuntime,
2099 return_instruction->base.source_node);2208 instruction->base.source_node);
2100 LLVMValueRef value = ir_llvm_value(g, return_instruction->value);2209 LLVMValueRef value = ir_llvm_value(g, instruction->operand);
2101 ZigType *return_type = return_instruction->value->value.type;2210 ZigType *return_type = instruction->operand->value.type;
2102 gen_assign_raw(g, g->cur_ret_ptr, get_pointer_to_type(g, return_type, false), value);2211 gen_assign_raw(g, g->cur_ret_ptr, get_pointer_to_type(g, return_type, false), value);
2103 LLVMBuildRetVoid(g->builder);2212 LLVMBuildRetVoid(g->builder);
2104 } else if (g->cur_fn->type_entry->data.fn.fn_type_id.cc != CallingConventionAsync &&2213 } else if (g->cur_fn->type_entry->data.fn.fn_type_id.cc != CallingConventionAsync &&
2105 handle_is_ptr(g->cur_fn->type_entry->data.fn.fn_type_id.return_type))2214 handle_is_ptr(g->cur_fn->type_entry->data.fn.fn_type_id.return_type))
2106 {2215 {
2107 if (return_instruction->value == nullptr) {2216 if (instruction->operand == nullptr) {
2108 LLVMValueRef by_val_value = gen_load_untyped(g, g->cur_ret_ptr, 0, false, "");2217 LLVMValueRef by_val_value = gen_load_untyped(g, g->cur_ret_ptr, 0, false, "");
2109 LLVMBuildRet(g->builder, by_val_value);2218 LLVMBuildRet(g->builder, by_val_value);
2110 } else {2219 } else {
2111 LLVMValueRef value = ir_llvm_value(g, return_instruction->value);2220 LLVMValueRef value = ir_llvm_value(g, instruction->operand);
2112 LLVMValueRef by_val_value = gen_load_untyped(g, value, 0, false, "");2221 LLVMValueRef by_val_value = gen_load_untyped(g, value, 0, false, "");
2113 LLVMBuildRet(g->builder, by_val_value);2222 LLVMBuildRet(g->builder, by_val_value);
2114 }2223 }
2115 } else if (return_instruction->value == nullptr) {2224 } else if (instruction->operand == nullptr) {
2116 LLVMBuildRetVoid(g->builder);2225 LLVMBuildRetVoid(g->builder);
2117 } else {2226 } else {
2118 LLVMValueRef value = ir_llvm_value(g, return_instruction->value);2227 LLVMValueRef value = ir_llvm_value(g, instruction->operand);
2119 LLVMBuildRet(g->builder, value);2228 LLVMBuildRet(g->builder, value);
2120 }2229 }
2121 return nullptr;2230 return nullptr;
...@@ -3417,7 +3526,7 @@ static void set_call_instr_sret(CodeGen *g, LLVMValueRef call_instr) {...@@ -3417,7 +3526,7 @@ static void set_call_instr_sret(CodeGen *g, LLVMValueRef call_instr) {
3417static void render_async_spills(CodeGen *g) {3526static void render_async_spills(CodeGen *g) {
3418 ZigType *fn_type = g->cur_fn->type_entry;3527 ZigType *fn_type = g->cur_fn->type_entry;
3419 ZigType *import = get_scope_import(&g->cur_fn->fndef_scope->base);3528 ZigType *import = get_scope_import(&g->cur_fn->fndef_scope->base);
3420 uint32_t async_var_index = frame_index_arg(g, &fn_type->data.fn.fn_type_id);3529 uint32_t async_var_index = frame_index_arg(g, fn_type->data.fn.fn_type_id.return_type);
3421 for (size_t var_i = 0; var_i < g->cur_fn->variable_list.length; var_i += 1) {3530 for (size_t var_i = 0; var_i < g->cur_fn->variable_list.length; var_i += 1) {
3422 ZigVar *var = g->cur_fn->variable_list.at(var_i);3531 ZigVar *var = g->cur_fn->variable_list.at(var_i);
34233532
...@@ -3450,7 +3559,7 @@ static void render_async_spills(CodeGen *g) {...@@ -3450,7 +3559,7 @@ static void render_async_spills(CodeGen *g) {
3450 }3559 }
3451 }3560 }
3452 // label (grep this): [coro_frame_struct_layout]3561 // label (grep this): [coro_frame_struct_layout]
3453 if (codegen_fn_has_err_ret_tracing_stack(g, g->cur_fn)) {3562 if (codegen_fn_has_err_ret_tracing_stack(g, g->cur_fn, true)) {
3454 async_var_index += 2;3563 async_var_index += 2;
3455 }3564 }
3456 for (size_t alloca_i = 0; alloca_i < g->cur_fn->alloca_gen_list.length; alloca_i += 1) {3565 for (size_t alloca_i = 0; alloca_i < g->cur_fn->alloca_gen_list.length; alloca_i += 1) {
...@@ -3553,7 +3662,7 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr...@@ -3553,7 +3662,7 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr
35533662
3554 if (ret_has_bits) {3663 if (ret_has_bits) {
3555 // Use the result location which is inside the frame if this is an async call.3664 // Use the result location which is inside the frame if this is an async call.
3556 ret_ptr = LLVMBuildStructGEP(g->builder, frame_result_loc, coro_ret_start + 1, "");3665 ret_ptr = LLVMBuildStructGEP(g->builder, frame_result_loc, coro_ret_start + 2, "");
3557 }3666 }
3558 } else {3667 } else {
3559 LLVMValueRef frame_slice_ptr = ir_llvm_value(g, instruction->new_stack);3668 LLVMValueRef frame_slice_ptr = ir_llvm_value(g, instruction->new_stack);
...@@ -3590,17 +3699,26 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr...@@ -3590,17 +3699,26 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr
3590 frame_result_loc = ir_llvm_value(g, instruction->frame_result_loc);3699 frame_result_loc = ir_llvm_value(g, instruction->frame_result_loc);
3591 awaiter_init_val = LLVMBuildPtrToInt(g->builder, g->cur_ret_ptr, usize_type_ref, ""); // caller's own frame pointer3700 awaiter_init_val = LLVMBuildPtrToInt(g->builder, g->cur_ret_ptr, usize_type_ref, ""); // caller's own frame pointer
3592 if (ret_has_bits) {3701 if (ret_has_bits) {
3593 if (result_loc != nullptr) {3702 if (result_loc == nullptr) {
3703 // return type is a scalar, but we still need a pointer to it. Use the async fn frame.
3704 ret_ptr = LLVMBuildStructGEP(g->builder, frame_result_loc, coro_ret_start + 2, "");
3705 } else {
3594 // Use the call instruction's result location.3706 // Use the call instruction's result location.
3595 ret_ptr = result_loc;3707 ret_ptr = result_loc;
3596 } else {
3597 // return type is a scalar, but we still need a pointer to it. Use the async fn frame.
3598 ret_ptr = LLVMBuildStructGEP(g->builder, frame_result_loc, coro_ret_start + 1, "");
3599 }3708 }
3709
3710 // Store a zero in the awaiter's result ptr to indicate we do not need a copy made.
3711 LLVMValueRef awaiter_ret_ptr = LLVMBuildStructGEP(g->builder, frame_result_loc, coro_ret_start + 1, "");
3712 LLVMValueRef zero_ptr = LLVMConstNull(LLVMGetElementType(LLVMTypeOf(awaiter_ret_ptr)));
3713 LLVMBuildStore(g->builder, zero_ptr, awaiter_ret_ptr);
3600 }3714 }
36013715
3602 // even if prefix_arg_err_ret_stack is true, let the async function do its3716 if (prefix_arg_err_ret_stack) {
3603 // error return tracing normally, and then we'll invoke merge_error_return_traces like normal.3717 LLVMValueRef err_ret_trace_ptr_ptr = LLVMBuildStructGEP(g->builder, frame_result_loc,
3718 frame_index_trace_arg(g, src_return_type), "");
3719 LLVMValueRef my_err_ret_trace_val = get_cur_err_ret_trace_val(g, instruction->base.scope);
3720 LLVMBuildStore(g->builder, my_err_ret_trace_val, err_ret_trace_ptr_ptr);
3721 }
3604 }3722 }
3605 if (instruction->is_async || callee_is_async) {3723 if (instruction->is_async || callee_is_async) {
3606 assert(frame_result_loc != nullptr);3724 assert(frame_result_loc != nullptr);
...@@ -3652,7 +3770,7 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr...@@ -3652,7 +3770,7 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr
3652 LLVMValueRef result;3770 LLVMValueRef result;
36533771
3654 if (instruction->is_async || callee_is_async) {3772 if (instruction->is_async || callee_is_async) {
3655 uint32_t arg_start_i = frame_index_arg(g, &fn_type->data.fn.fn_type_id);3773 uint32_t arg_start_i = frame_index_arg(g, fn_type->data.fn.fn_type_id.return_type);
36563774
3657 LLVMValueRef casted_frame;3775 LLVMValueRef casted_frame;
3658 if (instruction->new_stack != nullptr) {3776 if (instruction->new_stack != nullptr) {
...@@ -3678,8 +3796,7 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr...@@ -3678,8 +3796,7 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr
3678 }3796 }
3679 }3797 }
3680 if (instruction->is_async) {3798 if (instruction->is_async) {
3681 LLVMValueRef args[] = {frame_result_loc, LLVMGetUndef(usize_type_ref)};3799 gen_resume(g, fn_val, frame_result_loc, ResumeIdCall, nullptr);
3682 ZigLLVMBuildCall(g->builder, fn_val, args, 2, llvm_cc, fn_inline, "");
3683 if (instruction->new_stack != nullptr) {3800 if (instruction->new_stack != nullptr) {
3684 return frame_result_loc;3801 return frame_result_loc;
3685 }3802 }
...@@ -3694,36 +3811,23 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr...@@ -3694,36 +3811,23 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr
3694 LLVMAddCase(g->cur_async_switch_instr, new_block_index_val, call_bb);3811 LLVMAddCase(g->cur_async_switch_instr, new_block_index_val, call_bb);
36953812
3696 LLVMBuildStore(g->builder, new_block_index_val, g->cur_async_resume_index_ptr);3813 LLVMBuildStore(g->builder, new_block_index_val, g->cur_async_resume_index_ptr);
3697 LLVMValueRef args[] = {frame_result_loc, LLVMGetUndef(usize_type_ref)};3814
3698 LLVMValueRef call_inst = ZigLLVMBuildCall(g->builder, fn_val, args, 2, llvm_cc, fn_inline, "");3815 LLVMValueRef call_inst = gen_resume(g, fn_val, frame_result_loc, ResumeIdCall, nullptr);
3699 ZigLLVMSetTailCall(call_inst);3816 ZigLLVMSetTailCall(call_inst);
3700 LLVMBuildRetVoid(g->builder);3817 LLVMBuildRetVoid(g->builder);
37013818
3702 LLVMPositionBuilderAtEnd(g->builder, call_bb);3819 LLVMPositionBuilderAtEnd(g->builder, call_bb);
3703 if (ir_want_runtime_safety(g, &instruction->base)) {3820 gen_assert_resume_id(g, &instruction->base, ResumeIdReturn, PanicMsgIdResumedAnAwaitingFn, nullptr);
3704 LLVMBasicBlockRef bad_resume_block = LLVMAppendBasicBlock(g->cur_fn_val, "BadResume");
3705 LLVMBasicBlockRef ok_resume_block = LLVMAppendBasicBlock(g->cur_fn_val, "OkResume");
3706 LLVMValueRef arg_val = LLVMGetParam(g->cur_fn_val, 1);
3707 LLVMValueRef all_ones = LLVMConstAllOnes(usize_type_ref);
3708 LLVMValueRef ok_bit = LLVMBuildICmp(g->builder, LLVMIntNE, arg_val, all_ones, "");
3709 LLVMBuildCondBr(g->builder, ok_bit, ok_resume_block, bad_resume_block);
3710
3711 LLVMPositionBuilderAtEnd(g->builder, bad_resume_block);
3712 gen_safety_crash(g, PanicMsgIdResumedAnAwaitingFn);
3713
3714 LLVMPositionBuilderAtEnd(g->builder, ok_resume_block);
3715 }
3716
3717 render_async_var_decls(g, instruction->base.scope);3821 render_async_var_decls(g, instruction->base.scope);
37183822
3719 if (type_has_bits(src_return_type)) {3823 if (!type_has_bits(src_return_type))
3720 LLVMValueRef spilled_result_ptr = LLVMGetParam(g->cur_fn_val, 1);
3721 LLVMValueRef casted_spilled_result_ptr = LLVMBuildIntToPtr(g->builder, spilled_result_ptr,
3722 get_llvm_type(g, ptr_result_type), "");
3723 return get_handle_value(g, casted_spilled_result_ptr, src_return_type, ptr_result_type);
3724 } else {
3725 return nullptr;3824 return nullptr;
3726 }3825
3826 if (result_loc != nullptr)
3827 return get_handle_value(g, result_loc, src_return_type, ptr_result_type);
3828
3829 LLVMValueRef result_ptr = LLVMBuildStructGEP(g->builder, frame_result_loc, coro_ret_start + 2, "");
3830 return LLVMBuildLoad(g->builder, result_ptr, "");
3727 }3831 }
37283832
3729 if (instruction->new_stack == nullptr) {3833 if (instruction->new_stack == nullptr) {
...@@ -5191,8 +5295,9 @@ static LLVMValueRef ir_render_suspend_finish(CodeGen *g, IrExecutable *executabl...@@ -5191,8 +5295,9 @@ static LLVMValueRef ir_render_suspend_finish(CodeGen *g, IrExecutable *executabl
5191 return nullptr;5295 return nullptr;
5192}5296}
51935297
5194static LLVMValueRef ir_render_await(CodeGen *g, IrExecutable *executable, IrInstructionAwait *instruction) {5298static LLVMValueRef ir_render_await(CodeGen *g, IrExecutable *executable, IrInstructionAwaitGen *instruction) {
5195 LLVMTypeRef usize_type_ref = g->builtin_types.entry_usize->llvm_type;5299 LLVMTypeRef usize_type_ref = g->builtin_types.entry_usize->llvm_type;
5300 LLVMValueRef zero = LLVMConstNull(usize_type_ref);
5196 LLVMValueRef target_frame_ptr = ir_llvm_value(g, instruction->frame);5301 LLVMValueRef target_frame_ptr = ir_llvm_value(g, instruction->frame);
5197 ZigType *result_type = instruction->base.value.type;5302 ZigType *result_type = instruction->base.value.type;
5198 ZigType *ptr_result_type = get_pointer_to_type(g, result_type, true);5303 ZigType *ptr_result_type = get_pointer_to_type(g, result_type, true);
...@@ -5208,86 +5313,75 @@ static LLVMValueRef ir_render_await(CodeGen *g, IrExecutable *executable, IrInst...@@ -5208,86 +5313,75 @@ static LLVMValueRef ir_render_await(CodeGen *g, IrExecutable *executable, IrInst
5208 // At this point resuming the function will do the correct thing.5313 // At this point resuming the function will do the correct thing.
5209 // This code is as if it is running inside the suspend block.5314 // This code is as if it is running inside the suspend block.
52105315
5316 // supply the awaiter return pointer
5317 LLVMValueRef result_loc = (instruction->result_loc == nullptr) ?
5318 nullptr : ir_llvm_value(g, instruction->result_loc);
5319 if (type_has_bits(result_type)) {
5320 LLVMValueRef awaiter_ret_ptr_ptr = LLVMBuildStructGEP(g->builder, target_frame_ptr, coro_ret_start + 1, "");
5321 if (result_loc == nullptr) {
5322 // no copy needed
5323 LLVMBuildStore(g->builder, zero, awaiter_ret_ptr_ptr);
5324 } else {
5325 LLVMBuildStore(g->builder, result_loc, awaiter_ret_ptr_ptr);
5326 }
5327 }
5328
5329 // supply the error return trace pointer
5330 LLVMValueRef my_err_ret_trace_val = get_cur_err_ret_trace_val(g, instruction->base.scope);
5331 if (my_err_ret_trace_val != nullptr) {
5332 LLVMValueRef err_ret_trace_ptr_ptr = LLVMBuildStructGEP(g->builder, target_frame_ptr,
5333 frame_index_trace_arg(g, result_type), "");
5334 LLVMBuildStore(g->builder, my_err_ret_trace_val, err_ret_trace_ptr_ptr);
5335 }
5336
5211 // caller's own frame pointer5337 // caller's own frame pointer
5212 LLVMValueRef awaiter_init_val = LLVMBuildPtrToInt(g->builder, g->cur_ret_ptr, usize_type_ref, "");5338 LLVMValueRef awaiter_init_val = LLVMBuildPtrToInt(g->builder, g->cur_ret_ptr, usize_type_ref, "");
5213 LLVMValueRef awaiter_ptr = LLVMBuildStructGEP(g->builder, target_frame_ptr, coro_awaiter_index, "");5339 LLVMValueRef awaiter_ptr = LLVMBuildStructGEP(g->builder, target_frame_ptr, coro_awaiter_index, "");
5214 LLVMValueRef result_ptr_as_usize;
5215 if (type_has_bits(result_type)) {
5216 LLVMValueRef result_ptr_ptr = LLVMBuildStructGEP(g->builder, target_frame_ptr, coro_ret_start, "");
5217 LLVMValueRef result_ptr = LLVMBuildLoad(g->builder, result_ptr_ptr, "");
5218 result_ptr_as_usize = LLVMBuildPtrToInt(g->builder, result_ptr, usize_type_ref, "");
5219 } else {
5220 result_ptr_as_usize = LLVMGetUndef(usize_type_ref);
5221 }
5222 LLVMValueRef prev_val = LLVMBuildAtomicRMW(g->builder, LLVMAtomicRMWBinOpXchg, awaiter_ptr, awaiter_init_val,5340 LLVMValueRef prev_val = LLVMBuildAtomicRMW(g->builder, LLVMAtomicRMWBinOpXchg, awaiter_ptr, awaiter_init_val,
5223 LLVMAtomicOrderingMonotonic, g->is_single_threaded);5341 LLVMAtomicOrderingRelease, g->is_single_threaded);
52245342
5225 LLVMBasicBlockRef bad_await_block = LLVMAppendBasicBlock(g->cur_fn_val, "BadAwait");5343 LLVMBasicBlockRef bad_await_block = LLVMAppendBasicBlock(g->cur_fn_val, "BadAwait");
5226 LLVMBasicBlockRef complete_suspend_block = LLVMAppendBasicBlock(g->cur_fn_val, "CompleteSuspend");5344 LLVMBasicBlockRef complete_suspend_block = LLVMAppendBasicBlock(g->cur_fn_val, "CompleteSuspend");
5345 LLVMBasicBlockRef early_return_block = LLVMAppendBasicBlock(g->cur_fn_val, "EarlyReturn");
52275346
5228 LLVMValueRef zero = LLVMConstNull(usize_type_ref);
5229 LLVMValueRef all_ones = LLVMConstAllOnes(usize_type_ref);5347 LLVMValueRef all_ones = LLVMConstAllOnes(usize_type_ref);
5230 LLVMValueRef switch_instr = LLVMBuildSwitch(g->builder, prev_val, bad_await_block, 2);5348 LLVMValueRef switch_instr = LLVMBuildSwitch(g->builder, prev_val, bad_await_block, 2);
5231 LLVMBasicBlockRef predecessor_bb = LLVMGetInsertBlock(g->builder);
52325349
5233 LLVMAddCase(switch_instr, zero, complete_suspend_block);5350 LLVMAddCase(switch_instr, zero, complete_suspend_block);
52345351 LLVMAddCase(switch_instr, all_ones, early_return_block);
5235 // Early return: The async function has already completed. No need to suspend.
5236 LLVMAddCase(switch_instr, all_ones, resume_bb);
52375352
5238 // We discovered that another awaiter was already here.5353 // We discovered that another awaiter was already here.
5239 LLVMPositionBuilderAtEnd(g->builder, bad_await_block);5354 LLVMPositionBuilderAtEnd(g->builder, bad_await_block);
5240 gen_assertion(g, PanicMsgIdBadAwait, &instruction->base);5355 gen_assertion(g, PanicMsgIdBadAwait, &instruction->base);
52415356
5357 // Early return: The async function has already completed, but it is suspending before setting the result,
5358 // populating the error return trace if applicable, and running the defers.
5359 // Tail resume it now, so that it can complete.
5360 LLVMPositionBuilderAtEnd(g->builder, early_return_block);
5361 LLVMValueRef call_inst = gen_resume(g, nullptr, target_frame_ptr, ResumeIdAwaitEarlyReturn, awaiter_init_val);
5362 ZigLLVMSetTailCall(call_inst);
5363 LLVMBuildRetVoid(g->builder);
5364
5242 // Rely on the target to resume us from suspension.5365 // Rely on the target to resume us from suspension.
5243 LLVMPositionBuilderAtEnd(g->builder, complete_suspend_block);5366 LLVMPositionBuilderAtEnd(g->builder, complete_suspend_block);
5244 LLVMBuildRetVoid(g->builder);5367 LLVMBuildRetVoid(g->builder);
52455368
5246 LLVMPositionBuilderAtEnd(g->builder, resume_bb);5369 LLVMPositionBuilderAtEnd(g->builder, resume_bb);
5247 // We either got here from Entry (function call) or from the switch above5370 gen_assert_resume_id(g, &instruction->base, ResumeIdReturn, PanicMsgIdResumedAnAwaitingFn, nullptr);
5248 LLVMValueRef spilled_result_ptr = LLVMBuildPhi(g->builder, usize_type_ref, "");5371 if (type_has_bits(result_type) && result_loc != nullptr) {
5249 LLVMValueRef incoming_values[] = { LLVMGetParam(g->cur_fn_val, 1), result_ptr_as_usize };5372 return get_handle_value(g, result_loc, result_type, ptr_result_type);
5250 LLVMBasicBlockRef incoming_blocks[] = { g->cur_preamble_llvm_block, predecessor_bb };
5251 LLVMAddIncoming(spilled_result_ptr, incoming_values, incoming_blocks, 2);
5252
5253 if (ir_want_runtime_safety(g, &instruction->base)) {
5254 LLVMBasicBlockRef bad_resume_block = LLVMAppendBasicBlock(g->cur_fn_val, "BadResume");
5255 LLVMBasicBlockRef ok_resume_block = LLVMAppendBasicBlock(g->cur_fn_val, "OkResume");
5256 LLVMValueRef all_ones = LLVMConstAllOnes(usize_type_ref);
5257 LLVMValueRef ok_bit = LLVMBuildICmp(g->builder, LLVMIntNE, spilled_result_ptr, all_ones, "");
5258 LLVMBuildCondBr(g->builder, ok_bit, ok_resume_block, bad_resume_block);
5259
5260 LLVMPositionBuilderAtEnd(g->builder, bad_resume_block);
5261 gen_safety_crash(g, PanicMsgIdResumedAnAwaitingFn);
5262
5263 LLVMPositionBuilderAtEnd(g->builder, ok_resume_block);
5264 }
5265
5266 render_async_var_decls(g, instruction->base.scope);
5267
5268 if (type_has_bits(result_type)) {
5269 LLVMValueRef casted_spilled_result_ptr = LLVMBuildIntToPtr(g->builder, spilled_result_ptr,
5270 get_llvm_type(g, ptr_result_type), "");
5271 return get_handle_value(g, casted_spilled_result_ptr, result_type, ptr_result_type);
5272 } else {
5273 return nullptr;
5274 }5373 }
5374 return nullptr;
5275}5375}
52765376
5277static LLVMValueRef ir_render_coro_resume(CodeGen *g, IrExecutable *executable,5377static LLVMValueRef ir_render_coro_resume(CodeGen *g, IrExecutable *executable,
5278 IrInstructionCoroResume *instruction)5378 IrInstructionCoroResume *instruction)
5279{5379{
5280 LLVMTypeRef usize_type_ref = g->builtin_types.entry_usize->llvm_type;
5281 LLVMValueRef frame = ir_llvm_value(g, instruction->frame);5380 LLVMValueRef frame = ir_llvm_value(g, instruction->frame);
5282 ZigType *frame_type = instruction->frame->value.type;5381 ZigType *frame_type = instruction->frame->value.type;
5283 assert(frame_type->id == ZigTypeIdAnyFrame);5382 assert(frame_type->id == ZigTypeIdAnyFrame);
5284 LLVMValueRef fn_ptr_ptr = LLVMBuildStructGEP(g->builder, frame, coro_fn_ptr_index, "");5383
5285 LLVMValueRef uncasted_fn_val = LLVMBuildLoad(g->builder, fn_ptr_ptr, "");5384 gen_resume(g, nullptr, frame, ResumeIdManual, nullptr);
5286 LLVMValueRef fn_val = LLVMBuildIntToPtr(g->builder, uncasted_fn_val, g->anyframe_fn_type, "");
5287 LLVMValueRef arg_val = ir_want_runtime_safety(g, &instruction->base) ?
5288 LLVMConstAllOnes(usize_type_ref) : LLVMGetUndef(usize_type_ref);
5289 LLVMValueRef args[] = {frame, arg_val};
5290 ZigLLVMBuildCall(g->builder, fn_val, args, 2, LLVMFastCallConv, ZigLLVM_FnInlineAuto, "");
5291 return nullptr;5385 return nullptr;
5292}5386}
52935387
...@@ -5383,7 +5477,6 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,...@@ -5383,7 +5477,6 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
5383 case IrInstructionIdImplicitCast:5477 case IrInstructionIdImplicitCast:
5384 case IrInstructionIdResolveResult:5478 case IrInstructionIdResolveResult:
5385 case IrInstructionIdResetResult:5479 case IrInstructionIdResetResult:
5386 case IrInstructionIdResultPtr:
5387 case IrInstructionIdContainerInitList:5480 case IrInstructionIdContainerInitList:
5388 case IrInstructionIdSliceSrc:5481 case IrInstructionIdSliceSrc:
5389 case IrInstructionIdRef:5482 case IrInstructionIdRef:
...@@ -5393,10 +5486,13 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,...@@ -5393,10 +5486,13 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
5393 case IrInstructionIdFrameType:5486 case IrInstructionIdFrameType:
5394 case IrInstructionIdFrameSizeSrc:5487 case IrInstructionIdFrameSizeSrc:
5395 case IrInstructionIdAllocaGen:5488 case IrInstructionIdAllocaGen:
5489 case IrInstructionIdAwaitSrc:
5396 zig_unreachable();5490 zig_unreachable();
53975491
5398 case IrInstructionIdDeclVarGen:5492 case IrInstructionIdDeclVarGen:
5399 return ir_render_decl_var(g, executable, (IrInstructionDeclVarGen *)instruction);5493 return ir_render_decl_var(g, executable, (IrInstructionDeclVarGen *)instruction);
5494 case IrInstructionIdReturnBegin:
5495 return ir_render_return_begin(g, executable, (IrInstructionReturnBegin *)instruction);
5400 case IrInstructionIdReturn:5496 case IrInstructionIdReturn:
5401 return ir_render_return(g, executable, (IrInstructionReturn *)instruction);5497 return ir_render_return(g, executable, (IrInstructionReturn *)instruction);
5402 case IrInstructionIdBinOp:5498 case IrInstructionIdBinOp:
...@@ -5547,8 +5643,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,...@@ -5547,8 +5643,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
5547 return ir_render_coro_resume(g, executable, (IrInstructionCoroResume *)instruction);5643 return ir_render_coro_resume(g, executable, (IrInstructionCoroResume *)instruction);
5548 case IrInstructionIdFrameSizeGen:5644 case IrInstructionIdFrameSizeGen:
5549 return ir_render_frame_size(g, executable, (IrInstructionFrameSizeGen *)instruction);5645 return ir_render_frame_size(g, executable, (IrInstructionFrameSizeGen *)instruction);
5550 case IrInstructionIdAwait:5646 case IrInstructionIdAwaitGen:
5551 return ir_render_await(g, executable, (IrInstructionAwait *)instruction);5647 return ir_render_await(g, executable, (IrInstructionAwaitGen *)instruction);
5552 }5648 }
5553 zig_unreachable();5649 zig_unreachable();
5554}5650}
...@@ -6777,16 +6873,19 @@ static void do_code_gen(CodeGen *g) {...@@ -6777,16 +6873,19 @@ static void do_code_gen(CodeGen *g) {
6777 g->cur_async_awaiter_ptr = LLVMBuildStructGEP(g->builder, g->cur_ret_ptr, coro_awaiter_index, "");6873 g->cur_async_awaiter_ptr = LLVMBuildStructGEP(g->builder, g->cur_ret_ptr, coro_awaiter_index, "");
6778 LLVMValueRef resume_index_ptr = LLVMBuildStructGEP(g->builder, g->cur_ret_ptr, coro_resume_index, "");6874 LLVMValueRef resume_index_ptr = LLVMBuildStructGEP(g->builder, g->cur_ret_ptr, coro_resume_index, "");
6779 g->cur_async_resume_index_ptr = resume_index_ptr;6875 g->cur_async_resume_index_ptr = resume_index_ptr;
6780 LLVMValueRef err_ret_trace_val = nullptr;6876
6781 uint32_t trace_field_index;6877 if (type_has_bits(fn_type_id->return_type)) {
6878 g->cur_ret_ptr_ptr = LLVMBuildStructGEP(g->builder, g->cur_ret_ptr, coro_ret_start, "");
6879 }
6782 if (codegen_fn_has_err_ret_tracing_arg(g, fn_type_id->return_type)) {6880 if (codegen_fn_has_err_ret_tracing_arg(g, fn_type_id->return_type)) {
6783 trace_field_index = frame_index_trace_arg(g, fn_type_id);6881 uint32_t trace_field_index = frame_index_trace_arg(g, fn_type_id->return_type);
6784 err_ret_trace_val = LLVMBuildStructGEP(g->builder, g->cur_ret_ptr, trace_field_index, "");6882 g->cur_err_ret_trace_val_arg = LLVMBuildStructGEP(g->builder, g->cur_ret_ptr, trace_field_index, "");
6785 g->cur_err_ret_trace_val_arg = err_ret_trace_val;6883 }
6786 } else if (codegen_fn_has_err_ret_tracing_stack(g, fn_table_entry)) {6884 uint32_t trace_field_index_stack = UINT32_MAX;
6787 trace_field_index = frame_index_trace_stack(g, fn_type_id);6885 if (codegen_fn_has_err_ret_tracing_stack(g, fn_table_entry, true)) {
6788 err_ret_trace_val = LLVMBuildStructGEP(g->builder, g->cur_ret_ptr, trace_field_index, "");6886 trace_field_index_stack = frame_index_trace_stack(g, fn_type_id);
6789 g->cur_err_ret_trace_val_stack = err_ret_trace_val;6887 g->cur_err_ret_trace_val_stack = LLVMBuildStructGEP(g->builder, g->cur_ret_ptr,
6888 trace_field_index_stack, "");
6790 }6889 }
67916890
6792 LLVMValueRef resume_index = LLVMBuildLoad(g->builder, resume_index_ptr, "");6891 LLVMValueRef resume_index = LLVMBuildLoad(g->builder, resume_index_ptr, "");
...@@ -6798,11 +6897,11 @@ static void do_code_gen(CodeGen *g) {...@@ -6798,11 +6897,11 @@ static void do_code_gen(CodeGen *g) {
6798 LLVMAddCase(switch_instr, zero, entry_block->llvm_block);6897 LLVMAddCase(switch_instr, zero, entry_block->llvm_block);
6799 g->cur_resume_block_count += 1;6898 g->cur_resume_block_count += 1;
6800 LLVMPositionBuilderAtEnd(g->builder, entry_block->llvm_block);6899 LLVMPositionBuilderAtEnd(g->builder, entry_block->llvm_block);
6801 if (err_ret_trace_val != nullptr) {6900 if (trace_field_index_stack != UINT32_MAX) {
6802 LLVMValueRef trace_field_ptr = LLVMBuildStructGEP(g->builder, g->cur_ret_ptr,6901 LLVMValueRef trace_field_ptr = LLVMBuildStructGEP(g->builder, g->cur_ret_ptr,
6803 trace_field_index, "");6902 trace_field_index_stack, "");
6804 LLVMValueRef trace_field_addrs = LLVMBuildStructGEP(g->builder, g->cur_ret_ptr,6903 LLVMValueRef trace_field_addrs = LLVMBuildStructGEP(g->builder, g->cur_ret_ptr,
6805 trace_field_index + 1, "");6904 trace_field_index_stack + 1, "");
68066905
6807 LLVMValueRef index_ptr = LLVMBuildStructGEP(g->builder, trace_field_ptr, 0, "");6906 LLVMValueRef index_ptr = LLVMBuildStructGEP(g->builder, trace_field_ptr, 0, "");
6808 LLVMBuildStore(g->builder, zero, index_ptr);6907 LLVMBuildStore(g->builder, zero, index_ptr);
...@@ -9725,7 +9824,7 @@ bool codegen_fn_has_err_ret_tracing_arg(CodeGen *g, ZigType *return_type) {...@@ -9725,7 +9824,7 @@ bool codegen_fn_has_err_ret_tracing_arg(CodeGen *g, ZigType *return_type) {
9725 return_type->id == ZigTypeIdErrorSet);9824 return_type->id == ZigTypeIdErrorSet);
9726}9825}
97279826
9728bool codegen_fn_has_err_ret_tracing_stack(CodeGen *g, ZigFn *fn) {9827bool codegen_fn_has_err_ret_tracing_stack(CodeGen *g, ZigFn *fn, bool is_async) {
9729 return g->have_err_ret_tracing && fn->calls_or_awaits_errorable_fn &&9828 return g->have_err_ret_tracing && fn->calls_or_awaits_errorable_fn &&
9730 !codegen_fn_has_err_ret_tracing_arg(g, fn->type_entry->data.fn.fn_type_id.return_type);9829 (is_async || !codegen_fn_has_err_ret_tracing_arg(g, fn->type_entry->data.fn.fn_type_id.return_type));
9731}9830}
src/codegen.hpp+1-1
...@@ -62,6 +62,6 @@ TargetSubsystem detect_subsystem(CodeGen *g);...@@ -62,6 +62,6 @@ TargetSubsystem detect_subsystem(CodeGen *g);
6262
63void codegen_release_caches(CodeGen *codegen);63void codegen_release_caches(CodeGen *codegen);
64bool codegen_fn_has_err_ret_tracing_arg(CodeGen *g, ZigType *return_type);64bool codegen_fn_has_err_ret_tracing_arg(CodeGen *g, ZigType *return_type);
65bool codegen_fn_has_err_ret_tracing_stack(CodeGen *g, ZigFn *fn);65bool codegen_fn_has_err_ret_tracing_stack(CodeGen *g, ZigFn *fn, bool is_async);
6666
67#endif67#endif
src/ir.cpp+139-106
...@@ -525,6 +525,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionReturn *) {...@@ -525,6 +525,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionReturn *) {
525 return IrInstructionIdReturn;525 return IrInstructionIdReturn;
526}526}
527527
528static constexpr IrInstructionId ir_instruction_id(IrInstructionReturnBegin *) {
529 return IrInstructionIdReturnBegin;
530}
531
528static constexpr IrInstructionId ir_instruction_id(IrInstructionCast *) {532static constexpr IrInstructionId ir_instruction_id(IrInstructionCast *) {
529 return IrInstructionIdCast;533 return IrInstructionIdCast;
530}534}
...@@ -945,10 +949,6 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionResetResult *) {...@@ -945,10 +949,6 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionResetResult *) {
945 return IrInstructionIdResetResult;949 return IrInstructionIdResetResult;
946}950}
947951
948static constexpr IrInstructionId ir_instruction_id(IrInstructionResultPtr *) {
949 return IrInstructionIdResultPtr;
950}
951
952static constexpr IrInstructionId ir_instruction_id(IrInstructionPtrOfArrayToSlice *) {952static constexpr IrInstructionId ir_instruction_id(IrInstructionPtrOfArrayToSlice *) {
953 return IrInstructionIdPtrOfArrayToSlice;953 return IrInstructionIdPtrOfArrayToSlice;
954}954}
...@@ -1049,8 +1049,12 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionSuspendFinish *)...@@ -1049,8 +1049,12 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionSuspendFinish *)
1049 return IrInstructionIdSuspendFinish;1049 return IrInstructionIdSuspendFinish;
1050}1050}
10511051
1052static constexpr IrInstructionId ir_instruction_id(IrInstructionAwait *) {1052static constexpr IrInstructionId ir_instruction_id(IrInstructionAwaitSrc *) {
1053 return IrInstructionIdAwait;1053 return IrInstructionIdAwaitSrc;
1054}
1055
1056static constexpr IrInstructionId ir_instruction_id(IrInstructionAwaitGen *) {
1057 return IrInstructionIdAwaitGen;
1054}1058}
10551059
1056static constexpr IrInstructionId ir_instruction_id(IrInstructionCoroResume *) {1060static constexpr IrInstructionId ir_instruction_id(IrInstructionCoroResume *) {
...@@ -1109,18 +1113,32 @@ static IrInstruction *ir_build_cond_br(IrBuilder *irb, Scope *scope, AstNode *so...@@ -1109,18 +1113,32 @@ static IrInstruction *ir_build_cond_br(IrBuilder *irb, Scope *scope, AstNode *so
1109}1113}
11101114
1111static IrInstruction *ir_build_return(IrBuilder *irb, Scope *scope, AstNode *source_node,1115static IrInstruction *ir_build_return(IrBuilder *irb, Scope *scope, AstNode *source_node,
1112 IrInstruction *return_value)1116 IrInstruction *operand)
1113{1117{
1114 IrInstructionReturn *return_instruction = ir_build_instruction<IrInstructionReturn>(irb, scope, source_node);1118 IrInstructionReturn *return_instruction = ir_build_instruction<IrInstructionReturn>(irb, scope, source_node);
1115 return_instruction->base.value.type = irb->codegen->builtin_types.entry_unreachable;1119 return_instruction->base.value.type = irb->codegen->builtin_types.entry_unreachable;
1116 return_instruction->base.value.special = ConstValSpecialStatic;1120 return_instruction->base.value.special = ConstValSpecialStatic;
1117 return_instruction->value = return_value;1121 return_instruction->operand = operand;
1122
1123 if (operand != nullptr) ir_ref_instruction(operand, irb->current_basic_block);
1124
1125 return &return_instruction->base;
1126}
1127
1128static IrInstruction *ir_build_return_begin(IrBuilder *irb, Scope *scope, AstNode *source_node,
1129 IrInstruction *operand)
1130{
1131 IrInstructionReturnBegin *return_instruction = ir_build_instruction<IrInstructionReturnBegin>(irb, scope, source_node);
1132 return_instruction->base.value.type = irb->codegen->builtin_types.entry_void;
1133 return_instruction->base.value.special = ConstValSpecialStatic;
1134 return_instruction->operand = operand;
11181135
1119 if (return_value != nullptr) ir_ref_instruction(return_value, irb->current_basic_block);1136 ir_ref_instruction(operand, irb->current_basic_block);
11201137
1121 return &return_instruction->base;1138 return &return_instruction->base;
1122}1139}
11231140
1141
1124static IrInstruction *ir_build_const_void(IrBuilder *irb, Scope *scope, AstNode *source_node) {1142static IrInstruction *ir_build_const_void(IrBuilder *irb, Scope *scope, AstNode *source_node) {
1125 IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irb, scope, source_node);1143 IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irb, scope, source_node);
1126 const_instruction->base.value.type = irb->codegen->builtin_types.entry_void;1144 const_instruction->base.value.type = irb->codegen->builtin_types.entry_void;
...@@ -2525,11 +2543,12 @@ static IrInstruction *ir_build_align_of(IrBuilder *irb, Scope *scope, AstNode *s...@@ -2525,11 +2543,12 @@ static IrInstruction *ir_build_align_of(IrBuilder *irb, Scope *scope, AstNode *s
2525}2543}
25262544
2527static IrInstruction *ir_build_test_err_src(IrBuilder *irb, Scope *scope, AstNode *source_node,2545static IrInstruction *ir_build_test_err_src(IrBuilder *irb, Scope *scope, AstNode *source_node,
2528 IrInstruction *base_ptr, bool resolve_err_set)2546 IrInstruction *base_ptr, bool resolve_err_set, bool base_ptr_is_payload)
2529{2547{
2530 IrInstructionTestErrSrc *instruction = ir_build_instruction<IrInstructionTestErrSrc>(irb, scope, source_node);2548 IrInstructionTestErrSrc *instruction = ir_build_instruction<IrInstructionTestErrSrc>(irb, scope, source_node);
2531 instruction->base_ptr = base_ptr;2549 instruction->base_ptr = base_ptr;
2532 instruction->resolve_err_set = resolve_err_set;2550 instruction->resolve_err_set = resolve_err_set;
2551 instruction->base_ptr_is_payload = base_ptr_is_payload;
25332552
2534 ir_ref_instruction(base_ptr, irb->current_basic_block);2553 ir_ref_instruction(base_ptr, irb->current_basic_block);
25352554
...@@ -2971,18 +2990,6 @@ static IrInstruction *ir_build_reset_result(IrBuilder *irb, Scope *scope, AstNod...@@ -2971,18 +2990,6 @@ static IrInstruction *ir_build_reset_result(IrBuilder *irb, Scope *scope, AstNod
2971 return &instruction->base;2990 return &instruction->base;
2972}2991}
29732992
2974static IrInstruction *ir_build_result_ptr(IrBuilder *irb, Scope *scope, AstNode *source_node,
2975 ResultLoc *result_loc, IrInstruction *result)
2976{
2977 IrInstructionResultPtr *instruction = ir_build_instruction<IrInstructionResultPtr>(irb, scope, source_node);
2978 instruction->result_loc = result_loc;
2979 instruction->result = result;
2980
2981 ir_ref_instruction(result, irb->current_basic_block);
2982
2983 return &instruction->base;
2984}
2985
2986static IrInstruction *ir_build_opaque_type(IrBuilder *irb, Scope *scope, AstNode *source_node) {2993static IrInstruction *ir_build_opaque_type(IrBuilder *irb, Scope *scope, AstNode *source_node) {
2987 IrInstructionOpaqueType *instruction = ir_build_instruction<IrInstructionOpaqueType>(irb, scope, source_node);2994 IrInstructionOpaqueType *instruction = ir_build_instruction<IrInstructionOpaqueType>(irb, scope, source_node);
29882995
...@@ -3266,17 +3273,33 @@ static IrInstruction *ir_build_suspend_finish(IrBuilder *irb, Scope *scope, AstN...@@ -3266,17 +3273,33 @@ static IrInstruction *ir_build_suspend_finish(IrBuilder *irb, Scope *scope, AstN
3266 return &instruction->base;3273 return &instruction->base;
3267}3274}
32683275
3269static IrInstruction *ir_build_await(IrBuilder *irb, Scope *scope, AstNode *source_node,3276static IrInstruction *ir_build_await_src(IrBuilder *irb, Scope *scope, AstNode *source_node,
3270 IrInstruction *frame)3277 IrInstruction *frame, ResultLoc *result_loc)
3271{3278{
3272 IrInstructionAwait *instruction = ir_build_instruction<IrInstructionAwait>(irb, scope, source_node);3279 IrInstructionAwaitSrc *instruction = ir_build_instruction<IrInstructionAwaitSrc>(irb, scope, source_node);
3273 instruction->frame = frame;3280 instruction->frame = frame;
3281 instruction->result_loc = result_loc;
32743282
3275 ir_ref_instruction(frame, irb->current_basic_block);3283 ir_ref_instruction(frame, irb->current_basic_block);
32763284
3277 return &instruction->base;3285 return &instruction->base;
3278}3286}
32793287
3288static IrInstruction *ir_build_await_gen(IrAnalyze *ira, IrInstruction *source_instruction,
3289 IrInstruction *frame, ZigType *result_type, IrInstruction *result_loc)
3290{
3291 IrInstructionAwaitGen *instruction = ir_build_instruction<IrInstructionAwaitGen>(&ira->new_irb,
3292 source_instruction->scope, source_instruction->source_node);
3293 instruction->base.value.type = result_type;
3294 instruction->frame = frame;
3295 instruction->result_loc = result_loc;
3296
3297 ir_ref_instruction(frame, ira->new_irb.current_basic_block);
3298 if (result_loc != nullptr) ir_ref_instruction(result_loc, ira->new_irb.current_basic_block);
3299
3300 return &instruction->base;
3301}
3302
3280static IrInstruction *ir_build_coro_resume(IrBuilder *irb, Scope *scope, AstNode *source_node,3303static IrInstruction *ir_build_coro_resume(IrBuilder *irb, Scope *scope, AstNode *source_node,
3281 IrInstruction *frame)3304 IrInstruction *frame)
3282{3305{
...@@ -3416,16 +3439,6 @@ static ScopeDeferExpr *get_scope_defer_expr(Scope *scope) {...@@ -3416,16 +3439,6 @@ static ScopeDeferExpr *get_scope_defer_expr(Scope *scope) {
3416 return nullptr;3439 return nullptr;
3417}3440}
34183441
3419static IrInstruction *ir_gen_async_return(IrBuilder *irb, Scope *scope, AstNode *node, IrInstruction *return_value,
3420 bool is_generated_code)
3421{
3422 ir_mark_gen(ir_build_add_implicit_return_type(irb, scope, node, return_value));
3423
3424 IrInstruction *return_inst = ir_build_return(irb, scope, node, return_value);
3425 return_inst->is_gen = is_generated_code;
3426 return return_inst;
3427}
3428
3429static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node, LVal lval, ResultLoc *result_loc) {3442static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node, LVal lval, ResultLoc *result_loc) {
3430 assert(node->type == NodeTypeReturnExpr);3443 assert(node->type == NodeTypeReturnExpr);
34313444
...@@ -3467,19 +3480,16 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node,...@@ -3467,19 +3480,16 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node,
3467 return_value = ir_build_const_void(irb, scope, node);3480 return_value = ir_build_const_void(irb, scope, node);
3468 }3481 }
34693482
3483 ir_build_return_begin(irb, scope, node, return_value);
3484
3470 size_t defer_counts[2];3485 size_t defer_counts[2];
3471 ir_count_defers(irb, scope, outer_scope, defer_counts);3486 ir_count_defers(irb, scope, outer_scope, defer_counts);
3472 bool have_err_defers = defer_counts[ReturnKindError] > 0;3487 bool have_err_defers = defer_counts[ReturnKindError] > 0;
3473 if (have_err_defers || irb->codegen->have_err_ret_tracing) {3488 if (have_err_defers || irb->codegen->have_err_ret_tracing) {
3474 IrBasicBlock *err_block = ir_create_basic_block(irb, scope, "ErrRetErr");3489 IrBasicBlock *err_block = ir_create_basic_block(irb, scope, "ErrRetErr");
3475 IrBasicBlock *ok_block = ir_create_basic_block(irb, scope, "ErrRetOk");3490 IrBasicBlock *ok_block = ir_create_basic_block(irb, scope, "ErrRetOk");
3476 if (!have_err_defers) {
3477 ir_gen_defers_for_block(irb, scope, outer_scope, false);
3478 }
34793491
3480 IrInstruction *ret_ptr = ir_build_result_ptr(irb, scope, node, &result_loc_ret->base,3492 IrInstruction *is_err = ir_build_test_err_src(irb, scope, node, return_value, false, true);
3481 return_value);
3482 IrInstruction *is_err = ir_build_test_err_src(irb, scope, node, ret_ptr, false);
34833493
3484 bool should_inline = ir_should_inline(irb->exec, scope);3494 bool should_inline = ir_should_inline(irb->exec, scope);
3485 IrInstruction *is_comptime;3495 IrInstruction *is_comptime;
...@@ -3493,28 +3503,26 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node,...@@ -3493,28 +3503,26 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node,
3493 IrBasicBlock *ret_stmt_block = ir_create_basic_block(irb, scope, "RetStmt");3503 IrBasicBlock *ret_stmt_block = ir_create_basic_block(irb, scope, "RetStmt");
34943504
3495 ir_set_cursor_at_end_and_append_block(irb, err_block);3505 ir_set_cursor_at_end_and_append_block(irb, err_block);
3496 if (have_err_defers) {
3497 ir_gen_defers_for_block(irb, scope, outer_scope, true);
3498 }
3499 if (irb->codegen->have_err_ret_tracing && !should_inline) {3506 if (irb->codegen->have_err_ret_tracing && !should_inline) {
3500 ir_build_save_err_ret_addr(irb, scope, node);3507 ir_build_save_err_ret_addr(irb, scope, node);
3501 }3508 }
3509 ir_gen_defers_for_block(irb, scope, outer_scope, true);
3502 ir_build_br(irb, scope, node, ret_stmt_block, is_comptime);3510 ir_build_br(irb, scope, node, ret_stmt_block, is_comptime);
35033511
3504 ir_set_cursor_at_end_and_append_block(irb, ok_block);3512 ir_set_cursor_at_end_and_append_block(irb, ok_block);
3505 if (have_err_defers) {3513 ir_gen_defers_for_block(irb, scope, outer_scope, false);
3506 ir_gen_defers_for_block(irb, scope, outer_scope, false);
3507 }
3508 ir_build_br(irb, scope, node, ret_stmt_block, is_comptime);3514 ir_build_br(irb, scope, node, ret_stmt_block, is_comptime);
35093515
3510 ir_set_cursor_at_end_and_append_block(irb, ret_stmt_block);3516 ir_set_cursor_at_end_and_append_block(irb, ret_stmt_block);
3511 IrInstruction *result = ir_gen_async_return(irb, scope, node, return_value, false);3517 ir_mark_gen(ir_build_add_implicit_return_type(irb, scope, node, return_value));
3518 IrInstruction *result = ir_build_return(irb, scope, node, return_value);
3512 result_loc_ret->base.source_instruction = result;3519 result_loc_ret->base.source_instruction = result;
3513 return result;3520 return result;
3514 } else {3521 } else {
3515 // generate unconditional defers3522 // generate unconditional defers
3516 ir_gen_defers_for_block(irb, scope, outer_scope, false);3523 ir_gen_defers_for_block(irb, scope, outer_scope, false);
3517 IrInstruction *result = ir_gen_async_return(irb, scope, node, return_value, false);3524 ir_mark_gen(ir_build_add_implicit_return_type(irb, scope, node, return_value));
3525 IrInstruction *result = ir_build_return(irb, scope, node, return_value);
3518 result_loc_ret->base.source_instruction = result;3526 result_loc_ret->base.source_instruction = result;
3519 return result;3527 return result;
3520 }3528 }
...@@ -3525,7 +3533,7 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node,...@@ -3525,7 +3533,7 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node,
3525 IrInstruction *err_union_ptr = ir_gen_node_extra(irb, expr_node, scope, LValPtr, nullptr);3533 IrInstruction *err_union_ptr = ir_gen_node_extra(irb, expr_node, scope, LValPtr, nullptr);
3526 if (err_union_ptr == irb->codegen->invalid_instruction)3534 if (err_union_ptr == irb->codegen->invalid_instruction)
3527 return irb->codegen->invalid_instruction;3535 return irb->codegen->invalid_instruction;
3528 IrInstruction *is_err_val = ir_build_test_err_src(irb, scope, node, err_union_ptr, true);3536 IrInstruction *is_err_val = ir_build_test_err_src(irb, scope, node, err_union_ptr, true, false);
35293537
3530 IrBasicBlock *return_block = ir_create_basic_block(irb, scope, "ErrRetReturn");3538 IrBasicBlock *return_block = ir_create_basic_block(irb, scope, "ErrRetReturn");
3531 IrBasicBlock *continue_block = ir_create_basic_block(irb, scope, "ErrRetContinue");3539 IrBasicBlock *continue_block = ir_create_basic_block(irb, scope, "ErrRetContinue");
...@@ -3539,10 +3547,10 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node,...@@ -3539,10 +3547,10 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node,
3539 ir_mark_gen(ir_build_cond_br(irb, scope, node, is_err_val, return_block, continue_block, is_comptime));3547 ir_mark_gen(ir_build_cond_br(irb, scope, node, is_err_val, return_block, continue_block, is_comptime));
35403548
3541 ir_set_cursor_at_end_and_append_block(irb, return_block);3549 ir_set_cursor_at_end_and_append_block(irb, return_block);
3550 IrInstruction *err_val_ptr = ir_build_unwrap_err_code(irb, scope, node, err_union_ptr);
3551 IrInstruction *err_val = ir_build_load_ptr(irb, scope, node, err_val_ptr);
3552 ir_build_return_begin(irb, scope, node, err_val);
3542 if (!ir_gen_defers_for_block(irb, scope, outer_scope, true)) {3553 if (!ir_gen_defers_for_block(irb, scope, outer_scope, true)) {
3543 IrInstruction *err_val_ptr = ir_build_unwrap_err_code(irb, scope, node, err_union_ptr);
3544 IrInstruction *err_val = ir_build_load_ptr(irb, scope, node, err_val_ptr);
3545
3546 ResultLocReturn *result_loc_ret = allocate<ResultLocReturn>(1);3554 ResultLocReturn *result_loc_ret = allocate<ResultLocReturn>(1);
3547 result_loc_ret->base.id = ResultLocIdReturn;3555 result_loc_ret->base.id = ResultLocIdReturn;
3548 ir_build_reset_result(irb, scope, node, &result_loc_ret->base);3556 ir_build_reset_result(irb, scope, node, &result_loc_ret->base);
...@@ -3551,7 +3559,8 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node,...@@ -3551,7 +3559,8 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node,
3551 if (irb->codegen->have_err_ret_tracing && !should_inline) {3559 if (irb->codegen->have_err_ret_tracing && !should_inline) {
3552 ir_build_save_err_ret_addr(irb, scope, node);3560 ir_build_save_err_ret_addr(irb, scope, node);
3553 }3561 }
3554 IrInstruction *ret_inst = ir_gen_async_return(irb, scope, node, err_val, false);3562 ir_mark_gen(ir_build_add_implicit_return_type(irb, scope, node, err_val));
3563 IrInstruction *ret_inst = ir_build_return(irb, scope, node, err_val);
3555 result_loc_ret->base.source_instruction = ret_inst;3564 result_loc_ret->base.source_instruction = ret_inst;
3556 }3565 }
35573566
...@@ -6081,7 +6090,8 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n...@@ -6081,7 +6090,8 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n
6081 LValPtr, nullptr);6090 LValPtr, nullptr);
6082 if (err_val_ptr == irb->codegen->invalid_instruction)6091 if (err_val_ptr == irb->codegen->invalid_instruction)
6083 return err_val_ptr;6092 return err_val_ptr;
6084 IrInstruction *is_err = ir_build_test_err_src(irb, scope, node->data.while_expr.condition, err_val_ptr, true);6093 IrInstruction *is_err = ir_build_test_err_src(irb, scope, node->data.while_expr.condition, err_val_ptr,
6094 true, false);
6085 IrBasicBlock *after_cond_block = irb->current_basic_block;6095 IrBasicBlock *after_cond_block = irb->current_basic_block;
6086 IrInstruction *void_else_result = else_node ? nullptr : ir_mark_gen(ir_build_const_void(irb, scope, node));6096 IrInstruction *void_else_result = else_node ? nullptr : ir_mark_gen(ir_build_const_void(irb, scope, node));
6087 IrInstruction *cond_br_inst;6097 IrInstruction *cond_br_inst;
...@@ -6897,7 +6907,7 @@ static IrInstruction *ir_gen_if_err_expr(IrBuilder *irb, Scope *scope, AstNode *...@@ -6897,7 +6907,7 @@ static IrInstruction *ir_gen_if_err_expr(IrBuilder *irb, Scope *scope, AstNode *
6897 return err_val_ptr;6907 return err_val_ptr;
68986908
6899 IrInstruction *err_val = ir_build_load_ptr(irb, scope, node, err_val_ptr);6909 IrInstruction *err_val = ir_build_load_ptr(irb, scope, node, err_val_ptr);
6900 IrInstruction *is_err = ir_build_test_err_src(irb, scope, node, err_val_ptr, true);6910 IrInstruction *is_err = ir_build_test_err_src(irb, scope, node, err_val_ptr, true, false);
69016911
6902 IrBasicBlock *ok_block = ir_create_basic_block(irb, scope, "TryOk");6912 IrBasicBlock *ok_block = ir_create_basic_block(irb, scope, "TryOk");
6903 IrBasicBlock *else_block = ir_create_basic_block(irb, scope, "TryElse");6913 IrBasicBlock *else_block = ir_create_basic_block(irb, scope, "TryElse");
...@@ -7513,7 +7523,7 @@ static IrInstruction *ir_gen_catch(IrBuilder *irb, Scope *parent_scope, AstNode...@@ -7513,7 +7523,7 @@ static IrInstruction *ir_gen_catch(IrBuilder *irb, Scope *parent_scope, AstNode
7513 if (err_union_ptr == irb->codegen->invalid_instruction)7523 if (err_union_ptr == irb->codegen->invalid_instruction)
7514 return irb->codegen->invalid_instruction;7524 return irb->codegen->invalid_instruction;
75157525
7516 IrInstruction *is_err = ir_build_test_err_src(irb, parent_scope, node, err_union_ptr, true);7526 IrInstruction *is_err = ir_build_test_err_src(irb, parent_scope, node, err_union_ptr, true, false);
75177527
7518 IrInstruction *is_comptime;7528 IrInstruction *is_comptime;
7519 if (ir_should_inline(irb->exec, parent_scope)) {7529 if (ir_should_inline(irb->exec, parent_scope)) {
...@@ -7830,7 +7840,9 @@ static IrInstruction *ir_gen_resume(IrBuilder *irb, Scope *scope, AstNode *node)...@@ -7830,7 +7840,9 @@ static IrInstruction *ir_gen_resume(IrBuilder *irb, Scope *scope, AstNode *node)
7830 return ir_build_coro_resume(irb, scope, node, target_inst);7840 return ir_build_coro_resume(irb, scope, node, target_inst);
7831}7841}
78327842
7833static IrInstruction *ir_gen_await_expr(IrBuilder *irb, Scope *scope, AstNode *node) {7843static IrInstruction *ir_gen_await_expr(IrBuilder *irb, Scope *scope, AstNode *node, LVal lval,
7844 ResultLoc *result_loc)
7845{
7834 assert(node->type == NodeTypeAwaitExpr);7846 assert(node->type == NodeTypeAwaitExpr);
78357847
7836 ZigFn *fn_entry = exec_fn_entry(irb->exec);7848 ZigFn *fn_entry = exec_fn_entry(irb->exec);
...@@ -7852,7 +7864,8 @@ static IrInstruction *ir_gen_await_expr(IrBuilder *irb, Scope *scope, AstNode *n...@@ -7852,7 +7864,8 @@ static IrInstruction *ir_gen_await_expr(IrBuilder *irb, Scope *scope, AstNode *n
7852 if (target_inst == irb->codegen->invalid_instruction)7864 if (target_inst == irb->codegen->invalid_instruction)
7853 return irb->codegen->invalid_instruction;7865 return irb->codegen->invalid_instruction;
78547866
7855 return ir_build_await(irb, scope, node, target_inst);7867 IrInstruction *await_inst = ir_build_await_src(irb, scope, node, target_inst, result_loc);
7868 return ir_lval_wrap(irb, scope, await_inst, lval, result_loc);
7856}7869}
78577870
7858static IrInstruction *ir_gen_suspend(IrBuilder *irb, Scope *parent_scope, AstNode *node) {7871static IrInstruction *ir_gen_suspend(IrBuilder *irb, Scope *parent_scope, AstNode *node) {
...@@ -8016,7 +8029,7 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop...@@ -8016,7 +8029,7 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop
8016 case NodeTypeResume:8029 case NodeTypeResume:
8017 return ir_lval_wrap(irb, scope, ir_gen_resume(irb, scope, node), lval, result_loc);8030 return ir_lval_wrap(irb, scope, ir_gen_resume(irb, scope, node), lval, result_loc);
8018 case NodeTypeAwaitExpr:8031 case NodeTypeAwaitExpr:
8019 return ir_lval_wrap(irb, scope, ir_gen_await_expr(irb, scope, node), lval, result_loc);8032 return ir_gen_await_expr(irb, scope, node, lval, result_loc);
8020 case NodeTypeSuspend:8033 case NodeTypeSuspend:
8021 return ir_lval_wrap(irb, scope, ir_gen_suspend(irb, scope, node), lval, result_loc);8034 return ir_lval_wrap(irb, scope, ir_gen_suspend(irb, scope, node), lval, result_loc);
8022 case NodeTypeEnumLiteral:8035 case NodeTypeEnumLiteral:
...@@ -8088,8 +8101,10 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec...@@ -8088,8 +8101,10 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec
8088 return false;8101 return false;
80898102
8090 if (!instr_is_unreachable(result)) {8103 if (!instr_is_unreachable(result)) {
8104 ir_mark_gen(ir_build_return_begin(irb, scope, node, result));
8091 // no need for save_err_ret_addr because this cannot return error8105 // no need for save_err_ret_addr because this cannot return error
8092 ir_gen_async_return(irb, scope, result->source_node, result, true);8106 ir_mark_gen(ir_build_add_implicit_return_type(irb, scope, result->source_node, result));
8107 ir_mark_gen(ir_build_return(irb, scope, result->source_node, result));
8093 }8108 }
80948109
8095 return true;8110 return true;
...@@ -8181,18 +8196,19 @@ static ConstExprValue *ir_exec_const_result(CodeGen *codegen, IrExecutable *exec...@@ -8181,18 +8196,19 @@ static ConstExprValue *ir_exec_const_result(CodeGen *codegen, IrExecutable *exec
8181 IrInstruction *instruction = bb->instruction_list.at(i);8196 IrInstruction *instruction = bb->instruction_list.at(i);
8182 if (instruction->id == IrInstructionIdReturn) {8197 if (instruction->id == IrInstructionIdReturn) {
8183 IrInstructionReturn *ret_inst = (IrInstructionReturn *)instruction;8198 IrInstructionReturn *ret_inst = (IrInstructionReturn *)instruction;
8184 IrInstruction *value = ret_inst->value;8199 IrInstruction *operand = ret_inst->operand;
8185 if (value->value.special == ConstValSpecialRuntime) {8200 if (operand->value.special == ConstValSpecialRuntime) {
8186 exec_add_error_node(codegen, exec, value->source_node,8201 exec_add_error_node(codegen, exec, operand->source_node,
8187 buf_sprintf("unable to evaluate constant expression"));8202 buf_sprintf("unable to evaluate constant expression"));
8188 return &codegen->invalid_instruction->value;8203 return &codegen->invalid_instruction->value;
8189 }8204 }
8190 return &value->value;8205 return &operand->value;
8191 } else if (ir_has_side_effects(instruction)) {8206 } else if (ir_has_side_effects(instruction)) {
8192 if (instr_is_comptime(instruction)) {8207 if (instr_is_comptime(instruction)) {
8193 switch (instruction->id) {8208 switch (instruction->id) {
8194 case IrInstructionIdUnwrapErrPayload:8209 case IrInstructionIdUnwrapErrPayload:
8195 case IrInstructionIdUnionFieldPtr:8210 case IrInstructionIdUnionFieldPtr:
8211 case IrInstructionIdReturnBegin:
8196 continue;8212 continue;
8197 default:8213 default:
8198 break;8214 break;
...@@ -12593,12 +12609,32 @@ static IrInstruction *ir_analyze_instruction_add_implicit_return_type(IrAnalyze...@@ -12593,12 +12609,32 @@ static IrInstruction *ir_analyze_instruction_add_implicit_return_type(IrAnalyze
12593 return ir_const_void(ira, &instruction->base);12609 return ir_const_void(ira, &instruction->base);
12594}12610}
1259512611
12612static IrInstruction *ir_analyze_instruction_return_begin(IrAnalyze *ira, IrInstructionReturnBegin *instruction) {
12613 IrInstruction *operand = instruction->operand->child;
12614 if (type_is_invalid(operand->value.type))
12615 return ira->codegen->invalid_instruction;
12616
12617 IrInstruction *casted_operand = ir_implicit_cast(ira, operand, ira->explicit_return_type);
12618 if (type_is_invalid(casted_operand->value.type)) {
12619 AstNode *source_node = ira->explicit_return_type_source_node;
12620 if (source_node != nullptr) {
12621 ErrorMsg *msg = ira->codegen->errors.last();
12622 add_error_note(ira->codegen, msg, source_node,
12623 buf_sprintf("return type declared here"));
12624 }
12625 return ir_unreach_error(ira);
12626 }
12627
12628 return ir_build_return_begin(&ira->new_irb, instruction->base.scope, instruction->base.source_node,
12629 casted_operand);
12630}
12631
12596static IrInstruction *ir_analyze_instruction_return(IrAnalyze *ira, IrInstructionReturn *instruction) {12632static IrInstruction *ir_analyze_instruction_return(IrAnalyze *ira, IrInstructionReturn *instruction) {
12597 IrInstruction *value = instruction->value->child;12633 IrInstruction *operand = instruction->operand->child;
12598 if (type_is_invalid(value->value.type))12634 if (type_is_invalid(operand->value.type))
12599 return ir_unreach_error(ira);12635 return ir_unreach_error(ira);
1260012636
12601 if (!instr_is_comptime(value) && handle_is_ptr(ira->explicit_return_type)) {12637 if (!instr_is_comptime(operand) && handle_is_ptr(ira->explicit_return_type)) {
12602 // result location mechanism took care of it.12638 // result location mechanism took care of it.
12603 IrInstruction *result = ir_build_return(&ira->new_irb, instruction->base.scope,12639 IrInstruction *result = ir_build_return(&ira->new_irb, instruction->base.scope,
12604 instruction->base.source_node, nullptr);12640 instruction->base.source_node, nullptr);
...@@ -12606,26 +12642,21 @@ static IrInstruction *ir_analyze_instruction_return(IrAnalyze *ira, IrInstructio...@@ -12606,26 +12642,21 @@ static IrInstruction *ir_analyze_instruction_return(IrAnalyze *ira, IrInstructio
12606 return ir_finish_anal(ira, result);12642 return ir_finish_anal(ira, result);
12607 }12643 }
1260812644
12609 IrInstruction *casted_value = ir_implicit_cast(ira, value, ira->explicit_return_type);12645 IrInstruction *casted_operand = ir_implicit_cast(ira, operand, ira->explicit_return_type);
12610 if (type_is_invalid(casted_value->value.type)) {12646 if (type_is_invalid(casted_operand->value.type)) {
12611 AstNode *source_node = ira->explicit_return_type_source_node;12647 // error already reported by IrInstructionReturnBegin
12612 if (source_node != nullptr) {
12613 ErrorMsg *msg = ira->codegen->errors.last();
12614 add_error_note(ira->codegen, msg, source_node,
12615 buf_sprintf("return type declared here"));
12616 }
12617 return ir_unreach_error(ira);12648 return ir_unreach_error(ira);
12618 }12649 }
1261912650
12620 if (casted_value->value.special == ConstValSpecialRuntime &&12651 if (casted_operand->value.special == ConstValSpecialRuntime &&
12621 casted_value->value.type->id == ZigTypeIdPointer &&12652 casted_operand->value.type->id == ZigTypeIdPointer &&
12622 casted_value->value.data.rh_ptr == RuntimeHintPtrStack)12653 casted_operand->value.data.rh_ptr == RuntimeHintPtrStack)
12623 {12654 {
12624 ir_add_error(ira, casted_value, buf_sprintf("function returns address of local variable"));12655 ir_add_error(ira, casted_operand, buf_sprintf("function returns address of local variable"));
12625 return ir_unreach_error(ira);12656 return ir_unreach_error(ira);
12626 }12657 }
12627 IrInstruction *result = ir_build_return(&ira->new_irb, instruction->base.scope,12658 IrInstruction *result = ir_build_return(&ira->new_irb, instruction->base.scope,
12628 instruction->base.source_node, casted_value);12659 instruction->base.source_node, casted_operand);
12629 result->value.type = ira->codegen->builtin_types.entry_unreachable;12660 result->value.type = ira->codegen->builtin_types.entry_unreachable;
12630 return ir_finish_anal(ira, result);12661 return ir_finish_anal(ira, result);
12631}12662}
...@@ -22176,19 +22207,6 @@ static IrInstruction *ir_analyze_instruction_overflow_op(IrAnalyze *ira, IrInstr...@@ -22176,19 +22207,6 @@ static IrInstruction *ir_analyze_instruction_overflow_op(IrAnalyze *ira, IrInstr
22176 return result;22207 return result;
22177}22208}
2217822209
22179static IrInstruction *ir_analyze_instruction_result_ptr(IrAnalyze *ira, IrInstructionResultPtr *instruction) {
22180 IrInstruction *result = instruction->result->child;
22181 if (type_is_invalid(result->value.type))
22182 return result;
22183
22184 if (instruction->result_loc->written && instruction->result_loc->resolved_loc != nullptr &&
22185 !instr_is_comptime(result))
22186 {
22187 return instruction->result_loc->resolved_loc;
22188 }
22189 return ir_get_ref(ira, &instruction->base, result, true, false);
22190}
22191
22192static void ir_eval_mul_add(IrAnalyze *ira, IrInstructionMulAdd *source_instr, ZigType *float_type,22210static void ir_eval_mul_add(IrAnalyze *ira, IrInstructionMulAdd *source_instr, ZigType *float_type,
22193 ConstExprValue *op1, ConstExprValue *op2, ConstExprValue *op3, ConstExprValue *out_val) {22211 ConstExprValue *op1, ConstExprValue *op2, ConstExprValue *op3, ConstExprValue *out_val) {
22194 if (float_type->id == ZigTypeIdComptimeFloat) {22212 if (float_type->id == ZigTypeIdComptimeFloat) {
...@@ -22313,11 +22331,16 @@ static IrInstruction *ir_analyze_instruction_test_err(IrAnalyze *ira, IrInstruct...@@ -22313,11 +22331,16 @@ static IrInstruction *ir_analyze_instruction_test_err(IrAnalyze *ira, IrInstruct
22313 if (type_is_invalid(base_ptr->value.type))22331 if (type_is_invalid(base_ptr->value.type))
22314 return ira->codegen->invalid_instruction;22332 return ira->codegen->invalid_instruction;
2231522333
22316 IrInstruction *value = ir_get_deref(ira, &instruction->base, base_ptr, nullptr);22334 IrInstruction *value;
22335 if (instruction->base_ptr_is_payload) {
22336 value = base_ptr;
22337 } else {
22338 value = ir_get_deref(ira, &instruction->base, base_ptr, nullptr);
22339 }
22340
22317 ZigType *type_entry = value->value.type;22341 ZigType *type_entry = value->value.type;
22318 if (type_is_invalid(type_entry))22342 if (type_is_invalid(type_entry))
22319 return ira->codegen->invalid_instruction;22343 return ira->codegen->invalid_instruction;
22320
22321 if (type_entry->id == ZigTypeIdErrorUnion) {22344 if (type_entry->id == ZigTypeIdErrorUnion) {
22322 if (instr_is_comptime(value)) {22345 if (instr_is_comptime(value)) {
22323 ConstExprValue *err_union_val = ir_resolve_const(ira, value, UndefBad);22346 ConstExprValue *err_union_val = ir_resolve_const(ira, value, UndefBad);
...@@ -24443,7 +24466,7 @@ static IrInstruction *ir_analyze_instruction_suspend_finish(IrAnalyze *ira,...@@ -24443,7 +24466,7 @@ static IrInstruction *ir_analyze_instruction_suspend_finish(IrAnalyze *ira,
24443 return ir_build_suspend_finish(&ira->new_irb, instruction->base.scope, instruction->base.source_node, begin);24466 return ir_build_suspend_finish(&ira->new_irb, instruction->base.scope, instruction->base.source_node, begin);
24444}24467}
2444524468
24446static IrInstruction *ir_analyze_instruction_await(IrAnalyze *ira, IrInstructionAwait *instruction) {24469static IrInstruction *ir_analyze_instruction_await(IrAnalyze *ira, IrInstructionAwaitSrc *instruction) {
24447 IrInstruction *frame_ptr = instruction->frame->child;24470 IrInstruction *frame_ptr = instruction->frame->child;
24448 if (type_is_invalid(frame_ptr->value.type))24471 if (type_is_invalid(frame_ptr->value.type))
24449 return ira->codegen->invalid_instruction;24472 return ira->codegen->invalid_instruction;
...@@ -24484,9 +24507,17 @@ static IrInstruction *ir_analyze_instruction_await(IrAnalyze *ira, IrInstruction...@@ -24484,9 +24507,17 @@ static IrInstruction *ir_analyze_instruction_await(IrAnalyze *ira, IrInstruction
24484 fn_entry->calls_or_awaits_errorable_fn = true;24507 fn_entry->calls_or_awaits_errorable_fn = true;
24485 }24508 }
2448624509
24487 IrInstruction *result = ir_build_await(&ira->new_irb,24510 IrInstruction *result_loc;
24488 instruction->base.scope, instruction->base.source_node, frame);24511 if (type_has_bits(result_type)) {
24489 result->value.type = result_type;24512 result_loc = ir_resolve_result(ira, &instruction->base, instruction->result_loc,
24513 result_type, nullptr, true, false, true);
24514 if (result_loc != nullptr && (type_is_invalid(result_loc->value.type) || instr_is_unreachable(result_loc)))
24515 return result_loc;
24516 } else {
24517 result_loc = nullptr;
24518 }
24519
24520 IrInstruction *result = ir_build_await_gen(ira, &instruction->base, frame, result_type, result_loc);
24490 return ir_finish_anal(ira, result);24521 return ir_finish_anal(ira, result);
24491}24522}
2449224523
...@@ -24541,8 +24572,11 @@ static IrInstruction *ir_analyze_instruction_base(IrAnalyze *ira, IrInstruction...@@ -24541,8 +24572,11 @@ static IrInstruction *ir_analyze_instruction_base(IrAnalyze *ira, IrInstruction
24541 case IrInstructionIdRefGen:24572 case IrInstructionIdRefGen:
24542 case IrInstructionIdTestErrGen:24573 case IrInstructionIdTestErrGen:
24543 case IrInstructionIdFrameSizeGen:24574 case IrInstructionIdFrameSizeGen:
24575 case IrInstructionIdAwaitGen:
24544 zig_unreachable();24576 zig_unreachable();
2454524577
24578 case IrInstructionIdReturnBegin:
24579 return ir_analyze_instruction_return_begin(ira, (IrInstructionReturnBegin *)instruction);
24546 case IrInstructionIdReturn:24580 case IrInstructionIdReturn:
24547 return ir_analyze_instruction_return(ira, (IrInstructionReturn *)instruction);24581 return ir_analyze_instruction_return(ira, (IrInstructionReturn *)instruction);
24548 case IrInstructionIdConst:24582 case IrInstructionIdConst:
...@@ -24749,8 +24783,6 @@ static IrInstruction *ir_analyze_instruction_base(IrAnalyze *ira, IrInstruction...@@ -24749,8 +24783,6 @@ static IrInstruction *ir_analyze_instruction_base(IrAnalyze *ira, IrInstruction
24749 return ir_analyze_instruction_resolve_result(ira, (IrInstructionResolveResult *)instruction);24783 return ir_analyze_instruction_resolve_result(ira, (IrInstructionResolveResult *)instruction);
24750 case IrInstructionIdResetResult:24784 case IrInstructionIdResetResult:
24751 return ir_analyze_instruction_reset_result(ira, (IrInstructionResetResult *)instruction);24785 return ir_analyze_instruction_reset_result(ira, (IrInstructionResetResult *)instruction);
24752 case IrInstructionIdResultPtr:
24753 return ir_analyze_instruction_result_ptr(ira, (IrInstructionResultPtr *)instruction);
24754 case IrInstructionIdOpaqueType:24786 case IrInstructionIdOpaqueType:
24755 return ir_analyze_instruction_opaque_type(ira, (IrInstructionOpaqueType *)instruction);24787 return ir_analyze_instruction_opaque_type(ira, (IrInstructionOpaqueType *)instruction);
24756 case IrInstructionIdSetAlignStack:24788 case IrInstructionIdSetAlignStack:
...@@ -24807,8 +24839,8 @@ static IrInstruction *ir_analyze_instruction_base(IrAnalyze *ira, IrInstruction...@@ -24807,8 +24839,8 @@ static IrInstruction *ir_analyze_instruction_base(IrAnalyze *ira, IrInstruction
24807 return ir_analyze_instruction_suspend_finish(ira, (IrInstructionSuspendFinish *)instruction);24839 return ir_analyze_instruction_suspend_finish(ira, (IrInstructionSuspendFinish *)instruction);
24808 case IrInstructionIdCoroResume:24840 case IrInstructionIdCoroResume:
24809 return ir_analyze_instruction_coro_resume(ira, (IrInstructionCoroResume *)instruction);24841 return ir_analyze_instruction_coro_resume(ira, (IrInstructionCoroResume *)instruction);
24810 case IrInstructionIdAwait:24842 case IrInstructionIdAwaitSrc:
24811 return ir_analyze_instruction_await(ira, (IrInstructionAwait *)instruction);24843 return ir_analyze_instruction_await(ira, (IrInstructionAwaitSrc *)instruction);
24812 }24844 }
24813 zig_unreachable();24845 zig_unreachable();
24814}24846}
...@@ -24898,6 +24930,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {...@@ -24898,6 +24930,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {
24898 case IrInstructionIdStorePtr:24930 case IrInstructionIdStorePtr:
24899 case IrInstructionIdCallSrc:24931 case IrInstructionIdCallSrc:
24900 case IrInstructionIdCallGen:24932 case IrInstructionIdCallGen:
24933 case IrInstructionIdReturnBegin:
24901 case IrInstructionIdReturn:24934 case IrInstructionIdReturn:
24902 case IrInstructionIdUnreachable:24935 case IrInstructionIdUnreachable:
24903 case IrInstructionIdSetCold:24936 case IrInstructionIdSetCold:
...@@ -24943,7 +24976,8 @@ bool ir_has_side_effects(IrInstruction *instruction) {...@@ -24943,7 +24976,8 @@ bool ir_has_side_effects(IrInstruction *instruction) {
24943 case IrInstructionIdSuspendBegin:24976 case IrInstructionIdSuspendBegin:
24944 case IrInstructionIdSuspendFinish:24977 case IrInstructionIdSuspendFinish:
24945 case IrInstructionIdCoroResume:24978 case IrInstructionIdCoroResume:
24946 case IrInstructionIdAwait:24979 case IrInstructionIdAwaitSrc:
24980 case IrInstructionIdAwaitGen:
24947 return true;24981 return true;
2494824982
24949 case IrInstructionIdPhi:24983 case IrInstructionIdPhi:
...@@ -25041,7 +25075,6 @@ bool ir_has_side_effects(IrInstruction *instruction) {...@@ -25041,7 +25075,6 @@ bool ir_has_side_effects(IrInstruction *instruction) {
25041 case IrInstructionIdHasDecl:25075 case IrInstructionIdHasDecl:
25042 case IrInstructionIdAllocaSrc:25076 case IrInstructionIdAllocaSrc:
25043 case IrInstructionIdAllocaGen:25077 case IrInstructionIdAllocaGen:
25044 case IrInstructionIdResultPtr:
25045 return false;25078 return false;
2504625079
25047 case IrInstructionIdAsm:25080 case IrInstructionIdAsm:
src/ir_print.cpp+27-18
...@@ -64,11 +64,15 @@ static void ir_print_other_block(IrPrint *irp, IrBasicBlock *bb) {...@@ -64,11 +64,15 @@ static void ir_print_other_block(IrPrint *irp, IrBasicBlock *bb) {
64 }64 }
65}65}
6666
67static void ir_print_return(IrPrint *irp, IrInstructionReturn *return_instruction) {67static void ir_print_return_begin(IrPrint *irp, IrInstructionReturnBegin *instruction) {
68 fprintf(irp->f, "@returnBegin(");
69 ir_print_other_instruction(irp, instruction->operand);
70 fprintf(irp->f, ")");
71}
72
73static void ir_print_return(IrPrint *irp, IrInstructionReturn *instruction) {
68 fprintf(irp->f, "return ");74 fprintf(irp->f, "return ");
69 if (return_instruction->value != nullptr) {75 ir_print_other_instruction(irp, instruction->operand);
70 ir_print_other_instruction(irp, return_instruction->value);
71 }
72}76}
7377
74static void ir_print_const(IrPrint *irp, IrInstructionConst *const_instruction) {78static void ir_print_const(IrPrint *irp, IrInstructionConst *const_instruction) {
...@@ -1329,14 +1333,6 @@ static void ir_print_reset_result(IrPrint *irp, IrInstructionResetResult *instru...@@ -1329,14 +1333,6 @@ static void ir_print_reset_result(IrPrint *irp, IrInstructionResetResult *instru
1329 fprintf(irp->f, ")");1333 fprintf(irp->f, ")");
1330}1334}
13311335
1332static void ir_print_result_ptr(IrPrint *irp, IrInstructionResultPtr *instruction) {
1333 fprintf(irp->f, "ResultPtr(");
1334 ir_print_result_loc(irp, instruction->result_loc);
1335 fprintf(irp->f, ",");
1336 ir_print_other_instruction(irp, instruction->result);
1337 fprintf(irp->f, ")");
1338}
1339
1340static void ir_print_opaque_type(IrPrint *irp, IrInstructionOpaqueType *instruction) {1336static void ir_print_opaque_type(IrPrint *irp, IrInstructionOpaqueType *instruction) {
1341 fprintf(irp->f, "@OpaqueType()");1337 fprintf(irp->f, "@OpaqueType()");
1342}1338}
...@@ -1538,9 +1534,19 @@ static void ir_print_coro_resume(IrPrint *irp, IrInstructionCoroResume *instruct...@@ -1538,9 +1534,19 @@ static void ir_print_coro_resume(IrPrint *irp, IrInstructionCoroResume *instruct
1538 fprintf(irp->f, ")");1534 fprintf(irp->f, ")");
1539}1535}
15401536
1541static void ir_print_await(IrPrint *irp, IrInstructionAwait *instruction) {1537static void ir_print_await_src(IrPrint *irp, IrInstructionAwaitSrc *instruction) {
1542 fprintf(irp->f, "@await(");1538 fprintf(irp->f, "@await(");
1543 ir_print_other_instruction(irp, instruction->frame);1539 ir_print_other_instruction(irp, instruction->frame);
1540 fprintf(irp->f, ",");
1541 ir_print_result_loc(irp, instruction->result_loc);
1542 fprintf(irp->f, ")");
1543}
1544
1545static void ir_print_await_gen(IrPrint *irp, IrInstructionAwaitGen *instruction) {
1546 fprintf(irp->f, "@await(");
1547 ir_print_other_instruction(irp, instruction->frame);
1548 fprintf(irp->f, ",");
1549 ir_print_other_instruction(irp, instruction->result_loc);
1544 fprintf(irp->f, ")");1550 fprintf(irp->f, ")");
1545}1551}
15461552
...@@ -1549,6 +1555,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {...@@ -1549,6 +1555,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
1549 switch (instruction->id) {1555 switch (instruction->id) {
1550 case IrInstructionIdInvalid:1556 case IrInstructionIdInvalid:
1551 zig_unreachable();1557 zig_unreachable();
1558 case IrInstructionIdReturnBegin:
1559 ir_print_return_begin(irp, (IrInstructionReturnBegin *)instruction);
1560 break;
1552 case IrInstructionIdReturn:1561 case IrInstructionIdReturn:
1553 ir_print_return(irp, (IrInstructionReturn *)instruction);1562 ir_print_return(irp, (IrInstructionReturn *)instruction);
1554 break;1563 break;
...@@ -1921,9 +1930,6 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {...@@ -1921,9 +1930,6 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
1921 case IrInstructionIdResetResult:1930 case IrInstructionIdResetResult:
1922 ir_print_reset_result(irp, (IrInstructionResetResult *)instruction);1931 ir_print_reset_result(irp, (IrInstructionResetResult *)instruction);
1923 break;1932 break;
1924 case IrInstructionIdResultPtr:
1925 ir_print_result_ptr(irp, (IrInstructionResultPtr *)instruction);
1926 break;
1927 case IrInstructionIdOpaqueType:1933 case IrInstructionIdOpaqueType:
1928 ir_print_opaque_type(irp, (IrInstructionOpaqueType *)instruction);1934 ir_print_opaque_type(irp, (IrInstructionOpaqueType *)instruction);
1929 break;1935 break;
...@@ -2020,8 +2026,11 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {...@@ -2020,8 +2026,11 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
2020 case IrInstructionIdCoroResume:2026 case IrInstructionIdCoroResume:
2021 ir_print_coro_resume(irp, (IrInstructionCoroResume *)instruction);2027 ir_print_coro_resume(irp, (IrInstructionCoroResume *)instruction);
2022 break;2028 break;
2023 case IrInstructionIdAwait:2029 case IrInstructionIdAwaitSrc:
2024 ir_print_await(irp, (IrInstructionAwait *)instruction);2030 ir_print_await_src(irp, (IrInstructionAwaitSrc *)instruction);
2031 break;
2032 case IrInstructionIdAwaitGen:
2033 ir_print_await_gen(irp, (IrInstructionAwaitGen *)instruction);
2025 break;2034 break;
2026 }2035 }
2027 fprintf(irp->f, "\n");2036 fprintf(irp->f, "\n");