authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-08-15 14:05:12-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-08-15 14:05:12-04:00
log13b5a4bf8ca65c569e6b28ca0e41d101d12d0ff1
treee95ccf886a1433fe68e1779cffb357595f1774b2
parent64c293f8a4ce5fcbb506c32b989a88d982f005ce
signaturelock-open Commit is signed but in an unrecognized format.

remove `cancel`


24 files changed, 256 insertions(+), 806 deletions(-)

doc/docgen.zig-1
...@@ -750,7 +750,6 @@ fn tokenizeAndPrintRaw(docgen_tokenizer: *Tokenizer, out: var, source_token: Tok...@@ -750,7 +750,6 @@ fn tokenizeAndPrintRaw(docgen_tokenizer: *Tokenizer, out: var, source_token: Tok
750 .Keyword_async,750 .Keyword_async,
751 .Keyword_await,751 .Keyword_await,
752 .Keyword_break,752 .Keyword_break,
753 .Keyword_cancel,
754 .Keyword_catch,753 .Keyword_catch,
755 .Keyword_comptime,754 .Keyword_comptime,
756 .Keyword_const,755 .Keyword_const,
doc/langref.html.in+6-8
...@@ -5971,7 +5971,7 @@ test "global assembly" {...@@ -5971,7 +5971,7 @@ test "global assembly" {
5971 {#header_open|Async Functions#}5971 {#header_open|Async Functions#}
5972 <p>5972 <p>
5973 An async function is a function whose callsite is split into an {#syntax#}async{#endsyntax#} initiation,5973 An async function is a function whose callsite is split into an {#syntax#}async{#endsyntax#} initiation,
5974 followed by an {#syntax#}await{#endsyntax#} completion. They can also be canceled.5974 followed by an {#syntax#}await{#endsyntax#} completion.
5975 </p>5975 </p>
5976 <p>5976 <p>
5977 When you call a function, it creates a stack frame,5977 When you call a function, it creates a stack frame,
...@@ -6013,11 +6013,11 @@ test "global assembly" {...@@ -6013,11 +6013,11 @@ test "global assembly" {
6013 <p>6013 <p>
6014 The result of an async function call is a {#syntax#}promise->T{#endsyntax#} type, where {#syntax#}T{#endsyntax#}6014 The result of an async function call is a {#syntax#}promise->T{#endsyntax#} type, where {#syntax#}T{#endsyntax#}
6015 is the return type of the async function. Once a promise has been created, it must be6015 is the return type of the async function. Once a promise has been created, it must be
6016 consumed, either with {#syntax#}cancel{#endsyntax#} or {#syntax#}await{#endsyntax#}:6016 consumed with {#syntax#}await{#endsyntax#}:
6017 </p>6017 </p>
6018 <p>6018 <p>
6019 Async functions start executing when created, so in the following example, the entire6019 Async functions start executing when created, so in the following example, the entire
6020 async function completes before it is canceled:6020 TODO
6021 </p>6021 </p>
6022 {#code_begin|test#}6022 {#code_begin|test#}
6023const std = @import("std");6023const std = @import("std");
...@@ -6048,7 +6048,7 @@ fn simpleAsyncFn() void {...@@ -6048,7 +6048,7 @@ fn simpleAsyncFn() void {
6048 </p>6048 </p>
6049 <p>6049 <p>
6050 When an async function suspends itself, it must be sure that it will be6050 When an async function suspends itself, it must be sure that it will be
6051 resumed or canceled somehow, for example by registering its promise handle6051 resumed somehow, for example by registering its promise handle
6052 in an event loop. Use a suspend capture block to gain access to the6052 in an event loop. Use a suspend capture block to gain access to the
6053 promise (TODO this is outdated):6053 promise (TODO this is outdated):
6054 </p>6054 </p>
...@@ -6134,7 +6134,7 @@ async fn testResumeFromSuspend(my_result: *i32) void {...@@ -6134,7 +6134,7 @@ async fn testResumeFromSuspend(my_result: *i32) void {
6134 resumes the awaiter.6134 resumes the awaiter.
6135 </p>6135 </p>
6136 <p>6136 <p>
6137 A promise handle must be consumed exactly once after it is created, either by {#syntax#}cancel{#endsyntax#} or {#syntax#}await{#endsyntax#}.6137 A frame handle must be consumed exactly once after it is created with {#syntax#}await{#endsyntax#}.
6138 </p>6138 </p>
6139 <p>6139 <p>
6140 {#syntax#}await{#endsyntax#} counts as a suspend point, and therefore at every {#syntax#}await{#endsyntax#},6140 {#syntax#}await{#endsyntax#} counts as a suspend point, and therefore at every {#syntax#}await{#endsyntax#},
...@@ -9764,7 +9764,6 @@ PrimaryExpr...@@ -9764,7 +9764,6 @@ PrimaryExpr
9764 &lt;- AsmExpr9764 &lt;- AsmExpr
9765 / IfExpr9765 / IfExpr
9766 / KEYWORD_break BreakLabel? Expr?9766 / KEYWORD_break BreakLabel? Expr?
9767 / KEYWORD_cancel Expr
9768 / KEYWORD_comptime Expr9767 / KEYWORD_comptime Expr
9769 / KEYWORD_continue BreakLabel?9768 / KEYWORD_continue BreakLabel?
9770 / KEYWORD_resume Expr9769 / KEYWORD_resume Expr
...@@ -10120,7 +10119,6 @@ KEYWORD_asm &lt;- 'asm' end_of_word...@@ -10120,7 +10119,6 @@ KEYWORD_asm &lt;- 'asm' end_of_word
10120KEYWORD_async &lt;- 'async' end_of_word10119KEYWORD_async &lt;- 'async' end_of_word
10121KEYWORD_await &lt;- 'await' end_of_word10120KEYWORD_await &lt;- 'await' end_of_word
10122KEYWORD_break &lt;- 'break' end_of_word10121KEYWORD_break &lt;- 'break' end_of_word
10123KEYWORD_cancel &lt;- 'cancel' end_of_word
10124KEYWORD_catch &lt;- 'catch' end_of_word10122KEYWORD_catch &lt;- 'catch' end_of_word
10125KEYWORD_comptime &lt;- 'comptime' end_of_word10123KEYWORD_comptime &lt;- 'comptime' end_of_word
10126KEYWORD_const &lt;- 'const' end_of_word10124KEYWORD_const &lt;- 'const' end_of_word
...@@ -10165,7 +10163,7 @@ KEYWORD_volatile &lt;- 'volatile' end_of_word...@@ -10165,7 +10163,7 @@ KEYWORD_volatile &lt;- 'volatile' end_of_word
10165KEYWORD_while &lt;- 'while' end_of_word10163KEYWORD_while &lt;- 'while' end_of_word
1016610164
10167keyword &lt;- KEYWORD_align / KEYWORD_and / KEYWORD_allowzero / KEYWORD_asm10165keyword &lt;- KEYWORD_align / KEYWORD_and / KEYWORD_allowzero / KEYWORD_asm
10168 / KEYWORD_async / KEYWORD_await / KEYWORD_break / KEYWORD_cancel10166 / KEYWORD_async / KEYWORD_await / KEYWORD_break
10169 / KEYWORD_catch / KEYWORD_comptime / KEYWORD_const / KEYWORD_continue10167 / KEYWORD_catch / KEYWORD_comptime / KEYWORD_const / KEYWORD_continue
10170 / KEYWORD_defer / KEYWORD_else / KEYWORD_enum / KEYWORD_errdefer10168 / KEYWORD_defer / KEYWORD_else / KEYWORD_enum / KEYWORD_errdefer
10171 / KEYWORD_error / KEYWORD_export / KEYWORD_extern / KEYWORD_false10169 / KEYWORD_error / KEYWORD_export / KEYWORD_extern / KEYWORD_false
src-self-hosted/main.zig-3
...@@ -467,7 +467,6 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Co...@@ -467,7 +467,6 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Co
467467
468 comp.start();468 comp.start();
469 // TODO const process_build_events_handle = try async<loop.allocator> processBuildEvents(comp, color);469 // TODO const process_build_events_handle = try async<loop.allocator> processBuildEvents(comp, color);
470 defer cancel process_build_events_handle;
471 loop.run();470 loop.run();
472}471}
473472
...@@ -579,7 +578,6 @@ fn cmdLibC(allocator: *Allocator, args: []const []const u8) !void {...@@ -579,7 +578,6 @@ fn cmdLibC(allocator: *Allocator, args: []const []const u8) !void {
579 defer zig_compiler.deinit();578 defer zig_compiler.deinit();
580579
581 // TODO const handle = try async<loop.allocator> findLibCAsync(&zig_compiler);580 // TODO const handle = try async<loop.allocator> findLibCAsync(&zig_compiler);
582 defer cancel handle;
583581
584 loop.run();582 loop.run();
585}583}
...@@ -669,7 +667,6 @@ fn cmdFmt(allocator: *Allocator, args: []const []const u8) !void {...@@ -669,7 +667,6 @@ fn cmdFmt(allocator: *Allocator, args: []const []const u8) !void {
669 // TODO &flags,667 // TODO &flags,
670 // TODO color,668 // TODO color,
671 // TODO );669 // TODO );
672 defer cancel main_handle;
673 loop.run();670 loop.run();
674 return result;671 return result;
675}672}
src/all_types.hpp+1-32
...@@ -476,7 +476,6 @@ enum NodeType {...@@ -476,7 +476,6 @@ enum NodeType {
476 NodeTypeIfErrorExpr,476 NodeTypeIfErrorExpr,
477 NodeTypeIfOptional,477 NodeTypeIfOptional,
478 NodeTypeErrorSetDecl,478 NodeTypeErrorSetDecl,
479 NodeTypeCancel,
480 NodeTypeResume,479 NodeTypeResume,
481 NodeTypeAwaitExpr,480 NodeTypeAwaitExpr,
482 NodeTypeSuspend,481 NodeTypeSuspend,
...@@ -911,10 +910,6 @@ struct AstNodeBreakExpr {...@@ -911,10 +910,6 @@ struct AstNodeBreakExpr {
911 AstNode *expr; // may be null910 AstNode *expr; // may be null
912};911};
913912
914struct AstNodeCancelExpr {
915 AstNode *expr;
916};
917
918struct AstNodeResumeExpr {913struct AstNodeResumeExpr {
919 AstNode *expr;914 AstNode *expr;
920};915};
...@@ -1003,7 +998,6 @@ struct AstNode {...@@ -1003,7 +998,6 @@ struct AstNode {
1003 AstNodeInferredArrayType inferred_array_type;998 AstNodeInferredArrayType inferred_array_type;
1004 AstNodeErrorType error_type;999 AstNodeErrorType error_type;
1005 AstNodeErrorSetDecl err_set_decl;1000 AstNodeErrorSetDecl err_set_decl;
1006 AstNodeCancelExpr cancel_expr;
1007 AstNodeResumeExpr resume_expr;1001 AstNodeResumeExpr resume_expr;
1008 AstNodeAwaitExpr await_expr;1002 AstNodeAwaitExpr await_expr;
1009 AstNodeSuspend suspend;1003 AstNodeSuspend suspend;
...@@ -1561,7 +1555,6 @@ enum PanicMsgId {...@@ -1561,7 +1555,6 @@ enum PanicMsgId {
1561 PanicMsgIdBadAwait,1555 PanicMsgIdBadAwait,
1562 PanicMsgIdBadReturn,1556 PanicMsgIdBadReturn,
1563 PanicMsgIdResumedAnAwaitingFn,1557 PanicMsgIdResumedAnAwaitingFn,
1564 PanicMsgIdResumedACancelingFn,
1565 PanicMsgIdFrameTooSmall,1558 PanicMsgIdFrameTooSmall,
1566 PanicMsgIdResumedFnPendingAwait,1559 PanicMsgIdResumedFnPendingAwait,
15671560
...@@ -1729,8 +1722,6 @@ struct CodeGen {...@@ -1729,8 +1722,6 @@ struct CodeGen {
1729 LLVMValueRef cur_async_switch_instr;1722 LLVMValueRef cur_async_switch_instr;
1730 LLVMValueRef cur_async_resume_index_ptr;1723 LLVMValueRef cur_async_resume_index_ptr;
1731 LLVMValueRef cur_async_awaiter_ptr;1724 LLVMValueRef cur_async_awaiter_ptr;
1732 LLVMValueRef cur_async_prev_val;
1733 LLVMValueRef cur_async_prev_val_field_ptr;
1734 LLVMBasicBlockRef cur_preamble_llvm_block;1725 LLVMBasicBlockRef cur_preamble_llvm_block;
1735 size_t cur_resume_block_count;1726 size_t cur_resume_block_count;
1736 LLVMValueRef cur_err_ret_trace_val_arg;1727 LLVMValueRef cur_err_ret_trace_val_arg;
...@@ -1822,7 +1813,6 @@ struct CodeGen {...@@ -1822,7 +1813,6 @@ struct CodeGen {
18221813
1823 ZigType *align_amt_type;1814 ZigType *align_amt_type;
1824 ZigType *stack_trace_type;1815 ZigType *stack_trace_type;
1825 ZigType *ptr_to_stack_trace_type;
1826 ZigType *err_tag_type;1816 ZigType *err_tag_type;
1827 ZigType *test_fn_type;1817 ZigType *test_fn_type;
18281818
...@@ -1892,7 +1882,6 @@ struct CodeGen {...@@ -1892,7 +1882,6 @@ struct CodeGen {
1892 bool system_linker_hack;1882 bool system_linker_hack;
1893 bool reported_bad_link_libc_error;1883 bool reported_bad_link_libc_error;
1894 bool is_dynamic; // shared library rather than static library. dynamic musl rather than static musl.1884 bool is_dynamic; // shared library rather than static library. dynamic musl rather than static musl.
1895 bool cur_is_after_return;
18961885
1897 //////////////////////////// Participates in Input Parameter Cache Hash1886 //////////////////////////// Participates in Input Parameter Cache Hash
1898 /////// Note: there is a separate cache hash for builtin.zig, when adding fields,1887 /////// Note: there is a separate cache hash for builtin.zig, when adding fields,
...@@ -2235,7 +2224,6 @@ enum IrInstructionId {...@@ -2235,7 +2224,6 @@ enum IrInstructionId {
2235 IrInstructionIdCallGen,2224 IrInstructionIdCallGen,
2236 IrInstructionIdConst,2225 IrInstructionIdConst,
2237 IrInstructionIdReturn,2226 IrInstructionIdReturn,
2238 IrInstructionIdReturnBegin,
2239 IrInstructionIdCast,2227 IrInstructionIdCast,
2240 IrInstructionIdResizeSlice,2228 IrInstructionIdResizeSlice,
2241 IrInstructionIdContainerInitList,2229 IrInstructionIdContainerInitList,
...@@ -2345,7 +2333,6 @@ enum IrInstructionId {...@@ -2345,7 +2333,6 @@ enum IrInstructionId {
2345 IrInstructionIdExport,2333 IrInstructionIdExport,
2346 IrInstructionIdErrorReturnTrace,2334 IrInstructionIdErrorReturnTrace,
2347 IrInstructionIdErrorUnion,2335 IrInstructionIdErrorUnion,
2348 IrInstructionIdCancel,
2349 IrInstructionIdAtomicRmw,2336 IrInstructionIdAtomicRmw,
2350 IrInstructionIdAtomicLoad,2337 IrInstructionIdAtomicLoad,
2351 IrInstructionIdSaveErrRetAddr,2338 IrInstructionIdSaveErrRetAddr,
...@@ -2370,7 +2357,6 @@ enum IrInstructionId {...@@ -2370,7 +2357,6 @@ enum IrInstructionId {
2370 IrInstructionIdAwaitSrc,2357 IrInstructionIdAwaitSrc,
2371 IrInstructionIdAwaitGen,2358 IrInstructionIdAwaitGen,
2372 IrInstructionIdResume,2359 IrInstructionIdResume,
2373 IrInstructionIdTestCancelRequested,
2374 IrInstructionIdSpillBegin,2360 IrInstructionIdSpillBegin,
2375 IrInstructionIdSpillEnd,2361 IrInstructionIdSpillEnd,
2376};2362};
...@@ -2649,12 +2635,6 @@ struct IrInstructionReturn {...@@ -2649,12 +2635,6 @@ struct IrInstructionReturn {
2649 IrInstruction *operand;2635 IrInstruction *operand;
2650};2636};
26512637
2652struct IrInstructionReturnBegin {
2653 IrInstruction base;
2654
2655 IrInstruction *operand;
2656};
2657
2658enum CastOp {2638enum CastOp {
2659 CastOpNoCast, // signifies the function call expression is not a cast2639 CastOpNoCast, // signifies the function call expression is not a cast
2660 CastOpNoop, // fn call expr is a cast, but does nothing2640 CastOpNoop, // fn call expr is a cast, but does nothing
...@@ -3440,12 +3420,6 @@ struct IrInstructionErrorUnion {...@@ -3440,12 +3420,6 @@ struct IrInstructionErrorUnion {
3440 IrInstruction *payload;3420 IrInstruction *payload;
3441};3421};
34423422
3443struct IrInstructionCancel {
3444 IrInstruction base;
3445
3446 IrInstruction *frame;
3447};
3448
3449struct IrInstructionAtomicRmw {3423struct IrInstructionAtomicRmw {
3450 IrInstruction base;3424 IrInstruction base;
34513425
...@@ -3647,10 +3621,6 @@ struct IrInstructionResume {...@@ -3647,10 +3621,6 @@ struct IrInstructionResume {
3647 IrInstruction *frame;3621 IrInstruction *frame;
3648};3622};
36493623
3650struct IrInstructionTestCancelRequested {
3651 IrInstruction base;
3652};
3653
3654enum SpillId {3624enum SpillId {
3655 SpillIdInvalid,3625 SpillIdInvalid,
3656 SpillIdRetErrCode,3626 SpillIdRetErrCode,
...@@ -3756,8 +3726,7 @@ static const size_t err_union_err_index = 1;...@@ -3756,8 +3726,7 @@ static const size_t err_union_err_index = 1;
3756static const size_t frame_fn_ptr_index = 0;3726static const size_t frame_fn_ptr_index = 0;
3757static const size_t frame_resume_index = 1;3727static const size_t frame_resume_index = 1;
3758static const size_t frame_awaiter_index = 2;3728static const size_t frame_awaiter_index = 2;
3759static const size_t frame_prev_val_index = 3;3729static const size_t frame_ret_start = 3;
3760static const size_t frame_ret_start = 4;
37613730
3762// TODO https://github.com/ziglang/zig/issues/30563731// TODO https://github.com/ziglang/zig/issues/3056
3763// We require this to be a power of 2 so that we can use shifting rather than3732// We require this to be a power of 2 so that we can use shifting rather than
src/analyze.cpp+33-20
...@@ -828,17 +828,15 @@ bool calling_convention_allows_zig_types(CallingConvention cc) {...@@ -828,17 +828,15 @@ bool calling_convention_allows_zig_types(CallingConvention cc) {
828 zig_unreachable();828 zig_unreachable();
829}829}
830830
831ZigType *get_ptr_to_stack_trace_type(CodeGen *g) {831ZigType *get_stack_trace_type(CodeGen *g) {
832 if (g->stack_trace_type == nullptr) {832 if (g->stack_trace_type == nullptr) {
833 ConstExprValue *stack_trace_type_val = get_builtin_value(g, "StackTrace");833 ConstExprValue *stack_trace_type_val = get_builtin_value(g, "StackTrace");
834 assert(stack_trace_type_val->type->id == ZigTypeIdMetaType);834 assert(stack_trace_type_val->type->id == ZigTypeIdMetaType);
835835
836 g->stack_trace_type = stack_trace_type_val->data.x_type;836 g->stack_trace_type = stack_trace_type_val->data.x_type;
837 assertNoError(type_resolve(g, g->stack_trace_type, ResolveStatusZeroBitsKnown));837 assertNoError(type_resolve(g, g->stack_trace_type, ResolveStatusZeroBitsKnown));
838
839 g->ptr_to_stack_trace_type = get_pointer_to_type(g, g->stack_trace_type, false);
840 }838 }
841 return g->ptr_to_stack_trace_type;839 return g->stack_trace_type;
842}840}
843841
844bool want_first_arg_sret(CodeGen *g, FnTypeId *fn_type_id) {842bool want_first_arg_sret(CodeGen *g, FnTypeId *fn_type_id) {
...@@ -3035,7 +3033,6 @@ void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node) {...@@ -3035,7 +3033,6 @@ void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node) {
3035 case NodeTypeIfErrorExpr:3033 case NodeTypeIfErrorExpr:
3036 case NodeTypeIfOptional:3034 case NodeTypeIfOptional:
3037 case NodeTypeErrorSetDecl:3035 case NodeTypeErrorSetDecl:
3038 case NodeTypeCancel:
3039 case NodeTypeResume:3036 case NodeTypeResume:
3040 case NodeTypeAwaitExpr:3037 case NodeTypeAwaitExpr:
3041 case NodeTypeSuspend:3038 case NodeTypeSuspend:
...@@ -3822,11 +3819,9 @@ static void add_async_error_notes(CodeGen *g, ErrorMsg *msg, ZigFn *fn) {...@@ -3822,11 +3819,9 @@ static void add_async_error_notes(CodeGen *g, ErrorMsg *msg, ZigFn *fn) {
3822 } else if (fn->inferred_async_node->type == NodeTypeAwaitExpr) {3819 } else if (fn->inferred_async_node->type == NodeTypeAwaitExpr) {
3823 add_error_note(g, msg, fn->inferred_async_node,3820 add_error_note(g, msg, fn->inferred_async_node,
3824 buf_sprintf("await is a suspend point"));3821 buf_sprintf("await is a suspend point"));
3825 } else if (fn->inferred_async_node->type == NodeTypeCancel) {
3826 add_error_note(g, msg, fn->inferred_async_node,
3827 buf_sprintf("cancel is a suspend point"));
3828 } else {3822 } else {
3829 zig_unreachable();3823 add_error_note(g, msg, fn->inferred_async_node,
3824 buf_sprintf("suspends here"));
3830 }3825 }
3831}3826}
38323827
...@@ -5231,12 +5226,21 @@ static Error resolve_async_frame(CodeGen *g, ZigType *frame_type) {...@@ -5231,12 +5226,21 @@ static Error resolve_async_frame(CodeGen *g, ZigType *frame_type) {
5231 fields.append({"@fn_ptr", g->builtin_types.entry_usize, 0});5226 fields.append({"@fn_ptr", g->builtin_types.entry_usize, 0});
5232 fields.append({"@resume_index", g->builtin_types.entry_usize, 0});5227 fields.append({"@resume_index", g->builtin_types.entry_usize, 0});
5233 fields.append({"@awaiter", g->builtin_types.entry_usize, 0});5228 fields.append({"@awaiter", g->builtin_types.entry_usize, 0});
5234 fields.append({"@prev_val", g->builtin_types.entry_usize, 0});
52355229
5236 fields.append({"@result_ptr_callee", ptr_return_type, 0});5230 fields.append({"@result_ptr_callee", ptr_return_type, 0});
5237 fields.append({"@result_ptr_awaiter", ptr_return_type, 0});5231 fields.append({"@result_ptr_awaiter", ptr_return_type, 0});
5238 fields.append({"@result", fn_type_id->return_type, 0});5232 fields.append({"@result", fn_type_id->return_type, 0});
52395233
5234 if (codegen_fn_has_err_ret_tracing_arg(g, fn_type_id->return_type)) {
5235 ZigType *ptr_to_stack_trace_type = get_pointer_to_type(g, get_stack_trace_type(g), false);
5236 fields.append({"@ptr_stack_trace_callee", ptr_to_stack_trace_type, 0});
5237 fields.append({"@ptr_stack_trace_awaiter", ptr_to_stack_trace_type, 0});
5238
5239 fields.append({"@stack_trace", get_stack_trace_type(g), 0});
5240 fields.append({"@instruction_addresses",
5241 get_array_type(g, g->builtin_types.entry_usize, stack_trace_ptr_count), 0});
5242 }
5243
5240 frame_type->data.frame.locals_struct = get_struct_type(g, buf_ptr(&frame_type->name),5244 frame_type->data.frame.locals_struct = get_struct_type(g, buf_ptr(&frame_type->name),
5241 fields.items, fields.length, target_fn_align(g->zig_target));5245 fields.items, fields.length, target_fn_align(g->zig_target));
5242 frame_type->abi_size = frame_type->data.frame.locals_struct->abi_size;5246 frame_type->abi_size = frame_type->data.frame.locals_struct->abi_size;
...@@ -5311,14 +5315,15 @@ static Error resolve_async_frame(CodeGen *g, ZigType *frame_type) {...@@ -5311,14 +5315,15 @@ static Error resolve_async_frame(CodeGen *g, ZigType *frame_type) {
5311 fields.append({"@fn_ptr", fn_type, 0});5315 fields.append({"@fn_ptr", fn_type, 0});
5312 fields.append({"@resume_index", g->builtin_types.entry_usize, 0});5316 fields.append({"@resume_index", g->builtin_types.entry_usize, 0});
5313 fields.append({"@awaiter", g->builtin_types.entry_usize, 0});5317 fields.append({"@awaiter", g->builtin_types.entry_usize, 0});
5314 fields.append({"@prev_val", g->builtin_types.entry_usize, 0});
53155318
5316 fields.append({"@result_ptr_callee", ptr_return_type, 0});5319 fields.append({"@result_ptr_callee", ptr_return_type, 0});
5317 fields.append({"@result_ptr_awaiter", ptr_return_type, 0});5320 fields.append({"@result_ptr_awaiter", ptr_return_type, 0});
5318 fields.append({"@result", fn_type_id->return_type, 0});5321 fields.append({"@result", fn_type_id->return_type, 0});
53195322
5320 if (codegen_fn_has_err_ret_tracing_arg(g, fn_type_id->return_type)) {5323 if (codegen_fn_has_err_ret_tracing_arg(g, fn_type_id->return_type)) {
5321 fields.append({"@ptr_stack_trace", get_ptr_to_stack_trace_type(g), 0});5324 ZigType *ptr_stack_trace_type = get_pointer_to_type(g, get_stack_trace_type(g), false);
5325 fields.append({"@ptr_stack_trace_callee", ptr_stack_trace_type, 0});
5326 fields.append({"@ptr_stack_trace_awaiter", ptr_stack_trace_type, 0});
5322 }5327 }
53235328
5324 for (size_t arg_i = 0; arg_i < fn_type_id->param_count; arg_i += 1) {5329 for (size_t arg_i = 0; arg_i < fn_type_id->param_count; arg_i += 1) {
...@@ -5337,9 +5342,7 @@ static Error resolve_async_frame(CodeGen *g, ZigType *frame_type) {...@@ -5337,9 +5342,7 @@ static Error resolve_async_frame(CodeGen *g, ZigType *frame_type) {
5337 }5342 }
53385343
5339 if (codegen_fn_has_err_ret_tracing_stack(g, fn, true)) {5344 if (codegen_fn_has_err_ret_tracing_stack(g, fn, true)) {
5340 (void)get_ptr_to_stack_trace_type(g); // populate g->stack_trace_type5345 fields.append({"@stack_trace", get_stack_trace_type(g), 0});
5341
5342 fields.append({"@stack_trace", g->stack_trace_type, 0});
5343 fields.append({"@instruction_addresses",5346 fields.append({"@instruction_addresses",
5344 get_array_type(g, g->builtin_types.entry_usize, stack_trace_ptr_count), 0});5347 get_array_type(g, g->builtin_types.entry_usize, stack_trace_ptr_count), 0});
5345 }5348 }
...@@ -7553,7 +7556,7 @@ static void resolve_llvm_types_fn_type(CodeGen *g, ZigType *fn_type) {...@@ -7553,7 +7556,7 @@ static void resolve_llvm_types_fn_type(CodeGen *g, ZigType *fn_type) {
7553 fn_type->data.fn.gen_return_type = gen_return_type;7556 fn_type->data.fn.gen_return_type = gen_return_type;
75547557
7555 if (prefix_arg_error_return_trace && !is_async) {7558 if (prefix_arg_error_return_trace && !is_async) {
7556 ZigType *gen_type = get_ptr_to_stack_trace_type(g);7559 ZigType *gen_type = get_pointer_to_type(g, get_stack_trace_type(g), false);
7557 gen_param_types.append(get_llvm_type(g, gen_type));7560 gen_param_types.append(get_llvm_type(g, gen_type));
7558 param_di_types.append(get_llvm_di_type(g, gen_type));7561 param_di_types.append(get_llvm_di_type(g, gen_type));
7559 }7562 }
...@@ -7727,7 +7730,6 @@ static void resolve_llvm_types_any_frame(CodeGen *g, ZigType *any_frame_type, Re...@@ -7727,7 +7730,6 @@ static void resolve_llvm_types_any_frame(CodeGen *g, ZigType *any_frame_type, Re
7727 field_types.append(ptr_fn_llvm_type); // fn_ptr7730 field_types.append(ptr_fn_llvm_type); // fn_ptr
7728 field_types.append(usize_type_ref); // resume_index7731 field_types.append(usize_type_ref); // resume_index
7729 field_types.append(usize_type_ref); // awaiter7732 field_types.append(usize_type_ref); // awaiter
7730 field_types.append(usize_type_ref); // prev_val
77317733
7732 bool have_result_type = result_type != nullptr && type_has_bits(result_type);7734 bool have_result_type = result_type != nullptr && type_has_bits(result_type);
7733 if (have_result_type) {7735 if (have_result_type) {
...@@ -7735,7 +7737,9 @@ static void resolve_llvm_types_any_frame(CodeGen *g, ZigType *any_frame_type, Re...@@ -7735,7 +7737,9 @@ static void resolve_llvm_types_any_frame(CodeGen *g, ZigType *any_frame_type, Re
7735 field_types.append(get_llvm_type(g, ptr_result_type)); // result_ptr_awaiter7737 field_types.append(get_llvm_type(g, ptr_result_type)); // result_ptr_awaiter
7736 field_types.append(get_llvm_type(g, result_type)); // result7738 field_types.append(get_llvm_type(g, result_type)); // result
7737 if (codegen_fn_has_err_ret_tracing_arg(g, result_type)) {7739 if (codegen_fn_has_err_ret_tracing_arg(g, result_type)) {
7738 field_types.append(get_llvm_type(g, get_ptr_to_stack_trace_type(g))); // ptr_stack_trace7740 ZigType *ptr_stack_trace = get_pointer_to_type(g, get_stack_trace_type(g), false);
7741 field_types.append(get_llvm_type(g, ptr_stack_trace)); // ptr_stack_trace_callee
7742 field_types.append(get_llvm_type(g, ptr_stack_trace)); // ptr_stack_trace_awaiter
7739 }7743 }
7740 }7744 }
7741 LLVMStructSetBody(frame_header_type, field_types.items, field_types.length, false);7745 LLVMStructSetBody(frame_header_type, field_types.items, field_types.length, false);
...@@ -7792,14 +7796,23 @@ static void resolve_llvm_types_any_frame(CodeGen *g, ZigType *any_frame_type, Re...@@ -7792,14 +7796,23 @@ static void resolve_llvm_types_any_frame(CodeGen *g, ZigType *any_frame_type, Re
7792 ZigLLVM_DIFlags_Zero, get_llvm_di_type(g, result_type)));7796 ZigLLVM_DIFlags_Zero, get_llvm_di_type(g, result_type)));
77937797
7794 if (codegen_fn_has_err_ret_tracing_arg(g, result_type)) {7798 if (codegen_fn_has_err_ret_tracing_arg(g, result_type)) {
7799 ZigType *ptr_stack_trace = get_pointer_to_type(g, get_stack_trace_type(g), false);
7800 di_element_types.append(
7801 ZigLLVMCreateDebugMemberType(g->dbuilder,
7802 ZigLLVMTypeToScope(any_frame_type->llvm_di_type), "ptr_stack_trace_callee",
7803 di_file, line,
7804 8*LLVMABISizeOfType(g->target_data_ref, field_types.at(di_element_types.length)),
7805 8*LLVMABIAlignmentOfType(g->target_data_ref, field_types.at(di_element_types.length)),
7806 8*LLVMOffsetOfElement(g->target_data_ref, frame_header_type, di_element_types.length),
7807 ZigLLVM_DIFlags_Zero, get_llvm_di_type(g, ptr_stack_trace)));
7795 di_element_types.append(7808 di_element_types.append(
7796 ZigLLVMCreateDebugMemberType(g->dbuilder,7809 ZigLLVMCreateDebugMemberType(g->dbuilder,
7797 ZigLLVMTypeToScope(any_frame_type->llvm_di_type), "ptr_stack_trace",7810 ZigLLVMTypeToScope(any_frame_type->llvm_di_type), "ptr_stack_trace_awaiter",
7798 di_file, line,7811 di_file, line,
7799 8*LLVMABISizeOfType(g->target_data_ref, field_types.at(di_element_types.length)),7812 8*LLVMABISizeOfType(g->target_data_ref, field_types.at(di_element_types.length)),
7800 8*LLVMABIAlignmentOfType(g->target_data_ref, field_types.at(di_element_types.length)),7813 8*LLVMABIAlignmentOfType(g->target_data_ref, field_types.at(di_element_types.length)),
7801 8*LLVMOffsetOfElement(g->target_data_ref, frame_header_type, di_element_types.length),7814 8*LLVMOffsetOfElement(g->target_data_ref, frame_header_type, di_element_types.length),
7802 ZigLLVM_DIFlags_Zero, get_llvm_di_type(g, get_ptr_to_stack_trace_type(g))));7815 ZigLLVM_DIFlags_Zero, get_llvm_di_type(g, ptr_stack_trace)));
7803 }7816 }
7804 };7817 };
78057818
src/analyze.hpp+1-1
...@@ -195,7 +195,7 @@ void add_var_export(CodeGen *g, ZigVar *fn_table_entry, Buf *symbol_name, Global...@@ -195,7 +195,7 @@ void add_var_export(CodeGen *g, ZigVar *fn_table_entry, Buf *symbol_name, Global
195195
196196
197ConstExprValue *get_builtin_value(CodeGen *codegen, const char *name);197ConstExprValue *get_builtin_value(CodeGen *codegen, const char *name);
198ZigType *get_ptr_to_stack_trace_type(CodeGen *g);198ZigType *get_stack_trace_type(CodeGen *g);
199bool resolve_inferred_error_set(CodeGen *g, ZigType *err_set_type, AstNode *source_node);199bool resolve_inferred_error_set(CodeGen *g, ZigType *err_set_type, AstNode *source_node);
200200
201ZigType *get_auto_err_set_type(CodeGen *g, ZigFn *fn_entry);201ZigType *get_auto_err_set_type(CodeGen *g, ZigFn *fn_entry);
src/ast_render.cpp-8
...@@ -249,8 +249,6 @@ static const char *node_type_str(NodeType node_type) {...@@ -249,8 +249,6 @@ static const char *node_type_str(NodeType node_type) {
249 return "IfOptional";249 return "IfOptional";
250 case NodeTypeErrorSetDecl:250 case NodeTypeErrorSetDecl:
251 return "ErrorSetDecl";251 return "ErrorSetDecl";
252 case NodeTypeCancel:
253 return "Cancel";
254 case NodeTypeResume:252 case NodeTypeResume:
255 return "Resume";253 return "Resume";
256 case NodeTypeAwaitExpr:254 case NodeTypeAwaitExpr:
...@@ -1136,12 +1134,6 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {...@@ -1136,12 +1134,6 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {
1136 fprintf(ar->f, "}");1134 fprintf(ar->f, "}");
1137 break;1135 break;
1138 }1136 }
1139 case NodeTypeCancel:
1140 {
1141 fprintf(ar->f, "cancel ");
1142 render_node_grouped(ar, node->data.cancel_expr.expr);
1143 break;
1144 }
1145 case NodeTypeResume:1137 case NodeTypeResume:
1146 {1138 {
1147 fprintf(ar->f, "resume ");1139 fprintf(ar->f, "resume ");
src/codegen.cpp+156-256
...@@ -28,8 +28,6 @@ enum ResumeId {...@@ -28,8 +28,6 @@ enum ResumeId {
28 ResumeIdManual,28 ResumeIdManual,
29 ResumeIdReturn,29 ResumeIdReturn,
30 ResumeIdCall,30 ResumeIdCall,
31
32 ResumeIdAwaitEarlyReturn // must be last
33};31};
3432
35static void init_darwin_native(CodeGen *g) {33static void init_darwin_native(CodeGen *g) {
...@@ -317,8 +315,9 @@ static uint32_t frame_index_trace_arg(CodeGen *g, ZigType *return_type) {...@@ -317,8 +315,9 @@ static uint32_t frame_index_trace_arg(CodeGen *g, ZigType *return_type) {
317// label (grep this): [fn_frame_struct_layout]315// label (grep this): [fn_frame_struct_layout]
318static uint32_t frame_index_arg(CodeGen *g, ZigType *return_type) {316static uint32_t frame_index_arg(CodeGen *g, ZigType *return_type) {
319 bool have_stack_trace = codegen_fn_has_err_ret_tracing_arg(g, return_type);317 bool have_stack_trace = codegen_fn_has_err_ret_tracing_arg(g, return_type);
320 // [0] *StackTrace318 // [0] *StackTrace (callee's)
321 uint32_t trace_field_count = have_stack_trace ? 1 : 0;319 // [1] *StackTrace (awaiter's)
320 uint32_t trace_field_count = have_stack_trace ? 2 : 0;
322 return frame_index_trace_arg(g, return_type) + trace_field_count;321 return frame_index_trace_arg(g, return_type) + trace_field_count;
323}322}
324323
...@@ -916,8 +915,6 @@ static Buf *panic_msg_buf(PanicMsgId msg_id) {...@@ -916,8 +915,6 @@ static Buf *panic_msg_buf(PanicMsgId msg_id) {
916 return buf_create_from_str("async function returned twice");915 return buf_create_from_str("async function returned twice");
917 case PanicMsgIdResumedAnAwaitingFn:916 case PanicMsgIdResumedAnAwaitingFn:
918 return buf_create_from_str("awaiting function resumed");917 return buf_create_from_str("awaiting function resumed");
919 case PanicMsgIdResumedACancelingFn:
920 return buf_create_from_str("canceling function resumed");
921 case PanicMsgIdFrameTooSmall:918 case PanicMsgIdFrameTooSmall:
922 return buf_create_from_str("frame too small");919 return buf_create_from_str("frame too small");
923 case PanicMsgIdResumedFnPendingAwait:920 case PanicMsgIdResumedFnPendingAwait:
...@@ -946,13 +943,16 @@ static LLVMValueRef get_panic_msg_ptr_val(CodeGen *g, PanicMsgId msg_id) {...@@ -946,13 +943,16 @@ static LLVMValueRef get_panic_msg_ptr_val(CodeGen *g, PanicMsgId msg_id) {
946 return LLVMConstBitCast(val->global_refs->llvm_global, LLVMPointerType(get_llvm_type(g, str_type), 0));943 return LLVMConstBitCast(val->global_refs->llvm_global, LLVMPointerType(get_llvm_type(g, str_type), 0));
947}944}
948945
946static ZigType *ptr_to_stack_trace_type(CodeGen *g) {
947 return get_pointer_to_type(g, get_stack_trace_type(g), false);
948}
949
949static void gen_panic(CodeGen *g, LLVMValueRef msg_arg, LLVMValueRef stack_trace_arg) {950static void gen_panic(CodeGen *g, LLVMValueRef msg_arg, LLVMValueRef stack_trace_arg) {
950 assert(g->panic_fn != nullptr);951 assert(g->panic_fn != nullptr);
951 LLVMValueRef fn_val = fn_llvm_value(g, g->panic_fn);952 LLVMValueRef fn_val = fn_llvm_value(g, g->panic_fn);
952 LLVMCallConv llvm_cc = get_llvm_cc(g, g->panic_fn->type_entry->data.fn.fn_type_id.cc);953 LLVMCallConv llvm_cc = get_llvm_cc(g, g->panic_fn->type_entry->data.fn.fn_type_id.cc);
953 if (stack_trace_arg == nullptr) {954 if (stack_trace_arg == nullptr) {
954 ZigType *ptr_to_stack_trace_type = get_ptr_to_stack_trace_type(g);955 stack_trace_arg = LLVMConstNull(get_llvm_type(g, ptr_to_stack_trace_type(g)));
955 stack_trace_arg = LLVMConstNull(get_llvm_type(g, ptr_to_stack_trace_type));
956 }956 }
957 LLVMValueRef args[] = {957 LLVMValueRef args[] = {
958 msg_arg,958 msg_arg,
...@@ -1046,7 +1046,7 @@ static LLVMValueRef get_add_error_return_trace_addr_fn(CodeGen *g) {...@@ -1046,7 +1046,7 @@ static LLVMValueRef get_add_error_return_trace_addr_fn(CodeGen *g) {
1046 return g->add_error_return_trace_addr_fn_val;1046 return g->add_error_return_trace_addr_fn_val;
10471047
1048 LLVMTypeRef arg_types[] = {1048 LLVMTypeRef arg_types[] = {
1049 get_llvm_type(g, get_ptr_to_stack_trace_type(g)),1049 get_llvm_type(g, ptr_to_stack_trace_type(g)),
1050 g->builtin_types.entry_usize->llvm_type,1050 g->builtin_types.entry_usize->llvm_type,
1051 };1051 };
1052 LLVMTypeRef fn_type_ref = LLVMFunctionType(LLVMVoidType(), arg_types, 2, false);1052 LLVMTypeRef fn_type_ref = LLVMFunctionType(LLVMVoidType(), arg_types, 2, false);
...@@ -1127,7 +1127,7 @@ static LLVMValueRef get_return_err_fn(CodeGen *g) {...@@ -1127,7 +1127,7 @@ static LLVMValueRef get_return_err_fn(CodeGen *g) {
11271127
1128 LLVMTypeRef arg_types[] = {1128 LLVMTypeRef arg_types[] = {
1129 // error return trace pointer1129 // error return trace pointer
1130 get_llvm_type(g, get_ptr_to_stack_trace_type(g)),1130 get_llvm_type(g, ptr_to_stack_trace_type(g)),
1131 };1131 };
1132 LLVMTypeRef fn_type_ref = LLVMFunctionType(LLVMVoidType(), arg_types, 1, false);1132 LLVMTypeRef fn_type_ref = LLVMFunctionType(LLVMVoidType(), arg_types, 1, false);
11331133
...@@ -1205,7 +1205,7 @@ static LLVMValueRef get_safety_crash_err_fn(CodeGen *g) {...@@ -1205,7 +1205,7 @@ static LLVMValueRef get_safety_crash_err_fn(CodeGen *g) {
1205 LLVMTypeRef fn_type_ref;1205 LLVMTypeRef fn_type_ref;
1206 if (g->have_err_ret_tracing) {1206 if (g->have_err_ret_tracing) {
1207 LLVMTypeRef arg_types[] = {1207 LLVMTypeRef arg_types[] = {
1208 get_llvm_type(g, g->ptr_to_stack_trace_type),1208 get_llvm_type(g, get_pointer_to_type(g, get_stack_trace_type(g), false)),
1209 get_llvm_type(g, g->err_tag_type),1209 get_llvm_type(g, g->err_tag_type),
1210 };1210 };
1211 fn_type_ref = LLVMFunctionType(LLVMVoidType(), arg_types, 2, false);1211 fn_type_ref = LLVMFunctionType(LLVMVoidType(), arg_types, 2, false);
...@@ -1321,14 +1321,7 @@ static LLVMValueRef get_cur_err_ret_trace_val(CodeGen *g, Scope *scope) {...@@ -1321,14 +1321,7 @@ static LLVMValueRef get_cur_err_ret_trace_val(CodeGen *g, Scope *scope) {
1321 if (g->cur_err_ret_trace_val_stack != nullptr) {1321 if (g->cur_err_ret_trace_val_stack != nullptr) {
1322 return g->cur_err_ret_trace_val_stack;1322 return g->cur_err_ret_trace_val_stack;
1323 }1323 }
1324 if (g->cur_err_ret_trace_val_arg != nullptr) {1324 return g->cur_err_ret_trace_val_arg;
1325 if (fn_is_async(g->cur_fn)) {
1326 return LLVMBuildLoad(g->builder, g->cur_err_ret_trace_val_arg, "");
1327 } else {
1328 return g->cur_err_ret_trace_val_arg;
1329 }
1330 }
1331 return nullptr;
1332}1325}
13331326
1334static void gen_safety_crash_for_err(CodeGen *g, LLVMValueRef err_val, Scope *scope) {1327static void gen_safety_crash_for_err(CodeGen *g, LLVMValueRef err_val, Scope *scope) {
...@@ -1337,8 +1330,7 @@ static void gen_safety_crash_for_err(CodeGen *g, LLVMValueRef err_val, Scope *sc...@@ -1337,8 +1330,7 @@ static void gen_safety_crash_for_err(CodeGen *g, LLVMValueRef err_val, Scope *sc
1337 if (g->have_err_ret_tracing) {1330 if (g->have_err_ret_tracing) {
1338 LLVMValueRef err_ret_trace_val = get_cur_err_ret_trace_val(g, scope);1331 LLVMValueRef err_ret_trace_val = get_cur_err_ret_trace_val(g, scope);
1339 if (err_ret_trace_val == nullptr) {1332 if (err_ret_trace_val == nullptr) {
1340 ZigType *ptr_to_stack_trace_type = get_ptr_to_stack_trace_type(g);1333 err_ret_trace_val = LLVMConstNull(get_llvm_type(g, ptr_to_stack_trace_type(g)));
1341 err_ret_trace_val = LLVMConstNull(get_llvm_type(g, ptr_to_stack_trace_type));
1342 }1334 }
1343 LLVMValueRef args[] = {1335 LLVMValueRef args[] = {
1344 err_ret_trace_val,1336 err_ret_trace_val,
...@@ -2044,8 +2036,8 @@ static LLVMValueRef get_merge_err_ret_traces_fn_val(CodeGen *g) {...@@ -2044,8 +2036,8 @@ static LLVMValueRef get_merge_err_ret_traces_fn_val(CodeGen *g) {
2044 assert(g->stack_trace_type != nullptr);2036 assert(g->stack_trace_type != nullptr);
20452037
2046 LLVMTypeRef param_types[] = {2038 LLVMTypeRef param_types[] = {
2047 get_llvm_type(g, get_ptr_to_stack_trace_type(g)),2039 get_llvm_type(g, ptr_to_stack_trace_type(g)),
2048 get_llvm_type(g, get_ptr_to_stack_trace_type(g)),2040 get_llvm_type(g, ptr_to_stack_trace_type(g)),
2049 };2041 };
2050 LLVMTypeRef fn_type_ref = LLVMFunctionType(LLVMVoidType(), param_types, 2, false);2042 LLVMTypeRef fn_type_ref = LLVMFunctionType(LLVMVoidType(), param_types, 2, false);
20512043
...@@ -2058,7 +2050,6 @@ static LLVMValueRef get_merge_err_ret_traces_fn_val(CodeGen *g) {...@@ -2058,7 +2050,6 @@ static LLVMValueRef get_merge_err_ret_traces_fn_val(CodeGen *g) {
2058 addLLVMArgAttr(fn_val, (unsigned)0, "noalias");2050 addLLVMArgAttr(fn_val, (unsigned)0, "noalias");
2059 addLLVMArgAttr(fn_val, (unsigned)0, "writeonly");2051 addLLVMArgAttr(fn_val, (unsigned)0, "writeonly");
20602052
2061 addLLVMArgAttr(fn_val, (unsigned)1, "nonnull");
2062 addLLVMArgAttr(fn_val, (unsigned)1, "noalias");2053 addLLVMArgAttr(fn_val, (unsigned)1, "noalias");
2063 addLLVMArgAttr(fn_val, (unsigned)1, "readonly");2054 addLLVMArgAttr(fn_val, (unsigned)1, "readonly");
2064 if (g->build_mode == BuildModeDebug) {2055 if (g->build_mode == BuildModeDebug) {
...@@ -2075,7 +2066,7 @@ static LLVMValueRef get_merge_err_ret_traces_fn_val(CodeGen *g) {...@@ -2075,7 +2066,7 @@ static LLVMValueRef get_merge_err_ret_traces_fn_val(CodeGen *g) {
2075 LLVMPositionBuilderAtEnd(g->builder, entry_block);2066 LLVMPositionBuilderAtEnd(g->builder, entry_block);
2076 ZigLLVMClearCurrentDebugLocation(g->builder);2067 ZigLLVMClearCurrentDebugLocation(g->builder);
20772068
2078 // if (dest_stack_trace == null) return;2069 // if (dest_stack_trace == null or src_stack_trace == null) return;
2079 // var frame_index: usize = undefined;2070 // var frame_index: usize = undefined;
2080 // var frames_left: usize = undefined;2071 // var frames_left: usize = undefined;
2081 // if (src_stack_trace.index < src_stack_trace.instruction_addresses.len) {2072 // if (src_stack_trace.index < src_stack_trace.instruction_addresses.len) {
...@@ -2093,7 +2084,7 @@ static LLVMValueRef get_merge_err_ret_traces_fn_val(CodeGen *g) {...@@ -2093,7 +2084,7 @@ static LLVMValueRef get_merge_err_ret_traces_fn_val(CodeGen *g) {
2093 // frame_index = (frame_index + 1) % src_stack_trace.instruction_addresses.len;2084 // frame_index = (frame_index + 1) % src_stack_trace.instruction_addresses.len;
2094 // }2085 // }
2095 LLVMBasicBlockRef return_block = LLVMAppendBasicBlock(fn_val, "Return");2086 LLVMBasicBlockRef return_block = LLVMAppendBasicBlock(fn_val, "Return");
2096 LLVMBasicBlockRef dest_non_null_block = LLVMAppendBasicBlock(fn_val, "DestNonNull");2087 LLVMBasicBlockRef non_null_block = LLVMAppendBasicBlock(fn_val, "NonNull");
20972088
2098 LLVMValueRef frame_index_ptr = LLVMBuildAlloca(g->builder, g->builtin_types.entry_usize->llvm_type, "frame_index");2089 LLVMValueRef frame_index_ptr = LLVMBuildAlloca(g->builder, g->builtin_types.entry_usize->llvm_type, "frame_index");
2099 LLVMValueRef frames_left_ptr = LLVMBuildAlloca(g->builder, g->builtin_types.entry_usize->llvm_type, "frames_left");2090 LLVMValueRef frames_left_ptr = LLVMBuildAlloca(g->builder, g->builtin_types.entry_usize->llvm_type, "frames_left");
...@@ -2103,9 +2094,12 @@ static LLVMValueRef get_merge_err_ret_traces_fn_val(CodeGen *g) {...@@ -2103,9 +2094,12 @@ static LLVMValueRef get_merge_err_ret_traces_fn_val(CodeGen *g) {
21032094
2104 LLVMValueRef null_dest_bit = LLVMBuildICmp(g->builder, LLVMIntEQ, dest_stack_trace_ptr,2095 LLVMValueRef null_dest_bit = LLVMBuildICmp(g->builder, LLVMIntEQ, dest_stack_trace_ptr,
2105 LLVMConstNull(LLVMTypeOf(dest_stack_trace_ptr)), "");2096 LLVMConstNull(LLVMTypeOf(dest_stack_trace_ptr)), "");
2106 LLVMBuildCondBr(g->builder, null_dest_bit, return_block, dest_non_null_block);2097 LLVMValueRef null_src_bit = LLVMBuildICmp(g->builder, LLVMIntEQ, src_stack_trace_ptr,
2098 LLVMConstNull(LLVMTypeOf(src_stack_trace_ptr)), "");
2099 LLVMValueRef null_bit = LLVMBuildOr(g->builder, null_dest_bit, null_src_bit, "");
2100 LLVMBuildCondBr(g->builder, null_bit, return_block, non_null_block);
21072101
2108 LLVMPositionBuilderAtEnd(g->builder, dest_non_null_block);2102 LLVMPositionBuilderAtEnd(g->builder, non_null_block);
2109 size_t src_index_field_index = g->stack_trace_type->data.structure.fields[0].gen_index;2103 size_t src_index_field_index = g->stack_trace_type->data.structure.fields[0].gen_index;
2110 size_t src_addresses_field_index = g->stack_trace_type->data.structure.fields[1].gen_index;2104 size_t src_addresses_field_index = g->stack_trace_type->data.structure.fields[1].gen_index;
2111 LLVMValueRef src_index_field_ptr = LLVMBuildStructGEP(g->builder, src_stack_trace_ptr,2105 LLVMValueRef src_index_field_ptr = LLVMBuildStructGEP(g->builder, src_stack_trace_ptr,
...@@ -2183,13 +2177,11 @@ static LLVMValueRef ir_render_save_err_ret_addr(CodeGen *g, IrExecutable *execut...@@ -2183,13 +2177,11 @@ static LLVMValueRef ir_render_save_err_ret_addr(CodeGen *g, IrExecutable *execut
2183 ZigLLVMBuildCall(g->builder, return_err_fn, &my_err_trace_val, 1,2177 ZigLLVMBuildCall(g->builder, return_err_fn, &my_err_trace_val, 1,
2184 get_llvm_cc(g, CallingConventionUnspecified), ZigLLVM_FnInlineAuto, "");2178 get_llvm_cc(g, CallingConventionUnspecified), ZigLLVM_FnInlineAuto, "");
21852179
2186 if (fn_is_async(g->cur_fn) && g->cur_fn->calls_or_awaits_errorable_fn &&2180 ZigType *ret_type = g->cur_fn->type_entry->data.fn.fn_type_id.return_type;
2187 codegen_fn_has_err_ret_tracing_arg(g, g->cur_fn->type_entry->data.fn.fn_type_id.return_type))2181 if (fn_is_async(g->cur_fn) && codegen_fn_has_err_ret_tracing_arg(g, ret_type)) {
2188 {2182 LLVMValueRef trace_ptr_ptr = LLVMBuildStructGEP(g->builder, g->cur_frame_ptr,
2189 LLVMValueRef dest_trace_ptr = LLVMBuildLoad(g->builder, g->cur_err_ret_trace_val_arg, "");2183 frame_index_trace_arg(g, ret_type), "");
2190 LLVMValueRef args[] = { dest_trace_ptr, my_err_trace_val };2184 LLVMBuildStore(g->builder, my_err_trace_val, trace_ptr_ptr);
2191 ZigLLVMBuildCall(g->builder, get_merge_err_ret_traces_fn_val(g), args, 2,
2192 get_llvm_cc(g, CallingConventionUnspecified), ZigLLVM_FnInlineAuto, "");
2193 }2185 }
21942186
2195 return nullptr;2187 return nullptr;
...@@ -2201,16 +2193,9 @@ static void gen_assert_resume_id(CodeGen *g, IrInstruction *source_instr, Resume...@@ -2201,16 +2193,9 @@ static void gen_assert_resume_id(CodeGen *g, IrInstruction *source_instr, Resume
2201 LLVMTypeRef usize_type_ref = g->builtin_types.entry_usize->llvm_type;2193 LLVMTypeRef usize_type_ref = g->builtin_types.entry_usize->llvm_type;
2202 LLVMBasicBlockRef bad_resume_block = LLVMAppendBasicBlock(g->cur_fn_val, "BadResume");2194 LLVMBasicBlockRef bad_resume_block = LLVMAppendBasicBlock(g->cur_fn_val, "BadResume");
2203 if (end_bb == nullptr) end_bb = LLVMAppendBasicBlock(g->cur_fn_val, "OkResume");2195 if (end_bb == nullptr) end_bb = LLVMAppendBasicBlock(g->cur_fn_val, "OkResume");
2204 LLVMValueRef ok_bit;2196 LLVMValueRef expected_value = LLVMConstSub(LLVMConstAllOnes(usize_type_ref),
2205 if (resume_id == ResumeIdAwaitEarlyReturn) {2197 LLVMConstInt(usize_type_ref, resume_id, false));
2206 LLVMValueRef last_value = LLVMConstSub(LLVMConstAllOnes(usize_type_ref),2198 LLVMValueRef ok_bit = LLVMBuildICmp(g->builder, LLVMIntEQ, LLVMGetParam(g->cur_fn_val, 1), expected_value, "");
2207 LLVMConstInt(usize_type_ref, ResumeIdAwaitEarlyReturn, false));
2208 ok_bit = LLVMBuildICmp(g->builder, LLVMIntULT, LLVMGetParam(g->cur_fn_val, 1), last_value, "");
2209 } else {
2210 LLVMValueRef expected_value = LLVMConstSub(LLVMConstAllOnes(usize_type_ref),
2211 LLVMConstInt(usize_type_ref, resume_id, false));
2212 ok_bit = LLVMBuildICmp(g->builder, LLVMIntEQ, LLVMGetParam(g->cur_fn_val, 1), expected_value, "");
2213 }
2214 LLVMBuildCondBr(g->builder, ok_bit, end_bb, bad_resume_block);2199 LLVMBuildCondBr(g->builder, ok_bit, end_bb, bad_resume_block);
22152200
2216 LLVMPositionBuilderAtEnd(g->builder, bad_resume_block);2201 LLVMPositionBuilderAtEnd(g->builder, bad_resume_block);
...@@ -2219,36 +2204,19 @@ static void gen_assert_resume_id(CodeGen *g, IrInstruction *source_instr, Resume...@@ -2219,36 +2204,19 @@ static void gen_assert_resume_id(CodeGen *g, IrInstruction *source_instr, Resume
2219 LLVMPositionBuilderAtEnd(g->builder, end_bb);2204 LLVMPositionBuilderAtEnd(g->builder, end_bb);
2220}2205}
22212206
2222static LLVMValueRef gen_resume(CodeGen *g, LLVMValueRef fn_val, LLVMValueRef target_frame_ptr,2207static LLVMValueRef gen_resume(CodeGen *g, LLVMValueRef fn_val, LLVMValueRef target_frame_ptr, ResumeId resume_id) {
2223 ResumeId resume_id, LLVMValueRef arg_val)
2224{
2225 LLVMTypeRef usize_type_ref = g->builtin_types.entry_usize->llvm_type;2208 LLVMTypeRef usize_type_ref = g->builtin_types.entry_usize->llvm_type;
2226 if (fn_val == nullptr) {2209 if (fn_val == nullptr) {
2227 LLVMValueRef fn_ptr_ptr = LLVMBuildStructGEP(g->builder, target_frame_ptr, frame_fn_ptr_index, "");2210 LLVMValueRef fn_ptr_ptr = LLVMBuildStructGEP(g->builder, target_frame_ptr, frame_fn_ptr_index, "");
2228 fn_val = LLVMBuildLoad(g->builder, fn_ptr_ptr, "");2211 fn_val = LLVMBuildLoad(g->builder, fn_ptr_ptr, "");
2229 }2212 }
2230 if (arg_val == nullptr) {2213 LLVMValueRef arg_val = LLVMBuildSub(g->builder, LLVMConstAllOnes(usize_type_ref),
2231 arg_val = LLVMBuildSub(g->builder, LLVMConstAllOnes(usize_type_ref),2214 LLVMConstInt(usize_type_ref, resume_id, false), "");
2232 LLVMConstInt(usize_type_ref, resume_id, false), "");
2233 } else {
2234 assert(resume_id == ResumeIdAwaitEarlyReturn);
2235 }
2236 LLVMValueRef args[] = {target_frame_ptr, arg_val};2215 LLVMValueRef args[] = {target_frame_ptr, arg_val};
2237 return ZigLLVMBuildCall(g->builder, fn_val, args, 2, LLVMFastCallConv, ZigLLVM_FnInlineAuto, "");2216 return ZigLLVMBuildCall(g->builder, fn_val, args, 2, LLVMFastCallConv, ZigLLVM_FnInlineAuto, "");
2238}2217}
22392218
2240static LLVMValueRef get_cur_async_prev_val(CodeGen *g) {
2241 if (g->cur_async_prev_val != nullptr) {
2242 return g->cur_async_prev_val;
2243 }
2244 g->cur_async_prev_val = LLVMBuildLoad(g->builder, g->cur_async_prev_val_field_ptr, "");
2245 return g->cur_async_prev_val;
2246}
2247
2248static LLVMBasicBlockRef gen_suspend_begin(CodeGen *g, const char *name_hint) {2219static LLVMBasicBlockRef gen_suspend_begin(CodeGen *g, const char *name_hint) {
2249 // This becomes invalid when a suspend happens.
2250 g->cur_async_prev_val = nullptr;
2251
2252 LLVMTypeRef usize_type_ref = g->builtin_types.entry_usize->llvm_type;2220 LLVMTypeRef usize_type_ref = g->builtin_types.entry_usize->llvm_type;
2253 LLVMBasicBlockRef resume_bb = LLVMAppendBasicBlock(g->cur_fn_val, name_hint);2221 LLVMBasicBlockRef resume_bb = LLVMAppendBasicBlock(g->cur_fn_val, name_hint);
2254 size_t new_block_index = g->cur_resume_block_count;2222 size_t new_block_index = g->cur_resume_block_count;
...@@ -2259,6 +2227,10 @@ static LLVMBasicBlockRef gen_suspend_begin(CodeGen *g, const char *name_hint) {...@@ -2259,6 +2227,10 @@ static LLVMBasicBlockRef gen_suspend_begin(CodeGen *g, const char *name_hint) {
2259 return resume_bb;2227 return resume_bb;
2260}2228}
22612229
2230static void set_tail_call_if_appropriate(CodeGen *g, LLVMValueRef call_inst) {
2231 LLVMSetTailCall(call_inst, true);
2232}
2233
2262static LLVMValueRef gen_maybe_atomic_op(CodeGen *g, LLVMAtomicRMWBinOp op, LLVMValueRef ptr, LLVMValueRef val,2234static LLVMValueRef gen_maybe_atomic_op(CodeGen *g, LLVMAtomicRMWBinOp op, LLVMValueRef ptr, LLVMValueRef val,
2263 LLVMAtomicOrdering order)2235 LLVMAtomicOrdering order)
2264{2236{
...@@ -2282,32 +2254,32 @@ static LLVMValueRef gen_maybe_atomic_op(CodeGen *g, LLVMAtomicRMWBinOp op, LLVMV...@@ -2282,32 +2254,32 @@ static LLVMValueRef gen_maybe_atomic_op(CodeGen *g, LLVMAtomicRMWBinOp op, LLVMV
2282 }2254 }
2283}2255}
22842256
2285static LLVMValueRef ir_render_return_begin(CodeGen *g, IrExecutable *executable,2257static void gen_async_return(CodeGen *g, IrInstructionReturn *instruction) {
2286 IrInstructionReturnBegin *instruction)2258 LLVMTypeRef usize_type_ref = g->builtin_types.entry_usize->llvm_type;
2287{2259
2288 ZigType *operand_type = (instruction->operand != nullptr) ? instruction->operand->value.type : nullptr;2260 ZigType *operand_type = (instruction->operand != nullptr) ? instruction->operand->value.type : nullptr;
2289 bool operand_has_bits = (operand_type != nullptr) && type_has_bits(operand_type);2261 bool operand_has_bits = (operand_type != nullptr) && type_has_bits(operand_type);
2290 if (!fn_is_async(g->cur_fn)) {2262 ZigType *ret_type = g->cur_fn->type_entry->data.fn.fn_type_id.return_type;
2291 return operand_has_bits ? ir_llvm_value(g, instruction->operand) : nullptr;2263 bool ret_type_has_bits = type_has_bits(ret_type);
2292 }
22932264
2294 LLVMTypeRef usize_type_ref = g->builtin_types.entry_usize->llvm_type;
2295 if (operand_has_bits && instruction->operand != nullptr) {2265 if (operand_has_bits && instruction->operand != nullptr) {
2296 ZigType *ret_type = g->cur_fn->type_entry->data.fn.fn_type_id.return_type;
2297 bool need_store = instruction->operand->value.special != ConstValSpecialRuntime || !handle_is_ptr(ret_type);2266 bool need_store = instruction->operand->value.special != ConstValSpecialRuntime || !handle_is_ptr(ret_type);
2298 if (need_store) {2267 if (need_store) {
2299 // It didn't get written to the result ptr. We do that now so that we do not have to spill2268 // It didn't get written to the result ptr. We do that now.
2300 // the return operand.
2301 ZigType *ret_ptr_type = get_pointer_to_type(g, ret_type, true);2269 ZigType *ret_ptr_type = get_pointer_to_type(g, ret_type, true);
2302 gen_assign_raw(g, g->cur_ret_ptr, ret_ptr_type, ir_llvm_value(g, instruction->operand));2270 gen_assign_raw(g, g->cur_ret_ptr, ret_ptr_type, ir_llvm_value(g, instruction->operand));
2303 }2271 }
2304 }2272 }
23052273
2306 // Prepare to be suspended. We might end up not having to suspend though.2274 // Whether we tail resume the awaiter, or do an early return, we are done and will not be resumed.
2307 LLVMBasicBlockRef resume_bb = gen_suspend_begin(g, "ReturnResume");2275 if (ir_want_runtime_safety(g, &instruction->base)) {
2276 LLVMValueRef new_resume_index = LLVMConstAllOnes(usize_type_ref);
2277 LLVMBuildStore(g->builder, new_resume_index, g->cur_async_resume_index_ptr);
2278 }
23082279
2309 LLVMValueRef zero = LLVMConstNull(usize_type_ref);2280 LLVMValueRef zero = LLVMConstNull(usize_type_ref);
2310 LLVMValueRef all_ones = LLVMConstAllOnes(usize_type_ref);2281 LLVMValueRef all_ones = LLVMConstAllOnes(usize_type_ref);
2282
2311 LLVMValueRef prev_val = gen_maybe_atomic_op(g, LLVMAtomicRMWBinOpXor, g->cur_async_awaiter_ptr,2283 LLVMValueRef prev_val = gen_maybe_atomic_op(g, LLVMAtomicRMWBinOpXor, g->cur_async_awaiter_ptr,
2312 all_ones, LLVMAtomicOrderingAcquire);2284 all_ones, LLVMAtomicOrderingAcquire);
23132285
...@@ -2316,7 +2288,6 @@ static LLVMValueRef ir_render_return_begin(CodeGen *g, IrExecutable *executable,...@@ -2316,7 +2288,6 @@ static LLVMValueRef ir_render_return_begin(CodeGen *g, IrExecutable *executable,
2316 LLVMBasicBlockRef resume_them_block = LLVMAppendBasicBlock(g->cur_fn_val, "ResumeThem");2288 LLVMBasicBlockRef resume_them_block = LLVMAppendBasicBlock(g->cur_fn_val, "ResumeThem");
23172289
2318 LLVMValueRef switch_instr = LLVMBuildSwitch(g->builder, prev_val, resume_them_block, 2);2290 LLVMValueRef switch_instr = LLVMBuildSwitch(g->builder, prev_val, resume_them_block, 2);
2319 LLVMBasicBlockRef switch_bb = LLVMGetInsertBlock(g->builder);
23202291
2321 LLVMAddCase(switch_instr, zero, early_return_block);2292 LLVMAddCase(switch_instr, zero, early_return_block);
2322 LLVMAddCase(switch_instr, all_ones, bad_return_block);2293 LLVMAddCase(switch_instr, all_ones, bad_return_block);
...@@ -2325,90 +2296,63 @@ static LLVMValueRef ir_render_return_begin(CodeGen *g, IrExecutable *executable,...@@ -2325,90 +2296,63 @@ static LLVMValueRef ir_render_return_begin(CodeGen *g, IrExecutable *executable,
2325 LLVMPositionBuilderAtEnd(g->builder, bad_return_block);2296 LLVMPositionBuilderAtEnd(g->builder, bad_return_block);
2326 gen_assertion(g, PanicMsgIdBadReturn, &instruction->base);2297 gen_assertion(g, PanicMsgIdBadReturn, &instruction->base);
23272298
2328 // The caller has not done an await yet. So we suspend at the return instruction, until a2299 // There is no awaiter yet, but we're completely done.
2329 // cancel or await is performed.
2330 LLVMPositionBuilderAtEnd(g->builder, early_return_block);2300 LLVMPositionBuilderAtEnd(g->builder, early_return_block);
2331 LLVMBuildRetVoid(g->builder);2301 LLVMBuildRetVoid(g->builder);
23322302
2333 // Add a safety check for when getting resumed by the awaiter.2303 // We need to resume the caller by tail calling them,
2334 LLVMPositionBuilderAtEnd(g->builder, resume_bb);2304 // but first write through the result pointer and possibly
2335 LLVMBasicBlockRef after_resume_block = LLVMGetInsertBlock(g->builder);2305 // error return trace pointer.
2336 gen_assert_resume_id(g, &instruction->base, ResumeIdAwaitEarlyReturn, PanicMsgIdResumedFnPendingAwait,2306 LLVMPositionBuilderAtEnd(g->builder, resume_them_block);
2337 resume_them_block);2307
23382308 if (ret_type_has_bits) {
2339 // We need to resume the caller by tail calling them.2309 // If the awaiter result pointer is non-null, we need to copy the result to there.
2340 // That will happen when rendering IrInstructionReturn after running the defers/errdefers.2310 LLVMBasicBlockRef copy_block = LLVMAppendBasicBlock(g->cur_fn_val, "CopyResult");
2341 // We either got here from Entry (function call) or from the switch above2311 LLVMBasicBlockRef copy_end_block = LLVMAppendBasicBlock(g->cur_fn_val, "CopyResultEnd");
2342 g->cur_async_prev_val = LLVMBuildPhi(g->builder, usize_type_ref, "");2312 LLVMValueRef awaiter_ret_ptr_ptr = LLVMBuildStructGEP(g->builder, g->cur_frame_ptr, frame_ret_start + 1, "");
2343 LLVMValueRef incoming_values[] = { LLVMGetParam(g->cur_fn_val, 1), prev_val };2313 LLVMValueRef awaiter_ret_ptr = LLVMBuildLoad(g->builder, awaiter_ret_ptr_ptr, "");
2344 LLVMBasicBlockRef incoming_blocks[] = { after_resume_block, switch_bb };2314 LLVMValueRef zero_ptr = LLVMConstNull(LLVMTypeOf(awaiter_ret_ptr));
2345 LLVMAddIncoming(g->cur_async_prev_val, incoming_values, incoming_blocks, 2);2315 LLVMValueRef need_copy_bit = LLVMBuildICmp(g->builder, LLVMIntNE, awaiter_ret_ptr, zero_ptr, "");
23462316 LLVMBuildCondBr(g->builder, need_copy_bit, copy_block, copy_end_block);
2347 g->cur_is_after_return = true;2317
2348 LLVMBuildStore(g->builder, g->cur_async_prev_val, g->cur_async_prev_val_field_ptr);2318 LLVMPositionBuilderAtEnd(g->builder, copy_block);
23492319 LLVMTypeRef ptr_u8 = LLVMPointerType(LLVMInt8Type(), 0);
2350 if (!operand_has_bits) {2320 LLVMValueRef dest_ptr_casted = LLVMBuildBitCast(g->builder, awaiter_ret_ptr, ptr_u8, "");
2351 return nullptr;2321 LLVMValueRef src_ptr_casted = LLVMBuildBitCast(g->builder, g->cur_ret_ptr, ptr_u8, "");
2352 }2322 bool is_volatile = false;
23532323 uint32_t abi_align = get_abi_alignment(g, ret_type);
2354 return get_handle_value(g, g->cur_ret_ptr, operand_type, get_pointer_to_type(g, operand_type, true));2324 LLVMValueRef byte_count_val = LLVMConstInt(usize_type_ref, type_size(g, ret_type), false);
2355}2325 ZigLLVMBuildMemCpy(g->builder,
23562326 dest_ptr_casted, abi_align,
2357static void set_tail_call_if_appropriate(CodeGen *g, LLVMValueRef call_inst) {2327 src_ptr_casted, abi_align, byte_count_val, is_volatile);
2358 LLVMSetTailCall(call_inst, true);2328 LLVMBuildBr(g->builder, copy_end_block);
2329
2330 LLVMPositionBuilderAtEnd(g->builder, copy_end_block);
2331 if (codegen_fn_has_err_ret_tracing_arg(g, ret_type)) {
2332 LLVMValueRef awaiter_trace_ptr_ptr = LLVMBuildStructGEP(g->builder, g->cur_frame_ptr,
2333 frame_index_trace_arg(g, ret_type) + 1, "");
2334 LLVMValueRef dest_trace_ptr = LLVMBuildLoad(g->builder, awaiter_trace_ptr_ptr, "");
2335 LLVMValueRef my_err_trace_val = get_cur_err_ret_trace_val(g, instruction->base.scope);
2336 LLVMValueRef args[] = { dest_trace_ptr, my_err_trace_val };
2337 ZigLLVMBuildCall(g->builder, get_merge_err_ret_traces_fn_val(g), args, 2,
2338 get_llvm_cc(g, CallingConventionUnspecified), ZigLLVM_FnInlineAuto, "");
2339 }
2340 }
2341
2342 // Resume the caller by tail calling them.
2343 ZigType *any_frame_type = get_any_frame_type(g, ret_type);
2344 LLVMValueRef their_frame_ptr = LLVMBuildIntToPtr(g->builder, prev_val, get_llvm_type(g, any_frame_type), "");
2345 LLVMValueRef call_inst = gen_resume(g, nullptr, their_frame_ptr, ResumeIdReturn);
2346 set_tail_call_if_appropriate(g, call_inst);
2347 LLVMBuildRetVoid(g->builder);
2359}2348}
23602349
2361static LLVMValueRef ir_render_return(CodeGen *g, IrExecutable *executable, IrInstructionReturn *instruction) {2350static LLVMValueRef ir_render_return(CodeGen *g, IrExecutable *executable, IrInstructionReturn *instruction) {
2362 if (fn_is_async(g->cur_fn)) {2351 if (fn_is_async(g->cur_fn)) {
2363 LLVMTypeRef usize_type_ref = g->builtin_types.entry_usize->llvm_type;2352 gen_async_return(g, instruction);
2364 ZigType *ret_type = g->cur_fn->type_entry->data.fn.fn_type_id.return_type;
2365 bool ret_type_has_bits = type_has_bits(ret_type);
2366
2367 if (ir_want_runtime_safety(g, &instruction->base)) {
2368 LLVMValueRef new_resume_index = LLVMConstAllOnes(usize_type_ref);
2369 LLVMBuildStore(g->builder, new_resume_index, g->cur_async_resume_index_ptr);
2370 }
2371
2372 if (ret_type_has_bits) {
2373 // If the awaiter result pointer is non-null, we need to copy the result to there.
2374 LLVMBasicBlockRef copy_block = LLVMAppendBasicBlock(g->cur_fn_val, "CopyResult");
2375 LLVMBasicBlockRef copy_end_block = LLVMAppendBasicBlock(g->cur_fn_val, "CopyResultEnd");
2376 LLVMValueRef awaiter_ret_ptr_ptr = LLVMBuildStructGEP(g->builder, g->cur_frame_ptr, frame_ret_start + 1, "");
2377 LLVMValueRef awaiter_ret_ptr = LLVMBuildLoad(g->builder, awaiter_ret_ptr_ptr, "");
2378 LLVMValueRef zero_ptr = LLVMConstNull(LLVMTypeOf(awaiter_ret_ptr));
2379 LLVMValueRef need_copy_bit = LLVMBuildICmp(g->builder, LLVMIntNE, awaiter_ret_ptr, zero_ptr, "");
2380 LLVMBuildCondBr(g->builder, need_copy_bit, copy_block, copy_end_block);
2381
2382 LLVMPositionBuilderAtEnd(g->builder, copy_block);
2383 LLVMTypeRef ptr_u8 = LLVMPointerType(LLVMInt8Type(), 0);
2384 LLVMValueRef dest_ptr_casted = LLVMBuildBitCast(g->builder, awaiter_ret_ptr, ptr_u8, "");
2385 LLVMValueRef src_ptr_casted = LLVMBuildBitCast(g->builder, g->cur_ret_ptr, ptr_u8, "");
2386 bool is_volatile = false;
2387 uint32_t abi_align = get_abi_alignment(g, ret_type);
2388 LLVMValueRef byte_count_val = LLVMConstInt(usize_type_ref, type_size(g, ret_type), false);
2389 ZigLLVMBuildMemCpy(g->builder,
2390 dest_ptr_casted, abi_align,
2391 src_ptr_casted, abi_align, byte_count_val, is_volatile);
2392 LLVMBuildBr(g->builder, copy_end_block);
2393
2394 LLVMPositionBuilderAtEnd(g->builder, copy_end_block);
2395 }
2396
2397 // We need to resume the caller by tail calling them.
2398 ZigType *any_frame_type = get_any_frame_type(g, ret_type);
2399 LLVMValueRef one = LLVMConstInt(usize_type_ref, 1, false);
2400 LLVMValueRef mask_val = LLVMConstNot(one);
2401 LLVMValueRef masked_prev_val = LLVMBuildAnd(g->builder, get_cur_async_prev_val(g), mask_val, "");
2402 LLVMValueRef their_frame_ptr = LLVMBuildIntToPtr(g->builder, masked_prev_val,
2403 get_llvm_type(g, any_frame_type), "");
2404 LLVMValueRef call_inst = gen_resume(g, nullptr, their_frame_ptr, ResumeIdReturn, nullptr);
2405 set_tail_call_if_appropriate(g, call_inst);
2406 LLVMBuildRetVoid(g->builder);
2407
2408 g->cur_is_after_return = false;
2409
2410 return nullptr;2353 return nullptr;
2411 }2354 }
2355
2412 if (want_first_arg_sret(g, &g->cur_fn->type_entry->data.fn.fn_type_id)) {2356 if (want_first_arg_sret(g, &g->cur_fn->type_entry->data.fn.fn_type_id)) {
2413 if (instruction->operand == nullptr) {2357 if (instruction->operand == nullptr) {
2414 LLVMBuildRetVoid(g->builder);2358 LLVMBuildRetVoid(g->builder);
...@@ -3893,6 +3837,8 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr...@@ -3893,6 +3837,8 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr
3893 // even if prefix_arg_err_ret_stack is true, let the async function do its own3837 // even if prefix_arg_err_ret_stack is true, let the async function do its own
3894 // initialization.3838 // initialization.
3895 } else {3839 } else {
3840 // async function called as a normal function
3841
3896 frame_result_loc = ir_llvm_value(g, instruction->frame_result_loc);3842 frame_result_loc = ir_llvm_value(g, instruction->frame_result_loc);
3897 awaiter_init_val = LLVMBuildPtrToInt(g->builder, g->cur_frame_ptr, usize_type_ref, ""); // caller's own frame pointer3843 awaiter_init_val = LLVMBuildPtrToInt(g->builder, g->cur_frame_ptr, usize_type_ref, ""); // caller's own frame pointer
3898 if (ret_has_bits) {3844 if (ret_has_bits) {
...@@ -3912,7 +3858,7 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr...@@ -3912,7 +3858,7 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr
39123858
3913 if (prefix_arg_err_ret_stack) {3859 if (prefix_arg_err_ret_stack) {
3914 LLVMValueRef err_ret_trace_ptr_ptr = LLVMBuildStructGEP(g->builder, frame_result_loc,3860 LLVMValueRef err_ret_trace_ptr_ptr = LLVMBuildStructGEP(g->builder, frame_result_loc,
3915 frame_index_trace_arg(g, src_return_type), "");3861 frame_index_trace_arg(g, src_return_type) + 1, "");
3916 LLVMValueRef my_err_ret_trace_val = get_cur_err_ret_trace_val(g, instruction->base.scope);3862 LLVMValueRef my_err_ret_trace_val = get_cur_err_ret_trace_val(g, instruction->base.scope);
3917 LLVMBuildStore(g->builder, my_err_ret_trace_val, err_ret_trace_ptr_ptr);3863 LLVMBuildStore(g->builder, my_err_ret_trace_val, err_ret_trace_ptr_ptr);
3918 }3864 }
...@@ -4018,7 +3964,7 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr...@@ -4018,7 +3964,7 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr
4018 }3964 }
40193965
4020 if (instruction->is_async) {3966 if (instruction->is_async) {
4021 gen_resume(g, fn_val, frame_result_loc, ResumeIdCall, nullptr);3967 gen_resume(g, fn_val, frame_result_loc, ResumeIdCall);
4022 if (instruction->new_stack != nullptr) {3968 if (instruction->new_stack != nullptr) {
4023 return frame_result_loc;3969 return frame_result_loc;
4024 }3970 }
...@@ -4028,7 +3974,7 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr...@@ -4028,7 +3974,7 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr
40283974
4029 LLVMBasicBlockRef call_bb = gen_suspend_begin(g, "CallResume");3975 LLVMBasicBlockRef call_bb = gen_suspend_begin(g, "CallResume");
40303976
4031 LLVMValueRef call_inst = gen_resume(g, fn_val, frame_result_loc, ResumeIdCall, nullptr);3977 LLVMValueRef call_inst = gen_resume(g, fn_val, frame_result_loc, ResumeIdCall);
4032 set_tail_call_if_appropriate(g, call_inst);3978 set_tail_call_if_appropriate(g, call_inst);
4033 LLVMBuildRetVoid(g->builder);3979 LLVMBuildRetVoid(g->builder);
40343980
...@@ -4744,8 +4690,7 @@ static LLVMValueRef ir_render_error_return_trace(CodeGen *g, IrExecutable *execu...@@ -4744,8 +4690,7 @@ static LLVMValueRef ir_render_error_return_trace(CodeGen *g, IrExecutable *execu
4744{4690{
4745 LLVMValueRef cur_err_ret_trace_val = get_cur_err_ret_trace_val(g, instruction->base.scope);4691 LLVMValueRef cur_err_ret_trace_val = get_cur_err_ret_trace_val(g, instruction->base.scope);
4746 if (cur_err_ret_trace_val == nullptr) {4692 if (cur_err_ret_trace_val == nullptr) {
4747 ZigType *ptr_to_stack_trace_type = get_ptr_to_stack_trace_type(g);4693 return LLVMConstNull(get_llvm_type(g, ptr_to_stack_trace_type(g)));
4748 return LLVMConstNull(get_llvm_type(g, ptr_to_stack_trace_type));
4749 }4694 }
4750 return cur_err_ret_trace_val;4695 return cur_err_ret_trace_val;
4751}4696}
...@@ -5505,60 +5450,6 @@ static LLVMValueRef ir_render_suspend_finish(CodeGen *g, IrExecutable *executabl...@@ -5505,60 +5450,6 @@ static LLVMValueRef ir_render_suspend_finish(CodeGen *g, IrExecutable *executabl
5505 return nullptr;5450 return nullptr;
5506}5451}
55075452
5508static LLVMValueRef ir_render_cancel(CodeGen *g, IrExecutable *executable, IrInstructionCancel *instruction) {
5509 LLVMTypeRef usize_type_ref = g->builtin_types.entry_usize->llvm_type;
5510 LLVMValueRef zero = LLVMConstNull(usize_type_ref);
5511 LLVMValueRef all_ones = LLVMConstAllOnes(usize_type_ref);
5512 LLVMValueRef one = LLVMConstInt(usize_type_ref, 1, false);
5513 src_assert(instruction->frame->value.type->id == ZigTypeIdAnyFrame, instruction->base.source_node);
5514 ZigType *result_type = instruction->frame->value.type->data.any_frame.result_type;
5515
5516 LLVMValueRef target_frame_ptr = ir_llvm_value(g, instruction->frame);
5517 LLVMBasicBlockRef resume_bb = gen_suspend_begin(g, "CancelResume");
5518
5519 // supply null for the awaiter return pointer (no copy needed)
5520 if (type_has_bits(result_type)) {
5521 LLVMValueRef awaiter_ret_ptr_ptr = LLVMBuildStructGEP(g->builder, target_frame_ptr, frame_ret_start + 1, "");
5522 LLVMBuildStore(g->builder, LLVMConstNull(LLVMGetElementType(LLVMTypeOf(awaiter_ret_ptr_ptr))),
5523 awaiter_ret_ptr_ptr);
5524 }
5525
5526 // supply null for the error return trace pointer
5527 if (codegen_fn_has_err_ret_tracing_arg(g, result_type)) {
5528 LLVMValueRef err_ret_trace_ptr_ptr = LLVMBuildStructGEP(g->builder, target_frame_ptr,
5529 frame_index_trace_arg(g, result_type), "");
5530 LLVMBuildStore(g->builder, LLVMConstNull(LLVMGetElementType(LLVMTypeOf(err_ret_trace_ptr_ptr))),
5531 err_ret_trace_ptr_ptr);
5532 }
5533
5534 LLVMValueRef awaiter_val = LLVMBuildPtrToInt(g->builder, g->cur_frame_ptr, usize_type_ref, "");
5535 LLVMValueRef awaiter_ored_val = LLVMBuildOr(g->builder, awaiter_val, one, "");
5536 LLVMValueRef awaiter_ptr = LLVMBuildStructGEP(g->builder, target_frame_ptr, frame_awaiter_index, "");
5537
5538 LLVMValueRef prev_val = gen_maybe_atomic_op(g, LLVMAtomicRMWBinOpXchg, awaiter_ptr, awaiter_ored_val,
5539 LLVMAtomicOrderingRelease);
5540
5541 LLVMBasicBlockRef complete_suspend_block = LLVMAppendBasicBlock(g->cur_fn_val, "CancelSuspend");
5542 LLVMBasicBlockRef early_return_block = LLVMAppendBasicBlock(g->cur_fn_val, "EarlyReturn");
5543
5544 LLVMValueRef switch_instr = LLVMBuildSwitch(g->builder, prev_val, resume_bb, 2);
5545 LLVMAddCase(switch_instr, zero, complete_suspend_block);
5546 LLVMAddCase(switch_instr, all_ones, early_return_block);
5547
5548 LLVMPositionBuilderAtEnd(g->builder, complete_suspend_block);
5549 LLVMBuildRetVoid(g->builder);
5550
5551 LLVMPositionBuilderAtEnd(g->builder, early_return_block);
5552 LLVMValueRef call_inst = gen_resume(g, nullptr, target_frame_ptr, ResumeIdAwaitEarlyReturn, awaiter_ored_val);
5553 set_tail_call_if_appropriate(g, call_inst);
5554 LLVMBuildRetVoid(g->builder);
5555
5556 LLVMPositionBuilderAtEnd(g->builder, resume_bb);
5557 gen_assert_resume_id(g, &instruction->base, ResumeIdReturn, PanicMsgIdResumedACancelingFn, nullptr);
5558
5559 return nullptr;
5560}
5561
5562static LLVMValueRef ir_render_await(CodeGen *g, IrExecutable *executable, IrInstructionAwaitGen *instruction) {5453static LLVMValueRef ir_render_await(CodeGen *g, IrExecutable *executable, IrInstructionAwaitGen *instruction) {
5563 LLVMTypeRef usize_type_ref = g->builtin_types.entry_usize->llvm_type;5454 LLVMTypeRef usize_type_ref = g->builtin_types.entry_usize->llvm_type;
5564 LLVMValueRef zero = LLVMConstNull(usize_type_ref);5455 LLVMValueRef zero = LLVMConstNull(usize_type_ref);
...@@ -5568,8 +5459,9 @@ static LLVMValueRef ir_render_await(CodeGen *g, IrExecutable *executable, IrInst...@@ -5568,8 +5459,9 @@ static LLVMValueRef ir_render_await(CodeGen *g, IrExecutable *executable, IrInst
55685459
5569 // Prepare to be suspended5460 // Prepare to be suspended
5570 LLVMBasicBlockRef resume_bb = gen_suspend_begin(g, "AwaitResume");5461 LLVMBasicBlockRef resume_bb = gen_suspend_begin(g, "AwaitResume");
5462 LLVMBasicBlockRef end_bb = LLVMAppendBasicBlock(g->cur_fn_val, "AwaitEnd");
55715463
5572 // At this point resuming the function will do the correct thing.5464 // At this point resuming the function will continue from resume_bb.
5573 // This code is as if it is running inside the suspend block.5465 // This code is as if it is running inside the suspend block.
55745466
5575 // supply the awaiter return pointer5467 // supply the awaiter return pointer
...@@ -5591,15 +5483,15 @@ static LLVMValueRef ir_render_await(CodeGen *g, IrExecutable *executable, IrInst...@@ -5591,15 +5483,15 @@ static LLVMValueRef ir_render_await(CodeGen *g, IrExecutable *executable, IrInst
5591 LLVMValueRef my_err_ret_trace_val = get_cur_err_ret_trace_val(g, instruction->base.scope);5483 LLVMValueRef my_err_ret_trace_val = get_cur_err_ret_trace_val(g, instruction->base.scope);
5592 assert(my_err_ret_trace_val != nullptr);5484 assert(my_err_ret_trace_val != nullptr);
5593 LLVMValueRef err_ret_trace_ptr_ptr = LLVMBuildStructGEP(g->builder, target_frame_ptr,5485 LLVMValueRef err_ret_trace_ptr_ptr = LLVMBuildStructGEP(g->builder, target_frame_ptr,
5594 frame_index_trace_arg(g, result_type), "");5486 frame_index_trace_arg(g, result_type) + 1, "");
5595 LLVMBuildStore(g->builder, my_err_ret_trace_val, err_ret_trace_ptr_ptr);5487 LLVMBuildStore(g->builder, my_err_ret_trace_val, err_ret_trace_ptr_ptr);
5596 }5488 }
55975489
5598 // caller's own frame pointer5490 // caller's own frame pointer
5599 LLVMValueRef awaiter_init_val = LLVMBuildPtrToInt(g->builder, g->cur_frame_ptr, usize_type_ref, "");5491 LLVMValueRef awaiter_init_val = LLVMBuildPtrToInt(g->builder, g->cur_frame_ptr, usize_type_ref, "");
5600 LLVMValueRef awaiter_ptr = LLVMBuildStructGEP(g->builder, target_frame_ptr, frame_awaiter_index, "");5492 LLVMValueRef awaiter_ptr = LLVMBuildStructGEP(g->builder, target_frame_ptr, frame_awaiter_index, "");
5601 LLVMValueRef prev_val = LLVMBuildAtomicRMW(g->builder, LLVMAtomicRMWBinOpXchg, awaiter_ptr, awaiter_init_val,5493 LLVMValueRef prev_val = gen_maybe_atomic_op(g, LLVMAtomicRMWBinOpXchg, awaiter_ptr, awaiter_init_val,
5602 LLVMAtomicOrderingRelease, g->is_single_threaded);5494 LLVMAtomicOrderingRelease);
56035495
5604 LLVMBasicBlockRef bad_await_block = LLVMAppendBasicBlock(g->cur_fn_val, "BadAwait");5496 LLVMBasicBlockRef bad_await_block = LLVMAppendBasicBlock(g->cur_fn_val, "BadAwait");
5605 LLVMBasicBlockRef complete_suspend_block = LLVMAppendBasicBlock(g->cur_fn_val, "CompleteSuspend");5497 LLVMBasicBlockRef complete_suspend_block = LLVMAppendBasicBlock(g->cur_fn_val, "CompleteSuspend");
...@@ -5615,20 +5507,42 @@ static LLVMValueRef ir_render_await(CodeGen *g, IrExecutable *executable, IrInst...@@ -5615,20 +5507,42 @@ static LLVMValueRef ir_render_await(CodeGen *g, IrExecutable *executable, IrInst
5615 LLVMPositionBuilderAtEnd(g->builder, bad_await_block);5507 LLVMPositionBuilderAtEnd(g->builder, bad_await_block);
5616 gen_assertion(g, PanicMsgIdBadAwait, &instruction->base);5508 gen_assertion(g, PanicMsgIdBadAwait, &instruction->base);
56175509
5618 // Early return: The async function has already completed, but it is suspending before setting the result,
5619 // populating the error return trace if applicable, and running the defers.
5620 // Tail resume it now, so that it can complete.
5621 LLVMPositionBuilderAtEnd(g->builder, early_return_block);
5622 LLVMValueRef call_inst = gen_resume(g, nullptr, target_frame_ptr, ResumeIdAwaitEarlyReturn, awaiter_init_val);
5623 set_tail_call_if_appropriate(g, call_inst);
5624 LLVMBuildRetVoid(g->builder);
5625
5626 // Rely on the target to resume us from suspension.5510 // Rely on the target to resume us from suspension.
5627 LLVMPositionBuilderAtEnd(g->builder, complete_suspend_block);5511 LLVMPositionBuilderAtEnd(g->builder, complete_suspend_block);
5628 LLVMBuildRetVoid(g->builder);5512 LLVMBuildRetVoid(g->builder);
56295513
5514 // Early return: The async function has already completed. We must copy the result and
5515 // the error return trace if applicable.
5516 LLVMPositionBuilderAtEnd(g->builder, early_return_block);
5517 if (type_has_bits(result_type) && result_loc != nullptr) {
5518 LLVMValueRef their_result_ptr_ptr = LLVMBuildStructGEP(g->builder, target_frame_ptr, frame_ret_start, "");
5519 LLVMValueRef their_result_ptr = LLVMBuildLoad(g->builder, their_result_ptr_ptr, "");
5520 LLVMTypeRef ptr_u8 = LLVMPointerType(LLVMInt8Type(), 0);
5521 LLVMValueRef dest_ptr_casted = LLVMBuildBitCast(g->builder, result_loc, ptr_u8, "");
5522 LLVMValueRef src_ptr_casted = LLVMBuildBitCast(g->builder, their_result_ptr, ptr_u8, "");
5523 bool is_volatile = false;
5524 uint32_t abi_align = get_abi_alignment(g, result_type);
5525 LLVMValueRef byte_count_val = LLVMConstInt(usize_type_ref, type_size(g, result_type), false);
5526 ZigLLVMBuildMemCpy(g->builder,
5527 dest_ptr_casted, abi_align,
5528 src_ptr_casted, abi_align, byte_count_val, is_volatile);
5529 }
5530 if (codegen_fn_has_err_ret_tracing_arg(g, result_type)) {
5531 LLVMValueRef their_trace_ptr_ptr = LLVMBuildStructGEP(g->builder, target_frame_ptr,
5532 frame_index_trace_arg(g, result_type), "");
5533 LLVMValueRef src_trace_ptr = LLVMBuildLoad(g->builder, their_trace_ptr_ptr, "");
5534 LLVMValueRef dest_trace_ptr = get_cur_err_ret_trace_val(g, instruction->base.scope);
5535 LLVMValueRef args[] = { dest_trace_ptr, src_trace_ptr };
5536 ZigLLVMBuildCall(g->builder, get_merge_err_ret_traces_fn_val(g), args, 2,
5537 get_llvm_cc(g, CallingConventionUnspecified), ZigLLVM_FnInlineAuto, "");
5538 }
5539 LLVMBuildBr(g->builder, end_bb);
5540
5630 LLVMPositionBuilderAtEnd(g->builder, resume_bb);5541 LLVMPositionBuilderAtEnd(g->builder, resume_bb);
5631 gen_assert_resume_id(g, &instruction->base, ResumeIdReturn, PanicMsgIdResumedAnAwaitingFn, nullptr);5542 gen_assert_resume_id(g, &instruction->base, ResumeIdReturn, PanicMsgIdResumedAnAwaitingFn, nullptr);
5543 LLVMBuildBr(g->builder, end_bb);
5544
5545 LLVMPositionBuilderAtEnd(g->builder, end_bb);
5632 if (type_has_bits(result_type) && result_loc != nullptr) {5546 if (type_has_bits(result_type) && result_loc != nullptr) {
5633 return get_handle_value(g, result_loc, result_type, ptr_result_type);5547 return get_handle_value(g, result_loc, result_type, ptr_result_type);
5634 }5548 }
...@@ -5640,7 +5554,7 @@ static LLVMValueRef ir_render_resume(CodeGen *g, IrExecutable *executable, IrIns...@@ -5640,7 +5554,7 @@ static LLVMValueRef ir_render_resume(CodeGen *g, IrExecutable *executable, IrIns
5640 ZigType *frame_type = instruction->frame->value.type;5554 ZigType *frame_type = instruction->frame->value.type;
5641 assert(frame_type->id == ZigTypeIdAnyFrame);5555 assert(frame_type->id == ZigTypeIdAnyFrame);
56425556
5643 gen_resume(g, nullptr, frame, ResumeIdManual, nullptr);5557 gen_resume(g, nullptr, frame, ResumeIdManual);
5644 return nullptr;5558 return nullptr;
5645}5559}
56465560
...@@ -5651,18 +5565,6 @@ static LLVMValueRef ir_render_frame_size(CodeGen *g, IrExecutable *executable,...@@ -5651,18 +5565,6 @@ static LLVMValueRef ir_render_frame_size(CodeGen *g, IrExecutable *executable,
5651 return gen_frame_size(g, fn_val);5565 return gen_frame_size(g, fn_val);
5652}5566}
56535567
5654static LLVMValueRef ir_render_test_cancel_requested(CodeGen *g, IrExecutable *executable,
5655 IrInstructionTestCancelRequested *instruction)
5656{
5657 if (!fn_is_async(g->cur_fn))
5658 return LLVMConstInt(LLVMInt1Type(), 0, false);
5659 if (g->cur_is_after_return) {
5660 return LLVMBuildTrunc(g->builder, get_cur_async_prev_val(g), LLVMInt1Type(), "");
5661 } else {
5662 zig_panic("TODO");
5663 }
5664}
5665
5666static LLVMValueRef ir_render_spill_begin(CodeGen *g, IrExecutable *executable,5568static LLVMValueRef ir_render_spill_begin(CodeGen *g, IrExecutable *executable,
5667 IrInstructionSpillBegin *instruction)5569 IrInstructionSpillBegin *instruction)
5668{5570{
...@@ -5798,8 +5700,6 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,...@@ -5798,8 +5700,6 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
57985700
5799 case IrInstructionIdDeclVarGen:5701 case IrInstructionIdDeclVarGen:
5800 return ir_render_decl_var(g, executable, (IrInstructionDeclVarGen *)instruction);5702 return ir_render_decl_var(g, executable, (IrInstructionDeclVarGen *)instruction);
5801 case IrInstructionIdReturnBegin:
5802 return ir_render_return_begin(g, executable, (IrInstructionReturnBegin *)instruction);
5803 case IrInstructionIdReturn:5703 case IrInstructionIdReturn:
5804 return ir_render_return(g, executable, (IrInstructionReturn *)instruction);5704 return ir_render_return(g, executable, (IrInstructionReturn *)instruction);
5805 case IrInstructionIdBinOp:5705 case IrInstructionIdBinOp:
...@@ -5918,8 +5818,6 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,...@@ -5918,8 +5818,6 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
5918 return ir_render_align_cast(g, executable, (IrInstructionAlignCast *)instruction);5818 return ir_render_align_cast(g, executable, (IrInstructionAlignCast *)instruction);
5919 case IrInstructionIdErrorReturnTrace:5819 case IrInstructionIdErrorReturnTrace:
5920 return ir_render_error_return_trace(g, executable, (IrInstructionErrorReturnTrace *)instruction);5820 return ir_render_error_return_trace(g, executable, (IrInstructionErrorReturnTrace *)instruction);
5921 case IrInstructionIdCancel:
5922 return ir_render_cancel(g, executable, (IrInstructionCancel *)instruction);
5923 case IrInstructionIdAtomicRmw:5821 case IrInstructionIdAtomicRmw:
5924 return ir_render_atomic_rmw(g, executable, (IrInstructionAtomicRmw *)instruction);5822 return ir_render_atomic_rmw(g, executable, (IrInstructionAtomicRmw *)instruction);
5925 case IrInstructionIdAtomicLoad:5823 case IrInstructionIdAtomicLoad:
...@@ -5952,8 +5850,6 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,...@@ -5952,8 +5850,6 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
5952 return ir_render_frame_size(g, executable, (IrInstructionFrameSizeGen *)instruction);5850 return ir_render_frame_size(g, executable, (IrInstructionFrameSizeGen *)instruction);
5953 case IrInstructionIdAwaitGen:5851 case IrInstructionIdAwaitGen:
5954 return ir_render_await(g, executable, (IrInstructionAwaitGen *)instruction);5852 return ir_render_await(g, executable, (IrInstructionAwaitGen *)instruction);
5955 case IrInstructionIdTestCancelRequested:
5956 return ir_render_test_cancel_requested(g, executable, (IrInstructionTestCancelRequested *)instruction);
5957 case IrInstructionIdSpillBegin:5853 case IrInstructionIdSpillBegin:
5958 return ir_render_spill_begin(g, executable, (IrInstructionSpillBegin *)instruction);5854 return ir_render_spill_begin(g, executable, (IrInstructionSpillBegin *)instruction);
5959 case IrInstructionIdSpillEnd:5855 case IrInstructionIdSpillEnd:
...@@ -7060,9 +6956,9 @@ static void do_code_gen(CodeGen *g) {...@@ -7060,9 +6956,9 @@ static void do_code_gen(CodeGen *g) {
7060 ZigType *array_type = get_array_type(g, g->builtin_types.entry_usize, stack_trace_ptr_count);6956 ZigType *array_type = get_array_type(g, g->builtin_types.entry_usize, stack_trace_ptr_count);
7061 err_ret_array_val = build_alloca(g, array_type, "error_return_trace_addresses", get_abi_alignment(g, array_type));6957 err_ret_array_val = build_alloca(g, array_type, "error_return_trace_addresses", get_abi_alignment(g, array_type));
70626958
7063 // populate g->stack_trace_type6959 (void)get_llvm_type(g, get_stack_trace_type(g));
7064 (void)get_ptr_to_stack_trace_type(g);6960 g->cur_err_ret_trace_val_stack = build_alloca(g, get_stack_trace_type(g), "error_return_trace",
7065 g->cur_err_ret_trace_val_stack = build_alloca(g, g->stack_trace_type, "error_return_trace", get_abi_alignment(g, g->stack_trace_type));6961 get_abi_alignment(g, g->stack_trace_type));
7066 } else {6962 } else {
7067 g->cur_err_ret_trace_val_stack = nullptr;6963 g->cur_err_ret_trace_val_stack = nullptr;
7068 }6964 }
...@@ -7204,18 +7100,12 @@ static void do_code_gen(CodeGen *g) {...@@ -7204,18 +7100,12 @@ static void do_code_gen(CodeGen *g) {
7204 LLVMValueRef cur_ret_ptr_ptr = LLVMBuildStructGEP(g->builder, g->cur_frame_ptr, frame_ret_start, "");7100 LLVMValueRef cur_ret_ptr_ptr = LLVMBuildStructGEP(g->builder, g->cur_frame_ptr, frame_ret_start, "");
7205 g->cur_ret_ptr = LLVMBuildLoad(g->builder, cur_ret_ptr_ptr, "");7101 g->cur_ret_ptr = LLVMBuildLoad(g->builder, cur_ret_ptr_ptr, "");
7206 }7102 }
7207 if (codegen_fn_has_err_ret_tracing_arg(g, fn_type_id->return_type)) {
7208 uint32_t trace_field_index = frame_index_trace_arg(g, fn_type_id->return_type);
7209 g->cur_err_ret_trace_val_arg = LLVMBuildStructGEP(g->builder, g->cur_frame_ptr, trace_field_index, "");
7210 }
7211 uint32_t trace_field_index_stack = UINT32_MAX;7103 uint32_t trace_field_index_stack = UINT32_MAX;
7212 if (codegen_fn_has_err_ret_tracing_stack(g, fn_table_entry, true)) {7104 if (codegen_fn_has_err_ret_tracing_stack(g, fn_table_entry, true)) {
7213 trace_field_index_stack = frame_index_trace_stack(g, fn_type_id);7105 trace_field_index_stack = frame_index_trace_stack(g, fn_type_id);
7214 g->cur_err_ret_trace_val_stack = LLVMBuildStructGEP(g->builder, g->cur_frame_ptr,7106 g->cur_err_ret_trace_val_stack = LLVMBuildStructGEP(g->builder, g->cur_frame_ptr,
7215 trace_field_index_stack, "");7107 trace_field_index_stack, "");
7216 }7108 }
7217 g->cur_async_prev_val_field_ptr = LLVMBuildStructGEP(g->builder, g->cur_frame_ptr,
7218 frame_prev_val_index, "");
72197109
7220 LLVMValueRef resume_index = LLVMBuildLoad(g->builder, resume_index_ptr, "");7110 LLVMValueRef resume_index = LLVMBuildLoad(g->builder, resume_index_ptr, "");
7221 LLVMValueRef switch_instr = LLVMBuildSwitch(g->builder, resume_index, bad_resume_block, 4);7111 LLVMValueRef switch_instr = LLVMBuildSwitch(g->builder, resume_index, bad_resume_block, 4);
...@@ -7227,6 +7117,13 @@ static void do_code_gen(CodeGen *g) {...@@ -7227,6 +7117,13 @@ static void do_code_gen(CodeGen *g) {
7227 g->cur_resume_block_count += 1;7117 g->cur_resume_block_count += 1;
7228 LLVMPositionBuilderAtEnd(g->builder, entry_block->llvm_block);7118 LLVMPositionBuilderAtEnd(g->builder, entry_block->llvm_block);
7229 if (trace_field_index_stack != UINT32_MAX) {7119 if (trace_field_index_stack != UINT32_MAX) {
7120 if (codegen_fn_has_err_ret_tracing_arg(g, fn_type_id->return_type)) {
7121 LLVMValueRef trace_ptr_ptr = LLVMBuildStructGEP(g->builder, g->cur_frame_ptr,
7122 frame_index_trace_arg(g, fn_type_id->return_type), "");
7123 LLVMValueRef zero_ptr = LLVMConstNull(LLVMGetElementType(LLVMTypeOf(trace_ptr_ptr)));
7124 LLVMBuildStore(g->builder, zero_ptr, trace_ptr_ptr);
7125 }
7126
7230 LLVMValueRef trace_field_ptr = LLVMBuildStructGEP(g->builder, g->cur_frame_ptr,7127 LLVMValueRef trace_field_ptr = LLVMBuildStructGEP(g->builder, g->cur_frame_ptr,
7231 trace_field_index_stack, "");7128 trace_field_index_stack, "");
7232 LLVMValueRef trace_field_addrs = LLVMBuildStructGEP(g->builder, g->cur_frame_ptr,7129 LLVMValueRef trace_field_addrs = LLVMBuildStructGEP(g->builder, g->cur_frame_ptr,
...@@ -7273,8 +7170,6 @@ static void do_code_gen(CodeGen *g) {...@@ -7273,8 +7170,6 @@ static void do_code_gen(CodeGen *g) {
7273 LLVMDumpModule(g->module);7170 LLVMDumpModule(g->module);
7274 }7171 }
72757172
7276 // in release mode, we're sooooo confident that we've generated correct ir,
7277 // that we skip the verify module step in order to get better performance.
7278#ifndef NDEBUG7173#ifndef NDEBUG
7279 char *error = nullptr;7174 char *error = nullptr;
7280 LLVMVerifyModule(g->module, LLVMAbortProcessAction, &error);7175 LLVMVerifyModule(g->module, LLVMAbortProcessAction, &error);
...@@ -10157,6 +10052,11 @@ bool codegen_fn_has_err_ret_tracing_arg(CodeGen *g, ZigType *return_type) {...@@ -10157,6 +10052,11 @@ bool codegen_fn_has_err_ret_tracing_arg(CodeGen *g, ZigType *return_type) {
10157}10052}
1015810053
10159bool codegen_fn_has_err_ret_tracing_stack(CodeGen *g, ZigFn *fn, bool is_async) {10054bool codegen_fn_has_err_ret_tracing_stack(CodeGen *g, ZigFn *fn, bool is_async) {
10160 return g->have_err_ret_tracing && fn->calls_or_awaits_errorable_fn &&10055 if (is_async) {
10161 (is_async || !codegen_fn_has_err_ret_tracing_arg(g, fn->type_entry->data.fn.fn_type_id.return_type));10056 return g->have_err_ret_tracing && (fn->calls_or_awaits_errorable_fn ||
10057 codegen_fn_has_err_ret_tracing_arg(g, fn->type_entry->data.fn.fn_type_id.return_type));
10058 } else {
10059 return g->have_err_ret_tracing && fn->calls_or_awaits_errorable_fn &&
10060 !codegen_fn_has_err_ret_tracing_arg(g, fn->type_entry->data.fn.fn_type_id.return_type);
10061 }
10162}10062}
src/ir.cpp+29-201
...@@ -526,10 +526,6 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionReturn *) {...@@ -526,10 +526,6 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionReturn *) {
526 return IrInstructionIdReturn;526 return IrInstructionIdReturn;
527}527}
528528
529static constexpr IrInstructionId ir_instruction_id(IrInstructionReturnBegin *) {
530 return IrInstructionIdReturnBegin;
531}
532
533static constexpr IrInstructionId ir_instruction_id(IrInstructionCast *) {529static constexpr IrInstructionId ir_instruction_id(IrInstructionCast *) {
534 return IrInstructionIdCast;530 return IrInstructionIdCast;
535}531}
...@@ -974,10 +970,6 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionErrorUnion *) {...@@ -974,10 +970,6 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionErrorUnion *) {
974 return IrInstructionIdErrorUnion;970 return IrInstructionIdErrorUnion;
975}971}
976972
977static constexpr IrInstructionId ir_instruction_id(IrInstructionCancel *) {
978 return IrInstructionIdCancel;
979}
980
981static constexpr IrInstructionId ir_instruction_id(IrInstructionAtomicRmw *) {973static constexpr IrInstructionId ir_instruction_id(IrInstructionAtomicRmw *) {
982 return IrInstructionIdAtomicRmw;974 return IrInstructionIdAtomicRmw;
983}975}
...@@ -1062,10 +1054,6 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionResume *) {...@@ -1062,10 +1054,6 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionResume *) {
1062 return IrInstructionIdResume;1054 return IrInstructionIdResume;
1063}1055}
10641056
1065static constexpr IrInstructionId ir_instruction_id(IrInstructionTestCancelRequested *) {
1066 return IrInstructionIdTestCancelRequested;
1067}
1068
1069static constexpr IrInstructionId ir_instruction_id(IrInstructionSpillBegin *) {1057static constexpr IrInstructionId ir_instruction_id(IrInstructionSpillBegin *) {
1070 return IrInstructionIdSpillBegin;1058 return IrInstructionIdSpillBegin;
1071}1059}
...@@ -1138,18 +1126,6 @@ static IrInstruction *ir_build_return(IrBuilder *irb, Scope *scope, AstNode *sou...@@ -1138,18 +1126,6 @@ static IrInstruction *ir_build_return(IrBuilder *irb, Scope *scope, AstNode *sou
1138 return &return_instruction->base;1126 return &return_instruction->base;
1139}1127}
11401128
1141static IrInstruction *ir_build_return_begin(IrBuilder *irb, Scope *scope, AstNode *source_node,
1142 IrInstruction *operand)
1143{
1144 IrInstructionReturnBegin *return_instruction = ir_build_instruction<IrInstructionReturnBegin>(irb, scope, source_node);
1145 return_instruction->operand = operand;
1146
1147 ir_ref_instruction(operand, irb->current_basic_block);
1148
1149 return &return_instruction->base;
1150}
1151
1152
1153static IrInstruction *ir_build_const_void(IrBuilder *irb, Scope *scope, AstNode *source_node) {1129static IrInstruction *ir_build_const_void(IrBuilder *irb, Scope *scope, AstNode *source_node) {
1154 IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irb, scope, source_node);1130 IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irb, scope, source_node);
1155 const_instruction->base.value.type = irb->codegen->builtin_types.entry_void;1131 const_instruction->base.value.type = irb->codegen->builtin_types.entry_void;
...@@ -3284,16 +3260,6 @@ static IrInstruction *ir_build_suspend_finish(IrBuilder *irb, Scope *scope, AstN...@@ -3284,16 +3260,6 @@ static IrInstruction *ir_build_suspend_finish(IrBuilder *irb, Scope *scope, AstN
3284 return &instruction->base;3260 return &instruction->base;
3285}3261}
32863262
3287static IrInstruction *ir_build_cancel(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *frame) {
3288 IrInstructionCancel *instruction = ir_build_instruction<IrInstructionCancel>(irb, scope, source_node);
3289 instruction->base.value.type = irb->codegen->builtin_types.entry_void;
3290 instruction->frame = frame;
3291
3292 ir_ref_instruction(frame, irb->current_basic_block);
3293
3294 return &instruction->base;
3295}
3296
3297static IrInstruction *ir_build_await_src(IrBuilder *irb, Scope *scope, AstNode *source_node,3263static IrInstruction *ir_build_await_src(IrBuilder *irb, Scope *scope, AstNode *source_node,
3298 IrInstruction *frame, ResultLoc *result_loc)3264 IrInstruction *frame, ResultLoc *result_loc)
3299{3265{
...@@ -3331,13 +3297,6 @@ static IrInstruction *ir_build_resume(IrBuilder *irb, Scope *scope, AstNode *sou...@@ -3331,13 +3297,6 @@ static IrInstruction *ir_build_resume(IrBuilder *irb, Scope *scope, AstNode *sou
3331 return &instruction->base;3297 return &instruction->base;
3332}3298}
33333299
3334static IrInstruction *ir_build_test_cancel_requested(IrBuilder *irb, Scope *scope, AstNode *source_node) {
3335 IrInstructionTestCancelRequested *instruction = ir_build_instruction<IrInstructionTestCancelRequested>(irb, scope, source_node);
3336 instruction->base.value.type = irb->codegen->builtin_types.entry_bool;
3337
3338 return &instruction->base;
3339}
3340
3341static IrInstructionSpillBegin *ir_build_spill_begin(IrBuilder *irb, Scope *scope, AstNode *source_node,3300static IrInstructionSpillBegin *ir_build_spill_begin(IrBuilder *irb, Scope *scope, AstNode *source_node,
3342 IrInstruction *operand, SpillId spill_id)3301 IrInstruction *operand, SpillId spill_id)
3343{3302{
...@@ -3532,7 +3491,6 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node,...@@ -3532,7 +3491,6 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node,
3532 }3491 }
35333492
3534 ir_mark_gen(ir_build_add_implicit_return_type(irb, scope, node, return_value));3493 ir_mark_gen(ir_build_add_implicit_return_type(irb, scope, node, return_value));
3535 return_value = ir_build_return_begin(irb, scope, node, return_value);
35363494
3537 size_t defer_counts[2];3495 size_t defer_counts[2];
3538 ir_count_defers(irb, scope, outer_scope, defer_counts);3496 ir_count_defers(irb, scope, outer_scope, defer_counts);
...@@ -3545,49 +3503,40 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node,...@@ -3545,49 +3503,40 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node,
3545 return result;3503 return result;
3546 }3504 }
3547 bool should_inline = ir_should_inline(irb->exec, scope);3505 bool should_inline = ir_should_inline(irb->exec, scope);
3548 bool need_test_cancel = !should_inline && have_err_defers;
35493506
3550 IrBasicBlock *err_block = ir_create_basic_block(irb, scope, "ErrRetErr");3507 IrBasicBlock *err_block = ir_create_basic_block(irb, scope, "ErrRetErr");
3551 IrBasicBlock *normal_defers_block = ir_create_basic_block(irb, scope, "Defers");3508 IrBasicBlock *ok_block = ir_create_basic_block(irb, scope, "ErrRetOk");
3552 IrBasicBlock *ok_block = need_test_cancel ?3509
3553 ir_create_basic_block(irb, scope, "ErrRetOk") : normal_defers_block;3510 if (!have_err_defers) {
3554 IrBasicBlock *all_defers_block = have_err_defers ? ir_create_basic_block(irb, scope, "ErrDefers") : normal_defers_block;3511 ir_gen_defers_for_block(irb, scope, outer_scope, false);
3512 }
35553513
3556 IrInstruction *is_err = ir_build_test_err_src(irb, scope, node, return_value, false, true);3514 IrInstruction *is_err = ir_build_test_err_src(irb, scope, node, return_value, false, true);
35573515
3558 IrInstruction *force_comptime = ir_build_const_bool(irb, scope, node, should_inline);3516 IrInstruction *is_comptime;
3559 IrInstruction *err_is_comptime;
3560 if (should_inline) {3517 if (should_inline) {
3561 err_is_comptime = force_comptime;3518 is_comptime = ir_build_const_bool(irb, scope, node, should_inline);
3562 } else {3519 } else {
3563 err_is_comptime = ir_build_test_comptime(irb, scope, node, is_err);3520 is_comptime = ir_build_test_comptime(irb, scope, node, is_err);
3564 }3521 }
35653522
3566 ir_mark_gen(ir_build_cond_br(irb, scope, node, is_err, err_block, ok_block, err_is_comptime));3523 ir_mark_gen(ir_build_cond_br(irb, scope, node, is_err, err_block, ok_block, is_comptime));
3567 IrBasicBlock *ret_stmt_block = ir_create_basic_block(irb, scope, "RetStmt");3524 IrBasicBlock *ret_stmt_block = ir_create_basic_block(irb, scope, "RetStmt");
35683525
3569 ir_set_cursor_at_end_and_append_block(irb, err_block);3526 ir_set_cursor_at_end_and_append_block(irb, err_block);
3527 if (have_err_defers) {
3528 ir_gen_defers_for_block(irb, scope, outer_scope, true);
3529 }
3570 if (irb->codegen->have_err_ret_tracing && !should_inline) {3530 if (irb->codegen->have_err_ret_tracing && !should_inline) {
3571 ir_build_save_err_ret_addr(irb, scope, node);3531 ir_build_save_err_ret_addr(irb, scope, node);
3572 }3532 }
3573 ir_build_br(irb, scope, node, all_defers_block, err_is_comptime);3533 ir_build_br(irb, scope, node, ret_stmt_block, is_comptime);
3574
3575 if (need_test_cancel) {
3576 ir_set_cursor_at_end_and_append_block(irb, ok_block);
3577 IrInstruction *is_canceled = ir_build_test_cancel_requested(irb, scope, node);
3578 ir_mark_gen(ir_build_cond_br(irb, scope, node, is_canceled,
3579 all_defers_block, normal_defers_block, force_comptime));
3580 }
35813534
3582 if (all_defers_block != normal_defers_block) {3535 ir_set_cursor_at_end_and_append_block(irb, ok_block);
3583 ir_set_cursor_at_end_and_append_block(irb, all_defers_block);3536 if (have_err_defers) {
3584 ir_gen_defers_for_block(irb, scope, outer_scope, true);3537 ir_gen_defers_for_block(irb, scope, outer_scope, false);
3585 ir_build_br(irb, scope, node, ret_stmt_block, force_comptime);
3586 }3538 }
35873539 ir_build_br(irb, scope, node, ret_stmt_block, is_comptime);
3588 ir_set_cursor_at_end_and_append_block(irb, normal_defers_block);
3589 ir_gen_defers_for_block(irb, scope, outer_scope, false);
3590 ir_build_br(irb, scope, node, ret_stmt_block, force_comptime);
35913540
3592 ir_set_cursor_at_end_and_append_block(irb, ret_stmt_block);3541 ir_set_cursor_at_end_and_append_block(irb, ret_stmt_block);
3593 IrInstruction *result = ir_build_return(irb, scope, node, return_value);3542 IrInstruction *result = ir_build_return(irb, scope, node, return_value);
...@@ -3619,8 +3568,6 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node,...@@ -3619,8 +3568,6 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node,
3619 ir_mark_gen(ir_build_add_implicit_return_type(irb, scope, node, err_val));3568 ir_mark_gen(ir_build_add_implicit_return_type(irb, scope, node, err_val));
3620 IrInstructionSpillBegin *spill_begin = ir_build_spill_begin(irb, scope, node, err_val,3569 IrInstructionSpillBegin *spill_begin = ir_build_spill_begin(irb, scope, node, err_val,
3621 SpillIdRetErrCode);3570 SpillIdRetErrCode);
3622 ir_build_return_begin(irb, scope, node, err_val);
3623 err_val = ir_build_spill_end(irb, scope, node, spill_begin);
3624 ResultLocReturn *result_loc_ret = allocate<ResultLocReturn>(1);3571 ResultLocReturn *result_loc_ret = allocate<ResultLocReturn>(1);
3625 result_loc_ret->base.id = ResultLocIdReturn;3572 result_loc_ret->base.id = ResultLocIdReturn;
3626 ir_build_reset_result(irb, scope, node, &result_loc_ret->base);3573 ir_build_reset_result(irb, scope, node, &result_loc_ret->base);
...@@ -3629,6 +3576,7 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node,...@@ -3629,6 +3576,7 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node,
3629 if (irb->codegen->have_err_ret_tracing && !should_inline) {3576 if (irb->codegen->have_err_ret_tracing && !should_inline) {
3630 ir_build_save_err_ret_addr(irb, scope, node);3577 ir_build_save_err_ret_addr(irb, scope, node);
3631 }3578 }
3579 err_val = ir_build_spill_end(irb, scope, node, spill_begin);
3632 IrInstruction *ret_inst = ir_build_return(irb, scope, node, err_val);3580 IrInstruction *ret_inst = ir_build_return(irb, scope, node, err_val);
3633 result_loc_ret->base.source_instruction = ret_inst;3581 result_loc_ret->base.source_instruction = ret_inst;
3634 }3582 }
...@@ -3847,38 +3795,10 @@ static IrInstruction *ir_gen_block(IrBuilder *irb, Scope *parent_scope, AstNode...@@ -3847,38 +3795,10 @@ static IrInstruction *ir_gen_block(IrBuilder *irb, Scope *parent_scope, AstNode
3847 return result;3795 return result;
38483796
3849 // no need for save_err_ret_addr because this cannot return error3797 // no need for save_err_ret_addr because this cannot return error
3850 // but if it is a canceled async function we do need to run the errdefers3798 // only generate unconditional defers
38513799
3852 ir_mark_gen(ir_build_add_implicit_return_type(irb, child_scope, block_node, result));3800 ir_mark_gen(ir_build_add_implicit_return_type(irb, child_scope, block_node, result));
3853 result = ir_mark_gen(ir_build_return_begin(irb, child_scope, block_node, result));
3854
3855 size_t defer_counts[2];
3856 ir_count_defers(irb, child_scope, outer_block_scope, defer_counts);
3857 bool have_err_defers = defer_counts[ReturnKindError] > 0;
3858 if (!have_err_defers) {
3859 // only generate unconditional defers
3860 ir_gen_defers_for_block(irb, child_scope, outer_block_scope, false);
3861 return ir_mark_gen(ir_build_return(irb, child_scope, result->source_node, result));
3862 }
3863 IrInstruction *is_canceled = ir_build_test_cancel_requested(irb, child_scope, block_node);
3864 IrBasicBlock *all_defers_block = ir_create_basic_block(irb, child_scope, "ErrDefers");
3865 IrBasicBlock *normal_defers_block = ir_create_basic_block(irb, child_scope, "Defers");
3866 IrBasicBlock *ret_stmt_block = ir_create_basic_block(irb, child_scope, "RetStmt");
3867 bool should_inline = ir_should_inline(irb->exec, child_scope);
3868 IrInstruction *errdefers_is_comptime = ir_build_const_bool(irb, child_scope, block_node,
3869 should_inline || !have_err_defers);
3870 ir_mark_gen(ir_build_cond_br(irb, child_scope, block_node, is_canceled,
3871 all_defers_block, normal_defers_block, errdefers_is_comptime));
3872
3873 ir_set_cursor_at_end_and_append_block(irb, all_defers_block);
3874 ir_gen_defers_for_block(irb, child_scope, outer_block_scope, true);
3875 ir_build_br(irb, child_scope, block_node, ret_stmt_block, errdefers_is_comptime);
3876
3877 ir_set_cursor_at_end_and_append_block(irb, normal_defers_block);
3878 ir_gen_defers_for_block(irb, child_scope, outer_block_scope, false);3801 ir_gen_defers_for_block(irb, child_scope, outer_block_scope, false);
3879 ir_build_br(irb, child_scope, block_node, ret_stmt_block, errdefers_is_comptime);
3880
3881 ir_set_cursor_at_end_and_append_block(irb, ret_stmt_block);
3882 return ir_mark_gen(ir_build_return(irb, child_scope, result->source_node, result));3802 return ir_mark_gen(ir_build_return(irb, child_scope, result->source_node, result));
3883}3803}
38843804
...@@ -7930,31 +7850,6 @@ static IrInstruction *ir_gen_fn_proto(IrBuilder *irb, Scope *parent_scope, AstNo...@@ -7930,31 +7850,6 @@ static IrInstruction *ir_gen_fn_proto(IrBuilder *irb, Scope *parent_scope, AstNo
7930 return ir_build_fn_proto(irb, parent_scope, node, param_types, align_value, return_type, is_var_args);7850 return ir_build_fn_proto(irb, parent_scope, node, param_types, align_value, return_type, is_var_args);
7931}7851}
79327852
7933static IrInstruction *ir_gen_cancel(IrBuilder *irb, Scope *scope, AstNode *node) {
7934 assert(node->type == NodeTypeCancel);
7935
7936 ZigFn *fn_entry = exec_fn_entry(irb->exec);
7937 if (!fn_entry) {
7938 add_node_error(irb->codegen, node, buf_sprintf("cancel outside function definition"));
7939 return irb->codegen->invalid_instruction;
7940 }
7941 ScopeSuspend *existing_suspend_scope = get_scope_suspend(scope);
7942 if (existing_suspend_scope) {
7943 if (!existing_suspend_scope->reported_err) {
7944 ErrorMsg *msg = add_node_error(irb->codegen, node, buf_sprintf("cannot cancel inside suspend block"));
7945 add_error_note(irb->codegen, msg, existing_suspend_scope->base.source_node, buf_sprintf("suspend block here"));
7946 existing_suspend_scope->reported_err = true;
7947 }
7948 return irb->codegen->invalid_instruction;
7949 }
7950
7951 IrInstruction *operand = ir_gen_node_extra(irb, node->data.cancel_expr.expr, scope, LValPtr, nullptr);
7952 if (operand == irb->codegen->invalid_instruction)
7953 return irb->codegen->invalid_instruction;
7954
7955 return ir_build_cancel(irb, scope, node, operand);
7956}
7957
7958static IrInstruction *ir_gen_resume(IrBuilder *irb, Scope *scope, AstNode *node) {7853static IrInstruction *ir_gen_resume(IrBuilder *irb, Scope *scope, AstNode *node) {
7959 assert(node->type == NodeTypeResume);7854 assert(node->type == NodeTypeResume);
79607855
...@@ -8149,8 +8044,6 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop...@@ -8149,8 +8044,6 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop
8149 return ir_lval_wrap(irb, scope, ir_gen_fn_proto(irb, scope, node), lval, result_loc);8044 return ir_lval_wrap(irb, scope, ir_gen_fn_proto(irb, scope, node), lval, result_loc);
8150 case NodeTypeErrorSetDecl:8045 case NodeTypeErrorSetDecl:
8151 return ir_lval_wrap(irb, scope, ir_gen_err_set_decl(irb, scope, node), lval, result_loc);8046 return ir_lval_wrap(irb, scope, ir_gen_err_set_decl(irb, scope, node), lval, result_loc);
8152 case NodeTypeCancel:
8153 return ir_lval_wrap(irb, scope, ir_gen_cancel(irb, scope, node), lval, result_loc);
8154 case NodeTypeResume:8047 case NodeTypeResume:
8155 return ir_lval_wrap(irb, scope, ir_gen_resume(irb, scope, node), lval, result_loc);8048 return ir_lval_wrap(irb, scope, ir_gen_resume(irb, scope, node), lval, result_loc);
8156 case NodeTypeAwaitExpr:8049 case NodeTypeAwaitExpr:
...@@ -8228,7 +8121,6 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec...@@ -8228,7 +8121,6 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec
82288121
8229 if (!instr_is_unreachable(result)) {8122 if (!instr_is_unreachable(result)) {
8230 ir_mark_gen(ir_build_add_implicit_return_type(irb, scope, result->source_node, result));8123 ir_mark_gen(ir_build_add_implicit_return_type(irb, scope, result->source_node, result));
8231 result = ir_mark_gen(ir_build_return_begin(irb, scope, node, result));
8232 // no need for save_err_ret_addr because this cannot return error8124 // no need for save_err_ret_addr because this cannot return error
8233 ir_mark_gen(ir_build_return(irb, scope, result->source_node, result));8125 ir_mark_gen(ir_build_return(irb, scope, result->source_node, result));
8234 }8126 }
...@@ -8340,7 +8232,6 @@ static ConstExprValue *ir_exec_const_result(CodeGen *codegen, IrExecutable *exec...@@ -8340,7 +8232,6 @@ static ConstExprValue *ir_exec_const_result(CodeGen *codegen, IrExecutable *exec
8340 switch (instruction->id) {8232 switch (instruction->id) {
8341 case IrInstructionIdUnwrapErrPayload:8233 case IrInstructionIdUnwrapErrPayload:
8342 case IrInstructionIdUnionFieldPtr:8234 case IrInstructionIdUnionFieldPtr:
8343 case IrInstructionIdReturnBegin:
8344 continue;8235 continue;
8345 default:8236 default:
8346 break;8237 break;
...@@ -12745,17 +12636,17 @@ static IrInstruction *ir_analyze_instruction_add_implicit_return_type(IrAnalyze...@@ -12745,17 +12636,17 @@ static IrInstruction *ir_analyze_instruction_add_implicit_return_type(IrAnalyze
12745 return ir_const_void(ira, &instruction->base);12636 return ir_const_void(ira, &instruction->base);
12746}12637}
1274712638
12748static IrInstruction *ir_analyze_instruction_return_begin(IrAnalyze *ira, IrInstructionReturnBegin *instruction) {12639static IrInstruction *ir_analyze_instruction_return(IrAnalyze *ira, IrInstructionReturn *instruction) {
12749 IrInstruction *operand = instruction->operand->child;12640 IrInstruction *operand = instruction->operand->child;
12750 if (type_is_invalid(operand->value.type))12641 if (type_is_invalid(operand->value.type))
12751 return ira->codegen->invalid_instruction;12642 return ir_unreach_error(ira);
1275212643
12753 if (!instr_is_comptime(operand) && handle_is_ptr(ira->explicit_return_type)) {12644 if (!instr_is_comptime(operand) && handle_is_ptr(ira->explicit_return_type)) {
12754 // result location mechanism took care of it.12645 // result location mechanism took care of it.
12755 IrInstruction *result = ir_build_return_begin(&ira->new_irb, instruction->base.scope,12646 IrInstruction *result = ir_build_return(&ira->new_irb, instruction->base.scope,
12756 instruction->base.source_node, operand);12647 instruction->base.source_node, nullptr);
12757 copy_const_val(&result->value, &operand->value, true);12648 result->value.type = ira->codegen->builtin_types.entry_unreachable;
12758 return result;12649 return ir_finish_anal(ira, result);
12759 }12650 }
1276012651
12761 IrInstruction *casted_operand = ir_implicit_cast(ira, operand, ira->explicit_return_type);12652 IrInstruction *casted_operand = ir_implicit_cast(ira, operand, ira->explicit_return_type);
...@@ -12777,38 +12668,6 @@ static IrInstruction *ir_analyze_instruction_return_begin(IrAnalyze *ira, IrInst...@@ -12777,38 +12668,6 @@ static IrInstruction *ir_analyze_instruction_return_begin(IrAnalyze *ira, IrInst
12777 return ir_unreach_error(ira);12668 return ir_unreach_error(ira);
12778 }12669 }
1277912670
12780 IrInstruction *result = ir_build_return_begin(&ira->new_irb, instruction->base.scope,
12781 instruction->base.source_node, casted_operand);
12782 copy_const_val(&result->value, &casted_operand->value, true);
12783 return result;
12784}
12785
12786static IrInstruction *ir_analyze_instruction_return(IrAnalyze *ira, IrInstructionReturn *instruction) {
12787 IrInstruction *operand = instruction->operand->child;
12788 if (type_is_invalid(operand->value.type))
12789 return ir_unreach_error(ira);
12790
12791 if (!instr_is_comptime(operand) && handle_is_ptr(ira->explicit_return_type)) {
12792 // result location mechanism took care of it.
12793 IrInstruction *result = ir_build_return(&ira->new_irb, instruction->base.scope,
12794 instruction->base.source_node, nullptr);
12795 result->value.type = ira->codegen->builtin_types.entry_unreachable;
12796 return ir_finish_anal(ira, result);
12797 }
12798
12799 // This cast might have been already done from IrInstructionReturnBegin but it also
12800 // might not have, in the case of `try`.
12801 IrInstruction *casted_operand = ir_implicit_cast(ira, operand, ira->explicit_return_type);
12802 if (type_is_invalid(casted_operand->value.type)) {
12803 AstNode *source_node = ira->explicit_return_type_source_node;
12804 if (source_node != nullptr) {
12805 ErrorMsg *msg = ira->codegen->errors.last();
12806 add_error_note(ira->codegen, msg, source_node,
12807 buf_sprintf("return type declared here"));
12808 }
12809 return ir_unreach_error(ira);
12810 }
12811
12812 IrInstruction *result = ir_build_return(&ira->new_irb, instruction->base.scope,12671 IrInstruction *result = ir_build_return(&ira->new_irb, instruction->base.scope,
12813 instruction->base.source_node, casted_operand);12672 instruction->base.source_node, casted_operand);
12814 result->value.type = ira->codegen->builtin_types.entry_unreachable;12673 result->value.type = ira->codegen->builtin_types.entry_unreachable;
...@@ -14540,8 +14399,8 @@ static bool exec_has_err_ret_trace(CodeGen *g, IrExecutable *exec) {...@@ -14540,8 +14399,8 @@ static bool exec_has_err_ret_trace(CodeGen *g, IrExecutable *exec) {
14540static IrInstruction *ir_analyze_instruction_error_return_trace(IrAnalyze *ira,14399static IrInstruction *ir_analyze_instruction_error_return_trace(IrAnalyze *ira,
14541 IrInstructionErrorReturnTrace *instruction)14400 IrInstructionErrorReturnTrace *instruction)
14542{14401{
14402 ZigType *ptr_to_stack_trace_type = get_pointer_to_type(ira->codegen, get_stack_trace_type(ira->codegen), false);
14543 if (instruction->optional == IrInstructionErrorReturnTrace::Null) {14403 if (instruction->optional == IrInstructionErrorReturnTrace::Null) {
14544 ZigType *ptr_to_stack_trace_type = get_ptr_to_stack_trace_type(ira->codegen);
14545 ZigType *optional_type = get_optional_type(ira->codegen, ptr_to_stack_trace_type);14404 ZigType *optional_type = get_optional_type(ira->codegen, ptr_to_stack_trace_type);
14546 if (!exec_has_err_ret_trace(ira->codegen, ira->new_irb.exec)) {14405 if (!exec_has_err_ret_trace(ira->codegen, ira->new_irb.exec)) {
14547 IrInstruction *result = ir_const(ira, &instruction->base, optional_type);14406 IrInstruction *result = ir_const(ira, &instruction->base, optional_type);
...@@ -14559,7 +14418,7 @@ static IrInstruction *ir_analyze_instruction_error_return_trace(IrAnalyze *ira,...@@ -14559,7 +14418,7 @@ static IrInstruction *ir_analyze_instruction_error_return_trace(IrAnalyze *ira,
14559 assert(ira->codegen->have_err_ret_tracing);14418 assert(ira->codegen->have_err_ret_tracing);
14560 IrInstruction *new_instruction = ir_build_error_return_trace(&ira->new_irb, instruction->base.scope,14419 IrInstruction *new_instruction = ir_build_error_return_trace(&ira->new_irb, instruction->base.scope,
14561 instruction->base.source_node, instruction->optional);14420 instruction->base.source_node, instruction->optional);
14562 new_instruction->value.type = get_ptr_to_stack_trace_type(ira->codegen);14421 new_instruction->value.type = ptr_to_stack_trace_type;
14563 return new_instruction;14422 return new_instruction;
14564 }14423 }
14565}14424}
...@@ -15800,6 +15659,7 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c...@@ -15800,6 +15659,7 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c
1580015659
15801 if (impl_fn_type_id->cc == CallingConventionAsync && parent_fn_entry->inferred_async_node == nullptr) {15660 if (impl_fn_type_id->cc == CallingConventionAsync && parent_fn_entry->inferred_async_node == nullptr) {
15802 parent_fn_entry->inferred_async_node = fn_ref->source_node;15661 parent_fn_entry->inferred_async_node = fn_ref->source_node;
15662 parent_fn_entry->inferred_async_fn = impl_fn;
15803 }15663 }
1580415664
15805 IrInstructionCallGen *new_call_instruction = ir_build_call_gen(ira, &call_instruction->base,15665 IrInstructionCallGen *new_call_instruction = ir_build_call_gen(ira, &call_instruction->base,
...@@ -15923,6 +15783,7 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c...@@ -15923,6 +15783,7 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c
1592315783
15924 if (fn_type_id->cc == CallingConventionAsync && parent_fn_entry->inferred_async_node == nullptr) {15784 if (fn_type_id->cc == CallingConventionAsync && parent_fn_entry->inferred_async_node == nullptr) {
15925 parent_fn_entry->inferred_async_node = fn_ref->source_node;15785 parent_fn_entry->inferred_async_node = fn_ref->source_node;
15786 parent_fn_entry->inferred_async_fn = fn_entry;
15926 }15787 }
1592715788
15928 IrInstruction *result_loc;15789 IrInstruction *result_loc;
...@@ -24702,21 +24563,6 @@ static IrInstruction *analyze_frame_ptr_to_anyframe_T(IrAnalyze *ira, IrInstruct...@@ -24702,21 +24563,6 @@ static IrInstruction *analyze_frame_ptr_to_anyframe_T(IrAnalyze *ira, IrInstruct
24702 return casted_frame;24563 return casted_frame;
24703}24564}
2470424565
24705static IrInstruction *ir_analyze_instruction_cancel(IrAnalyze *ira, IrInstructionCancel *instruction) {
24706 IrInstruction *frame = analyze_frame_ptr_to_anyframe_T(ira, &instruction->base, instruction->frame->child);
24707 if (type_is_invalid(frame->value.type))
24708 return ira->codegen->invalid_instruction;
24709
24710 ZigFn *fn_entry = exec_fn_entry(ira->new_irb.exec);
24711 ir_assert(fn_entry != nullptr, &instruction->base);
24712
24713 if (fn_entry->inferred_async_node == nullptr) {
24714 fn_entry->inferred_async_node = instruction->base.source_node;
24715 }
24716
24717 return ir_build_cancel(&ira->new_irb, instruction->base.scope, instruction->base.source_node, frame);
24718}
24719
24720static IrInstruction *ir_analyze_instruction_await(IrAnalyze *ira, IrInstructionAwaitSrc *instruction) {24566static IrInstruction *ir_analyze_instruction_await(IrAnalyze *ira, IrInstructionAwaitSrc *instruction) {
24721 IrInstruction *frame = analyze_frame_ptr_to_anyframe_T(ira, &instruction->base, instruction->frame->child);24567 IrInstruction *frame = analyze_frame_ptr_to_anyframe_T(ira, &instruction->base, instruction->frame->child);
24722 if (type_is_invalid(frame->value.type))24568 if (type_is_invalid(frame->value.type))
...@@ -24772,15 +24618,6 @@ static IrInstruction *ir_analyze_instruction_resume(IrAnalyze *ira, IrInstructio...@@ -24772,15 +24618,6 @@ static IrInstruction *ir_analyze_instruction_resume(IrAnalyze *ira, IrInstructio
24772 return ir_build_resume(&ira->new_irb, instruction->base.scope, instruction->base.source_node, casted_frame);24618 return ir_build_resume(&ira->new_irb, instruction->base.scope, instruction->base.source_node, casted_frame);
24773}24619}
2477424620
24775static IrInstruction *ir_analyze_instruction_test_cancel_requested(IrAnalyze *ira,
24776 IrInstructionTestCancelRequested *instruction)
24777{
24778 if (ir_should_inline(ira->new_irb.exec, instruction->base.scope)) {
24779 return ir_const_bool(ira, &instruction->base, false);
24780 }
24781 return ir_build_test_cancel_requested(&ira->new_irb, instruction->base.scope, instruction->base.source_node);
24782}
24783
24784static IrInstruction *ir_analyze_instruction_spill_begin(IrAnalyze *ira, IrInstructionSpillBegin *instruction) {24621static IrInstruction *ir_analyze_instruction_spill_begin(IrAnalyze *ira, IrInstructionSpillBegin *instruction) {
24785 if (ir_should_inline(ira->new_irb.exec, instruction->base.scope))24622 if (ir_should_inline(ira->new_irb.exec, instruction->base.scope))
24786 return ir_const_void(ira, &instruction->base);24623 return ir_const_void(ira, &instruction->base);
...@@ -24848,8 +24685,6 @@ static IrInstruction *ir_analyze_instruction_base(IrAnalyze *ira, IrInstruction...@@ -24848,8 +24685,6 @@ static IrInstruction *ir_analyze_instruction_base(IrAnalyze *ira, IrInstruction
24848 case IrInstructionIdAwaitGen:24685 case IrInstructionIdAwaitGen:
24849 zig_unreachable();24686 zig_unreachable();
2485024687
24851 case IrInstructionIdReturnBegin:
24852 return ir_analyze_instruction_return_begin(ira, (IrInstructionReturnBegin *)instruction);
24853 case IrInstructionIdReturn:24688 case IrInstructionIdReturn:
24854 return ir_analyze_instruction_return(ira, (IrInstructionReturn *)instruction);24689 return ir_analyze_instruction_return(ira, (IrInstructionReturn *)instruction);
24855 case IrInstructionIdConst:24690 case IrInstructionIdConst:
...@@ -25070,8 +24905,6 @@ static IrInstruction *ir_analyze_instruction_base(IrAnalyze *ira, IrInstruction...@@ -25070,8 +24905,6 @@ static IrInstruction *ir_analyze_instruction_base(IrAnalyze *ira, IrInstruction
25070 return ir_analyze_instruction_error_return_trace(ira, (IrInstructionErrorReturnTrace *)instruction);24905 return ir_analyze_instruction_error_return_trace(ira, (IrInstructionErrorReturnTrace *)instruction);
25071 case IrInstructionIdErrorUnion:24906 case IrInstructionIdErrorUnion:
25072 return ir_analyze_instruction_error_union(ira, (IrInstructionErrorUnion *)instruction);24907 return ir_analyze_instruction_error_union(ira, (IrInstructionErrorUnion *)instruction);
25073 case IrInstructionIdCancel:
25074 return ir_analyze_instruction_cancel(ira, (IrInstructionCancel *)instruction);
25075 case IrInstructionIdAtomicRmw:24908 case IrInstructionIdAtomicRmw:
25076 return ir_analyze_instruction_atomic_rmw(ira, (IrInstructionAtomicRmw *)instruction);24909 return ir_analyze_instruction_atomic_rmw(ira, (IrInstructionAtomicRmw *)instruction);
25077 case IrInstructionIdAtomicLoad:24910 case IrInstructionIdAtomicLoad:
...@@ -25114,8 +24947,6 @@ static IrInstruction *ir_analyze_instruction_base(IrAnalyze *ira, IrInstruction...@@ -25114,8 +24947,6 @@ static IrInstruction *ir_analyze_instruction_base(IrAnalyze *ira, IrInstruction
25114 return ir_analyze_instruction_resume(ira, (IrInstructionResume *)instruction);24947 return ir_analyze_instruction_resume(ira, (IrInstructionResume *)instruction);
25115 case IrInstructionIdAwaitSrc:24948 case IrInstructionIdAwaitSrc:
25116 return ir_analyze_instruction_await(ira, (IrInstructionAwaitSrc *)instruction);24949 return ir_analyze_instruction_await(ira, (IrInstructionAwaitSrc *)instruction);
25117 case IrInstructionIdTestCancelRequested:
25118 return ir_analyze_instruction_test_cancel_requested(ira, (IrInstructionTestCancelRequested *)instruction);
25119 case IrInstructionIdSpillBegin:24950 case IrInstructionIdSpillBegin:
25120 return ir_analyze_instruction_spill_begin(ira, (IrInstructionSpillBegin *)instruction);24951 return ir_analyze_instruction_spill_begin(ira, (IrInstructionSpillBegin *)instruction);
25121 case IrInstructionIdSpillEnd:24952 case IrInstructionIdSpillEnd:
...@@ -25209,7 +25040,6 @@ bool ir_has_side_effects(IrInstruction *instruction) {...@@ -25209,7 +25040,6 @@ bool ir_has_side_effects(IrInstruction *instruction) {
25209 case IrInstructionIdStorePtr:25040 case IrInstructionIdStorePtr:
25210 case IrInstructionIdCallSrc:25041 case IrInstructionIdCallSrc:
25211 case IrInstructionIdCallGen:25042 case IrInstructionIdCallGen:
25212 case IrInstructionIdReturnBegin:
25213 case IrInstructionIdReturn:25043 case IrInstructionIdReturn:
25214 case IrInstructionIdUnreachable:25044 case IrInstructionIdUnreachable:
25215 case IrInstructionIdSetCold:25045 case IrInstructionIdSetCold:
...@@ -25235,7 +25065,6 @@ bool ir_has_side_effects(IrInstruction *instruction) {...@@ -25235,7 +25065,6 @@ bool ir_has_side_effects(IrInstruction *instruction) {
25235 case IrInstructionIdPtrType:25065 case IrInstructionIdPtrType:
25236 case IrInstructionIdSetAlignStack:25066 case IrInstructionIdSetAlignStack:
25237 case IrInstructionIdExport:25067 case IrInstructionIdExport:
25238 case IrInstructionIdCancel:
25239 case IrInstructionIdSaveErrRetAddr:25068 case IrInstructionIdSaveErrRetAddr:
25240 case IrInstructionIdAddImplicitReturnType:25069 case IrInstructionIdAddImplicitReturnType:
25241 case IrInstructionIdAtomicRmw:25070 case IrInstructionIdAtomicRmw:
...@@ -25355,7 +25184,6 @@ bool ir_has_side_effects(IrInstruction *instruction) {...@@ -25355,7 +25184,6 @@ bool ir_has_side_effects(IrInstruction *instruction) {
25355 case IrInstructionIdHasDecl:25184 case IrInstructionIdHasDecl:
25356 case IrInstructionIdAllocaSrc:25185 case IrInstructionIdAllocaSrc:
25357 case IrInstructionIdAllocaGen:25186 case IrInstructionIdAllocaGen:
25358 case IrInstructionIdTestCancelRequested:
25359 case IrInstructionIdSpillEnd:25187 case IrInstructionIdSpillEnd:
25360 return false;25188 return false;
2536125189
src/ir_print.cpp-24
...@@ -64,12 +64,6 @@ static void ir_print_other_block(IrPrint *irp, IrBasicBlock *bb) {...@@ -64,12 +64,6 @@ static void ir_print_other_block(IrPrint *irp, IrBasicBlock *bb) {
64 }64 }
65}65}
6666
67static void ir_print_return_begin(IrPrint *irp, IrInstructionReturnBegin *instruction) {
68 fprintf(irp->f, "@returnBegin(");
69 ir_print_other_instruction(irp, instruction->operand);
70 fprintf(irp->f, ")");
71}
72
73static void ir_print_return(IrPrint *irp, IrInstructionReturn *instruction) {67static void ir_print_return(IrPrint *irp, IrInstructionReturn *instruction) {
74 fprintf(irp->f, "return ");68 fprintf(irp->f, "return ");
75 ir_print_other_instruction(irp, instruction->operand);69 ir_print_other_instruction(irp, instruction->operand);
...@@ -1394,11 +1388,6 @@ static void ir_print_error_union(IrPrint *irp, IrInstructionErrorUnion *instruct...@@ -1394,11 +1388,6 @@ static void ir_print_error_union(IrPrint *irp, IrInstructionErrorUnion *instruct
1394 ir_print_other_instruction(irp, instruction->payload);1388 ir_print_other_instruction(irp, instruction->payload);
1395}1389}
13961390
1397static void ir_print_cancel(IrPrint *irp, IrInstructionCancel *instruction) {
1398 fprintf(irp->f, "cancel ");
1399 ir_print_other_instruction(irp, instruction->frame);
1400}
1401
1402static void ir_print_atomic_rmw(IrPrint *irp, IrInstructionAtomicRmw *instruction) {1391static void ir_print_atomic_rmw(IrPrint *irp, IrInstructionAtomicRmw *instruction) {
1403 fprintf(irp->f, "@atomicRmw(");1392 fprintf(irp->f, "@atomicRmw(");
1404 if (instruction->operand_type != nullptr) {1393 if (instruction->operand_type != nullptr) {
...@@ -1549,10 +1538,6 @@ static void ir_print_await_gen(IrPrint *irp, IrInstructionAwaitGen *instruction)...@@ -1549,10 +1538,6 @@ static void ir_print_await_gen(IrPrint *irp, IrInstructionAwaitGen *instruction)
1549 fprintf(irp->f, ")");1538 fprintf(irp->f, ")");
1550}1539}
15511540
1552static void ir_print_test_cancel_requested(IrPrint *irp, IrInstructionTestCancelRequested *instruction) {
1553 fprintf(irp->f, "@testCancelRequested()");
1554}
1555
1556static void ir_print_spill_begin(IrPrint *irp, IrInstructionSpillBegin *instruction) {1541static void ir_print_spill_begin(IrPrint *irp, IrInstructionSpillBegin *instruction) {
1557 fprintf(irp->f, "@spillBegin(");1542 fprintf(irp->f, "@spillBegin(");
1558 ir_print_other_instruction(irp, instruction->operand);1543 ir_print_other_instruction(irp, instruction->operand);
...@@ -1570,9 +1555,6 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {...@@ -1570,9 +1555,6 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
1570 switch (instruction->id) {1555 switch (instruction->id) {
1571 case IrInstructionIdInvalid:1556 case IrInstructionIdInvalid:
1572 zig_unreachable();1557 zig_unreachable();
1573 case IrInstructionIdReturnBegin:
1574 ir_print_return_begin(irp, (IrInstructionReturnBegin *)instruction);
1575 break;
1576 case IrInstructionIdReturn:1558 case IrInstructionIdReturn:
1577 ir_print_return(irp, (IrInstructionReturn *)instruction);1559 ir_print_return(irp, (IrInstructionReturn *)instruction);
1578 break;1560 break;
...@@ -1966,9 +1948,6 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {...@@ -1966,9 +1948,6 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
1966 case IrInstructionIdErrorUnion:1948 case IrInstructionIdErrorUnion:
1967 ir_print_error_union(irp, (IrInstructionErrorUnion *)instruction);1949 ir_print_error_union(irp, (IrInstructionErrorUnion *)instruction);
1968 break;1950 break;
1969 case IrInstructionIdCancel:
1970 ir_print_cancel(irp, (IrInstructionCancel *)instruction);
1971 break;
1972 case IrInstructionIdAtomicRmw:1951 case IrInstructionIdAtomicRmw:
1973 ir_print_atomic_rmw(irp, (IrInstructionAtomicRmw *)instruction);1952 ir_print_atomic_rmw(irp, (IrInstructionAtomicRmw *)instruction);
1974 break;1953 break;
...@@ -2047,9 +2026,6 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {...@@ -2047,9 +2026,6 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
2047 case IrInstructionIdAwaitGen:2026 case IrInstructionIdAwaitGen:
2048 ir_print_await_gen(irp, (IrInstructionAwaitGen *)instruction);2027 ir_print_await_gen(irp, (IrInstructionAwaitGen *)instruction);
2049 break;2028 break;
2050 case IrInstructionIdTestCancelRequested:
2051 ir_print_test_cancel_requested(irp, (IrInstructionTestCancelRequested *)instruction);
2052 break;
2053 case IrInstructionIdSpillBegin:2029 case IrInstructionIdSpillBegin:
2054 ir_print_spill_begin(irp, (IrInstructionSpillBegin *)instruction);2030 ir_print_spill_begin(irp, (IrInstructionSpillBegin *)instruction);
2055 break;2031 break;
src/parser.cpp-12
...@@ -1167,7 +1167,6 @@ static AstNode *ast_parse_prefix_expr(ParseContext *pc) {...@@ -1167,7 +1167,6 @@ static AstNode *ast_parse_prefix_expr(ParseContext *pc) {
1167// <- AsmExpr1167// <- AsmExpr
1168// / IfExpr1168// / IfExpr
1169// / KEYWORD_break BreakLabel? Expr?1169// / KEYWORD_break BreakLabel? Expr?
1170// / KEYWORD_cancel Expr
1171// / KEYWORD_comptime Expr1170// / KEYWORD_comptime Expr
1172// / KEYWORD_continue BreakLabel?1171// / KEYWORD_continue BreakLabel?
1173// / KEYWORD_resume Expr1172// / KEYWORD_resume Expr
...@@ -1195,14 +1194,6 @@ static AstNode *ast_parse_primary_expr(ParseContext *pc) {...@@ -1195,14 +1194,6 @@ static AstNode *ast_parse_primary_expr(ParseContext *pc) {
1195 return res;1194 return res;
1196 }1195 }
11971196
1198 Token *cancel = eat_token_if(pc, TokenIdKeywordCancel);
1199 if (cancel != nullptr) {
1200 AstNode *expr = ast_expect(pc, ast_parse_expr);
1201 AstNode *res = ast_create_node(pc, NodeTypeCancel, cancel);
1202 res->data.cancel_expr.expr = expr;
1203 return res;
1204 }
1205
1206 Token *comptime = eat_token_if(pc, TokenIdKeywordCompTime);1197 Token *comptime = eat_token_if(pc, TokenIdKeywordCompTime);
1207 if (comptime != nullptr) {1198 if (comptime != nullptr) {
1208 AstNode *expr = ast_expect(pc, ast_parse_expr);1199 AstNode *expr = ast_expect(pc, ast_parse_expr);
...@@ -3035,9 +3026,6 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont...@@ -3035,9 +3026,6 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont
3035 case NodeTypeErrorSetDecl:3026 case NodeTypeErrorSetDecl:
3036 visit_node_list(&node->data.err_set_decl.decls, visit, context);3027 visit_node_list(&node->data.err_set_decl.decls, visit, context);
3037 break;3028 break;
3038 case NodeTypeCancel:
3039 visit_field(&node->data.cancel_expr.expr, visit, context);
3040 break;
3041 case NodeTypeResume:3029 case NodeTypeResume:
3042 visit_field(&node->data.resume_expr.expr, visit, context);3030 visit_field(&node->data.resume_expr.expr, visit, context);
3043 break;3031 break;
src/tokenizer.cpp-2
...@@ -114,7 +114,6 @@ static const struct ZigKeyword zig_keywords[] = {...@@ -114,7 +114,6 @@ static const struct ZigKeyword zig_keywords[] = {
114 {"async", TokenIdKeywordAsync},114 {"async", TokenIdKeywordAsync},
115 {"await", TokenIdKeywordAwait},115 {"await", TokenIdKeywordAwait},
116 {"break", TokenIdKeywordBreak},116 {"break", TokenIdKeywordBreak},
117 {"cancel", TokenIdKeywordCancel},
118 {"catch", TokenIdKeywordCatch},117 {"catch", TokenIdKeywordCatch},
119 {"comptime", TokenIdKeywordCompTime},118 {"comptime", TokenIdKeywordCompTime},
120 {"const", TokenIdKeywordConst},119 {"const", TokenIdKeywordConst},
...@@ -1531,7 +1530,6 @@ const char * token_name(TokenId id) {...@@ -1531,7 +1530,6 @@ const char * token_name(TokenId id) {
1531 case TokenIdKeywordAwait: return "await";1530 case TokenIdKeywordAwait: return "await";
1532 case TokenIdKeywordResume: return "resume";1531 case TokenIdKeywordResume: return "resume";
1533 case TokenIdKeywordSuspend: return "suspend";1532 case TokenIdKeywordSuspend: return "suspend";
1534 case TokenIdKeywordCancel: return "cancel";
1535 case TokenIdKeywordAlign: return "align";1533 case TokenIdKeywordAlign: return "align";
1536 case TokenIdKeywordAnd: return "and";1534 case TokenIdKeywordAnd: return "and";
1537 case TokenIdKeywordAnyFrame: return "anyframe";1535 case TokenIdKeywordAnyFrame: return "anyframe";
src/tokenizer.hpp-1
...@@ -58,7 +58,6 @@ enum TokenId {...@@ -58,7 +58,6 @@ enum TokenId {
58 TokenIdKeywordAsync,58 TokenIdKeywordAsync,
59 TokenIdKeywordAwait,59 TokenIdKeywordAwait,
60 TokenIdKeywordBreak,60 TokenIdKeywordBreak,
61 TokenIdKeywordCancel,
62 TokenIdKeywordCatch,61 TokenIdKeywordCatch,
63 TokenIdKeywordCompTime,62 TokenIdKeywordCompTime,
64 TokenIdKeywordConst,63 TokenIdKeywordConst,
std/event/fs.zig+1-1
...@@ -1301,7 +1301,7 @@ async fn testFsWatch(loop: *Loop) !void {...@@ -1301,7 +1301,7 @@ async fn testFsWatch(loop: *Loop) !void {
13011301
1302 const ev = try async watch.channel.get();1302 const ev = try async watch.channel.get();
1303 var ev_consumed = false;1303 var ev_consumed = false;
1304 defer if (!ev_consumed) cancel ev;1304 defer if (!ev_consumed) await ev;
13051305
1306 // overwrite line 21306 // overwrite line 2
1307 const fd = try await try async openReadWrite(loop, file_path, File.default_mode);1307 const fd = try await try async openReadWrite(loop, file_path, File.default_mode);
std/event/future.zig+1-1
...@@ -110,7 +110,7 @@ async fn testFuture(loop: *Loop) void {...@@ -110,7 +110,7 @@ async fn testFuture(loop: *Loop) void {
110 const b_result = await b;110 const b_result = await b;
111 const result = a_result + b_result;111 const result = a_result + b_result;
112112
113 cancel c;113 await c;
114 testing.expect(result == 12);114 testing.expect(result == 12);
115}115}
116116
std/event/group.zig+5-15
...@@ -27,17 +27,6 @@ pub fn Group(comptime ReturnType: type) type {...@@ -27,17 +27,6 @@ pub fn Group(comptime ReturnType: type) type {
27 };27 };
28 }28 }
2929
30 /// Cancel all the outstanding frames. Can be called even if wait was already called.
31 pub fn deinit(self: *Self) void {
32 while (self.frame_stack.pop()) |node| {
33 cancel node.data;
34 }
35 while (self.alloc_stack.pop()) |node| {
36 cancel node.data;
37 self.lock.loop.allocator.destroy(node);
38 }
39 }
40
41 /// Add a frame to the group. Thread-safe.30 /// Add a frame to the group. Thread-safe.
42 pub fn add(self: *Self, handle: anyframe->ReturnType) (error{OutOfMemory}!void) {31 pub fn add(self: *Self, handle: anyframe->ReturnType) (error{OutOfMemory}!void) {
43 const node = try self.lock.loop.allocator.create(Stack.Node);32 const node = try self.lock.loop.allocator.create(Stack.Node);
...@@ -64,13 +53,14 @@ pub fn Group(comptime ReturnType: type) type {...@@ -64,13 +53,14 @@ pub fn Group(comptime ReturnType: type) type {
64 const held = self.lock.acquire();53 const held = self.lock.acquire();
65 defer held.release();54 defer held.release();
6655
56 var result: ReturnType = {};
57
67 while (self.frame_stack.pop()) |node| {58 while (self.frame_stack.pop()) |node| {
68 if (Error == void) {59 if (Error == void) {
69 await node.data;60 await node.data;
70 } else {61 } else {
71 (await node.data) catch |err| {62 (await node.data) catch |err| {
72 self.deinit();63 result = err;
73 return err;
74 };64 };
75 }65 }
76 }66 }
...@@ -81,11 +71,11 @@ pub fn Group(comptime ReturnType: type) type {...@@ -81,11 +71,11 @@ pub fn Group(comptime ReturnType: type) type {
81 await handle;71 await handle;
82 } else {72 } else {
83 (await handle) catch |err| {73 (await handle) catch |err| {
84 self.deinit();74 result = err;
85 return err;
86 };75 };
87 }76 }
88 }77 }
78 return result;
89 }79 }
90 };80 };
91}81}
std/event/net.zig+2-6
...@@ -54,7 +54,7 @@ pub const Server = struct {...@@ -54,7 +54,7 @@ pub const Server = struct {
54 self.listen_address = std.net.Address.initPosix(try os.getsockname(sockfd));54 self.listen_address = std.net.Address.initPosix(try os.getsockname(sockfd));
5555
56 self.accept_frame = async Server.handler(self);56 self.accept_frame = async Server.handler(self);
57 errdefer cancel self.accept_frame.?;57 errdefer await self.accept_frame.?;
5858
59 self.listen_resume_node.handle = self.accept_frame.?;59 self.listen_resume_node.handle = self.accept_frame.?;
60 try self.loop.linuxAddFd(sockfd, &self.listen_resume_node, os.EPOLLIN | os.EPOLLOUT | os.EPOLLET);60 try self.loop.linuxAddFd(sockfd, &self.listen_resume_node, os.EPOLLIN | os.EPOLLOUT | os.EPOLLET);
...@@ -71,7 +71,7 @@ pub const Server = struct {...@@ -71,7 +71,7 @@ pub const Server = struct {
71 }71 }
7272
73 pub fn deinit(self: *Server) void {73 pub fn deinit(self: *Server) void {
74 if (self.accept_frame) |accept_frame| cancel accept_frame;74 if (self.accept_frame) |accept_frame| await accept_frame;
75 if (self.sockfd) |sockfd| os.close(sockfd);75 if (self.sockfd) |sockfd| os.close(sockfd);
76 }76 }
7777
...@@ -274,13 +274,9 @@ test "listen on a port, send bytes, receive bytes" {...@@ -274,13 +274,9 @@ test "listen on a port, send bytes, receive bytes" {
274 const self = @fieldParentPtr(Self, "tcp_server", tcp_server);274 const self = @fieldParentPtr(Self, "tcp_server", tcp_server);
275 var socket = _socket; // TODO https://github.com/ziglang/zig/issues/1592275 var socket = _socket; // TODO https://github.com/ziglang/zig/issues/1592
276 defer socket.close();276 defer socket.close();
277 // TODO guarantee elision of this allocation
278 const next_handler = errorableHandler(self, _addr, socket) catch |err| {277 const next_handler = errorableHandler(self, _addr, socket) catch |err| {
279 std.debug.panic("unable to handle connection: {}\n", err);278 std.debug.panic("unable to handle connection: {}\n", err);
280 };279 };
281 suspend {
282 cancel @frame();
283 }
284 }280 }
285 async fn errorableHandler(self: *Self, _addr: *const std.net.Address, _socket: File) !void {281 async fn errorableHandler(self: *Self, _addr: *const std.net.Address, _socket: File) !void {
286 const addr = _addr.*; // TODO https://github.com/ziglang/zig/issues/1592282 const addr = _addr.*; // TODO https://github.com/ziglang/zig/issues/1592
std/zig/parse.zig-15
...@@ -814,7 +814,6 @@ fn parsePrefixExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {...@@ -814,7 +814,6 @@ fn parsePrefixExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
814/// <- AsmExpr814/// <- AsmExpr
815/// / IfExpr815/// / IfExpr
816/// / KEYWORD_break BreakLabel? Expr?816/// / KEYWORD_break BreakLabel? Expr?
817/// / KEYWORD_cancel Expr
818/// / KEYWORD_comptime Expr817/// / KEYWORD_comptime Expr
819/// / KEYWORD_continue BreakLabel?818/// / KEYWORD_continue BreakLabel?
820/// / KEYWORD_resume Expr819/// / KEYWORD_resume Expr
...@@ -839,20 +838,6 @@ fn parsePrimaryExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node...@@ -839,20 +838,6 @@ fn parsePrimaryExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node
839 return &node.base;838 return &node.base;
840 }839 }
841840
842 if (eatToken(it, .Keyword_cancel)) |token| {
843 const expr_node = try expectNode(arena, it, tree, parseExpr, AstError{
844 .ExpectedExpr = AstError.ExpectedExpr{ .token = it.index },
845 });
846 const node = try arena.create(Node.PrefixOp);
847 node.* = Node.PrefixOp{
848 .base = Node{ .id = .PrefixOp },
849 .op_token = token,
850 .op = Node.PrefixOp.Op.Cancel,
851 .rhs = expr_node,
852 };
853 return &node.base;
854 }
855
856 if (eatToken(it, .Keyword_comptime)) |token| {841 if (eatToken(it, .Keyword_comptime)) |token| {
857 const expr_node = try expectNode(arena, it, tree, parseExpr, AstError{842 const expr_node = try expectNode(arena, it, tree, parseExpr, AstError{
858 .ExpectedExpr = AstError.ExpectedExpr{ .token = it.index },843 .ExpectedExpr = AstError.ExpectedExpr{ .token = it.index },
std/zig/parser_test.zig+2-2
...@@ -2115,10 +2115,10 @@ test "zig fmt: async functions" {...@@ -2115,10 +2115,10 @@ test "zig fmt: async functions" {
2115 \\ await p;2115 \\ await p;
2116 \\}2116 \\}
2117 \\2117 \\
2118 \\test "suspend, resume, cancel" {2118 \\test "suspend, resume, await" {
2119 \\ const p: anyframe = async testAsyncSeq();2119 \\ const p: anyframe = async testAsyncSeq();
2120 \\ resume p;2120 \\ resume p;
2121 \\ cancel p;2121 \\ await p;
2122 \\}2122 \\}
2123 \\2123 \\
2124 );2124 );
std/zig/tokenizer.zig-2
...@@ -21,7 +21,6 @@ pub const Token = struct {...@@ -21,7 +21,6 @@ pub const Token = struct {
21 Keyword{ .bytes = "await", .id = Id.Keyword_await },21 Keyword{ .bytes = "await", .id = Id.Keyword_await },
22 Keyword{ .bytes = "break", .id = Id.Keyword_break },22 Keyword{ .bytes = "break", .id = Id.Keyword_break },
23 Keyword{ .bytes = "catch", .id = Id.Keyword_catch },23 Keyword{ .bytes = "catch", .id = Id.Keyword_catch },
24 Keyword{ .bytes = "cancel", .id = Id.Keyword_cancel },
25 Keyword{ .bytes = "comptime", .id = Id.Keyword_comptime },24 Keyword{ .bytes = "comptime", .id = Id.Keyword_comptime },
26 Keyword{ .bytes = "const", .id = Id.Keyword_const },25 Keyword{ .bytes = "const", .id = Id.Keyword_const },
27 Keyword{ .bytes = "continue", .id = Id.Keyword_continue },26 Keyword{ .bytes = "continue", .id = Id.Keyword_continue },
...@@ -151,7 +150,6 @@ pub const Token = struct {...@@ -151,7 +150,6 @@ pub const Token = struct {
151 Keyword_async,150 Keyword_async,
152 Keyword_await,151 Keyword_await,
153 Keyword_break,152 Keyword_break,
154 Keyword_cancel,
155 Keyword_catch,153 Keyword_catch,
156 Keyword_comptime,154 Keyword_comptime,
157 Keyword_const,155 Keyword_const,
test/compile_errors.zig+5-3
...@@ -61,13 +61,15 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -61,13 +61,15 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
61 cases.add(61 cases.add(
62 "runtime-known async function called",62 "runtime-known async function called",
63 \\export fn entry() void {63 \\export fn entry() void {
64 \\ _ = async amain();
65 \\}
66 \\fn amain() void {
64 \\ var ptr = afunc;67 \\ var ptr = afunc;
65 \\ _ = ptr();68 \\ _ = ptr();
66 \\}69 \\}
67 \\
68 \\async fn afunc() void {}70 \\async fn afunc() void {}
69 ,71 ,
70 "tmp.zig:3:12: error: function is not comptime-known; @asyncCall required",72 "tmp.zig:6:12: error: function is not comptime-known; @asyncCall required",
71 );73 );
7274
73 cases.add(75 cases.add(
...@@ -3388,7 +3390,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -3388,7 +3390,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
3388 \\3390 \\
3389 \\export fn entry() usize { return @sizeOf(@typeOf(Foo)); }3391 \\export fn entry() usize { return @sizeOf(@typeOf(Foo)); }
3390 ,3392 ,
3391 "tmp.zig:5:18: error: unable to evaluate constant expression",3393 "tmp.zig:5:25: error: unable to evaluate constant expression",
3392 "tmp.zig:2:12: note: called from here",3394 "tmp.zig:2:12: note: called from here",
3393 "tmp.zig:2:8: note: called from here",3395 "tmp.zig:2:8: note: called from here",
3394 );3396 );
test/stage1/behavior.zig-1
...@@ -41,7 +41,6 @@ comptime {...@@ -41,7 +41,6 @@ comptime {
41 _ = @import("behavior/bugs/920.zig");41 _ = @import("behavior/bugs/920.zig");
42 _ = @import("behavior/byteswap.zig");42 _ = @import("behavior/byteswap.zig");
43 _ = @import("behavior/byval_arg_var.zig");43 _ = @import("behavior/byval_arg_var.zig");
44 _ = @import("behavior/cancel.zig");
45 _ = @import("behavior/cast.zig");44 _ = @import("behavior/cast.zig");
46 _ = @import("behavior/const_slice_child.zig");45 _ = @import("behavior/const_slice_child.zig");
47 _ = @import("behavior/defer.zig");46 _ = @import("behavior/defer.zig");
test/stage1/behavior/async_fn.zig+14-76
...@@ -150,7 +150,7 @@ test "coroutine suspend, resume" {...@@ -150,7 +150,7 @@ test "coroutine suspend, resume" {
150 seq('a');150 seq('a');
151 var f = async testAsyncSeq();151 var f = async testAsyncSeq();
152 seq('c');152 seq('c');
153 cancel f;153 await f;
154 seq('g');154 seq('g');
155 }155 }
156156
...@@ -271,7 +271,6 @@ test "async function with dot syntax" {...@@ -271,7 +271,6 @@ test "async function with dot syntax" {
271 }271 }
272 };272 };
273 const p = async S.foo();273 const p = async S.foo();
274 // can't cancel in tests because they are non-async functions
275 expect(S.y == 2);274 expect(S.y == 2);
276}275}
277276
...@@ -286,7 +285,7 @@ test "async fn pointer in a struct field" {...@@ -286,7 +285,7 @@ test "async fn pointer in a struct field" {
286 comptime expect(@typeOf(f) == anyframe->void);285 comptime expect(@typeOf(f) == anyframe->void);
287 expect(data == 2);286 expect(data == 2);
288 resume f;287 resume f;
289 expect(data == 2);288 expect(data == 4);
290 _ = async doTheAwait(f);289 _ = async doTheAwait(f);
291 expect(data == 4);290 expect(data == 4);
292}291}
...@@ -394,7 +393,6 @@ async fn printTrace(p: anyframe->(anyerror!void)) void {...@@ -394,7 +393,6 @@ async fn printTrace(p: anyframe->(anyerror!void)) void {
394test "break from suspend" {393test "break from suspend" {
395 var my_result: i32 = 1;394 var my_result: i32 = 1;
396 const p = async testBreakFromSuspend(&my_result);395 const p = async testBreakFromSuspend(&my_result);
397 // can't cancel here
398 std.testing.expect(my_result == 2);396 std.testing.expect(my_result == 2);
399}397}
400async fn testBreakFromSuspend(my_result: *i32) void {398async fn testBreakFromSuspend(my_result: *i32) void {
...@@ -530,45 +528,6 @@ test "call async function which has struct return type" {...@@ -530,45 +528,6 @@ test "call async function which has struct return type" {
530 S.doTheTest();528 S.doTheTest();
531}529}
532530
533test "errdefers in scope get run when canceling async fn call" {
534 const S = struct {
535 var frame: anyframe = undefined;
536 var x: u32 = 0;
537
538 fn doTheTest() void {
539 x = 9;
540 _ = async cancelIt();
541 resume frame;
542 expect(x == 6);
543
544 x = 9;
545 _ = async awaitIt();
546 resume frame;
547 expect(x == 11);
548 }
549
550 fn cancelIt() void {
551 var f = async func();
552 cancel f;
553 }
554
555 fn awaitIt() void {
556 var f = async func();
557 await f;
558 }
559
560 fn func() void {
561 defer x += 1;
562 errdefer x /= 2;
563 defer x += 1;
564 suspend {
565 frame = @frame();
566 }
567 }
568 };
569 S.doTheTest();
570}
571
572test "pass string literal to async function" {531test "pass string literal to async function" {
573 const S = struct {532 const S = struct {
574 var frame: anyframe = undefined;533 var frame: anyframe = undefined;
...@@ -590,7 +549,7 @@ test "pass string literal to async function" {...@@ -590,7 +549,7 @@ test "pass string literal to async function" {
590 S.doTheTest();549 S.doTheTest();
591}550}
592551
593test "cancel inside an errdefer" {552test "await inside an errdefer" {
594 const S = struct {553 const S = struct {
595 var frame: anyframe = undefined;554 var frame: anyframe = undefined;
596555
...@@ -601,7 +560,7 @@ test "cancel inside an errdefer" {...@@ -601,7 +560,7 @@ test "cancel inside an errdefer" {
601560
602 fn amainWrap() !void {561 fn amainWrap() !void {
603 var foo = async func();562 var foo = async func();
604 errdefer cancel foo;563 errdefer await foo;
605 return error.Bad;564 return error.Bad;
606 }565 }
607566
...@@ -614,35 +573,6 @@ test "cancel inside an errdefer" {...@@ -614,35 +573,6 @@ test "cancel inside an errdefer" {
614 S.doTheTest();573 S.doTheTest();
615}574}
616575
617test "combining try with errdefer cancel" {
618 const S = struct {
619 var frame: anyframe = undefined;
620 var ok = false;
621
622 fn doTheTest() void {
623 _ = async amain();
624 resume frame;
625 expect(ok);
626 }
627
628 fn amain() !void {
629 var f = async func("https://example.com/");
630 errdefer cancel f;
631
632 _ = try await f;
633 }
634
635 fn func(url: []const u8) ![]u8 {
636 errdefer ok = true;
637 frame = @frame();
638 suspend;
639 return error.Bad;
640 }
641
642 };
643 S.doTheTest();
644}
645
646test "try in an async function with error union and non-zero-bit payload" {576test "try in an async function with error union and non-zero-bit payload" {
647 const S = struct {577 const S = struct {
648 var frame: anyframe = undefined;578 var frame: anyframe = undefined;
...@@ -730,14 +660,22 @@ fn testAsyncAwaitTypicalUsage(comptime simulate_fail_download: bool, comptime si...@@ -730,14 +660,22 @@ fn testAsyncAwaitTypicalUsage(comptime simulate_fail_download: bool, comptime si
730 fn amain() !void {660 fn amain() !void {
731 const allocator = std.heap.direct_allocator; // TODO once we have the debug allocator, use that, so that this can detect leaks661 const allocator = std.heap.direct_allocator; // TODO once we have the debug allocator, use that, so that this can detect leaks
732 var download_frame = async fetchUrl(allocator, "https://example.com/");662 var download_frame = async fetchUrl(allocator, "https://example.com/");
733 errdefer cancel download_frame;663 var download_awaited = false;
664 errdefer if (!download_awaited) {
665 if (await download_frame) |x| allocator.free(x) else |_| {}
666 };
734667
735 var file_frame = async readFile(allocator, "something.txt");668 var file_frame = async readFile(allocator, "something.txt");
736 errdefer cancel file_frame;669 var file_awaited = false;
670 errdefer if (!file_awaited) {
671 if (await file_frame) |x| allocator.free(x) else |_| {}
672 };
737673
674 download_awaited = true;
738 const download_text = try await download_frame;675 const download_text = try await download_frame;
739 defer allocator.free(download_text);676 defer allocator.free(download_text);
740677
678 file_awaited = true;
741 const file_text = try await file_frame;679 const file_text = try await file_frame;
742 defer allocator.free(file_text);680 defer allocator.free(file_text);
743681
test/stage1/behavior/cancel.zig deleted-115
...@@ -1,115 +0,0 @@
1const std = @import("std");
2const expect = std.testing.expect;
3
4var defer_f1: bool = false;
5var defer_f2: bool = false;
6var defer_f3: bool = false;
7var f3_frame: anyframe = undefined;
8
9test "cancel forwards" {
10 _ = async atest1();
11 resume f3_frame;
12}
13
14fn atest1() void {
15 const p = async f1();
16 cancel &p;
17 expect(defer_f1);
18 expect(defer_f2);
19 expect(defer_f3);
20}
21
22async fn f1() void {
23 defer {
24 defer_f1 = true;
25 }
26 var f2_frame = async f2();
27 await f2_frame;
28}
29
30async fn f2() void {
31 defer {
32 defer_f2 = true;
33 }
34 f3();
35}
36
37async fn f3() void {
38 f3_frame = @frame();
39 defer {
40 defer_f3 = true;
41 }
42 suspend;
43}
44
45var defer_b1: bool = false;
46var defer_b2: bool = false;
47var defer_b3: bool = false;
48var defer_b4: bool = false;
49
50test "cancel backwards" {
51 var b1_frame = async b1();
52 resume b4_handle;
53 _ = async awaitAFrame(&b1_frame);
54 expect(defer_b1);
55 expect(defer_b2);
56 expect(defer_b3);
57 expect(defer_b4);
58}
59
60async fn b1() void {
61 defer {
62 defer_b1 = true;
63 }
64 b2();
65}
66
67var b4_handle: anyframe->void = undefined;
68
69async fn b2() void {
70 const b3_handle = async b3();
71 resume b4_handle;
72 defer {
73 defer_b2 = true;
74 }
75 const value = await b3_handle;
76 expect(value == 1234);
77}
78
79async fn b3() i32 {
80 defer {
81 defer_b3 = true;
82 }
83 b4();
84 return 1234;
85}
86
87async fn b4() void {
88 defer {
89 defer_b4 = true;
90 }
91 suspend {
92 b4_handle = @frame();
93 }
94 suspend;
95}
96
97fn awaitAFrame(f: anyframe->void) void {
98 await f;
99}
100
101test "cancel on a non-pointer" {
102 const S = struct {
103 fn doTheTest() void {
104 _ = async atest();
105 }
106 fn atest() void {
107 var f = async func();
108 cancel f;
109 }
110 fn func() void {
111 suspend;
112 }
113 };
114 S.doTheTest();
115}