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
signature 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
750750 .Keyword_async,
751751 .Keyword_await,
752752 .Keyword_break,
753 .Keyword_cancel,
754753 .Keyword_catch,
755754 .Keyword_comptime,
756755 .Keyword_const,
doc/langref.html.in+6-8
......@@ -5971,7 +5971,7 @@ test "global assembly" {
59715971 {#header_open|Async Functions#}
59725972 <p>
59735973 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.
59755975 </p>
59765976 <p>
59775977 When you call a function, it creates a stack frame,
......@@ -6013,11 +6013,11 @@ test "global assembly" {
60136013 <p>
60146014 The result of an async function call is a {#syntax#}promise->T{#endsyntax#} type, where {#syntax#}T{#endsyntax#}
60156015 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#}:
60176017 </p>
60186018 <p>
60196019 Async functions start executing when created, so in the following example, the entire
6020 async function completes before it is canceled:
6020 TODO
60216021 </p>
60226022 {#code_begin|test#}
60236023const std = @import("std");
......@@ -6048,7 +6048,7 @@ fn simpleAsyncFn() void {
60486048 </p>
60496049 <p>
60506050 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 handle
6051 resumed somehow, for example by registering its promise handle
60526052 in an event loop. Use a suspend capture block to gain access to the
60536053 promise (TODO this is outdated):
60546054 </p>
......@@ -6134,7 +6134,7 @@ async fn testResumeFromSuspend(my_result: *i32) void {
61346134 resumes the awaiter.
61356135 </p>
61366136 <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#}.
61386138 </p>
61396139 <p>
61406140 {#syntax#}await{#endsyntax#} counts as a suspend point, and therefore at every {#syntax#}await{#endsyntax#},
......@@ -9764,7 +9764,6 @@ PrimaryExpr
97649764 &lt;- AsmExpr
97659765 / IfExpr
97669766 / KEYWORD_break BreakLabel? Expr?
9767 / KEYWORD_cancel Expr
97689767 / KEYWORD_comptime Expr
97699768 / KEYWORD_continue BreakLabel?
97709769 / KEYWORD_resume Expr
......@@ -10120,7 +10119,6 @@ KEYWORD_asm &lt;- 'asm' end_of_word
1012010119KEYWORD_async &lt;- 'async' end_of_word
1012110120KEYWORD_await &lt;- 'await' end_of_word
1012210121KEYWORD_break &lt;- 'break' end_of_word
10123KEYWORD_cancel &lt;- 'cancel' end_of_word
1012410122KEYWORD_catch &lt;- 'catch' end_of_word
1012510123KEYWORD_comptime &lt;- 'comptime' end_of_word
1012610124KEYWORD_const &lt;- 'const' end_of_word
......@@ -10165,7 +10163,7 @@ KEYWORD_volatile &lt;- 'volatile' end_of_word
1016510163KEYWORD_while &lt;- 'while' end_of_word
1016610164
1016710165keyword &lt;- KEYWORD_align / KEYWORD_and / KEYWORD_allowzero / KEYWORD_asm
10168 / KEYWORD_async / KEYWORD_await / KEYWORD_break / KEYWORD_cancel
10166 / KEYWORD_async / KEYWORD_await / KEYWORD_break
1016910167 / KEYWORD_catch / KEYWORD_comptime / KEYWORD_const / KEYWORD_continue
1017010168 / KEYWORD_defer / KEYWORD_else / KEYWORD_enum / KEYWORD_errdefer
1017110169 / 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
467467
468468 comp.start();
469469 // TODO const process_build_events_handle = try async<loop.allocator> processBuildEvents(comp, color);
470 defer cancel process_build_events_handle;
471470 loop.run();
472471}
473472
......@@ -579,7 +578,6 @@ fn cmdLibC(allocator: *Allocator, args: []const []const u8) !void {
579578 defer zig_compiler.deinit();
580579
581580 // TODO const handle = try async<loop.allocator> findLibCAsync(&zig_compiler);
582 defer cancel handle;
583581
584582 loop.run();
585583}
......@@ -669,7 +667,6 @@ fn cmdFmt(allocator: *Allocator, args: []const []const u8) !void {
669667 // TODO &flags,
670668 // TODO color,
671669 // TODO );
672 defer cancel main_handle;
673670 loop.run();
674671 return result;
675672}
src/all_types.hpp+1-32
......@@ -476,7 +476,6 @@ enum NodeType {
476476 NodeTypeIfErrorExpr,
477477 NodeTypeIfOptional,
478478 NodeTypeErrorSetDecl,
479 NodeTypeCancel,
480479 NodeTypeResume,
481480 NodeTypeAwaitExpr,
482481 NodeTypeSuspend,
......@@ -911,10 +910,6 @@ struct AstNodeBreakExpr {
911910 AstNode *expr; // may be null
912911};
913912
914struct AstNodeCancelExpr {
915 AstNode *expr;
916};
917
918913struct AstNodeResumeExpr {
919914 AstNode *expr;
920915};
......@@ -1003,7 +998,6 @@ struct AstNode {
1003998 AstNodeInferredArrayType inferred_array_type;
1004999 AstNodeErrorType error_type;
10051000 AstNodeErrorSetDecl err_set_decl;
1006 AstNodeCancelExpr cancel_expr;
10071001 AstNodeResumeExpr resume_expr;
10081002 AstNodeAwaitExpr await_expr;
10091003 AstNodeSuspend suspend;
......@@ -1561,7 +1555,6 @@ enum PanicMsgId {
15611555 PanicMsgIdBadAwait,
15621556 PanicMsgIdBadReturn,
15631557 PanicMsgIdResumedAnAwaitingFn,
1564 PanicMsgIdResumedACancelingFn,
15651558 PanicMsgIdFrameTooSmall,
15661559 PanicMsgIdResumedFnPendingAwait,
15671560
......@@ -1729,8 +1722,6 @@ struct CodeGen {
17291722 LLVMValueRef cur_async_switch_instr;
17301723 LLVMValueRef cur_async_resume_index_ptr;
17311724 LLVMValueRef cur_async_awaiter_ptr;
1732 LLVMValueRef cur_async_prev_val;
1733 LLVMValueRef cur_async_prev_val_field_ptr;
17341725 LLVMBasicBlockRef cur_preamble_llvm_block;
17351726 size_t cur_resume_block_count;
17361727 LLVMValueRef cur_err_ret_trace_val_arg;
......@@ -1822,7 +1813,6 @@ struct CodeGen {
18221813
18231814 ZigType *align_amt_type;
18241815 ZigType *stack_trace_type;
1825 ZigType *ptr_to_stack_trace_type;
18261816 ZigType *err_tag_type;
18271817 ZigType *test_fn_type;
18281818
......@@ -1892,7 +1882,6 @@ struct CodeGen {
18921882 bool system_linker_hack;
18931883 bool reported_bad_link_libc_error;
18941884 bool is_dynamic; // shared library rather than static library. dynamic musl rather than static musl.
1895 bool cur_is_after_return;
18961885
18971886 //////////////////////////// Participates in Input Parameter Cache Hash
18981887 /////// Note: there is a separate cache hash for builtin.zig, when adding fields,
......@@ -2235,7 +2224,6 @@ enum IrInstructionId {
22352224 IrInstructionIdCallGen,
22362225 IrInstructionIdConst,
22372226 IrInstructionIdReturn,
2238 IrInstructionIdReturnBegin,
22392227 IrInstructionIdCast,
22402228 IrInstructionIdResizeSlice,
22412229 IrInstructionIdContainerInitList,
......@@ -2345,7 +2333,6 @@ enum IrInstructionId {
23452333 IrInstructionIdExport,
23462334 IrInstructionIdErrorReturnTrace,
23472335 IrInstructionIdErrorUnion,
2348 IrInstructionIdCancel,
23492336 IrInstructionIdAtomicRmw,
23502337 IrInstructionIdAtomicLoad,
23512338 IrInstructionIdSaveErrRetAddr,
......@@ -2370,7 +2357,6 @@ enum IrInstructionId {
23702357 IrInstructionIdAwaitSrc,
23712358 IrInstructionIdAwaitGen,
23722359 IrInstructionIdResume,
2373 IrInstructionIdTestCancelRequested,
23742360 IrInstructionIdSpillBegin,
23752361 IrInstructionIdSpillEnd,
23762362};
......@@ -2649,12 +2635,6 @@ struct IrInstructionReturn {
26492635 IrInstruction *operand;
26502636};
26512637
2652struct IrInstructionReturnBegin {
2653 IrInstruction base;
2654
2655 IrInstruction *operand;
2656};
2657
26582638enum CastOp {
26592639 CastOpNoCast, // signifies the function call expression is not a cast
26602640 CastOpNoop, // fn call expr is a cast, but does nothing
......@@ -3440,12 +3420,6 @@ struct IrInstructionErrorUnion {
34403420 IrInstruction *payload;
34413421};
34423422
3443struct IrInstructionCancel {
3444 IrInstruction base;
3445
3446 IrInstruction *frame;
3447};
3448
34493423struct IrInstructionAtomicRmw {
34503424 IrInstruction base;
34513425
......@@ -3647,10 +3621,6 @@ struct IrInstructionResume {
36473621 IrInstruction *frame;
36483622};
36493623
3650struct IrInstructionTestCancelRequested {
3651 IrInstruction base;
3652};
3653
36543624enum SpillId {
36553625 SpillIdInvalid,
36563626 SpillIdRetErrCode,
......@@ -3756,8 +3726,7 @@ static const size_t err_union_err_index = 1;
37563726static const size_t frame_fn_ptr_index = 0;
37573727static const size_t frame_resume_index = 1;
37583728static const size_t frame_awaiter_index = 2;
3759static const size_t frame_prev_val_index = 3;
3760static const size_t frame_ret_start = 4;
3729static const size_t frame_ret_start = 3;
37613730
37623731// TODO https://github.com/ziglang/zig/issues/3056
37633732// 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) {
828828 zig_unreachable();
829829}
830830
831ZigType *get_ptr_to_stack_trace_type(CodeGen *g) {
831ZigType *get_stack_trace_type(CodeGen *g) {
832832 if (g->stack_trace_type == nullptr) {
833833 ConstExprValue *stack_trace_type_val = get_builtin_value(g, "StackTrace");
834834 assert(stack_trace_type_val->type->id == ZigTypeIdMetaType);
835835
836836 g->stack_trace_type = stack_trace_type_val->data.x_type;
837837 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);
840838 }
841 return g->ptr_to_stack_trace_type;
839 return g->stack_trace_type;
842840}
843841
844842bool want_first_arg_sret(CodeGen *g, FnTypeId *fn_type_id) {
......@@ -3035,7 +3033,6 @@ void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node) {
30353033 case NodeTypeIfErrorExpr:
30363034 case NodeTypeIfOptional:
30373035 case NodeTypeErrorSetDecl:
3038 case NodeTypeCancel:
30393036 case NodeTypeResume:
30403037 case NodeTypeAwaitExpr:
30413038 case NodeTypeSuspend:
......@@ -3822,11 +3819,9 @@ static void add_async_error_notes(CodeGen *g, ErrorMsg *msg, ZigFn *fn) {
38223819 } else if (fn->inferred_async_node->type == NodeTypeAwaitExpr) {
38233820 add_error_note(g, msg, fn->inferred_async_node,
38243821 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"));
38283822 } else {
3829 zig_unreachable();
3823 add_error_note(g, msg, fn->inferred_async_node,
3824 buf_sprintf("suspends here"));
38303825 }
38313826}
38323827
......@@ -5231,12 +5226,21 @@ static Error resolve_async_frame(CodeGen *g, ZigType *frame_type) {
52315226 fields.append({"@fn_ptr", g->builtin_types.entry_usize, 0});
52325227 fields.append({"@resume_index", g->builtin_types.entry_usize, 0});
52335228 fields.append({"@awaiter", g->builtin_types.entry_usize, 0});
5234 fields.append({"@prev_val", g->builtin_types.entry_usize, 0});
52355229
52365230 fields.append({"@result_ptr_callee", ptr_return_type, 0});
52375231 fields.append({"@result_ptr_awaiter", ptr_return_type, 0});
52385232 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
52405244 frame_type->data.frame.locals_struct = get_struct_type(g, buf_ptr(&frame_type->name),
52415245 fields.items, fields.length, target_fn_align(g->zig_target));
52425246 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) {
53115315 fields.append({"@fn_ptr", fn_type, 0});
53125316 fields.append({"@resume_index", g->builtin_types.entry_usize, 0});
53135317 fields.append({"@awaiter", g->builtin_types.entry_usize, 0});
5314 fields.append({"@prev_val", g->builtin_types.entry_usize, 0});
53155318
53165319 fields.append({"@result_ptr_callee", ptr_return_type, 0});
53175320 fields.append({"@result_ptr_awaiter", ptr_return_type, 0});
53185321 fields.append({"@result", fn_type_id->return_type, 0});
53195322
53205323 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});
53225327 }
53235328
53245329 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) {
53375342 }
53385343
53395344 if (codegen_fn_has_err_ret_tracing_stack(g, fn, true)) {
5340 (void)get_ptr_to_stack_trace_type(g); // populate g->stack_trace_type
5341
5342 fields.append({"@stack_trace", g->stack_trace_type, 0});
5345 fields.append({"@stack_trace", get_stack_trace_type(g), 0});
53435346 fields.append({"@instruction_addresses",
53445347 get_array_type(g, g->builtin_types.entry_usize, stack_trace_ptr_count), 0});
53455348 }
......@@ -7553,7 +7556,7 @@ static void resolve_llvm_types_fn_type(CodeGen *g, ZigType *fn_type) {
75537556 fn_type->data.fn.gen_return_type = gen_return_type;
75547557
75557558 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);
75577560 gen_param_types.append(get_llvm_type(g, gen_type));
75587561 param_di_types.append(get_llvm_di_type(g, gen_type));
75597562 }
......@@ -7727,7 +7730,6 @@ static void resolve_llvm_types_any_frame(CodeGen *g, ZigType *any_frame_type, Re
77277730 field_types.append(ptr_fn_llvm_type); // fn_ptr
77287731 field_types.append(usize_type_ref); // resume_index
77297732 field_types.append(usize_type_ref); // awaiter
7730 field_types.append(usize_type_ref); // prev_val
77317733
77327734 bool have_result_type = result_type != nullptr && type_has_bits(result_type);
77337735 if (have_result_type) {
......@@ -7735,7 +7737,9 @@ static void resolve_llvm_types_any_frame(CodeGen *g, ZigType *any_frame_type, Re
77357737 field_types.append(get_llvm_type(g, ptr_result_type)); // result_ptr_awaiter
77367738 field_types.append(get_llvm_type(g, result_type)); // result
77377739 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_trace
7740 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
77397743 }
77407744 }
77417745 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
77927796 ZigLLVM_DIFlags_Zero, get_llvm_di_type(g, result_type)));
77937797
77947798 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)));
77957808 di_element_types.append(
77967809 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",
77987811 di_file, line,
77997812 8*LLVMABISizeOfType(g->target_data_ref, field_types.at(di_element_types.length)),
78007813 8*LLVMABIAlignmentOfType(g->target_data_ref, field_types.at(di_element_types.length)),
78017814 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)));
78037816 }
78047817 };
78057818
src/analyze.hpp+1-1
......@@ -195,7 +195,7 @@ void add_var_export(CodeGen *g, ZigVar *fn_table_entry, Buf *symbol_name, Global
195195
196196
197197ConstExprValue *get_builtin_value(CodeGen *codegen, const char *name);
198ZigType *get_ptr_to_stack_trace_type(CodeGen *g);
198ZigType *get_stack_trace_type(CodeGen *g);
199199bool resolve_inferred_error_set(CodeGen *g, ZigType *err_set_type, AstNode *source_node);
200200
201201ZigType *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) {
249249 return "IfOptional";
250250 case NodeTypeErrorSetDecl:
251251 return "ErrorSetDecl";
252 case NodeTypeCancel:
253 return "Cancel";
254252 case NodeTypeResume:
255253 return "Resume";
256254 case NodeTypeAwaitExpr:
......@@ -1136,12 +1134,6 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {
11361134 fprintf(ar->f, "}");
11371135 break;
11381136 }
1139 case NodeTypeCancel:
1140 {
1141 fprintf(ar->f, "cancel ");
1142 render_node_grouped(ar, node->data.cancel_expr.expr);
1143 break;
1144 }
11451137 case NodeTypeResume:
11461138 {
11471139 fprintf(ar->f, "resume ");
src/codegen.cpp+156-256
......@@ -28,8 +28,6 @@ enum ResumeId {
2828 ResumeIdManual,
2929 ResumeIdReturn,
3030 ResumeIdCall,
31
32 ResumeIdAwaitEarlyReturn // must be last
3331};
3432
3533static void init_darwin_native(CodeGen *g) {
......@@ -317,8 +315,9 @@ static uint32_t frame_index_trace_arg(CodeGen *g, ZigType *return_type) {
317315// label (grep this): [fn_frame_struct_layout]
318316static uint32_t frame_index_arg(CodeGen *g, ZigType *return_type) {
319317 bool have_stack_trace = codegen_fn_has_err_ret_tracing_arg(g, return_type);
320 // [0] *StackTrace
321 uint32_t trace_field_count = have_stack_trace ? 1 : 0;
318 // [0] *StackTrace (callee's)
319 // [1] *StackTrace (awaiter's)
320 uint32_t trace_field_count = have_stack_trace ? 2 : 0;
322321 return frame_index_trace_arg(g, return_type) + trace_field_count;
323322}
324323
......@@ -916,8 +915,6 @@ static Buf *panic_msg_buf(PanicMsgId msg_id) {
916915 return buf_create_from_str("async function returned twice");
917916 case PanicMsgIdResumedAnAwaitingFn:
918917 return buf_create_from_str("awaiting function resumed");
919 case PanicMsgIdResumedACancelingFn:
920 return buf_create_from_str("canceling function resumed");
921918 case PanicMsgIdFrameTooSmall:
922919 return buf_create_from_str("frame too small");
923920 case PanicMsgIdResumedFnPendingAwait:
......@@ -946,13 +943,16 @@ static LLVMValueRef get_panic_msg_ptr_val(CodeGen *g, PanicMsgId msg_id) {
946943 return LLVMConstBitCast(val->global_refs->llvm_global, LLVMPointerType(get_llvm_type(g, str_type), 0));
947944}
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
949950static void gen_panic(CodeGen *g, LLVMValueRef msg_arg, LLVMValueRef stack_trace_arg) {
950951 assert(g->panic_fn != nullptr);
951952 LLVMValueRef fn_val = fn_llvm_value(g, g->panic_fn);
952953 LLVMCallConv llvm_cc = get_llvm_cc(g, g->panic_fn->type_entry->data.fn.fn_type_id.cc);
953954 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));
955 stack_trace_arg = LLVMConstNull(get_llvm_type(g, ptr_to_stack_trace_type(g)));
956956 }
957957 LLVMValueRef args[] = {
958958 msg_arg,
......@@ -1046,7 +1046,7 @@ static LLVMValueRef get_add_error_return_trace_addr_fn(CodeGen *g) {
10461046 return g->add_error_return_trace_addr_fn_val;
10471047
10481048 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)),
10501050 g->builtin_types.entry_usize->llvm_type,
10511051 };
10521052 LLVMTypeRef fn_type_ref = LLVMFunctionType(LLVMVoidType(), arg_types, 2, false);
......@@ -1127,7 +1127,7 @@ static LLVMValueRef get_return_err_fn(CodeGen *g) {
11271127
11281128 LLVMTypeRef arg_types[] = {
11291129 // 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)),
11311131 };
11321132 LLVMTypeRef fn_type_ref = LLVMFunctionType(LLVMVoidType(), arg_types, 1, false);
11331133
......@@ -1205,7 +1205,7 @@ static LLVMValueRef get_safety_crash_err_fn(CodeGen *g) {
12051205 LLVMTypeRef fn_type_ref;
12061206 if (g->have_err_ret_tracing) {
12071207 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)),
12091209 get_llvm_type(g, g->err_tag_type),
12101210 };
12111211 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) {
13211321 if (g->cur_err_ret_trace_val_stack != nullptr) {
13221322 return g->cur_err_ret_trace_val_stack;
13231323 }
1324 if (g->cur_err_ret_trace_val_arg != nullptr) {
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;
1324 return g->cur_err_ret_trace_val_arg;
13321325}
13331326
13341327static 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
13371330 if (g->have_err_ret_tracing) {
13381331 LLVMValueRef err_ret_trace_val = get_cur_err_ret_trace_val(g, scope);
13391332 if (err_ret_trace_val == nullptr) {
1340 ZigType *ptr_to_stack_trace_type = get_ptr_to_stack_trace_type(g);
1341 err_ret_trace_val = LLVMConstNull(get_llvm_type(g, ptr_to_stack_trace_type));
1333 err_ret_trace_val = LLVMConstNull(get_llvm_type(g, ptr_to_stack_trace_type(g)));
13421334 }
13431335 LLVMValueRef args[] = {
13441336 err_ret_trace_val,
......@@ -2044,8 +2036,8 @@ static LLVMValueRef get_merge_err_ret_traces_fn_val(CodeGen *g) {
20442036 assert(g->stack_trace_type != nullptr);
20452037
20462038 LLVMTypeRef param_types[] = {
2047 get_llvm_type(g, get_ptr_to_stack_trace_type(g)),
2048 get_llvm_type(g, get_ptr_to_stack_trace_type(g)),
2039 get_llvm_type(g, ptr_to_stack_trace_type(g)),
2040 get_llvm_type(g, ptr_to_stack_trace_type(g)),
20492041 };
20502042 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) {
20582050 addLLVMArgAttr(fn_val, (unsigned)0, "noalias");
20592051 addLLVMArgAttr(fn_val, (unsigned)0, "writeonly");
20602052
2061 addLLVMArgAttr(fn_val, (unsigned)1, "nonnull");
20622053 addLLVMArgAttr(fn_val, (unsigned)1, "noalias");
20632054 addLLVMArgAttr(fn_val, (unsigned)1, "readonly");
20642055 if (g->build_mode == BuildModeDebug) {
......@@ -2075,7 +2066,7 @@ static LLVMValueRef get_merge_err_ret_traces_fn_val(CodeGen *g) {
20752066 LLVMPositionBuilderAtEnd(g->builder, entry_block);
20762067 ZigLLVMClearCurrentDebugLocation(g->builder);
20772068
2078 // if (dest_stack_trace == null) return;
2069 // if (dest_stack_trace == null or src_stack_trace == null) return;
20792070 // var frame_index: usize = undefined;
20802071 // var frames_left: usize = undefined;
20812072 // 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) {
20932084 // frame_index = (frame_index + 1) % src_stack_trace.instruction_addresses.len;
20942085 // }
20952086 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
20982089 LLVMValueRef frame_index_ptr = LLVMBuildAlloca(g->builder, g->builtin_types.entry_usize->llvm_type, "frame_index");
20992090 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) {
21032094
21042095 LLVMValueRef null_dest_bit = LLVMBuildICmp(g->builder, LLVMIntEQ, dest_stack_trace_ptr,
21052096 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);
21092103 size_t src_index_field_index = g->stack_trace_type->data.structure.fields[0].gen_index;
21102104 size_t src_addresses_field_index = g->stack_trace_type->data.structure.fields[1].gen_index;
21112105 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
21832177 ZigLLVMBuildCall(g->builder, return_err_fn, &my_err_trace_val, 1,
21842178 get_llvm_cc(g, CallingConventionUnspecified), ZigLLVM_FnInlineAuto, "");
21852179
2186 if (fn_is_async(g->cur_fn) && g->cur_fn->calls_or_awaits_errorable_fn &&
2187 codegen_fn_has_err_ret_tracing_arg(g, g->cur_fn->type_entry->data.fn.fn_type_id.return_type))
2188 {
2189 LLVMValueRef dest_trace_ptr = LLVMBuildLoad(g->builder, g->cur_err_ret_trace_val_arg, "");
2190 LLVMValueRef args[] = { dest_trace_ptr, my_err_trace_val };
2191 ZigLLVMBuildCall(g->builder, get_merge_err_ret_traces_fn_val(g), args, 2,
2192 get_llvm_cc(g, CallingConventionUnspecified), ZigLLVM_FnInlineAuto, "");
2180 ZigType *ret_type = 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)) {
2182 LLVMValueRef trace_ptr_ptr = LLVMBuildStructGEP(g->builder, g->cur_frame_ptr,
2183 frame_index_trace_arg(g, ret_type), "");
2184 LLVMBuildStore(g->builder, my_err_trace_val, trace_ptr_ptr);
21932185 }
21942186
21952187 return nullptr;
......@@ -2201,16 +2193,9 @@ static void gen_assert_resume_id(CodeGen *g, IrInstruction *source_instr, Resume
22012193 LLVMTypeRef usize_type_ref = g->builtin_types.entry_usize->llvm_type;
22022194 LLVMBasicBlockRef bad_resume_block = LLVMAppendBasicBlock(g->cur_fn_val, "BadResume");
22032195 if (end_bb == nullptr) end_bb = LLVMAppendBasicBlock(g->cur_fn_val, "OkResume");
2204 LLVMValueRef ok_bit;
2205 if (resume_id == ResumeIdAwaitEarlyReturn) {
2206 LLVMValueRef last_value = LLVMConstSub(LLVMConstAllOnes(usize_type_ref),
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 }
2196 LLVMValueRef expected_value = LLVMConstSub(LLVMConstAllOnes(usize_type_ref),
2197 LLVMConstInt(usize_type_ref, resume_id, false));
2198 LLVMValueRef ok_bit = LLVMBuildICmp(g->builder, LLVMIntEQ, LLVMGetParam(g->cur_fn_val, 1), expected_value, "");
22142199 LLVMBuildCondBr(g->builder, ok_bit, end_bb, bad_resume_block);
22152200
22162201 LLVMPositionBuilderAtEnd(g->builder, bad_resume_block);
......@@ -2219,36 +2204,19 @@ static void gen_assert_resume_id(CodeGen *g, IrInstruction *source_instr, Resume
22192204 LLVMPositionBuilderAtEnd(g->builder, end_bb);
22202205}
22212206
2222static LLVMValueRef gen_resume(CodeGen *g, LLVMValueRef fn_val, LLVMValueRef target_frame_ptr,
2223 ResumeId resume_id, LLVMValueRef arg_val)
2224{
2207static LLVMValueRef gen_resume(CodeGen *g, LLVMValueRef fn_val, LLVMValueRef target_frame_ptr, ResumeId resume_id) {
22252208 LLVMTypeRef usize_type_ref = g->builtin_types.entry_usize->llvm_type;
22262209 if (fn_val == nullptr) {
22272210 LLVMValueRef fn_ptr_ptr = LLVMBuildStructGEP(g->builder, target_frame_ptr, frame_fn_ptr_index, "");
22282211 fn_val = LLVMBuildLoad(g->builder, fn_ptr_ptr, "");
22292212 }
2230 if (arg_val == nullptr) {
2231 arg_val = LLVMBuildSub(g->builder, LLVMConstAllOnes(usize_type_ref),
2232 LLVMConstInt(usize_type_ref, resume_id, false), "");
2233 } else {
2234 assert(resume_id == ResumeIdAwaitEarlyReturn);
2235 }
2213 LLVMValueRef arg_val = LLVMBuildSub(g->builder, LLVMConstAllOnes(usize_type_ref),
2214 LLVMConstInt(usize_type_ref, resume_id, false), "");
22362215 LLVMValueRef args[] = {target_frame_ptr, arg_val};
22372216 return ZigLLVMBuildCall(g->builder, fn_val, args, 2, LLVMFastCallConv, ZigLLVM_FnInlineAuto, "");
22382217}
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
22482219static 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
22522220 LLVMTypeRef usize_type_ref = g->builtin_types.entry_usize->llvm_type;
22532221 LLVMBasicBlockRef resume_bb = LLVMAppendBasicBlock(g->cur_fn_val, name_hint);
22542222 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) {
22592227 return resume_bb;
22602228}
22612229
2230static void set_tail_call_if_appropriate(CodeGen *g, LLVMValueRef call_inst) {
2231 LLVMSetTailCall(call_inst, true);
2232}
2233
22622234static LLVMValueRef gen_maybe_atomic_op(CodeGen *g, LLVMAtomicRMWBinOp op, LLVMValueRef ptr, LLVMValueRef val,
22632235 LLVMAtomicOrdering order)
22642236{
......@@ -2282,32 +2254,32 @@ static LLVMValueRef gen_maybe_atomic_op(CodeGen *g, LLVMAtomicRMWBinOp op, LLVMV
22822254 }
22832255}
22842256
2285static LLVMValueRef ir_render_return_begin(CodeGen *g, IrExecutable *executable,
2286 IrInstructionReturnBegin *instruction)
2287{
2257static void gen_async_return(CodeGen *g, IrInstructionReturn *instruction) {
2258 LLVMTypeRef usize_type_ref = g->builtin_types.entry_usize->llvm_type;
2259
22882260 ZigType *operand_type = (instruction->operand != nullptr) ? instruction->operand->value.type : nullptr;
22892261 bool operand_has_bits = (operand_type != nullptr) && type_has_bits(operand_type);
2290 if (!fn_is_async(g->cur_fn)) {
2291 return operand_has_bits ? ir_llvm_value(g, instruction->operand) : nullptr;
2292 }
2262 ZigType *ret_type = g->cur_fn->type_entry->data.fn.fn_type_id.return_type;
2263 bool ret_type_has_bits = type_has_bits(ret_type);
22932264
2294 LLVMTypeRef usize_type_ref = g->builtin_types.entry_usize->llvm_type;
22952265 if (operand_has_bits && instruction->operand != nullptr) {
2296 ZigType *ret_type = g->cur_fn->type_entry->data.fn.fn_type_id.return_type;
22972266 bool need_store = instruction->operand->value.special != ConstValSpecialRuntime || !handle_is_ptr(ret_type);
22982267 if (need_store) {
2299 // It didn't get written to the result ptr. We do that now so that we do not have to spill
2300 // the return operand.
2268 // It didn't get written to the result ptr. We do that now.
23012269 ZigType *ret_ptr_type = get_pointer_to_type(g, ret_type, true);
23022270 gen_assign_raw(g, g->cur_ret_ptr, ret_ptr_type, ir_llvm_value(g, instruction->operand));
23032271 }
23042272 }
23052273
2306 // Prepare to be suspended. We might end up not having to suspend though.
2307 LLVMBasicBlockRef resume_bb = gen_suspend_begin(g, "ReturnResume");
2274 // Whether we tail resume the awaiter, or do an early return, we are done and will not be resumed.
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
23092280 LLVMValueRef zero = LLVMConstNull(usize_type_ref);
23102281 LLVMValueRef all_ones = LLVMConstAllOnes(usize_type_ref);
2282
23112283 LLVMValueRef prev_val = gen_maybe_atomic_op(g, LLVMAtomicRMWBinOpXor, g->cur_async_awaiter_ptr,
23122284 all_ones, LLVMAtomicOrderingAcquire);
23132285
......@@ -2316,7 +2288,6 @@ static LLVMValueRef ir_render_return_begin(CodeGen *g, IrExecutable *executable,
23162288 LLVMBasicBlockRef resume_them_block = LLVMAppendBasicBlock(g->cur_fn_val, "ResumeThem");
23172289
23182290 LLVMValueRef switch_instr = LLVMBuildSwitch(g->builder, prev_val, resume_them_block, 2);
2319 LLVMBasicBlockRef switch_bb = LLVMGetInsertBlock(g->builder);
23202291
23212292 LLVMAddCase(switch_instr, zero, early_return_block);
23222293 LLVMAddCase(switch_instr, all_ones, bad_return_block);
......@@ -2325,90 +2296,63 @@ static LLVMValueRef ir_render_return_begin(CodeGen *g, IrExecutable *executable,
23252296 LLVMPositionBuilderAtEnd(g->builder, bad_return_block);
23262297 gen_assertion(g, PanicMsgIdBadReturn, &instruction->base);
23272298
2328 // The caller has not done an await yet. So we suspend at the return instruction, until a
2329 // cancel or await is performed.
2299 // There is no awaiter yet, but we're completely done.
23302300 LLVMPositionBuilderAtEnd(g->builder, early_return_block);
23312301 LLVMBuildRetVoid(g->builder);
23322302
2333 // Add a safety check for when getting resumed by the awaiter.
2334 LLVMPositionBuilderAtEnd(g->builder, resume_bb);
2335 LLVMBasicBlockRef after_resume_block = LLVMGetInsertBlock(g->builder);
2336 gen_assert_resume_id(g, &instruction->base, ResumeIdAwaitEarlyReturn, PanicMsgIdResumedFnPendingAwait,
2337 resume_them_block);
2338
2339 // We need to resume the caller by tail calling them.
2340 // That will happen when rendering IrInstructionReturn after running the defers/errdefers.
2341 // We either got here from Entry (function call) or from the switch above
2342 g->cur_async_prev_val = LLVMBuildPhi(g->builder, usize_type_ref, "");
2343 LLVMValueRef incoming_values[] = { LLVMGetParam(g->cur_fn_val, 1), prev_val };
2344 LLVMBasicBlockRef incoming_blocks[] = { after_resume_block, switch_bb };
2345 LLVMAddIncoming(g->cur_async_prev_val, incoming_values, incoming_blocks, 2);
2346
2347 g->cur_is_after_return = true;
2348 LLVMBuildStore(g->builder, g->cur_async_prev_val, g->cur_async_prev_val_field_ptr);
2349
2350 if (!operand_has_bits) {
2351 return nullptr;
2352 }
2353
2354 return get_handle_value(g, g->cur_ret_ptr, operand_type, get_pointer_to_type(g, operand_type, true));
2355}
2356
2357static void set_tail_call_if_appropriate(CodeGen *g, LLVMValueRef call_inst) {
2358 LLVMSetTailCall(call_inst, true);
2303 // We need to resume the caller by tail calling them,
2304 // but first write through the result pointer and possibly
2305 // error return trace pointer.
2306 LLVMPositionBuilderAtEnd(g->builder, resume_them_block);
2307
2308 if (ret_type_has_bits) {
2309 // If the awaiter result pointer is non-null, we need to copy the result to there.
2310 LLVMBasicBlockRef copy_block = LLVMAppendBasicBlock(g->cur_fn_val, "CopyResult");
2311 LLVMBasicBlockRef copy_end_block = LLVMAppendBasicBlock(g->cur_fn_val, "CopyResultEnd");
2312 LLVMValueRef awaiter_ret_ptr_ptr = LLVMBuildStructGEP(g->builder, g->cur_frame_ptr, frame_ret_start + 1, "");
2313 LLVMValueRef awaiter_ret_ptr = LLVMBuildLoad(g->builder, awaiter_ret_ptr_ptr, "");
2314 LLVMValueRef zero_ptr = LLVMConstNull(LLVMTypeOf(awaiter_ret_ptr));
2315 LLVMValueRef need_copy_bit = LLVMBuildICmp(g->builder, LLVMIntNE, awaiter_ret_ptr, zero_ptr, "");
2316 LLVMBuildCondBr(g->builder, need_copy_bit, copy_block, copy_end_block);
2317
2318 LLVMPositionBuilderAtEnd(g->builder, copy_block);
2319 LLVMTypeRef ptr_u8 = LLVMPointerType(LLVMInt8Type(), 0);
2320 LLVMValueRef dest_ptr_casted = LLVMBuildBitCast(g->builder, awaiter_ret_ptr, ptr_u8, "");
2321 LLVMValueRef src_ptr_casted = LLVMBuildBitCast(g->builder, g->cur_ret_ptr, ptr_u8, "");
2322 bool is_volatile = false;
2323 uint32_t abi_align = get_abi_alignment(g, ret_type);
2324 LLVMValueRef byte_count_val = LLVMConstInt(usize_type_ref, type_size(g, ret_type), false);
2325 ZigLLVMBuildMemCpy(g->builder,
2326 dest_ptr_casted, abi_align,
2327 src_ptr_casted, abi_align, byte_count_val, is_volatile);
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);
23592348}
23602349
23612350static LLVMValueRef ir_render_return(CodeGen *g, IrExecutable *executable, IrInstructionReturn *instruction) {
23622351 if (fn_is_async(g->cur_fn)) {
2363 LLVMTypeRef usize_type_ref = g->builtin_types.entry_usize->llvm_type;
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
2352 gen_async_return(g, instruction);
24102353 return nullptr;
24112354 }
2355
24122356 if (want_first_arg_sret(g, &g->cur_fn->type_entry->data.fn.fn_type_id)) {
24132357 if (instruction->operand == nullptr) {
24142358 LLVMBuildRetVoid(g->builder);
......@@ -3893,6 +3837,8 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr
38933837 // even if prefix_arg_err_ret_stack is true, let the async function do its own
38943838 // initialization.
38953839 } else {
3840 // async function called as a normal function
3841
38963842 frame_result_loc = ir_llvm_value(g, instruction->frame_result_loc);
38973843 awaiter_init_val = LLVMBuildPtrToInt(g->builder, g->cur_frame_ptr, usize_type_ref, ""); // caller's own frame pointer
38983844 if (ret_has_bits) {
......@@ -3912,7 +3858,7 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr
39123858
39133859 if (prefix_arg_err_ret_stack) {
39143860 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, "");
39163862 LLVMValueRef my_err_ret_trace_val = get_cur_err_ret_trace_val(g, instruction->base.scope);
39173863 LLVMBuildStore(g->builder, my_err_ret_trace_val, err_ret_trace_ptr_ptr);
39183864 }
......@@ -4018,7 +3964,7 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr
40183964 }
40193965
40203966 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);
40223968 if (instruction->new_stack != nullptr) {
40233969 return frame_result_loc;
40243970 }
......@@ -4028,7 +3974,7 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr
40283974
40293975 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);
40323978 set_tail_call_if_appropriate(g, call_inst);
40333979 LLVMBuildRetVoid(g->builder);
40343980
......@@ -4744,8 +4690,7 @@ static LLVMValueRef ir_render_error_return_trace(CodeGen *g, IrExecutable *execu
47444690{
47454691 LLVMValueRef cur_err_ret_trace_val = get_cur_err_ret_trace_val(g, instruction->base.scope);
47464692 if (cur_err_ret_trace_val == nullptr) {
4747 ZigType *ptr_to_stack_trace_type = get_ptr_to_stack_trace_type(g);
4748 return LLVMConstNull(get_llvm_type(g, ptr_to_stack_trace_type));
4693 return LLVMConstNull(get_llvm_type(g, ptr_to_stack_trace_type(g)));
47494694 }
47504695 return cur_err_ret_trace_val;
47514696}
......@@ -5505,60 +5450,6 @@ static LLVMValueRef ir_render_suspend_finish(CodeGen *g, IrExecutable *executabl
55055450 return nullptr;
55065451}
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
55625453static LLVMValueRef ir_render_await(CodeGen *g, IrExecutable *executable, IrInstructionAwaitGen *instruction) {
55635454 LLVMTypeRef usize_type_ref = g->builtin_types.entry_usize->llvm_type;
55645455 LLVMValueRef zero = LLVMConstNull(usize_type_ref);
......@@ -5568,8 +5459,9 @@ static LLVMValueRef ir_render_await(CodeGen *g, IrExecutable *executable, IrInst
55685459
55695460 // Prepare to be suspended
55705461 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.
55735465 // This code is as if it is running inside the suspend block.
55745466
55755467 // supply the awaiter return pointer
......@@ -5591,15 +5483,15 @@ static LLVMValueRef ir_render_await(CodeGen *g, IrExecutable *executable, IrInst
55915483 LLVMValueRef my_err_ret_trace_val = get_cur_err_ret_trace_val(g, instruction->base.scope);
55925484 assert(my_err_ret_trace_val != nullptr);
55935485 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, "");
55955487 LLVMBuildStore(g->builder, my_err_ret_trace_val, err_ret_trace_ptr_ptr);
55965488 }
55975489
55985490 // caller's own frame pointer
55995491 LLVMValueRef awaiter_init_val = LLVMBuildPtrToInt(g->builder, g->cur_frame_ptr, usize_type_ref, "");
56005492 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,
5602 LLVMAtomicOrderingRelease, g->is_single_threaded);
5493 LLVMValueRef prev_val = gen_maybe_atomic_op(g, LLVMAtomicRMWBinOpXchg, awaiter_ptr, awaiter_init_val,
5494 LLVMAtomicOrderingRelease);
56035495
56045496 LLVMBasicBlockRef bad_await_block = LLVMAppendBasicBlock(g->cur_fn_val, "BadAwait");
56055497 LLVMBasicBlockRef complete_suspend_block = LLVMAppendBasicBlock(g->cur_fn_val, "CompleteSuspend");
......@@ -5615,20 +5507,42 @@ static LLVMValueRef ir_render_await(CodeGen *g, IrExecutable *executable, IrInst
56155507 LLVMPositionBuilderAtEnd(g->builder, bad_await_block);
56165508 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
56265510 // Rely on the target to resume us from suspension.
56275511 LLVMPositionBuilderAtEnd(g->builder, complete_suspend_block);
56285512 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
56305541 LLVMPositionBuilderAtEnd(g->builder, resume_bb);
56315542 gen_assert_resume_id(g, &instruction->base, ResumeIdReturn, PanicMsgIdResumedAnAwaitingFn, nullptr);
5543 LLVMBuildBr(g->builder, end_bb);
5544
5545 LLVMPositionBuilderAtEnd(g->builder, end_bb);
56325546 if (type_has_bits(result_type) && result_loc != nullptr) {
56335547 return get_handle_value(g, result_loc, result_type, ptr_result_type);
56345548 }
......@@ -5640,7 +5554,7 @@ static LLVMValueRef ir_render_resume(CodeGen *g, IrExecutable *executable, IrIns
56405554 ZigType *frame_type = instruction->frame->value.type;
56415555 assert(frame_type->id == ZigTypeIdAnyFrame);
56425556
5643 gen_resume(g, nullptr, frame, ResumeIdManual, nullptr);
5557 gen_resume(g, nullptr, frame, ResumeIdManual);
56445558 return nullptr;
56455559}
56465560
......@@ -5651,18 +5565,6 @@ static LLVMValueRef ir_render_frame_size(CodeGen *g, IrExecutable *executable,
56515565 return gen_frame_size(g, fn_val);
56525566}
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
56665568static LLVMValueRef ir_render_spill_begin(CodeGen *g, IrExecutable *executable,
56675569 IrInstructionSpillBegin *instruction)
56685570{
......@@ -5798,8 +5700,6 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
57985700
57995701 case IrInstructionIdDeclVarGen:
58005702 return ir_render_decl_var(g, executable, (IrInstructionDeclVarGen *)instruction);
5801 case IrInstructionIdReturnBegin:
5802 return ir_render_return_begin(g, executable, (IrInstructionReturnBegin *)instruction);
58035703 case IrInstructionIdReturn:
58045704 return ir_render_return(g, executable, (IrInstructionReturn *)instruction);
58055705 case IrInstructionIdBinOp:
......@@ -5918,8 +5818,6 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
59185818 return ir_render_align_cast(g, executable, (IrInstructionAlignCast *)instruction);
59195819 case IrInstructionIdErrorReturnTrace:
59205820 return ir_render_error_return_trace(g, executable, (IrInstructionErrorReturnTrace *)instruction);
5921 case IrInstructionIdCancel:
5922 return ir_render_cancel(g, executable, (IrInstructionCancel *)instruction);
59235821 case IrInstructionIdAtomicRmw:
59245822 return ir_render_atomic_rmw(g, executable, (IrInstructionAtomicRmw *)instruction);
59255823 case IrInstructionIdAtomicLoad:
......@@ -5952,8 +5850,6 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
59525850 return ir_render_frame_size(g, executable, (IrInstructionFrameSizeGen *)instruction);
59535851 case IrInstructionIdAwaitGen:
59545852 return ir_render_await(g, executable, (IrInstructionAwaitGen *)instruction);
5955 case IrInstructionIdTestCancelRequested:
5956 return ir_render_test_cancel_requested(g, executable, (IrInstructionTestCancelRequested *)instruction);
59575853 case IrInstructionIdSpillBegin:
59585854 return ir_render_spill_begin(g, executable, (IrInstructionSpillBegin *)instruction);
59595855 case IrInstructionIdSpillEnd:
......@@ -7060,9 +6956,9 @@ static void do_code_gen(CodeGen *g) {
70606956 ZigType *array_type = get_array_type(g, g->builtin_types.entry_usize, stack_trace_ptr_count);
70616957 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_type
7064 (void)get_ptr_to_stack_trace_type(g);
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));
6959 (void)get_llvm_type(g, get_stack_trace_type(g));
6960 g->cur_err_ret_trace_val_stack = build_alloca(g, get_stack_trace_type(g), "error_return_trace",
6961 get_abi_alignment(g, g->stack_trace_type));
70666962 } else {
70676963 g->cur_err_ret_trace_val_stack = nullptr;
70686964 }
......@@ -7204,18 +7100,12 @@ static void do_code_gen(CodeGen *g) {
72047100 LLVMValueRef cur_ret_ptr_ptr = LLVMBuildStructGEP(g->builder, g->cur_frame_ptr, frame_ret_start, "");
72057101 g->cur_ret_ptr = LLVMBuildLoad(g->builder, cur_ret_ptr_ptr, "");
72067102 }
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 }
72117103 uint32_t trace_field_index_stack = UINT32_MAX;
72127104 if (codegen_fn_has_err_ret_tracing_stack(g, fn_table_entry, true)) {
72137105 trace_field_index_stack = frame_index_trace_stack(g, fn_type_id);
72147106 g->cur_err_ret_trace_val_stack = LLVMBuildStructGEP(g->builder, g->cur_frame_ptr,
72157107 trace_field_index_stack, "");
72167108 }
7217 g->cur_async_prev_val_field_ptr = LLVMBuildStructGEP(g->builder, g->cur_frame_ptr,
7218 frame_prev_val_index, "");
72197109
72207110 LLVMValueRef resume_index = LLVMBuildLoad(g->builder, resume_index_ptr, "");
72217111 LLVMValueRef switch_instr = LLVMBuildSwitch(g->builder, resume_index, bad_resume_block, 4);
......@@ -7227,6 +7117,13 @@ static void do_code_gen(CodeGen *g) {
72277117 g->cur_resume_block_count += 1;
72287118 LLVMPositionBuilderAtEnd(g->builder, entry_block->llvm_block);
72297119 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
72307127 LLVMValueRef trace_field_ptr = LLVMBuildStructGEP(g->builder, g->cur_frame_ptr,
72317128 trace_field_index_stack, "");
72327129 LLVMValueRef trace_field_addrs = LLVMBuildStructGEP(g->builder, g->cur_frame_ptr,
......@@ -7273,8 +7170,6 @@ static void do_code_gen(CodeGen *g) {
72737170 LLVMDumpModule(g->module);
72747171 }
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.
72787173#ifndef NDEBUG
72797174 char *error = nullptr;
72807175 LLVMVerifyModule(g->module, LLVMAbortProcessAction, &error);
......@@ -10157,6 +10052,11 @@ bool codegen_fn_has_err_ret_tracing_arg(CodeGen *g, ZigType *return_type) {
1015710052}
1015810053
1015910054bool 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 &&
10161 (is_async || !codegen_fn_has_err_ret_tracing_arg(g, fn->type_entry->data.fn.fn_type_id.return_type));
10055 if (is_async) {
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 }
1016210062}
src/ir.cpp+29-201
......@@ -526,10 +526,6 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionReturn *) {
526526 return IrInstructionIdReturn;
527527}
528528
529static constexpr IrInstructionId ir_instruction_id(IrInstructionReturnBegin *) {
530 return IrInstructionIdReturnBegin;
531}
532
533529static constexpr IrInstructionId ir_instruction_id(IrInstructionCast *) {
534530 return IrInstructionIdCast;
535531}
......@@ -974,10 +970,6 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionErrorUnion *) {
974970 return IrInstructionIdErrorUnion;
975971}
976972
977static constexpr IrInstructionId ir_instruction_id(IrInstructionCancel *) {
978 return IrInstructionIdCancel;
979}
980
981973static constexpr IrInstructionId ir_instruction_id(IrInstructionAtomicRmw *) {
982974 return IrInstructionIdAtomicRmw;
983975}
......@@ -1062,10 +1054,6 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionResume *) {
10621054 return IrInstructionIdResume;
10631055}
10641056
1065static constexpr IrInstructionId ir_instruction_id(IrInstructionTestCancelRequested *) {
1066 return IrInstructionIdTestCancelRequested;
1067}
1068
10691057static constexpr IrInstructionId ir_instruction_id(IrInstructionSpillBegin *) {
10701058 return IrInstructionIdSpillBegin;
10711059}
......@@ -1138,18 +1126,6 @@ static IrInstruction *ir_build_return(IrBuilder *irb, Scope *scope, AstNode *sou
11381126 return &return_instruction->base;
11391127}
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
11531129static IrInstruction *ir_build_const_void(IrBuilder *irb, Scope *scope, AstNode *source_node) {
11541130 IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irb, scope, source_node);
11551131 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
32843260 return &instruction->base;
32853261}
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
32973263static IrInstruction *ir_build_await_src(IrBuilder *irb, Scope *scope, AstNode *source_node,
32983264 IrInstruction *frame, ResultLoc *result_loc)
32993265{
......@@ -3331,13 +3297,6 @@ static IrInstruction *ir_build_resume(IrBuilder *irb, Scope *scope, AstNode *sou
33313297 return &instruction->base;
33323298}
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
33413300static IrInstructionSpillBegin *ir_build_spill_begin(IrBuilder *irb, Scope *scope, AstNode *source_node,
33423301 IrInstruction *operand, SpillId spill_id)
33433302{
......@@ -3532,7 +3491,6 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node,
35323491 }
35333492
35343493 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
35373495 size_t defer_counts[2];
35383496 ir_count_defers(irb, scope, outer_scope, defer_counts);
......@@ -3545,49 +3503,40 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node,
35453503 return result;
35463504 }
35473505 bool should_inline = ir_should_inline(irb->exec, scope);
3548 bool need_test_cancel = !should_inline && have_err_defers;
35493506
35503507 IrBasicBlock *err_block = ir_create_basic_block(irb, scope, "ErrRetErr");
3551 IrBasicBlock *normal_defers_block = ir_create_basic_block(irb, scope, "Defers");
3552 IrBasicBlock *ok_block = need_test_cancel ?
3553 ir_create_basic_block(irb, scope, "ErrRetOk") : normal_defers_block;
3554 IrBasicBlock *all_defers_block = have_err_defers ? ir_create_basic_block(irb, scope, "ErrDefers") : normal_defers_block;
3508 IrBasicBlock *ok_block = ir_create_basic_block(irb, scope, "ErrRetOk");
3509
3510 if (!have_err_defers) {
3511 ir_gen_defers_for_block(irb, scope, outer_scope, false);
3512 }
35553513
35563514 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);
3559 IrInstruction *err_is_comptime;
3516 IrInstruction *is_comptime;
35603517 if (should_inline) {
3561 err_is_comptime = force_comptime;
3518 is_comptime = ir_build_const_bool(irb, scope, node, should_inline);
35623519 } 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);
35643521 }
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));
35673524 IrBasicBlock *ret_stmt_block = ir_create_basic_block(irb, scope, "RetStmt");
35683525
35693526 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 }
35703530 if (irb->codegen->have_err_ret_tracing && !should_inline) {
35713531 ir_build_save_err_ret_addr(irb, scope, node);
35723532 }
3573 ir_build_br(irb, scope, node, all_defers_block, err_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 }
3533 ir_build_br(irb, scope, node, ret_stmt_block, is_comptime);
35813534
3582 if (all_defers_block != normal_defers_block) {
3583 ir_set_cursor_at_end_and_append_block(irb, all_defers_block);
3584 ir_gen_defers_for_block(irb, scope, outer_scope, true);
3585 ir_build_br(irb, scope, node, ret_stmt_block, force_comptime);
3535 ir_set_cursor_at_end_and_append_block(irb, ok_block);
3536 if (have_err_defers) {
3537 ir_gen_defers_for_block(irb, scope, outer_scope, false);
35863538 }
3587
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);
3539 ir_build_br(irb, scope, node, ret_stmt_block, is_comptime);
35913540
35923541 ir_set_cursor_at_end_and_append_block(irb, ret_stmt_block);
35933542 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,
36193568 ir_mark_gen(ir_build_add_implicit_return_type(irb, scope, node, err_val));
36203569 IrInstructionSpillBegin *spill_begin = ir_build_spill_begin(irb, scope, node, err_val,
36213570 SpillIdRetErrCode);
3622 ir_build_return_begin(irb, scope, node, err_val);
3623 err_val = ir_build_spill_end(irb, scope, node, spill_begin);
36243571 ResultLocReturn *result_loc_ret = allocate<ResultLocReturn>(1);
36253572 result_loc_ret->base.id = ResultLocIdReturn;
36263573 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,
36293576 if (irb->codegen->have_err_ret_tracing && !should_inline) {
36303577 ir_build_save_err_ret_addr(irb, scope, node);
36313578 }
3579 err_val = ir_build_spill_end(irb, scope, node, spill_begin);
36323580 IrInstruction *ret_inst = ir_build_return(irb, scope, node, err_val);
36333581 result_loc_ret->base.source_instruction = ret_inst;
36343582 }
......@@ -3847,38 +3795,10 @@ static IrInstruction *ir_gen_block(IrBuilder *irb, Scope *parent_scope, AstNode
38473795 return result;
38483796
38493797 // 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 errdefers
3798 // only generate unconditional defers
38513799
38523800 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);
38783801 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);
38823802 return ir_mark_gen(ir_build_return(irb, child_scope, result->source_node, result));
38833803}
38843804
......@@ -7930,31 +7850,6 @@ static IrInstruction *ir_gen_fn_proto(IrBuilder *irb, Scope *parent_scope, AstNo
79307850 return ir_build_fn_proto(irb, parent_scope, node, param_types, align_value, return_type, is_var_args);
79317851}
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
79587853static IrInstruction *ir_gen_resume(IrBuilder *irb, Scope *scope, AstNode *node) {
79597854 assert(node->type == NodeTypeResume);
79607855
......@@ -8149,8 +8044,6 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop
81498044 return ir_lval_wrap(irb, scope, ir_gen_fn_proto(irb, scope, node), lval, result_loc);
81508045 case NodeTypeErrorSetDecl:
81518046 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);
81548047 case NodeTypeResume:
81558048 return ir_lval_wrap(irb, scope, ir_gen_resume(irb, scope, node), lval, result_loc);
81568049 case NodeTypeAwaitExpr:
......@@ -8228,7 +8121,6 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec
82288121
82298122 if (!instr_is_unreachable(result)) {
82308123 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));
82328124 // no need for save_err_ret_addr because this cannot return error
82338125 ir_mark_gen(ir_build_return(irb, scope, result->source_node, result));
82348126 }
......@@ -8340,7 +8232,6 @@ static ConstExprValue *ir_exec_const_result(CodeGen *codegen, IrExecutable *exec
83408232 switch (instruction->id) {
83418233 case IrInstructionIdUnwrapErrPayload:
83428234 case IrInstructionIdUnionFieldPtr:
8343 case IrInstructionIdReturnBegin:
83448235 continue;
83458236 default:
83468237 break;
......@@ -12745,17 +12636,17 @@ static IrInstruction *ir_analyze_instruction_add_implicit_return_type(IrAnalyze
1274512636 return ir_const_void(ira, &instruction->base);
1274612637}
1274712638
12748static IrInstruction *ir_analyze_instruction_return_begin(IrAnalyze *ira, IrInstructionReturnBegin *instruction) {
12639static IrInstruction *ir_analyze_instruction_return(IrAnalyze *ira, IrInstructionReturn *instruction) {
1274912640 IrInstruction *operand = instruction->operand->child;
1275012641 if (type_is_invalid(operand->value.type))
12751 return ira->codegen->invalid_instruction;
12642 return ir_unreach_error(ira);
1275212643
1275312644 if (!instr_is_comptime(operand) && handle_is_ptr(ira->explicit_return_type)) {
1275412645 // result location mechanism took care of it.
12755 IrInstruction *result = ir_build_return_begin(&ira->new_irb, instruction->base.scope,
12756 instruction->base.source_node, operand);
12757 copy_const_val(&result->value, &operand->value, true);
12758 return result;
12646 IrInstruction *result = ir_build_return(&ira->new_irb, instruction->base.scope,
12647 instruction->base.source_node, nullptr);
12648 result->value.type = ira->codegen->builtin_types.entry_unreachable;
12649 return ir_finish_anal(ira, result);
1275912650 }
1276012651
1276112652 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
1277712668 return ir_unreach_error(ira);
1277812669 }
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
1281212671 IrInstruction *result = ir_build_return(&ira->new_irb, instruction->base.scope,
1281312672 instruction->base.source_node, casted_operand);
1281412673 result->value.type = ira->codegen->builtin_types.entry_unreachable;
......@@ -14540,8 +14399,8 @@ static bool exec_has_err_ret_trace(CodeGen *g, IrExecutable *exec) {
1454014399static IrInstruction *ir_analyze_instruction_error_return_trace(IrAnalyze *ira,
1454114400 IrInstructionErrorReturnTrace *instruction)
1454214401{
14402 ZigType *ptr_to_stack_trace_type = get_pointer_to_type(ira->codegen, get_stack_trace_type(ira->codegen), false);
1454314403 if (instruction->optional == IrInstructionErrorReturnTrace::Null) {
14544 ZigType *ptr_to_stack_trace_type = get_ptr_to_stack_trace_type(ira->codegen);
1454514404 ZigType *optional_type = get_optional_type(ira->codegen, ptr_to_stack_trace_type);
1454614405 if (!exec_has_err_ret_trace(ira->codegen, ira->new_irb.exec)) {
1454714406 IrInstruction *result = ir_const(ira, &instruction->base, optional_type);
......@@ -14559,7 +14418,7 @@ static IrInstruction *ir_analyze_instruction_error_return_trace(IrAnalyze *ira,
1455914418 assert(ira->codegen->have_err_ret_tracing);
1456014419 IrInstruction *new_instruction = ir_build_error_return_trace(&ira->new_irb, instruction->base.scope,
1456114420 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;
1456314422 return new_instruction;
1456414423 }
1456514424}
......@@ -15800,6 +15659,7 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c
1580015659
1580115660 if (impl_fn_type_id->cc == CallingConventionAsync && parent_fn_entry->inferred_async_node == nullptr) {
1580215661 parent_fn_entry->inferred_async_node = fn_ref->source_node;
15662 parent_fn_entry->inferred_async_fn = impl_fn;
1580315663 }
1580415664
1580515665 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
1592315783
1592415784 if (fn_type_id->cc == CallingConventionAsync && parent_fn_entry->inferred_async_node == nullptr) {
1592515785 parent_fn_entry->inferred_async_node = fn_ref->source_node;
15786 parent_fn_entry->inferred_async_fn = fn_entry;
1592615787 }
1592715788
1592815789 IrInstruction *result_loc;
......@@ -24702,21 +24563,6 @@ static IrInstruction *analyze_frame_ptr_to_anyframe_T(IrAnalyze *ira, IrInstruct
2470224563 return casted_frame;
2470324564}
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
2472024566static IrInstruction *ir_analyze_instruction_await(IrAnalyze *ira, IrInstructionAwaitSrc *instruction) {
2472124567 IrInstruction *frame = analyze_frame_ptr_to_anyframe_T(ira, &instruction->base, instruction->frame->child);
2472224568 if (type_is_invalid(frame->value.type))
......@@ -24772,15 +24618,6 @@ static IrInstruction *ir_analyze_instruction_resume(IrAnalyze *ira, IrInstructio
2477224618 return ir_build_resume(&ira->new_irb, instruction->base.scope, instruction->base.source_node, casted_frame);
2477324619}
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
2478424621static IrInstruction *ir_analyze_instruction_spill_begin(IrAnalyze *ira, IrInstructionSpillBegin *instruction) {
2478524622 if (ir_should_inline(ira->new_irb.exec, instruction->base.scope))
2478624623 return ir_const_void(ira, &instruction->base);
......@@ -24848,8 +24685,6 @@ static IrInstruction *ir_analyze_instruction_base(IrAnalyze *ira, IrInstruction
2484824685 case IrInstructionIdAwaitGen:
2484924686 zig_unreachable();
2485024687
24851 case IrInstructionIdReturnBegin:
24852 return ir_analyze_instruction_return_begin(ira, (IrInstructionReturnBegin *)instruction);
2485324688 case IrInstructionIdReturn:
2485424689 return ir_analyze_instruction_return(ira, (IrInstructionReturn *)instruction);
2485524690 case IrInstructionIdConst:
......@@ -25070,8 +24905,6 @@ static IrInstruction *ir_analyze_instruction_base(IrAnalyze *ira, IrInstruction
2507024905 return ir_analyze_instruction_error_return_trace(ira, (IrInstructionErrorReturnTrace *)instruction);
2507124906 case IrInstructionIdErrorUnion:
2507224907 return ir_analyze_instruction_error_union(ira, (IrInstructionErrorUnion *)instruction);
25073 case IrInstructionIdCancel:
25074 return ir_analyze_instruction_cancel(ira, (IrInstructionCancel *)instruction);
2507524908 case IrInstructionIdAtomicRmw:
2507624909 return ir_analyze_instruction_atomic_rmw(ira, (IrInstructionAtomicRmw *)instruction);
2507724910 case IrInstructionIdAtomicLoad:
......@@ -25114,8 +24947,6 @@ static IrInstruction *ir_analyze_instruction_base(IrAnalyze *ira, IrInstruction
2511424947 return ir_analyze_instruction_resume(ira, (IrInstructionResume *)instruction);
2511524948 case IrInstructionIdAwaitSrc:
2511624949 return ir_analyze_instruction_await(ira, (IrInstructionAwaitSrc *)instruction);
25117 case IrInstructionIdTestCancelRequested:
25118 return ir_analyze_instruction_test_cancel_requested(ira, (IrInstructionTestCancelRequested *)instruction);
2511924950 case IrInstructionIdSpillBegin:
2512024951 return ir_analyze_instruction_spill_begin(ira, (IrInstructionSpillBegin *)instruction);
2512124952 case IrInstructionIdSpillEnd:
......@@ -25209,7 +25040,6 @@ bool ir_has_side_effects(IrInstruction *instruction) {
2520925040 case IrInstructionIdStorePtr:
2521025041 case IrInstructionIdCallSrc:
2521125042 case IrInstructionIdCallGen:
25212 case IrInstructionIdReturnBegin:
2521325043 case IrInstructionIdReturn:
2521425044 case IrInstructionIdUnreachable:
2521525045 case IrInstructionIdSetCold:
......@@ -25235,7 +25065,6 @@ bool ir_has_side_effects(IrInstruction *instruction) {
2523525065 case IrInstructionIdPtrType:
2523625066 case IrInstructionIdSetAlignStack:
2523725067 case IrInstructionIdExport:
25238 case IrInstructionIdCancel:
2523925068 case IrInstructionIdSaveErrRetAddr:
2524025069 case IrInstructionIdAddImplicitReturnType:
2524125070 case IrInstructionIdAtomicRmw:
......@@ -25355,7 +25184,6 @@ bool ir_has_side_effects(IrInstruction *instruction) {
2535525184 case IrInstructionIdHasDecl:
2535625185 case IrInstructionIdAllocaSrc:
2535725186 case IrInstructionIdAllocaGen:
25358 case IrInstructionIdTestCancelRequested:
2535925187 case IrInstructionIdSpillEnd:
2536025188 return false;
2536125189
src/ir_print.cpp-24
......@@ -64,12 +64,6 @@ static void ir_print_other_block(IrPrint *irp, IrBasicBlock *bb) {
6464 }
6565}
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
7367static void ir_print_return(IrPrint *irp, IrInstructionReturn *instruction) {
7468 fprintf(irp->f, "return ");
7569 ir_print_other_instruction(irp, instruction->operand);
......@@ -1394,11 +1388,6 @@ static void ir_print_error_union(IrPrint *irp, IrInstructionErrorUnion *instruct
13941388 ir_print_other_instruction(irp, instruction->payload);
13951389}
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
14021391static void ir_print_atomic_rmw(IrPrint *irp, IrInstructionAtomicRmw *instruction) {
14031392 fprintf(irp->f, "@atomicRmw(");
14041393 if (instruction->operand_type != nullptr) {
......@@ -1549,10 +1538,6 @@ static void ir_print_await_gen(IrPrint *irp, IrInstructionAwaitGen *instruction)
15491538 fprintf(irp->f, ")");
15501539}
15511540
1552static void ir_print_test_cancel_requested(IrPrint *irp, IrInstructionTestCancelRequested *instruction) {
1553 fprintf(irp->f, "@testCancelRequested()");
1554}
1555
15561541static void ir_print_spill_begin(IrPrint *irp, IrInstructionSpillBegin *instruction) {
15571542 fprintf(irp->f, "@spillBegin(");
15581543 ir_print_other_instruction(irp, instruction->operand);
......@@ -1570,9 +1555,6 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
15701555 switch (instruction->id) {
15711556 case IrInstructionIdInvalid:
15721557 zig_unreachable();
1573 case IrInstructionIdReturnBegin:
1574 ir_print_return_begin(irp, (IrInstructionReturnBegin *)instruction);
1575 break;
15761558 case IrInstructionIdReturn:
15771559 ir_print_return(irp, (IrInstructionReturn *)instruction);
15781560 break;
......@@ -1966,9 +1948,6 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
19661948 case IrInstructionIdErrorUnion:
19671949 ir_print_error_union(irp, (IrInstructionErrorUnion *)instruction);
19681950 break;
1969 case IrInstructionIdCancel:
1970 ir_print_cancel(irp, (IrInstructionCancel *)instruction);
1971 break;
19721951 case IrInstructionIdAtomicRmw:
19731952 ir_print_atomic_rmw(irp, (IrInstructionAtomicRmw *)instruction);
19741953 break;
......@@ -2047,9 +2026,6 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
20472026 case IrInstructionIdAwaitGen:
20482027 ir_print_await_gen(irp, (IrInstructionAwaitGen *)instruction);
20492028 break;
2050 case IrInstructionIdTestCancelRequested:
2051 ir_print_test_cancel_requested(irp, (IrInstructionTestCancelRequested *)instruction);
2052 break;
20532029 case IrInstructionIdSpillBegin:
20542030 ir_print_spill_begin(irp, (IrInstructionSpillBegin *)instruction);
20552031 break;
src/parser.cpp-12
......@@ -1167,7 +1167,6 @@ static AstNode *ast_parse_prefix_expr(ParseContext *pc) {
11671167// <- AsmExpr
11681168// / IfExpr
11691169// / KEYWORD_break BreakLabel? Expr?
1170// / KEYWORD_cancel Expr
11711170// / KEYWORD_comptime Expr
11721171// / KEYWORD_continue BreakLabel?
11731172// / KEYWORD_resume Expr
......@@ -1195,14 +1194,6 @@ static AstNode *ast_parse_primary_expr(ParseContext *pc) {
11951194 return res;
11961195 }
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
12061197 Token *comptime = eat_token_if(pc, TokenIdKeywordCompTime);
12071198 if (comptime != nullptr) {
12081199 AstNode *expr = ast_expect(pc, ast_parse_expr);
......@@ -3035,9 +3026,6 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont
30353026 case NodeTypeErrorSetDecl:
30363027 visit_node_list(&node->data.err_set_decl.decls, visit, context);
30373028 break;
3038 case NodeTypeCancel:
3039 visit_field(&node->data.cancel_expr.expr, visit, context);
3040 break;
30413029 case NodeTypeResume:
30423030 visit_field(&node->data.resume_expr.expr, visit, context);
30433031 break;
src/tokenizer.cpp-2
......@@ -114,7 +114,6 @@ static const struct ZigKeyword zig_keywords[] = {
114114 {"async", TokenIdKeywordAsync},
115115 {"await", TokenIdKeywordAwait},
116116 {"break", TokenIdKeywordBreak},
117 {"cancel", TokenIdKeywordCancel},
118117 {"catch", TokenIdKeywordCatch},
119118 {"comptime", TokenIdKeywordCompTime},
120119 {"const", TokenIdKeywordConst},
......@@ -1531,7 +1530,6 @@ const char * token_name(TokenId id) {
15311530 case TokenIdKeywordAwait: return "await";
15321531 case TokenIdKeywordResume: return "resume";
15331532 case TokenIdKeywordSuspend: return "suspend";
1534 case TokenIdKeywordCancel: return "cancel";
15351533 case TokenIdKeywordAlign: return "align";
15361534 case TokenIdKeywordAnd: return "and";
15371535 case TokenIdKeywordAnyFrame: return "anyframe";
src/tokenizer.hpp-1
......@@ -58,7 +58,6 @@ enum TokenId {
5858 TokenIdKeywordAsync,
5959 TokenIdKeywordAwait,
6060 TokenIdKeywordBreak,
61 TokenIdKeywordCancel,
6261 TokenIdKeywordCatch,
6362 TokenIdKeywordCompTime,
6463 TokenIdKeywordConst,
std/event/fs.zig+1-1
......@@ -1301,7 +1301,7 @@ async fn testFsWatch(loop: *Loop) !void {
13011301
13021302 const ev = try async watch.channel.get();
13031303 var ev_consumed = false;
1304 defer if (!ev_consumed) cancel ev;
1304 defer if (!ev_consumed) await ev;
13051305
13061306 // overwrite line 2
13071307 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 {
110110 const b_result = await b;
111111 const result = a_result + b_result;
112112
113 cancel c;
113 await c;
114114 testing.expect(result == 12);
115115}
116116
std/event/group.zig+5-15
......@@ -27,17 +27,6 @@ pub fn Group(comptime ReturnType: type) type {
2727 };
2828 }
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
4130 /// Add a frame to the group. Thread-safe.
4231 pub fn add(self: *Self, handle: anyframe->ReturnType) (error{OutOfMemory}!void) {
4332 const node = try self.lock.loop.allocator.create(Stack.Node);
......@@ -64,13 +53,14 @@ pub fn Group(comptime ReturnType: type) type {
6453 const held = self.lock.acquire();
6554 defer held.release();
6655
56 var result: ReturnType = {};
57
6758 while (self.frame_stack.pop()) |node| {
6859 if (Error == void) {
6960 await node.data;
7061 } else {
7162 (await node.data) catch |err| {
72 self.deinit();
73 return err;
63 result = err;
7464 };
7565 }
7666 }
......@@ -81,11 +71,11 @@ pub fn Group(comptime ReturnType: type) type {
8171 await handle;
8272 } else {
8373 (await handle) catch |err| {
84 self.deinit();
85 return err;
74 result = err;
8675 };
8776 }
8877 }
78 return result;
8979 }
9080 };
9181}
std/event/net.zig+2-6
......@@ -54,7 +54,7 @@ pub const Server = struct {
5454 self.listen_address = std.net.Address.initPosix(try os.getsockname(sockfd));
5555
5656 self.accept_frame = async Server.handler(self);
57 errdefer cancel self.accept_frame.?;
57 errdefer await self.accept_frame.?;
5858
5959 self.listen_resume_node.handle = self.accept_frame.?;
6060 try self.loop.linuxAddFd(sockfd, &self.listen_resume_node, os.EPOLLIN | os.EPOLLOUT | os.EPOLLET);
......@@ -71,7 +71,7 @@ pub const Server = struct {
7171 }
7272
7373 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;
7575 if (self.sockfd) |sockfd| os.close(sockfd);
7676 }
7777
......@@ -274,13 +274,9 @@ test "listen on a port, send bytes, receive bytes" {
274274 const self = @fieldParentPtr(Self, "tcp_server", tcp_server);
275275 var socket = _socket; // TODO https://github.com/ziglang/zig/issues/1592
276276 defer socket.close();
277 // TODO guarantee elision of this allocation
278277 const next_handler = errorableHandler(self, _addr, socket) catch |err| {
279278 std.debug.panic("unable to handle connection: {}\n", err);
280279 };
281 suspend {
282 cancel @frame();
283 }
284280 }
285281 async fn errorableHandler(self: *Self, _addr: *const std.net.Address, _socket: File) !void {
286282 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 {
814814/// <- AsmExpr
815815/// / IfExpr
816816/// / KEYWORD_break BreakLabel? Expr?
817/// / KEYWORD_cancel Expr
818817/// / KEYWORD_comptime Expr
819818/// / KEYWORD_continue BreakLabel?
820819/// / KEYWORD_resume Expr
......@@ -839,20 +838,6 @@ fn parsePrimaryExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node
839838 return &node.base;
840839 }
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
856841 if (eatToken(it, .Keyword_comptime)) |token| {
857842 const expr_node = try expectNode(arena, it, tree, parseExpr, AstError{
858843 .ExpectedExpr = AstError.ExpectedExpr{ .token = it.index },
std/zig/parser_test.zig+2-2
......@@ -2115,10 +2115,10 @@ test "zig fmt: async functions" {
21152115 \\ await p;
21162116 \\}
21172117 \\
2118 \\test "suspend, resume, cancel" {
2118 \\test "suspend, resume, await" {
21192119 \\ const p: anyframe = async testAsyncSeq();
21202120 \\ resume p;
2121 \\ cancel p;
2121 \\ await p;
21222122 \\}
21232123 \\
21242124 );
std/zig/tokenizer.zig-2
......@@ -21,7 +21,6 @@ pub const Token = struct {
2121 Keyword{ .bytes = "await", .id = Id.Keyword_await },
2222 Keyword{ .bytes = "break", .id = Id.Keyword_break },
2323 Keyword{ .bytes = "catch", .id = Id.Keyword_catch },
24 Keyword{ .bytes = "cancel", .id = Id.Keyword_cancel },
2524 Keyword{ .bytes = "comptime", .id = Id.Keyword_comptime },
2625 Keyword{ .bytes = "const", .id = Id.Keyword_const },
2726 Keyword{ .bytes = "continue", .id = Id.Keyword_continue },
......@@ -151,7 +150,6 @@ pub const Token = struct {
151150 Keyword_async,
152151 Keyword_await,
153152 Keyword_break,
154 Keyword_cancel,
155153 Keyword_catch,
156154 Keyword_comptime,
157155 Keyword_const,
test/compile_errors.zig+5-3
......@@ -61,13 +61,15 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
6161 cases.add(
6262 "runtime-known async function called",
6363 \\export fn entry() void {
64 \\ _ = async amain();
65 \\}
66 \\fn amain() void {
6467 \\ var ptr = afunc;
6568 \\ _ = ptr();
6669 \\}
67 \\
6870 \\async fn afunc() void {}
6971 ,
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",
7173 );
7274
7375 cases.add(
......@@ -3388,7 +3390,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
33883390 \\
33893391 \\export fn entry() usize { return @sizeOf(@typeOf(Foo)); }
33903392 ,
3391 "tmp.zig:5:18: error: unable to evaluate constant expression",
3393 "tmp.zig:5:25: error: unable to evaluate constant expression",
33923394 "tmp.zig:2:12: note: called from here",
33933395 "tmp.zig:2:8: note: called from here",
33943396 );
test/stage1/behavior.zig-1
......@@ -41,7 +41,6 @@ comptime {
4141 _ = @import("behavior/bugs/920.zig");
4242 _ = @import("behavior/byteswap.zig");
4343 _ = @import("behavior/byval_arg_var.zig");
44 _ = @import("behavior/cancel.zig");
4544 _ = @import("behavior/cast.zig");
4645 _ = @import("behavior/const_slice_child.zig");
4746 _ = @import("behavior/defer.zig");
test/stage1/behavior/async_fn.zig+14-76
......@@ -150,7 +150,7 @@ test "coroutine suspend, resume" {
150150 seq('a');
151151 var f = async testAsyncSeq();
152152 seq('c');
153 cancel f;
153 await f;
154154 seq('g');
155155 }
156156
......@@ -271,7 +271,6 @@ test "async function with dot syntax" {
271271 }
272272 };
273273 const p = async S.foo();
274 // can't cancel in tests because they are non-async functions
275274 expect(S.y == 2);
276275}
277276
......@@ -286,7 +285,7 @@ test "async fn pointer in a struct field" {
286285 comptime expect(@typeOf(f) == anyframe->void);
287286 expect(data == 2);
288287 resume f;
289 expect(data == 2);
288 expect(data == 4);
290289 _ = async doTheAwait(f);
291290 expect(data == 4);
292291}
......@@ -394,7 +393,6 @@ async fn printTrace(p: anyframe->(anyerror!void)) void {
394393test "break from suspend" {
395394 var my_result: i32 = 1;
396395 const p = async testBreakFromSuspend(&my_result);
397 // can't cancel here
398396 std.testing.expect(my_result == 2);
399397}
400398async fn testBreakFromSuspend(my_result: *i32) void {
......@@ -530,45 +528,6 @@ test "call async function which has struct return type" {
530528 S.doTheTest();
531529}
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
572531test "pass string literal to async function" {
573532 const S = struct {
574533 var frame: anyframe = undefined;
......@@ -590,7 +549,7 @@ test "pass string literal to async function" {
590549 S.doTheTest();
591550}
592551
593test "cancel inside an errdefer" {
552test "await inside an errdefer" {
594553 const S = struct {
595554 var frame: anyframe = undefined;
596555
......@@ -601,7 +560,7 @@ test "cancel inside an errdefer" {
601560
602561 fn amainWrap() !void {
603562 var foo = async func();
604 errdefer cancel foo;
563 errdefer await foo;
605564 return error.Bad;
606565 }
607566
......@@ -614,35 +573,6 @@ test "cancel inside an errdefer" {
614573 S.doTheTest();
615574}
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
646576test "try in an async function with error union and non-zero-bit payload" {
647577 const S = struct {
648578 var frame: anyframe = undefined;
......@@ -730,14 +660,22 @@ fn testAsyncAwaitTypicalUsage(comptime simulate_fail_download: bool, comptime si
730660 fn amain() !void {
731661 const allocator = std.heap.direct_allocator; // TODO once we have the debug allocator, use that, so that this can detect leaks
732662 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
735668 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;
738675 const download_text = try await download_frame;
739676 defer allocator.free(download_text);
740677
678 file_awaited = true;
741679 const file_text = try await file_frame;
742680 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}