| author | |
| committer | |
| log | 400500a3afafca8178f13a7e4e1cd0ae7808aff2 |
| tree | f6ee011721206db3cda4952dd2eccaeb71c7e632 |
| parent | 20f63e588e62c4a7250bc96c9e5b54c8106ad1af |
| signature |
* 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->T | 33 | - anyframe, anyframe->T |
| 34 | * safety for double await | 34 | * safety for double await |
| 35 | * call graph analysis to have fewer stack trace frames | 35 | * 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, | ||
| 1560 | 1561 | ||
| 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 | }; |
| 2361 | 2365 | ||
| ... | @@ -2630,7 +2634,13 @@ struct IrInstructionConst { | ... | @@ -2630,7 +2634,13 @@ struct IrInstructionConst { |
| 2630 | struct IrInstructionReturn { | 2634 | struct IrInstructionReturn { |
| 2631 | IrInstruction base; | 2635 | IrInstruction base; |
| 2632 | 2636 | ||
| 2633 | IrInstruction *value; | 2637 | IrInstruction *operand; |
| 2638 | }; | ||
| 2639 | |||
| 2640 | struct IrInstructionReturnBegin { | ||
| 2641 | IrInstruction base; | ||
| 2642 | |||
| 2643 | IrInstruction *operand; | ||
| 2634 | }; | 2644 | }; |
| 2635 | 2645 | ||
| 2636 | enum CastOp { | 2646 | enum CastOp { |
| ... | @@ -3136,6 +3146,7 @@ struct IrInstructionTestErrSrc { | ... | @@ -3136,6 +3146,7 @@ struct IrInstructionTestErrSrc { |
| 3136 | IrInstruction base; | 3146 | IrInstruction base; |
| 3137 | 3147 | ||
| 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 | }; |
| 3141 | 3152 | ||
| ... | @@ -3603,10 +3614,18 @@ struct IrInstructionSuspendFinish { | ... | @@ -3603,10 +3614,18 @@ struct IrInstructionSuspendFinish { |
| 3603 | IrInstructionSuspendBegin *begin; | 3614 | IrInstructionSuspendBegin *begin; |
| 3604 | }; | 3615 | }; |
| 3605 | 3616 | ||
| 3606 | struct IrInstructionAwait { | 3617 | struct IrInstructionAwaitSrc { |
| 3607 | IrInstruction base; | 3618 | IrInstruction base; |
| 3608 | 3619 | ||
| 3609 | IrInstruction *frame; | 3620 | IrInstruction *frame; |
| 3621 | ResultLoc *result_loc; | ||
| 3622 | }; | ||
| 3623 | |||
| 3624 | struct IrInstructionAwaitGen { | ||
| 3625 | IrInstruction base; | ||
| 3626 | |||
| 3627 | IrInstruction *frame; | ||
| 3628 | IrInstruction *result_loc; | ||
| 3610 | }; | 3629 | }; |
| 3611 | 3630 | ||
| 3612 | struct IrInstructionCoroResume { | 3631 | struct 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) { |
| 3848 | 3848 | ||
| 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) { |
| 5224 | 5231 | ||
| 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); |
| 5229 | 5239 | ||
| 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); |
| 5232 | 5242 | ||
| 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_type | 5244 | field_names.append("@ptr_stack_trace"); |
| 5235 | 5245 | 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 | } |
| 5242 | 5247 | ||
| 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 | } |
| 5257 | 5262 | ||
| 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_type | 5264 | (void)get_ptr_to_stack_trace_type(g); // populate g->stack_trace_type |
| 5260 | 5265 | ||
| 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 |
| 7570 | 7575 | ||
| 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_result | 7578 | 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)); // result | 7580 | 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_trace | 7582 | 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 | }; |
| 7644 | 7649 |
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> |
| 26 | 26 | ||
| 27 | enum ResumeId { | ||
| 28 | ResumeIdManual, | ||
| 29 | ResumeIdReturn, | ||
| 30 | ResumeIdCall, | ||
| 31 | |||
| 32 | ResumeIdAwaitEarlyReturn // must be last | ||
| 33 | }; | ||
| 34 | |||
| 27 | static void init_darwin_native(CodeGen *g) { | 35 | static 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 | } |
| 299 | 307 | ||
| 300 | // label (grep this): [coro_frame_struct_layout] | 308 | // label (grep this): [coro_frame_struct_layout] |
| 301 | static uint32_t frame_index_trace_arg(CodeGen *g, FnTypeId *fn_type_id) { | 309 | static uint32_t frame_index_trace_arg(CodeGen *g, ZigType *return_type) { |
| 302 | // [0] *ReturnType | 310 | // [0] *ReturnType (callee's) |
| 303 | // [1] ReturnType | 311 | // [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 | } |
| 307 | 316 | ||
| 308 | // label (grep this): [coro_frame_struct_layout] | 317 | // label (grep this): [coro_frame_struct_layout] |
| 309 | static uint32_t frame_index_arg(CodeGen *g, FnTypeId *fn_type_id) { | 318 | static 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] StackTrace | 320 | // [0] *StackTrace |
| 312 | // [1] [stack_trace_ptr_count]usize | 321 | 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 | } |
| 316 | 324 | ||
| 317 | // label (grep this): [coro_frame_struct_layout] | 325 | // label (grep this): [coro_frame_struct_layout] |
| 318 | static uint32_t frame_index_trace_stack(CodeGen *g, FnTypeId *fn_type_id) { | 326 | static 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 | } |
| 1306 | 1323 | ||
| 1307 | static void gen_safety_crash_for_err(CodeGen *g, LLVMValueRef err_val, Scope *scope) { | 1324 | static 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 | } |
| 2025 | 2042 | ||
| 2026 | static LLVMValueRef ir_render_return(CodeGen *g, IrExecutable *executable, | 2043 | static 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 | |||
| 2067 | static 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 | |||
| 2088 | static 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 | |||
| 2153 | static 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; |
| 2034 | 2159 | ||
| 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 | } |
| 2039 | 2164 | ||
| 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 signals | 2174 | |
| 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); | ||
| 2076 | 2190 | ||
| 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); |
| 2089 | 2198 | ||
| 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) { |
| 3417 | static void render_async_spills(CodeGen *g) { | 3526 | static 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); |
| 3423 | 3532 | ||
| ... | @@ -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 |
| 3553 | 3662 | ||
| 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 pointer | 3700 | 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 | } |
| 3601 | 3715 | ||
| 3602 | // even if prefix_arg_err_ret_stack is true, let the async function do its | 3716 | 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; |
| 3653 | 3771 | ||
| 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); |
| 3656 | 3774 | ||
| 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); |
| 3695 | 3812 | ||
| 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); |
| 3701 | 3818 | ||
| 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); |
| 3718 | 3822 | ||
| 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 | } |
| 3728 | 3832 | ||
| 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 | } |
| 5193 | 5297 | ||
| 5194 | static LLVMValueRef ir_render_await(CodeGen *g, IrExecutable *executable, IrInstructionAwait *instruction) { | 5298 | static 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. |
| 5210 | 5315 | ||
| 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 pointer | 5337 | // 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); |
| 5224 | 5342 | ||
| 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"); | ||
| 5227 | 5346 | ||
| 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); | ||
| 5232 | 5349 | ||
| 5233 | LLVMAddCase(switch_instr, zero, complete_suspend_block); | 5350 | LLVMAddCase(switch_instr, zero, complete_suspend_block); |
| 5234 | 5351 | 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); | ||
| 5237 | 5352 | ||
| 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); |
| 5241 | 5356 | ||
| 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); |
| 5245 | 5368 | ||
| 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 above | 5370 | 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 | } |
| 5276 | 5376 | ||
| 5277 | static LLVMValueRef ir_render_coro_resume(CodeGen *g, IrExecutable *executable, | 5377 | static 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 | } |
| 5293 | 5387 | ||
| ... | @@ -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(); |
| 5397 | 5491 | ||
| 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 | } |
| 6791 | 6890 | ||
| 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, ""); |
| 6806 | 6905 | ||
| 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 | } |
| 9727 | 9826 | ||
| 9728 | bool codegen_fn_has_err_ret_tracing_stack(CodeGen *g, ZigFn *fn) { | 9827 | bool 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); |
| 62 | 62 | ||
| 63 | void codegen_release_caches(CodeGen *codegen); | 63 | void codegen_release_caches(CodeGen *codegen); |
| 64 | bool codegen_fn_has_err_ret_tracing_arg(CodeGen *g, ZigType *return_type); | 64 | bool codegen_fn_has_err_ret_tracing_arg(CodeGen *g, ZigType *return_type); |
| 65 | bool codegen_fn_has_err_ret_tracing_stack(CodeGen *g, ZigFn *fn); | 65 | bool codegen_fn_has_err_ret_tracing_stack(CodeGen *g, ZigFn *fn, bool is_async); |
| 66 | 66 | ||
| 67 | #endif | 67 | #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 | } |
| 527 | 527 | ||
| 528 | static constexpr IrInstructionId ir_instruction_id(IrInstructionReturnBegin *) { | ||
| 529 | return IrInstructionIdReturnBegin; | ||
| 530 | } | ||
| 531 | |||
| 528 | static constexpr IrInstructionId ir_instruction_id(IrInstructionCast *) { | 532 | static 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 | } |
| 947 | 951 | ||
| 948 | static constexpr IrInstructionId ir_instruction_id(IrInstructionResultPtr *) { | ||
| 949 | return IrInstructionIdResultPtr; | ||
| 950 | } | ||
| 951 | |||
| 952 | static constexpr IrInstructionId ir_instruction_id(IrInstructionPtrOfArrayToSlice *) { | 952 | static 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 | } |
| 1051 | 1051 | ||
| 1052 | static constexpr IrInstructionId ir_instruction_id(IrInstructionAwait *) { | 1052 | static constexpr IrInstructionId ir_instruction_id(IrInstructionAwaitSrc *) { |
| 1053 | return IrInstructionIdAwait; | 1053 | return IrInstructionIdAwaitSrc; |
| 1054 | } | ||
| 1055 | |||
| 1056 | static constexpr IrInstructionId ir_instruction_id(IrInstructionAwaitGen *) { | ||
| 1057 | return IrInstructionIdAwaitGen; | ||
| 1054 | } | 1058 | } |
| 1055 | 1059 | ||
| 1056 | static constexpr IrInstructionId ir_instruction_id(IrInstructionCoroResume *) { | 1060 | static 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 | } |
| 1110 | 1114 | ||
| 1111 | static IrInstruction *ir_build_return(IrBuilder *irb, Scope *scope, AstNode *source_node, | 1115 | static 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 | |||
| 1128 | static 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; | ||
| 1118 | 1135 | ||
| 1119 | if (return_value != nullptr) ir_ref_instruction(return_value, irb->current_basic_block); | 1136 | ir_ref_instruction(operand, irb->current_basic_block); |
| 1120 | 1137 | ||
| 1121 | return &return_instruction->base; | 1138 | return &return_instruction->base; |
| 1122 | } | 1139 | } |
| 1123 | 1140 | ||
| 1141 | |||
| 1124 | static IrInstruction *ir_build_const_void(IrBuilder *irb, Scope *scope, AstNode *source_node) { | 1142 | static 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 | } |
| 2526 | 2544 | ||
| 2527 | static IrInstruction *ir_build_test_err_src(IrBuilder *irb, Scope *scope, AstNode *source_node, | 2545 | static 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; | ||
| 2533 | 2552 | ||
| 2534 | ir_ref_instruction(base_ptr, irb->current_basic_block); | 2553 | ir_ref_instruction(base_ptr, irb->current_basic_block); |
| 2535 | 2554 | ||
| ... | @@ -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 | } |
| 2973 | 2992 | ||
| 2974 | static 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 | |||
| 2986 | static IrInstruction *ir_build_opaque_type(IrBuilder *irb, Scope *scope, AstNode *source_node) { | 2993 | static 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); |
| 2988 | 2995 | ||
| ... | @@ -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 | } |
| 3268 | 3275 | ||
| 3269 | static IrInstruction *ir_build_await(IrBuilder *irb, Scope *scope, AstNode *source_node, | 3276 | static 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; | ||
| 3274 | 3282 | ||
| 3275 | ir_ref_instruction(frame, irb->current_basic_block); | 3283 | ir_ref_instruction(frame, irb->current_basic_block); |
| 3276 | 3284 | ||
| 3277 | return &instruction->base; | 3285 | return &instruction->base; |
| 3278 | } | 3286 | } |
| 3279 | 3287 | ||
| 3288 | static 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 | |||
| 3280 | static IrInstruction *ir_build_coro_resume(IrBuilder *irb, Scope *scope, AstNode *source_node, | 3303 | static 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 | } |
| 3418 | 3441 | ||
| 3419 | static 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 | |||
| 3429 | static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node, LVal lval, ResultLoc *result_loc) { | 3442 | static 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); |
| 3431 | 3444 | ||
| ... | @@ -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 | } |
| 3469 | 3482 | ||
| 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 | } | ||
| 3479 | 3491 | ||
| 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); | ||
| 3483 | 3493 | ||
| 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"); |
| 3494 | 3504 | ||
| 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); |
| 3503 | 3511 | ||
| 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); |
| 3509 | 3515 | ||
| 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 defers | 3522 | // 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); |
| 3529 | 3537 | ||
| 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)); |
| 3540 | 3548 | ||
| 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 | } |
| 3557 | 3566 | ||
| ... | @@ -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; |
| 6898 | 6908 | ||
| 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); |
| 6901 | 6911 | ||
| 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; |
| 7515 | 7525 | ||
| 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); |
| 7517 | 7527 | ||
| 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 | } |
| 7832 | 7842 | ||
| 7833 | static IrInstruction *ir_gen_await_expr(IrBuilder *irb, Scope *scope, AstNode *node) { | 7843 | static 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); |
| 7835 | 7847 | ||
| 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; |
| 7854 | 7866 | ||
| 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 | } |
| 7857 | 7870 | ||
| 7858 | static IrInstruction *ir_gen_suspend(IrBuilder *irb, Scope *parent_scope, AstNode *node) { | 7871 | static 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; |
| 8089 | 8102 | ||
| 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 error | 8105 | // 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 | } |
| 8094 | 8109 | ||
| 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 | } |
| 12595 | 12611 | ||
| 12612 | static 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 | |||
| 12596 | static IrInstruction *ir_analyze_instruction_return(IrAnalyze *ira, IrInstructionReturn *instruction) { | 12632 | static 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); |
| 12600 | 12636 | ||
| 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 | } |
| 12608 | 12644 | ||
| 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 | } |
| 12619 | 12650 | ||
| 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 | } |
| 22178 | 22209 | ||
| 22179 | static 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 | |||
| 22192 | static void ir_eval_mul_add(IrAnalyze *ira, IrInstructionMulAdd *source_instr, ZigType *float_type, | 22210 | static 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; |
| 22315 | 22333 | ||
| 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 | } |
| 24445 | 24468 | ||
| 24446 | static IrInstruction *ir_analyze_instruction_await(IrAnalyze *ira, IrInstructionAwait *instruction) { | 24469 | static 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 | } |
| 24486 | 24509 | ||
| 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 | } |
| 24492 | 24523 | ||
| ... | @@ -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(); |
| 24545 | 24577 | ||
| 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; |
| 24948 | 24982 | ||
| 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; |
| 25046 | 25079 | ||
| 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 | } |
| 66 | 66 | ||
| 67 | static void ir_print_return(IrPrint *irp, IrInstructionReturn *return_instruction) { | 67 | static 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 | |||
| 73 | static 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 | } |
| 73 | 77 | ||
| 74 | static void ir_print_const(IrPrint *irp, IrInstructionConst *const_instruction) { | 78 | static 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 | } |
| 1331 | 1335 | ||
| 1332 | static 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 | |||
| 1340 | static void ir_print_opaque_type(IrPrint *irp, IrInstructionOpaqueType *instruction) { | 1336 | static 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 | } |
| 1540 | 1536 | ||
| 1541 | static void ir_print_await(IrPrint *irp, IrInstructionAwait *instruction) { | 1537 | static 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 | |||
| 1545 | static 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 | } |
| 1546 | 1552 | ||
| ... | @@ -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"); |