| author | |
| committer | |
| log | 2e7f53f1f0d8339b8dc90ad7e0bc9963f1ec471c |
| tree | eb01071160fb814d972d4db3ee611d5ae5524629 |
| parent | 614cab5d68176ea56e48195d04997738297429a1 |
| signature |
6 files changed, 58 insertions(+), 17 deletions(-)
src/all_types.hpp+4-3| ... | @@ -1725,6 +1725,7 @@ struct CodeGen { | ... | @@ -1725,6 +1725,7 @@ struct CodeGen { |
| 1725 | LLVMValueRef cur_async_resume_index_ptr; | 1725 | LLVMValueRef cur_async_resume_index_ptr; |
| 1726 | LLVMValueRef cur_async_awaiter_ptr; | 1726 | LLVMValueRef cur_async_awaiter_ptr; |
| 1727 | LLVMValueRef cur_async_prev_val; | 1727 | LLVMValueRef cur_async_prev_val; |
| 1728 | LLVMValueRef cur_async_prev_val_field_ptr; | ||
| 1728 | LLVMBasicBlockRef cur_preamble_llvm_block; | 1729 | LLVMBasicBlockRef cur_preamble_llvm_block; |
| 1729 | size_t cur_resume_block_count; | 1730 | size_t cur_resume_block_count; |
| 1730 | LLVMValueRef cur_err_ret_trace_val_arg; | 1731 | LLVMValueRef cur_err_ret_trace_val_arg; |
| ... | @@ -1886,6 +1887,7 @@ struct CodeGen { | ... | @@ -1886,6 +1887,7 @@ struct CodeGen { |
| 1886 | bool system_linker_hack; | 1887 | bool system_linker_hack; |
| 1887 | bool reported_bad_link_libc_error; | 1888 | bool reported_bad_link_libc_error; |
| 1888 | bool is_dynamic; // shared library rather than static library. dynamic musl rather than static musl. | 1889 | bool is_dynamic; // shared library rather than static library. dynamic musl rather than static musl. |
| 1890 | bool cur_is_after_return; | ||
| 1889 | 1891 | ||
| 1890 | //////////////////////////// Participates in Input Parameter Cache Hash | 1892 | //////////////////////////// Participates in Input Parameter Cache Hash |
| 1891 | /////// Note: there is a separate cache hash for builtin.zig, when adding fields, | 1893 | /////// Note: there is a separate cache hash for builtin.zig, when adding fields, |
| ... | @@ -3639,8 +3641,6 @@ struct IrInstructionCoroResume { | ... | @@ -3639,8 +3641,6 @@ struct IrInstructionCoroResume { |
| 3639 | 3641 | ||
| 3640 | struct IrInstructionTestCancelRequested { | 3642 | struct IrInstructionTestCancelRequested { |
| 3641 | IrInstruction base; | 3643 | IrInstruction base; |
| 3642 | |||
| 3643 | bool use_return_begin_prev_value; | ||
| 3644 | }; | 3644 | }; |
| 3645 | 3645 | ||
| 3646 | enum ResultLocId { | 3646 | enum ResultLocId { |
| ... | @@ -3730,7 +3730,8 @@ static const size_t err_union_payload_index = 1; | ... | @@ -3730,7 +3730,8 @@ static const size_t err_union_payload_index = 1; |
| 3730 | static const size_t coro_fn_ptr_index = 0; | 3730 | static const size_t coro_fn_ptr_index = 0; |
| 3731 | static const size_t coro_resume_index = 1; | 3731 | static const size_t coro_resume_index = 1; |
| 3732 | static const size_t coro_awaiter_index = 2; | 3732 | static const size_t coro_awaiter_index = 2; |
| 3733 | static const size_t coro_ret_start = 3; | 3733 | static const size_t coro_prev_val_index = 3; |
| 3734 | static const size_t coro_ret_start = 4; | ||
| 3734 | 3735 | ||
| 3735 | // TODO call graph analysis to find out what this number needs to be for every function | 3736 | // TODO call graph analysis to find out what this number needs to be for every function |
| 3736 | // MUST BE A POWER OF TWO. | 3737 | // MUST BE A POWER OF TWO. |
src/analyze.cpp+4| ... | @@ -5246,6 +5246,9 @@ static Error resolve_coro_frame(CodeGen *g, ZigType *frame_type) { | ... | @@ -5246,6 +5246,9 @@ static Error resolve_coro_frame(CodeGen *g, ZigType *frame_type) { |
| 5246 | field_names.append("@awaiter"); | 5246 | field_names.append("@awaiter"); |
| 5247 | field_types.append(g->builtin_types.entry_usize); | 5247 | field_types.append(g->builtin_types.entry_usize); |
| 5248 | 5248 | ||
| 5249 | field_names.append("@prev_val"); | ||
| 5250 | field_types.append(g->builtin_types.entry_usize); | ||
| 5251 | |||
| 5249 | FnTypeId *fn_type_id = &fn_type->data.fn.fn_type_id; | 5252 | FnTypeId *fn_type_id = &fn_type->data.fn.fn_type_id; |
| 5250 | ZigType *ptr_return_type = get_pointer_to_type(g, fn_type_id->return_type, false); | 5253 | ZigType *ptr_return_type = get_pointer_to_type(g, fn_type_id->return_type, false); |
| 5251 | field_names.append("@result_ptr_callee"); | 5254 | field_names.append("@result_ptr_callee"); |
| ... | @@ -7592,6 +7595,7 @@ static void resolve_llvm_types_any_frame(CodeGen *g, ZigType *any_frame_type, Re | ... | @@ -7592,6 +7595,7 @@ static void resolve_llvm_types_any_frame(CodeGen *g, ZigType *any_frame_type, Re |
| 7592 | field_types.append(ptr_fn_llvm_type); // fn_ptr | 7595 | field_types.append(ptr_fn_llvm_type); // fn_ptr |
| 7593 | field_types.append(usize_type_ref); // resume_index | 7596 | field_types.append(usize_type_ref); // resume_index |
| 7594 | field_types.append(usize_type_ref); // awaiter | 7597 | field_types.append(usize_type_ref); // awaiter |
| 7598 | field_types.append(usize_type_ref); // prev_val | ||
| 7595 | 7599 | ||
| 7596 | bool have_result_type = result_type != nullptr && type_has_bits(result_type); | 7600 | bool have_result_type = result_type != nullptr && type_has_bits(result_type); |
| 7597 | if (have_result_type) { | 7601 | if (have_result_type) { |
src/codegen.cpp+20-3| ... | @@ -2226,7 +2226,18 @@ static LLVMValueRef gen_resume(CodeGen *g, LLVMValueRef fn_val, LLVMValueRef tar | ... | @@ -2226,7 +2226,18 @@ static LLVMValueRef gen_resume(CodeGen *g, LLVMValueRef fn_val, LLVMValueRef tar |
| 2226 | return ZigLLVMBuildCall(g->builder, fn_val, args, 2, LLVMFastCallConv, ZigLLVM_FnInlineAuto, ""); | 2226 | return ZigLLVMBuildCall(g->builder, fn_val, args, 2, LLVMFastCallConv, ZigLLVM_FnInlineAuto, ""); |
| 2227 | } | 2227 | } |
| 2228 | 2228 | ||
| 2229 | static LLVMValueRef get_cur_async_prev_val(CodeGen *g) { | ||
| 2230 | if (g->cur_async_prev_val != nullptr) { | ||
| 2231 | return g->cur_async_prev_val; | ||
| 2232 | } | ||
| 2233 | g->cur_async_prev_val = LLVMBuildLoad(g->builder, g->cur_async_prev_val_field_ptr, ""); | ||
| 2234 | return g->cur_async_prev_val; | ||
| 2235 | } | ||
| 2236 | |||
| 2229 | static LLVMBasicBlockRef gen_suspend_begin(CodeGen *g, const char *name_hint) { | 2237 | static LLVMBasicBlockRef gen_suspend_begin(CodeGen *g, const char *name_hint) { |
| 2238 | // This becomes invalid when a suspend happens. | ||
| 2239 | g->cur_async_prev_val = nullptr; | ||
| 2240 | |||
| 2230 | LLVMTypeRef usize_type_ref = g->builtin_types.entry_usize->llvm_type; | 2241 | LLVMTypeRef usize_type_ref = g->builtin_types.entry_usize->llvm_type; |
| 2231 | LLVMBasicBlockRef resume_bb = LLVMAppendBasicBlock(g->cur_fn_val, name_hint); | 2242 | LLVMBasicBlockRef resume_bb = LLVMAppendBasicBlock(g->cur_fn_val, name_hint); |
| 2232 | size_t new_block_index = g->cur_resume_block_count; | 2243 | size_t new_block_index = g->cur_resume_block_count; |
| ... | @@ -2319,6 +2330,9 @@ static LLVMValueRef ir_render_return_begin(CodeGen *g, IrExecutable *executable, | ... | @@ -2319,6 +2330,9 @@ static LLVMValueRef ir_render_return_begin(CodeGen *g, IrExecutable *executable, |
| 2319 | LLVMBasicBlockRef incoming_blocks[] = { after_resume_block, switch_bb }; | 2330 | LLVMBasicBlockRef incoming_blocks[] = { after_resume_block, switch_bb }; |
| 2320 | LLVMAddIncoming(g->cur_async_prev_val, incoming_values, incoming_blocks, 2); | 2331 | LLVMAddIncoming(g->cur_async_prev_val, incoming_values, incoming_blocks, 2); |
| 2321 | 2332 | ||
| 2333 | g->cur_is_after_return = true; | ||
| 2334 | LLVMBuildStore(g->builder, g->cur_async_prev_val, g->cur_async_prev_val_field_ptr); | ||
| 2335 | |||
| 2322 | if (!ret_type_has_bits) { | 2336 | if (!ret_type_has_bits) { |
| 2323 | return nullptr; | 2337 | return nullptr; |
| 2324 | } | 2338 | } |
| ... | @@ -2366,7 +2380,7 @@ static LLVMValueRef ir_render_return(CodeGen *g, IrExecutable *executable, IrIns | ... | @@ -2366,7 +2380,7 @@ static LLVMValueRef ir_render_return(CodeGen *g, IrExecutable *executable, IrIns |
| 2366 | ZigType *any_frame_type = get_any_frame_type(g, ret_type); | 2380 | ZigType *any_frame_type = get_any_frame_type(g, ret_type); |
| 2367 | LLVMValueRef one = LLVMConstInt(usize_type_ref, 1, false); | 2381 | LLVMValueRef one = LLVMConstInt(usize_type_ref, 1, false); |
| 2368 | LLVMValueRef mask_val = LLVMConstNot(one); | 2382 | LLVMValueRef mask_val = LLVMConstNot(one); |
| 2369 | LLVMValueRef masked_prev_val = LLVMBuildAnd(g->builder, g->cur_async_prev_val, mask_val, ""); | 2383 | LLVMValueRef masked_prev_val = LLVMBuildAnd(g->builder, get_cur_async_prev_val(g), mask_val, ""); |
| 2370 | LLVMValueRef their_frame_ptr = LLVMBuildIntToPtr(g->builder, masked_prev_val, | 2384 | LLVMValueRef their_frame_ptr = LLVMBuildIntToPtr(g->builder, masked_prev_val, |
| 2371 | get_llvm_type(g, any_frame_type), ""); | 2385 | get_llvm_type(g, any_frame_type), ""); |
| 2372 | LLVMValueRef call_inst = gen_resume(g, nullptr, their_frame_ptr, ResumeIdReturn, nullptr); | 2386 | LLVMValueRef call_inst = gen_resume(g, nullptr, their_frame_ptr, ResumeIdReturn, nullptr); |
| ... | @@ -5590,8 +5604,8 @@ static LLVMValueRef ir_render_test_cancel_requested(CodeGen *g, IrExecutable *ex | ... | @@ -5590,8 +5604,8 @@ static LLVMValueRef ir_render_test_cancel_requested(CodeGen *g, IrExecutable *ex |
| 5590 | { | 5604 | { |
| 5591 | if (!fn_is_async(g->cur_fn)) | 5605 | if (!fn_is_async(g->cur_fn)) |
| 5592 | return LLVMConstInt(LLVMInt1Type(), 0, false); | 5606 | return LLVMConstInt(LLVMInt1Type(), 0, false); |
| 5593 | if (instruction->use_return_begin_prev_value) { | 5607 | if (g->cur_is_after_return) { |
| 5594 | return LLVMBuildTrunc(g->builder, g->cur_async_prev_val, LLVMInt1Type(), ""); | 5608 | return LLVMBuildTrunc(g->builder, get_cur_async_prev_val(g), LLVMInt1Type(), ""); |
| 5595 | } else { | 5609 | } else { |
| 5596 | zig_panic("TODO"); | 5610 | zig_panic("TODO"); |
| 5597 | } | 5611 | } |
| ... | @@ -7063,6 +7077,7 @@ static void do_code_gen(CodeGen *g) { | ... | @@ -7063,6 +7077,7 @@ static void do_code_gen(CodeGen *g) { |
| 7063 | } | 7077 | } |
| 7064 | 7078 | ||
| 7065 | if (is_async) { | 7079 | if (is_async) { |
| 7080 | g->cur_is_after_return = false; | ||
| 7066 | g->cur_resume_block_count = 0; | 7081 | g->cur_resume_block_count = 0; |
| 7067 | 7082 | ||
| 7068 | LLVMTypeRef usize_type_ref = g->builtin_types.entry_usize->llvm_type; | 7083 | LLVMTypeRef usize_type_ref = g->builtin_types.entry_usize->llvm_type; |
| ... | @@ -7099,6 +7114,8 @@ static void do_code_gen(CodeGen *g) { | ... | @@ -7099,6 +7114,8 @@ static void do_code_gen(CodeGen *g) { |
| 7099 | g->cur_err_ret_trace_val_stack = LLVMBuildStructGEP(g->builder, g->cur_frame_ptr, | 7114 | g->cur_err_ret_trace_val_stack = LLVMBuildStructGEP(g->builder, g->cur_frame_ptr, |
| 7100 | trace_field_index_stack, ""); | 7115 | trace_field_index_stack, ""); |
| 7101 | } | 7116 | } |
| 7117 | g->cur_async_prev_val_field_ptr = LLVMBuildStructGEP(g->builder, g->cur_frame_ptr, | ||
| 7118 | coro_prev_val_index, ""); | ||
| 7102 | 7119 | ||
| 7103 | LLVMValueRef resume_index = LLVMBuildLoad(g->builder, resume_index_ptr, ""); | 7120 | LLVMValueRef resume_index = LLVMBuildLoad(g->builder, resume_index_ptr, ""); |
| 7104 | LLVMValueRef switch_instr = LLVMBuildSwitch(g->builder, resume_index, bad_resume_block, 4); | 7121 | LLVMValueRef switch_instr = LLVMBuildSwitch(g->builder, resume_index, bad_resume_block, 4); |
src/ir.cpp+4-8| ... | @@ -3325,12 +3325,9 @@ static IrInstruction *ir_build_coro_resume(IrBuilder *irb, Scope *scope, AstNode | ... | @@ -3325,12 +3325,9 @@ static IrInstruction *ir_build_coro_resume(IrBuilder *irb, Scope *scope, AstNode |
| 3325 | return &instruction->base; | 3325 | return &instruction->base; |
| 3326 | } | 3326 | } |
| 3327 | 3327 | ||
| 3328 | static IrInstruction *ir_build_test_cancel_requested(IrBuilder *irb, Scope *scope, AstNode *source_node, | 3328 | static IrInstruction *ir_build_test_cancel_requested(IrBuilder *irb, Scope *scope, AstNode *source_node) { |
| 3329 | bool use_return_begin_prev_value) | ||
| 3330 | { | ||
| 3331 | IrInstructionTestCancelRequested *instruction = ir_build_instruction<IrInstructionTestCancelRequested>(irb, scope, source_node); | 3329 | IrInstructionTestCancelRequested *instruction = ir_build_instruction<IrInstructionTestCancelRequested>(irb, scope, source_node); |
| 3332 | instruction->base.value.type = irb->codegen->builtin_types.entry_bool; | 3330 | instruction->base.value.type = irb->codegen->builtin_types.entry_bool; |
| 3333 | instruction->use_return_begin_prev_value = use_return_begin_prev_value; | ||
| 3334 | 3331 | ||
| 3335 | return &instruction->base; | 3332 | return &instruction->base; |
| 3336 | } | 3333 | } |
| ... | @@ -3546,7 +3543,7 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node, | ... | @@ -3546,7 +3543,7 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node, |
| 3546 | 3543 | ||
| 3547 | if (need_test_cancel) { | 3544 | if (need_test_cancel) { |
| 3548 | ir_set_cursor_at_end_and_append_block(irb, ok_block); | 3545 | ir_set_cursor_at_end_and_append_block(irb, ok_block); |
| 3549 | IrInstruction *is_canceled = ir_build_test_cancel_requested(irb, scope, node, true); | 3546 | IrInstruction *is_canceled = ir_build_test_cancel_requested(irb, scope, node); |
| 3550 | ir_mark_gen(ir_build_cond_br(irb, scope, node, is_canceled, | 3547 | ir_mark_gen(ir_build_cond_br(irb, scope, node, is_canceled, |
| 3551 | all_defers_block, normal_defers_block, force_comptime)); | 3548 | all_defers_block, normal_defers_block, force_comptime)); |
| 3552 | } | 3549 | } |
| ... | @@ -3830,7 +3827,7 @@ static IrInstruction *ir_gen_block(IrBuilder *irb, Scope *parent_scope, AstNode | ... | @@ -3830,7 +3827,7 @@ static IrInstruction *ir_gen_block(IrBuilder *irb, Scope *parent_scope, AstNode |
| 3830 | ir_gen_defers_for_block(irb, child_scope, outer_block_scope, false); | 3827 | ir_gen_defers_for_block(irb, child_scope, outer_block_scope, false); |
| 3831 | return ir_mark_gen(ir_build_return(irb, child_scope, result->source_node, result)); | 3828 | return ir_mark_gen(ir_build_return(irb, child_scope, result->source_node, result)); |
| 3832 | } | 3829 | } |
| 3833 | IrInstruction *is_canceled = ir_build_test_cancel_requested(irb, child_scope, block_node, true); | 3830 | IrInstruction *is_canceled = ir_build_test_cancel_requested(irb, child_scope, block_node); |
| 3834 | IrBasicBlock *all_defers_block = ir_create_basic_block(irb, child_scope, "ErrDefers"); | 3831 | IrBasicBlock *all_defers_block = ir_create_basic_block(irb, child_scope, "ErrDefers"); |
| 3835 | IrBasicBlock *normal_defers_block = ir_create_basic_block(irb, child_scope, "Defers"); | 3832 | IrBasicBlock *normal_defers_block = ir_create_basic_block(irb, child_scope, "Defers"); |
| 3836 | IrBasicBlock *ret_stmt_block = ir_create_basic_block(irb, child_scope, "RetStmt"); | 3833 | IrBasicBlock *ret_stmt_block = ir_create_basic_block(irb, child_scope, "RetStmt"); |
| ... | @@ -24725,8 +24722,7 @@ static IrInstruction *ir_analyze_instruction_test_cancel_requested(IrAnalyze *ir | ... | @@ -24725,8 +24722,7 @@ static IrInstruction *ir_analyze_instruction_test_cancel_requested(IrAnalyze *ir |
| 24725 | if (ir_should_inline(ira->new_irb.exec, instruction->base.scope)) { | 24722 | if (ir_should_inline(ira->new_irb.exec, instruction->base.scope)) { |
| 24726 | return ir_const_bool(ira, &instruction->base, false); | 24723 | return ir_const_bool(ira, &instruction->base, false); |
| 24727 | } | 24724 | } |
| 24728 | return ir_build_test_cancel_requested(&ira->new_irb, instruction->base.scope, instruction->base.source_node, | 24725 | return ir_build_test_cancel_requested(&ira->new_irb, instruction->base.scope, instruction->base.source_node); |
| 24729 | instruction->use_return_begin_prev_value); | ||
| 24730 | } | 24726 | } |
| 24731 | 24727 | ||
| 24732 | static IrInstruction *ir_analyze_instruction_base(IrAnalyze *ira, IrInstruction *instruction) { | 24728 | static IrInstruction *ir_analyze_instruction_base(IrAnalyze *ira, IrInstruction *instruction) { |
src/ir_print.cpp+1-2| ... | @@ -1551,8 +1551,7 @@ static void ir_print_await_gen(IrPrint *irp, IrInstructionAwaitGen *instruction) | ... | @@ -1551,8 +1551,7 @@ static void ir_print_await_gen(IrPrint *irp, IrInstructionAwaitGen *instruction) |
| 1551 | } | 1551 | } |
| 1552 | 1552 | ||
| 1553 | static void ir_print_test_cancel_requested(IrPrint *irp, IrInstructionTestCancelRequested *instruction) { | 1553 | static void ir_print_test_cancel_requested(IrPrint *irp, IrInstructionTestCancelRequested *instruction) { |
| 1554 | const char *arg = instruction->use_return_begin_prev_value ? "UseReturnBeginPrevValue" : "AdditionalCheck"; | 1554 | fprintf(irp->f, "@testCancelRequested()"); |
| 1555 | fprintf(irp->f, "@testCancelRequested(%s)", arg); | ||
| 1556 | } | 1555 | } |
| 1557 | 1556 | ||
| 1558 | static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) { | 1557 | static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) { |
test/stage1/behavior/coroutines.zig+25-1| ... | @@ -318,7 +318,7 @@ test "@asyncCall with return type" { | ... | @@ -318,7 +318,7 @@ test "@asyncCall with return type" { |
| 318 | } | 318 | } |
| 319 | }; | 319 | }; |
| 320 | var foo = Foo{ .bar = Foo.middle }; | 320 | var foo = Foo{ .bar = Foo.middle }; |
| 321 | var bytes: [100]u8 = undefined; | 321 | var bytes: [150]u8 = undefined; |
| 322 | var aresult: i32 = 0; | 322 | var aresult: i32 = 0; |
| 323 | _ = @asyncCall(&bytes, &aresult, foo.bar); | 323 | _ = @asyncCall(&bytes, &aresult, foo.bar); |
| 324 | expect(aresult == 0); | 324 | expect(aresult == 0); |
| ... | @@ -589,3 +589,27 @@ test "pass string literal to async function" { | ... | @@ -589,3 +589,27 @@ test "pass string literal to async function" { |
| 589 | }; | 589 | }; |
| 590 | S.doTheTest(); | 590 | S.doTheTest(); |
| 591 | } | 591 | } |
| 592 | |||
| 593 | test "cancel inside an errdefer" { | ||
| 594 | const S = struct { | ||
| 595 | var frame: anyframe = undefined; | ||
| 596 | |||
| 597 | fn doTheTest() void { | ||
| 598 | _ = async amainWrap(); | ||
| 599 | resume frame; | ||
| 600 | } | ||
| 601 | |||
| 602 | fn amainWrap() !void { | ||
| 603 | var foo = async func(); | ||
| 604 | errdefer cancel foo; | ||
| 605 | return error.Bad; | ||
| 606 | } | ||
| 607 | |||
| 608 | fn func() void { | ||
| 609 | frame = @frame(); | ||
| 610 | suspend; | ||
| 611 | } | ||
| 612 | |||
| 613 | }; | ||
| 614 | S.doTheTest(); | ||
| 615 | } |