From 58dc2b719c8e5a13c91ebbbbf476998c7f3e925b Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Wed, 28 Feb 2018 18:22:43 -0500 Subject: [PATCH] better coroutine codegen, now passing first coro test we have to use the Suspend block with llvm.coro.end to return from the coro --- src/ir.cpp | 9 ++------- test/behavior.zig | 3 ++- test/cases/coroutines.zig | 16 ++++++++++++++++ 3 files changed, 20 insertions(+), 8 deletions(-) create mode 100644 test/cases/coroutines.zig diff --git a/src/ir.cpp b/src/ir.cpp index e9f29d1caa..06a23af07c 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -6225,19 +6225,14 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec ir_build_call(irb, scope, node, nullptr, free_fn, arg_count, args, false, FnInlineAuto, false, nullptr); IrBasicBlock *resume_block = ir_create_basic_block(irb, scope, "Resume"); - IrBasicBlock *return_block = ir_create_basic_block(irb, scope, "Return"); - ir_build_cond_br(irb, scope, node, resume_awaiter, resume_block, return_block, const_bool_false); + ir_build_cond_br(irb, scope, node, resume_awaiter, resume_block, irb->exec->coro_suspend_block, const_bool_false); ir_set_cursor_at_end_and_append_block(irb, resume_block); IrInstruction *unwrapped_await_handle_ptr = ir_build_unwrap_maybe(irb, scope, node, irb->exec->coro_awaiter_field_ptr, false); IrInstruction *awaiter_handle = ir_build_load_ptr(irb, scope, node, unwrapped_await_handle_ptr); ir_build_coro_resume(irb, scope, node, awaiter_handle); - ir_build_br(irb, scope, node, return_block, const_bool_false); - - ir_set_cursor_at_end_and_append_block(irb, return_block); - IrInstruction *undef = ir_build_const_undefined(irb, scope, node); - ir_build_return(irb, scope, node, undef); + ir_build_br(irb, scope, node, irb->exec->coro_suspend_block, const_bool_false); } return true; diff --git a/test/behavior.zig b/test/behavior.zig index e718ba6c86..81f2c5dd00 100644 --- a/test/behavior.zig +++ b/test/behavior.zig @@ -11,6 +11,7 @@ comptime { _ = @import("cases/bugs/656.zig"); _ = @import("cases/cast.zig"); _ = @import("cases/const_slice_child.zig"); + _ = @import("cases/coroutines.zig"); _ = @import("cases/defer.zig"); _ = @import("cases/enum.zig"); _ = @import("cases/enum_with_members.zig"); @@ -34,8 +35,8 @@ comptime { _ = @import("cases/sizeof_and_typeof.zig"); _ = @import("cases/slice.zig"); _ = @import("cases/struct.zig"); - _ = @import("cases/struct_contains_slice_of_itself.zig"); _ = @import("cases/struct_contains_null_ptr_itself.zig"); + _ = @import("cases/struct_contains_slice_of_itself.zig"); _ = @import("cases/switch.zig"); _ = @import("cases/switch_prong_err_enum.zig"); _ = @import("cases/switch_prong_implicit_cast.zig"); diff --git a/test/cases/coroutines.zig b/test/cases/coroutines.zig new file mode 100644 index 0000000000..a20a314c8b --- /dev/null +++ b/test/cases/coroutines.zig @@ -0,0 +1,16 @@ +const std = @import("std"); +const assert = std.debug.assert; + +var x: i32 = 1; + +test "create a coroutine and cancel it" { + const p = try (async(std.debug.global_allocator) emptyAsyncFn()); + cancel p; + assert(x == 2); +} + +async fn emptyAsyncFn() void { + x += 1; + suspend; + x += 1; +}