Skip to content

Commit 7f7d1fb

Browse files
committed
Implement noasync awaits
Note that there is not yet runtime safety for this. See #3157
1 parent cb3a818 commit 7f7d1fb

File tree

6 files changed

+28
-10
lines changed

6 files changed

+28
-10
lines changed

src/all_types.hpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1139,6 +1139,7 @@ struct AstNodeErrorType {
11391139
};
11401140

11411141
struct AstNodeAwaitExpr {
1142+
Token *noasync_token;
11421143
AstNode *expr;
11431144
};
11441145

@@ -4500,6 +4501,7 @@ struct IrInstSrcAwait {
45004501

45014502
IrInstSrc *frame;
45024503
ResultLoc *result_loc;
4504+
bool is_noasync;
45034505
};
45044506

45054507
struct IrInstGenAwait {
@@ -4508,6 +4510,7 @@ struct IrInstGenAwait {
45084510
IrInstGen *frame;
45094511
IrInstGen *result_loc;
45104512
ZigFn *target_fn;
4513+
bool is_noasync;
45114514
};
45124515

45134516
struct IrInstSrcResume {

src/analyze.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4710,8 +4710,7 @@ static void analyze_fn_async(CodeGen *g, ZigFn *fn, bool resolve_frame) {
47104710
}
47114711
for (size_t i = 0; i < fn->await_list.length; i += 1) {
47124712
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;
47154714
switch (analyze_callee_async(g, fn, await->target_fn, await->base.base.source_node, must_not_be_async,
47164715
CallModifierNone))
47174716
{
@@ -6315,8 +6314,9 @@ static Error resolve_async_frame(CodeGen *g, ZigType *frame_type) {
63156314
// The funtion call result of foo() must be spilled.
63166315
for (size_t i = 0; i < fn->await_list.length; i += 1) {
63176316
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+
}
63206320
if (await->base.value->special != ConstValSpecialRuntime) {
63216321
// Known at comptime. No spill, no suspend.
63226322
continue;

src/codegen.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6188,7 +6188,9 @@ static LLVMValueRef ir_render_await(CodeGen *g, IrExecutableGen *executable, IrI
61886188
LLVMValueRef result_loc = (instruction->result_loc == nullptr) ?
61896189
nullptr : ir_llvm_value(g, instruction->result_loc);
61906190

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+
{
61926194
return gen_await_early_return(g, &instruction->base, target_frame_ptr, result_type,
61936195
ptr_result_type, result_loc, true);
61946196
}

src/ir.cpp

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4956,25 +4956,27 @@ static IrInstGen *ir_build_suspend_finish_gen(IrAnalyze *ira, IrInst *source_ins
49564956
}
49574957

49584958
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)
49604960
{
49614961
IrInstSrcAwait *instruction = ir_build_instruction<IrInstSrcAwait>(irb, scope, source_node);
49624962
instruction->frame = frame;
49634963
instruction->result_loc = result_loc;
4964+
instruction->is_noasync = is_noasync;
49644965

49654966
ir_ref_instruction(frame, irb->current_basic_block);
49664967

49674968
return &instruction->base;
49684969
}
49694970

49704971
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)
49724973
{
49734974
IrInstGenAwait *instruction = ir_build_inst_gen<IrInstGenAwait>(&ira->new_irb,
49744975
source_instruction->scope, source_instruction->source_node);
49754976
instruction->base.value->type = result_type;
49764977
instruction->frame = frame;
49774978
instruction->result_loc = result_loc;
4979+
instruction->is_noasync = is_noasync;
49784980

49794981
ir_ref_inst_gen(frame, ira->new_irb.current_basic_block);
49804982
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
99539955
{
99549956
assert(node->type == NodeTypeAwaitExpr);
99559957

9958+
bool is_noasync = node->data.await_expr.noasync_token != nullptr;
9959+
99569960
AstNode *expr_node = node->data.await_expr.expr;
99579961
if (expr_node->type == NodeTypeFnCallExpr && expr_node->data.fn_call_expr.modifier == CallModifierBuiltin) {
99589962
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
99859989
if (target_inst == irb->codegen->invalid_inst_src)
99869990
return irb->codegen->invalid_inst_src;
99879991

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);
99899993
return ir_lval_wrap(irb, scope, await_inst, lval, result_loc);
99909994
}
99919995

@@ -29505,7 +29509,7 @@ static IrInstGen *ir_analyze_instruction_await(IrAnalyze *ira, IrInstSrcAwait *i
2950529509
ir_assert(fn_entry != nullptr, &instruction->base.base);
2950629510

2950729511
// 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) {
2950929513
if (fn_entry->inferred_async_node == nullptr) {
2951029514
fn_entry->inferred_async_node = instruction->base.base.source_node;
2951129515
}
@@ -29528,7 +29532,8 @@ static IrInstGen *ir_analyze_instruction_await(IrAnalyze *ira, IrInstSrcAwait *i
2952829532
result_loc = nullptr;
2952929533
}
2953029534

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);
2953229537
result->target_fn = target_fn;
2953329538
fn_entry->await_list.append(result);
2953429539
return ir_finish_anal(ira, &result->base);

src/parser.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2596,10 +2596,14 @@ static AstNode *ast_parse_prefix_op(ParseContext *pc) {
25962596
return res;
25972597
}
25982598

2599+
Token *noasync_token = eat_token_if(pc, TokenIdKeywordNoAsync);
25992600
Token *await = eat_token_if(pc, TokenIdKeywordAwait);
26002601
if (await != nullptr) {
26012602
AstNode *res = ast_create_node(pc, NodeTypeAwaitExpr, await);
2603+
res->data.await_expr.noasync_token = noasync_token;
26022604
return res;
2605+
} else if (noasync_token != nullptr) {
2606+
put_back_token(pc);
26032607
}
26042608

26052609
return nullptr;

test/stage1/behavior/async_fn.zig

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1513,9 +1513,12 @@ test "take address of temporary async frame" {
15131513

15141514
test "noasync await" {
15151515
const S = struct {
1516+
var finished = false;
1517+
15161518
fn doTheTest() void {
15171519
var frame = async foo(false);
15181520
expect(noasync await frame == 42);
1521+
finished = true;
15191522
}
15201523

15211524
fn foo(want_suspend: bool) i32 {
@@ -1526,4 +1529,5 @@ test "noasync await" {
15261529
}
15271530
};
15281531
S.doTheTest();
1532+
expect(S.finished);
15291533
}

0 commit comments

Comments
 (0)