authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-03-01 15:46:35-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-03-01 15:46:35-05:00
log8a0e1d4c02480809fe7ab9ee40ce279ffcb4fd16
tree057dd60209228dee4b821288a41b167702f9bf92
parenta7c87ae1e4b621291a844df678cbe0fbfb531029

await keyword works


3 files changed, 51 insertions(+), 4 deletions(-)

src/all_types.hpp+2-1
...@@ -58,8 +58,9 @@ struct IrExecutable {...@@ -58,8 +58,9 @@ struct IrExecutable {
58 ZigList<Tld *> tld_list;58 ZigList<Tld *> tld_list;
5959
60 IrInstruction *coro_handle;60 IrInstruction *coro_handle;
61 IrInstruction *coro_awaiter_field_ptr;61 IrInstruction *coro_awaiter_field_ptr; // this one is shared and in the promise
62 IrInstruction *coro_result_ptr_field_ptr;62 IrInstruction *coro_result_ptr_field_ptr;
63 IrInstruction *await_handle_var_ptr; // this one is where we put the one we extracted from the promise
63 IrBasicBlock *coro_early_final;64 IrBasicBlock *coro_early_final;
64 IrBasicBlock *coro_normal_final;65 IrBasicBlock *coro_normal_final;
65 IrBasicBlock *coro_suspend_block;66 IrBasicBlock *coro_suspend_block;
src/ir.cpp+10-3
...@@ -2752,6 +2752,7 @@ static IrInstruction *ir_gen_async_return(IrBuilder *irb, Scope *scope, AstNode...@@ -2752,6 +2752,7 @@ static IrInstruction *ir_gen_async_return(IrBuilder *irb, Scope *scope, AstNode
2752 IrInstruction *maybe_await_handle = ir_build_atomic_rmw(irb, scope, node,2752 IrInstruction *maybe_await_handle = ir_build_atomic_rmw(irb, scope, node,
2753 promise_type_val, irb->exec->coro_awaiter_field_ptr, nullptr, replacement_value, nullptr,2753 promise_type_val, irb->exec->coro_awaiter_field_ptr, nullptr, replacement_value, nullptr,
2754 AtomicRmwOp_xchg, AtomicOrderSeqCst);2754 AtomicRmwOp_xchg, AtomicOrderSeqCst);
2755 ir_build_store_ptr(irb, scope, node, irb->exec->await_handle_var_ptr, maybe_await_handle);
2755 IrInstruction *is_non_null = ir_build_test_nonnull(irb, scope, node, maybe_await_handle);2756 IrInstruction *is_non_null = ir_build_test_nonnull(irb, scope, node, maybe_await_handle);
2756 IrInstruction *is_comptime = ir_build_const_bool(irb, scope, node, false);2757 IrInstruction *is_comptime = ir_build_const_bool(irb, scope, node, false);
2757 return ir_build_cond_br(irb, scope, node, is_non_null, irb->exec->coro_normal_final, irb->exec->coro_early_final,2758 return ir_build_cond_br(irb, scope, node, is_non_null, irb->exec->coro_normal_final, irb->exec->coro_early_final,
...@@ -6020,7 +6021,6 @@ static IrInstruction *ir_gen_await_expr(IrBuilder *irb, Scope *parent_scope, Ast...@@ -6020,7 +6021,6 @@ static IrInstruction *ir_gen_await_expr(IrBuilder *irb, Scope *parent_scope, Ast
6020 ir_build_br(irb, parent_scope, node, merge_block, const_bool_false);6021 ir_build_br(irb, parent_scope, node, merge_block, const_bool_false);
60216022
6022 ir_set_cursor_at_end_and_append_block(irb, yes_suspend_block);6023 ir_set_cursor_at_end_and_append_block(irb, yes_suspend_block);
6023 ir_build_coro_resume(irb, parent_scope, node, target_inst);
6024 IrInstruction *suspend_code = ir_build_coro_suspend(irb, parent_scope, node, save_token, const_bool_false);6024 IrInstruction *suspend_code = ir_build_coro_suspend(irb, parent_scope, node, save_token, const_bool_false);
6025 IrBasicBlock *cleanup_block = ir_create_basic_block(irb, parent_scope, "SuspendCleanup");6025 IrBasicBlock *cleanup_block = ir_create_basic_block(irb, parent_scope, "SuspendCleanup");
6026 IrBasicBlock *resume_block = ir_create_basic_block(irb, parent_scope, "SuspendResume");6026 IrBasicBlock *resume_block = ir_create_basic_block(irb, parent_scope, "SuspendResume");
...@@ -6277,13 +6277,20 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec...@@ -6277,13 +6277,20 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec
6277 // create the coro promise6277 // create the coro promise
6278 const_bool_false = ir_build_const_bool(irb, scope, node, false);6278 const_bool_false = ir_build_const_bool(irb, scope, node, false);
6279 VariableTableEntry *promise_var = ir_create_var(irb, node, scope, nullptr, false, false, true, const_bool_false);6279 VariableTableEntry *promise_var = ir_create_var(irb, node, scope, nullptr, false, false, true, const_bool_false);
6280 //scope = promise_var->child_scope;
62816280
6282 return_type = fn_entry->type_entry->data.fn.fn_type_id.return_type;6281 return_type = fn_entry->type_entry->data.fn.fn_type_id.return_type;
6283 IrInstruction *promise_init = ir_build_const_promise_init(irb, scope, node, return_type);6282 IrInstruction *promise_init = ir_build_const_promise_init(irb, scope, node, return_type);
6284 ir_build_var_decl(irb, scope, node, promise_var, nullptr, nullptr, promise_init);6283 ir_build_var_decl(irb, scope, node, promise_var, nullptr, nullptr, promise_init);
6285 IrInstruction *coro_promise_ptr = ir_build_var_ptr(irb, scope, node, promise_var, false, false);6284 IrInstruction *coro_promise_ptr = ir_build_var_ptr(irb, scope, node, promise_var, false, false);
62866285
6286 VariableTableEntry *await_handle_var = ir_create_var(irb, node, scope, nullptr, false, false, true, const_bool_false);
6287 IrInstruction *null_value = ir_build_const_null(irb, scope, node);
6288 IrInstruction *await_handle_type_val = ir_build_const_type(irb, scope, node,
6289 get_maybe_type(irb->codegen, irb->codegen->builtin_types.entry_promise));
6290 ir_build_var_decl(irb, scope, node, await_handle_var, await_handle_type_val, nullptr, null_value);
6291 irb->exec->await_handle_var_ptr = ir_build_var_ptr(irb, scope, node,
6292 await_handle_var, false, false);
6293
6287 u8_ptr_type = ir_build_const_type(irb, scope, node,6294 u8_ptr_type = ir_build_const_type(irb, scope, node,
6288 get_pointer_to_type(irb->codegen, irb->codegen->builtin_types.entry_u8, false));6295 get_pointer_to_type(irb->codegen, irb->codegen->builtin_types.entry_u8, false));
6289 IrInstruction *promise_as_u8_ptr = ir_build_ptr_cast(irb, scope, node, u8_ptr_type, coro_promise_ptr);6296 IrInstruction *promise_as_u8_ptr = ir_build_ptr_cast(irb, scope, node, u8_ptr_type, coro_promise_ptr);
...@@ -6409,7 +6416,7 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec...@@ -6409,7 +6416,7 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec
64096416
6410 ir_set_cursor_at_end_and_append_block(irb, resume_block);6417 ir_set_cursor_at_end_and_append_block(irb, resume_block);
6411 IrInstruction *unwrapped_await_handle_ptr = ir_build_unwrap_maybe(irb, scope, node,6418 IrInstruction *unwrapped_await_handle_ptr = ir_build_unwrap_maybe(irb, scope, node,
6412 irb->exec->coro_awaiter_field_ptr, false);6419 irb->exec->await_handle_var_ptr, false);
6413 IrInstruction *awaiter_handle = ir_build_load_ptr(irb, scope, node, unwrapped_await_handle_ptr);6420 IrInstruction *awaiter_handle = ir_build_load_ptr(irb, scope, node, unwrapped_await_handle_ptr);
6414 ir_build_coro_resume(irb, scope, node, awaiter_handle);6421 ir_build_coro_resume(irb, scope, node, awaiter_handle);
6415 ir_build_br(irb, scope, node, irb->exec->coro_suspend_block, const_bool_false);6422 ir_build_br(irb, scope, node, irb->exec->coro_suspend_block, const_bool_false);
test/cases/coroutines.zig+39
...@@ -59,3 +59,42 @@ async fn testSuspendBlock() void {...@@ -59,3 +59,42 @@ async fn testSuspendBlock() void {
59 }59 }
60 result = true;60 result = true;
61}61}
62
63var await_a_promise: promise = undefined;
64var await_final_result: i32 = 0;
65
66test "coroutine await" {
67 await_seq('a');
68 const p = async(std.debug.global_allocator) await_amain() catch unreachable;
69 await_seq('f');
70 resume await_a_promise;
71 await_seq('i');
72 assert(await_final_result == 1234);
73 assert(std.mem.eql(u8, await_points, "abcdefghi"));
74}
75
76async fn await_amain() void {
77 await_seq('b');
78 const p = async await_another() catch unreachable;
79 await_seq('e');
80 await_final_result = await p;
81 await_seq('h');
82}
83
84async fn await_another() i32 {
85 await_seq('c');
86 suspend |p| {
87 await_seq('d');
88 await_a_promise = p;
89 }
90 await_seq('g');
91 return 1234;
92}
93
94var await_points = []u8{0} ** "abcdefghi".len;
95var await_seq_index: usize = 0;
96
97fn await_seq(c: u8) void {
98 await_points[await_seq_index] = c;
99 await_seq_index += 1;
100}