| author | |
| committer | |
| log | 7f7d1fbe5ad16fd41eeaeb20e3e71a39bdd3f991 |
| tree | 1c726145e8b301beb25ab781ab9e06d27c146797 |
| parent | cb3a818699649a985d5879151936b3b88ffddfa4 |
| signature | Commit is signed but in an unrecognized format. |
Note that there is not yet runtime safety for this.
See #31576 files changed, 28 insertions(+), 10 deletions(-)
src/all_types.hpp+3| ... | ... | @@ -1139,6 +1139,7 @@ struct AstNodeErrorType { |
| 1139 | 1139 | }; |
| 1140 | 1140 | |
| 1141 | 1141 | struct AstNodeAwaitExpr { |
| 1142 | Token *noasync_token; | |
| 1142 | 1143 | AstNode *expr; |
| 1143 | 1144 | }; |
| 1144 | 1145 | |
| ... | ... | @@ -4500,6 +4501,7 @@ struct IrInstSrcAwait { |
| 4500 | 4501 | |
| 4501 | 4502 | IrInstSrc *frame; |
| 4502 | 4503 | ResultLoc *result_loc; |
| 4504 | bool is_noasync; | |
| 4503 | 4505 | }; |
| 4504 | 4506 | |
| 4505 | 4507 | struct IrInstGenAwait { |
| ... | ... | @@ -4508,6 +4510,7 @@ struct IrInstGenAwait { |
| 4508 | 4510 | IrInstGen *frame; |
| 4509 | 4511 | IrInstGen *result_loc; |
| 4510 | 4512 | ZigFn *target_fn; |
| 4513 | bool is_noasync; | |
| 4511 | 4514 | }; |
| 4512 | 4515 | |
| 4513 | 4516 | struct IrInstSrcResume { |
src/analyze.cpp+4-4| ... | ... | @@ -4710,8 +4710,7 @@ static void analyze_fn_async(CodeGen *g, ZigFn *fn, bool resolve_frame) { |
| 4710 | 4710 | } |
| 4711 | 4711 | for (size_t i = 0; i < fn->await_list.length; i += 1) { |
| 4712 | 4712 | IrInstGenAwait *await = fn->await_list.at(i); |
| 4713 | // TODO If this is a noasync await, it doesn't count | |
| 4714 | // https://github.com/ziglang/zig/issues/3157 | |
| 4713 | if (await->is_noasync) continue; | |
| 4715 | 4714 | switch (analyze_callee_async(g, fn, await->target_fn, await->base.base.source_node, must_not_be_async, |
| 4716 | 4715 | CallModifierNone)) |
| 4717 | 4716 | { |
| ... | ... | @@ -6315,8 +6314,9 @@ static Error resolve_async_frame(CodeGen *g, ZigType *frame_type) { |
| 6315 | 6314 | // The funtion call result of foo() must be spilled. |
| 6316 | 6315 | for (size_t i = 0; i < fn->await_list.length; i += 1) { |
| 6317 | 6316 | IrInstGenAwait *await = fn->await_list.at(i); |
| 6318 | // TODO If this is a noasync await, it doesn't suspend | |
| 6319 | // https://github.com/ziglang/zig/issues/3157 | |
| 6317 | if (await->is_noasync) { | |
| 6318 | continue; | |
| 6319 | } | |
| 6320 | 6320 | if (await->base.value->special != ConstValSpecialRuntime) { |
| 6321 | 6321 | // Known at comptime. No spill, no suspend. |
| 6322 | 6322 | continue; |
src/codegen.cpp+3-1| ... | ... | @@ -6188,7 +6188,9 @@ static LLVMValueRef ir_render_await(CodeGen *g, IrExecutableGen *executable, IrI |
| 6188 | 6188 | LLVMValueRef result_loc = (instruction->result_loc == nullptr) ? |
| 6189 | 6189 | nullptr : ir_llvm_value(g, instruction->result_loc); |
| 6190 | 6190 | |
| 6191 | if (instruction->target_fn != nullptr && !fn_is_async(instruction->target_fn)) { | |
| 6191 | if (instruction->is_noasync || | |
| 6192 | (instruction->target_fn != nullptr && !fn_is_async(instruction->target_fn))) | |
| 6193 | { | |
| 6192 | 6194 | return gen_await_early_return(g, &instruction->base, target_frame_ptr, result_type, |
| 6193 | 6195 | ptr_result_type, result_loc, true); |
| 6194 | 6196 | } |
src/ir.cpp+10-5| ... | ... | @@ -4956,11 +4956,12 @@ static IrInstGen *ir_build_suspend_finish_gen(IrAnalyze *ira, IrInst *source_ins |
| 4956 | 4956 | } |
| 4957 | 4957 | |
| 4958 | 4958 | static IrInstSrc *ir_build_await_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, |
| 4959 | IrInstSrc *frame, ResultLoc *result_loc) | |
| 4959 | IrInstSrc *frame, ResultLoc *result_loc, bool is_noasync) | |
| 4960 | 4960 | { |
| 4961 | 4961 | IrInstSrcAwait *instruction = ir_build_instruction<IrInstSrcAwait>(irb, scope, source_node); |
| 4962 | 4962 | instruction->frame = frame; |
| 4963 | 4963 | instruction->result_loc = result_loc; |
| 4964 | instruction->is_noasync = is_noasync; | |
| 4964 | 4965 | |
| 4965 | 4966 | ir_ref_instruction(frame, irb->current_basic_block); |
| 4966 | 4967 | |
| ... | ... | @@ -4968,13 +4969,14 @@ static IrInstSrc *ir_build_await_src(IrBuilderSrc *irb, Scope *scope, AstNode *s |
| 4968 | 4969 | } |
| 4969 | 4970 | |
| 4970 | 4971 | static IrInstGenAwait *ir_build_await_gen(IrAnalyze *ira, IrInst *source_instruction, |
| 4971 | IrInstGen *frame, ZigType *result_type, IrInstGen *result_loc) | |
| 4972 | IrInstGen *frame, ZigType *result_type, IrInstGen *result_loc, bool is_noasync) | |
| 4972 | 4973 | { |
| 4973 | 4974 | IrInstGenAwait *instruction = ir_build_inst_gen<IrInstGenAwait>(&ira->new_irb, |
| 4974 | 4975 | source_instruction->scope, source_instruction->source_node); |
| 4975 | 4976 | instruction->base.value->type = result_type; |
| 4976 | 4977 | instruction->frame = frame; |
| 4977 | 4978 | instruction->result_loc = result_loc; |
| 4979 | instruction->is_noasync = is_noasync; | |
| 4978 | 4980 | |
| 4979 | 4981 | ir_ref_inst_gen(frame, ira->new_irb.current_basic_block); |
| 4980 | 4982 | if (result_loc != nullptr) ir_ref_inst_gen(result_loc, ira->new_irb.current_basic_block); |
| ... | ... | @@ -9953,6 +9955,8 @@ static IrInstSrc *ir_gen_await_expr(IrBuilderSrc *irb, Scope *scope, AstNode *no |
| 9953 | 9955 | { |
| 9954 | 9956 | assert(node->type == NodeTypeAwaitExpr); |
| 9955 | 9957 | |
| 9958 | bool is_noasync = node->data.await_expr.noasync_token != nullptr; | |
| 9959 | ||
| 9956 | 9960 | AstNode *expr_node = node->data.await_expr.expr; |
| 9957 | 9961 | if (expr_node->type == NodeTypeFnCallExpr && expr_node->data.fn_call_expr.modifier == CallModifierBuiltin) { |
| 9958 | 9962 | AstNode *fn_ref_expr = expr_node->data.fn_call_expr.fn_ref_expr; |
| ... | ... | @@ -9985,7 +9989,7 @@ static IrInstSrc *ir_gen_await_expr(IrBuilderSrc *irb, Scope *scope, AstNode *no |
| 9985 | 9989 | if (target_inst == irb->codegen->invalid_inst_src) |
| 9986 | 9990 | return irb->codegen->invalid_inst_src; |
| 9987 | 9991 | |
| 9988 | IrInstSrc *await_inst = ir_build_await_src(irb, scope, node, target_inst, result_loc); | |
| 9992 | IrInstSrc *await_inst = ir_build_await_src(irb, scope, node, target_inst, result_loc, is_noasync); | |
| 9989 | 9993 | return ir_lval_wrap(irb, scope, await_inst, lval, result_loc); |
| 9990 | 9994 | } |
| 9991 | 9995 | |
| ... | ... | @@ -29505,7 +29509,7 @@ static IrInstGen *ir_analyze_instruction_await(IrAnalyze *ira, IrInstSrcAwait *i |
| 29505 | 29509 | ir_assert(fn_entry != nullptr, &instruction->base.base); |
| 29506 | 29510 | |
| 29507 | 29511 | // If it's not @Frame(func) then it's definitely a suspend point |
| 29508 | if (target_fn == nullptr) { | |
| 29512 | if (target_fn == nullptr && !instruction->is_noasync) { | |
| 29509 | 29513 | if (fn_entry->inferred_async_node == nullptr) { |
| 29510 | 29514 | fn_entry->inferred_async_node = instruction->base.base.source_node; |
| 29511 | 29515 | } |
| ... | ... | @@ -29528,7 +29532,8 @@ static IrInstGen *ir_analyze_instruction_await(IrAnalyze *ira, IrInstSrcAwait *i |
| 29528 | 29532 | result_loc = nullptr; |
| 29529 | 29533 | } |
| 29530 | 29534 | |
| 29531 | IrInstGenAwait *result = ir_build_await_gen(ira, &instruction->base.base, frame, result_type, result_loc); | |
| 29535 | IrInstGenAwait *result = ir_build_await_gen(ira, &instruction->base.base, frame, result_type, result_loc, | |
| 29536 | instruction->is_noasync); | |
| 29532 | 29537 | result->target_fn = target_fn; |
| 29533 | 29538 | fn_entry->await_list.append(result); |
| 29534 | 29539 | return ir_finish_anal(ira, &result->base); |
src/parser.cpp+4| ... | ... | @@ -2596,10 +2596,14 @@ static AstNode *ast_parse_prefix_op(ParseContext *pc) { |
| 2596 | 2596 | return res; |
| 2597 | 2597 | } |
| 2598 | 2598 | |
| 2599 | Token *noasync_token = eat_token_if(pc, TokenIdKeywordNoAsync); | |
| 2599 | 2600 | Token *await = eat_token_if(pc, TokenIdKeywordAwait); |
| 2600 | 2601 | if (await != nullptr) { |
| 2601 | 2602 | AstNode *res = ast_create_node(pc, NodeTypeAwaitExpr, await); |
| 2603 | res->data.await_expr.noasync_token = noasync_token; | |
| 2602 | 2604 | return res; |
| 2605 | } else if (noasync_token != nullptr) { | |
| 2606 | put_back_token(pc); | |
| 2603 | 2607 | } |
| 2604 | 2608 | |
| 2605 | 2609 | return nullptr; |
test/stage1/behavior/async_fn.zig+4| ... | ... | @@ -1513,9 +1513,12 @@ test "take address of temporary async frame" { |
| 1513 | 1513 | |
| 1514 | 1514 | test "noasync await" { |
| 1515 | 1515 | const S = struct { |
| 1516 | var finished = false; | |
| 1517 | ||
| 1516 | 1518 | fn doTheTest() void { |
| 1517 | 1519 | var frame = async foo(false); |
| 1518 | 1520 | expect(noasync await frame == 42); |
| 1521 | finished = true; | |
| 1519 | 1522 | } |
| 1520 | 1523 | |
| 1521 | 1524 | fn foo(want_suspend: bool) i32 { |
| ... | ... | @@ -1526,4 +1529,5 @@ test "noasync await" { |
| 1526 | 1529 | } |
| 1527 | 1530 | }; |
| 1528 | 1531 | S.doTheTest(); |
| 1532 | expect(S.finished); | |
| 1529 | 1533 | } |