authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-07-30 12:22:54-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-07-30 12:22:54-04:00
log6fd6bc94f57b815774f9717d52bacbf304a496be
treefe8ffdd734845ca63f0cfd3aef708e6543f2d3b0
parent09304aab77a7b6af5693600fa6b3a35322f7469d

await sets suspend bit; return clears suspend bit


1 files changed, 53 insertions(+), 12 deletions(-)

src/ir.cpp+53-12
...@@ -6744,13 +6744,9 @@ static IrInstruction *ir_gen_cancel(IrBuilder *irb, Scope *scope, AstNode *node)...@@ -6744,13 +6744,9 @@ static IrInstruction *ir_gen_cancel(IrBuilder *irb, Scope *scope, AstNode *node)
6744 return ir_gen_cancel_target(irb, scope, node, target_inst, false, true);6744 return ir_gen_cancel_target(irb, scope, node, target_inst, false, true);
6745}6745}
67466746
6747static IrInstruction *ir_gen_resume(IrBuilder *irb, Scope *scope, AstNode *node) {6747static IrInstruction *ir_gen_resume_target(IrBuilder *irb, Scope *scope, AstNode *node,
6748 assert(node->type == NodeTypeResume);6748 IrInstruction *target_inst)
67496749{
6750 IrInstruction *target_inst = ir_gen_node(irb, node->data.resume_expr.expr, scope);
6751 if (target_inst == irb->codegen->invalid_instruction)
6752 return irb->codegen->invalid_instruction;
6753
6754 IrBasicBlock *done_block = ir_create_basic_block(irb, scope, "ResumeDone");6750 IrBasicBlock *done_block = ir_create_basic_block(irb, scope, "ResumeDone");
6755 IrBasicBlock *not_canceled_block = ir_create_basic_block(irb, scope, "NotCanceled");6751 IrBasicBlock *not_canceled_block = ir_create_basic_block(irb, scope, "NotCanceled");
6756 IrBasicBlock *suspended_block = ir_create_basic_block(irb, scope, "IsSuspended");6752 IrBasicBlock *suspended_block = ir_create_basic_block(irb, scope, "IsSuspended");
...@@ -6797,6 +6793,16 @@ static IrInstruction *ir_gen_resume(IrBuilder *irb, Scope *scope, AstNode *node)...@@ -6797,6 +6793,16 @@ static IrInstruction *ir_gen_resume(IrBuilder *irb, Scope *scope, AstNode *node)
6797 return ir_build_const_void(irb, scope, node);6793 return ir_build_const_void(irb, scope, node);
6798}6794}
67996795
6796static IrInstruction *ir_gen_resume(IrBuilder *irb, Scope *scope, AstNode *node) {
6797 assert(node->type == NodeTypeResume);
6798
6799 IrInstruction *target_inst = ir_gen_node(irb, node->data.resume_expr.expr, scope);
6800 if (target_inst == irb->codegen->invalid_instruction)
6801 return irb->codegen->invalid_instruction;
6802
6803 return ir_gen_resume_target(irb, scope, node, target_inst);
6804}
6805
6800static IrInstruction *ir_gen_await_expr(IrBuilder *irb, Scope *scope, AstNode *node) {6806static IrInstruction *ir_gen_await_expr(IrBuilder *irb, Scope *scope, AstNode *node) {
6801 assert(node->type == NodeTypeAwaitExpr);6807 assert(node->type == NodeTypeAwaitExpr);
68026808
...@@ -6847,6 +6853,10 @@ static IrInstruction *ir_gen_await_expr(IrBuilder *irb, Scope *scope, AstNode *n...@@ -6847,6 +6853,10 @@ static IrInstruction *ir_gen_await_expr(IrBuilder *irb, Scope *scope, AstNode *n
6847 IrBasicBlock *cancel_target_block = ir_create_basic_block(irb, scope, "CancelTarget");6853 IrBasicBlock *cancel_target_block = ir_create_basic_block(irb, scope, "CancelTarget");
6848 IrBasicBlock *do_cancel_block = ir_create_basic_block(irb, scope, "DoCancel");6854 IrBasicBlock *do_cancel_block = ir_create_basic_block(irb, scope, "DoCancel");
6849 IrBasicBlock *do_defers_block = ir_create_basic_block(irb, scope, "DoDefers");6855 IrBasicBlock *do_defers_block = ir_create_basic_block(irb, scope, "DoDefers");
6856 IrBasicBlock *destroy_block = ir_create_basic_block(irb, scope, "DestroyBlock");
6857 IrBasicBlock *my_suspended_block = ir_create_basic_block(irb, scope, "AlreadySuspended");
6858 IrBasicBlock *my_not_suspended_block = ir_create_basic_block(irb, scope, "NotAlreadySuspended");
6859 IrBasicBlock *do_suspend_block = ir_create_basic_block(irb, scope, "DoSuspend");
68506860
6851 Buf *atomic_state_field_name = buf_create_from_str(ATOMIC_STATE_FIELD_NAME);6861 Buf *atomic_state_field_name = buf_create_from_str(ATOMIC_STATE_FIELD_NAME);
6852 IrInstruction *atomic_state_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr,6862 IrInstruction *atomic_state_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr,
...@@ -6861,6 +6871,7 @@ static IrInstruction *ir_gen_await_expr(IrBuilder *irb, Scope *scope, AstNode *n...@@ -6861,6 +6871,7 @@ static IrInstruction *ir_gen_await_expr(IrBuilder *irb, Scope *scope, AstNode *n
6861 IrInstruction *ptr_mask = ir_build_un_op(irb, scope, node, IrUnOpBinNot, inverted_ptr_mask); // 0b111...0006871 IrInstruction *ptr_mask = ir_build_un_op(irb, scope, node, IrUnOpBinNot, inverted_ptr_mask); // 0b111...000
6862 IrInstruction *await_mask = ir_build_const_usize(irb, scope, node, 0x4); // 0b1006872 IrInstruction *await_mask = ir_build_const_usize(irb, scope, node, 0x4); // 0b100
6863 IrInstruction *is_canceled_mask = ir_build_const_usize(irb, scope, node, 0x1); // 0b0016873 IrInstruction *is_canceled_mask = ir_build_const_usize(irb, scope, node, 0x1); // 0b001
6874 IrInstruction *is_suspended_mask = ir_build_const_usize(irb, scope, node, 0x2); // 0b010
68646875
6865 VariableTableEntry *result_var = ir_create_var(irb, node, scope, nullptr,6876 VariableTableEntry *result_var = ir_create_var(irb, node, scope, nullptr,
6866 false, false, true, const_bool_false);6877 false, false, true, const_bool_false);
...@@ -6917,22 +6928,42 @@ static IrInstruction *ir_gen_await_expr(IrBuilder *irb, Scope *scope, AstNode *n...@@ -6917,22 +6928,42 @@ static IrInstruction *ir_gen_await_expr(IrBuilder *irb, Scope *scope, AstNode *n
69176928
69186929
6919 ir_set_cursor_at_end_and_append_block(irb, yes_suspend_block);6930 ir_set_cursor_at_end_and_append_block(irb, yes_suspend_block);
6931 IrInstruction *my_prev_atomic_value = ir_build_atomic_rmw(irb, scope, node,
6932 usize_type_val, irb->exec->atomic_state_field_ptr, nullptr, is_suspended_mask, nullptr,
6933 AtomicRmwOp_or, AtomicOrderSeqCst);
6934 IrInstruction *my_is_suspended_value = ir_build_bin_op(irb, scope, node, IrBinOpBinAnd, my_prev_atomic_value, is_suspended_mask, false);
6935 IrInstruction *my_is_suspended_bool = ir_build_bin_op(irb, scope, node, IrBinOpCmpNotEq, my_is_suspended_value, zero, false);
6936 ir_build_cond_br(irb, scope, node, my_is_suspended_bool, my_suspended_block, my_not_suspended_block, const_bool_false);
6937
6938 ir_set_cursor_at_end_and_append_block(irb, my_suspended_block);
6939 ir_build_unreachable(irb, scope, node);
6940
6941 ir_set_cursor_at_end_and_append_block(irb, my_not_suspended_block);
6942 IrInstruction *my_is_canceled_value = ir_build_bin_op(irb, scope, node, IrBinOpBinAnd, my_prev_atomic_value, is_canceled_mask, false);
6943 IrInstruction *my_is_canceled_bool = ir_build_bin_op(irb, scope, node, IrBinOpCmpNotEq, my_is_canceled_value, zero, false);
6944 ir_build_cond_br(irb, scope, node, my_is_canceled_bool, cleanup_block, do_suspend_block, const_bool_false);
6945
6946 ir_set_cursor_at_end_and_append_block(irb, do_suspend_block);
6920 IrInstruction *suspend_code = ir_build_coro_suspend(irb, scope, node, save_token, const_bool_false);6947 IrInstruction *suspend_code = ir_build_coro_suspend(irb, scope, node, save_token, const_bool_false);
69216948
6922 IrInstructionSwitchBrCase *cases = allocate<IrInstructionSwitchBrCase>(2);6949 IrInstructionSwitchBrCase *cases = allocate<IrInstructionSwitchBrCase>(2);
6923 cases[0].value = ir_build_const_u8(irb, scope, node, 0);6950 cases[0].value = ir_build_const_u8(irb, scope, node, 0);
6924 cases[0].block = resume_block;6951 cases[0].block = resume_block;
6925 cases[1].value = ir_build_const_u8(irb, scope, node, 1);6952 cases[1].value = ir_build_const_u8(irb, scope, node, 1);
6926 cases[1].block = cleanup_block;6953 cases[1].block = destroy_block;
6927 ir_build_switch_br(irb, scope, node, suspend_code, irb->exec->coro_suspend_block,6954 ir_build_switch_br(irb, scope, node, suspend_code, irb->exec->coro_suspend_block,
6928 2, cases, const_bool_false, nullptr);6955 2, cases, const_bool_false, nullptr);
69296956
6957 ir_set_cursor_at_end_and_append_block(irb, destroy_block);
6958 ir_gen_cancel_target(irb, scope, node, target_inst, false, true);
6959 ir_mark_gen(ir_build_br(irb, scope, node, cleanup_block, const_bool_false));
6960
6930 ir_set_cursor_at_end_and_append_block(irb, cleanup_block);6961 ir_set_cursor_at_end_and_append_block(irb, cleanup_block);
6931 IrInstruction *my_mask_bits = ir_build_bin_op(irb, scope, node, IrBinOpBinOr, ptr_mask, is_canceled_mask, false);6962 IrInstruction *my_mask_bits = ir_build_bin_op(irb, scope, node, IrBinOpBinOr, ptr_mask, is_canceled_mask, false);
6932 IrInstruction *my_prev_atomic_value = ir_build_atomic_rmw(irb, scope, node, 6963 IrInstruction *b_my_prev_atomic_value = ir_build_atomic_rmw(irb, scope, node,
6933 usize_type_val, irb->exec->atomic_state_field_ptr, nullptr, my_mask_bits, nullptr,6964 usize_type_val, irb->exec->atomic_state_field_ptr, nullptr, my_mask_bits, nullptr,
6934 AtomicRmwOp_or, AtomicOrderSeqCst);6965 AtomicRmwOp_or, AtomicOrderSeqCst);
6935 IrInstruction *my_await_handle_addr = ir_build_bin_op(irb, scope, node, IrBinOpBinAnd, my_prev_atomic_value, ptr_mask, false);6966 IrInstruction *my_await_handle_addr = ir_build_bin_op(irb, scope, node, IrBinOpBinAnd, b_my_prev_atomic_value, ptr_mask, false);
6936 IrInstruction *dont_have_my_await_handle = ir_build_bin_op(irb, scope, node, IrBinOpCmpEq, my_await_handle_addr, zero, false);6967 IrInstruction *dont_have_my_await_handle = ir_build_bin_op(irb, scope, node, IrBinOpCmpEq, my_await_handle_addr, zero, false);
6937 IrInstruction *dont_destroy_ourselves = ir_build_bin_op(irb, scope, node, IrBinOpBoolAnd, dont_have_my_await_handle, is_canceled_bool, false);6968 IrInstruction *dont_destroy_ourselves = ir_build_bin_op(irb, scope, node, IrBinOpBoolAnd, dont_have_my_await_handle, is_canceled_bool, false);
6938 ir_build_cond_br(irb, scope, node, dont_have_my_await_handle, do_defers_block, do_cancel_block, const_bool_false);6969 ir_build_cond_br(irb, scope, node, dont_have_my_await_handle, do_defers_block, do_cancel_block, const_bool_false);
...@@ -6996,6 +7027,7 @@ static IrInstruction *ir_gen_suspend(IrBuilder *irb, Scope *parent_scope, AstNod...@@ -6996,6 +7027,7 @@ static IrInstruction *ir_gen_suspend(IrBuilder *irb, Scope *parent_scope, AstNod
6996 IrBasicBlock *cancel_awaiter_block = ir_create_basic_block(irb, parent_scope, "CancelAwaiter");7027 IrBasicBlock *cancel_awaiter_block = ir_create_basic_block(irb, parent_scope, "CancelAwaiter");
69977028
6998 IrInstruction *promise_type_val = ir_build_const_type(irb, parent_scope, node, irb->codegen->builtin_types.entry_promise);7029 IrInstruction *promise_type_val = ir_build_const_type(irb, parent_scope, node, irb->codegen->builtin_types.entry_promise);
7030 IrInstruction *const_bool_true = ir_build_const_bool(irb, parent_scope, node, true);
6999 IrInstruction *const_bool_false = ir_build_const_bool(irb, parent_scope, node, false);7031 IrInstruction *const_bool_false = ir_build_const_bool(irb, parent_scope, node, false);
7000 IrInstruction *usize_type_val = ir_build_const_type(irb, parent_scope, node, irb->codegen->builtin_types.entry_usize);7032 IrInstruction *usize_type_val = ir_build_const_type(irb, parent_scope, node, irb->codegen->builtin_types.entry_usize);
7001 IrInstruction *is_canceled_mask = ir_build_const_usize(irb, parent_scope, node, 0x1); // 0b0017033 IrInstruction *is_canceled_mask = ir_build_const_usize(irb, parent_scope, node, 0x1); // 0b001
...@@ -7015,11 +7047,13 @@ static IrInstruction *ir_gen_suspend(IrBuilder *irb, Scope *parent_scope, AstNod...@@ -7015,11 +7047,13 @@ static IrInstruction *ir_gen_suspend(IrBuilder *irb, Scope *parent_scope, AstNod
7015 ir_set_cursor_at_end_and_append_block(irb, canceled_block);7047 ir_set_cursor_at_end_and_append_block(irb, canceled_block);
7016 IrInstruction *await_handle_addr = ir_build_bin_op(irb, parent_scope, node, IrBinOpBinAnd, prev_atomic_value, ptr_mask, false);7048 IrInstruction *await_handle_addr = ir_build_bin_op(irb, parent_scope, node, IrBinOpBinAnd, prev_atomic_value, ptr_mask, false);
7017 IrInstruction *have_await_handle = ir_build_bin_op(irb, parent_scope, node, IrBinOpCmpNotEq, await_handle_addr, zero, false);7049 IrInstruction *have_await_handle = ir_build_bin_op(irb, parent_scope, node, IrBinOpCmpNotEq, await_handle_addr, zero, false);
7050 IrBasicBlock *post_canceled_block = irb->current_basic_block;
7018 ir_build_cond_br(irb, parent_scope, node, have_await_handle, cancel_awaiter_block, cleanup_block, const_bool_false);7051 ir_build_cond_br(irb, parent_scope, node, have_await_handle, cancel_awaiter_block, cleanup_block, const_bool_false);
70197052
7020 ir_set_cursor_at_end_and_append_block(irb, cancel_awaiter_block);7053 ir_set_cursor_at_end_and_append_block(irb, cancel_awaiter_block);
7021 IrInstruction *await_handle = ir_build_int_to_ptr(irb, parent_scope, node, promise_type_val, await_handle_addr);7054 IrInstruction *await_handle = ir_build_int_to_ptr(irb, parent_scope, node, promise_type_val, await_handle_addr);
7022 ir_gen_cancel_target(irb, parent_scope, node, await_handle, true, false);7055 ir_gen_cancel_target(irb, parent_scope, node, await_handle, true, false);
7056 IrBasicBlock *post_cancel_awaiter_block = irb->current_basic_block;
7023 ir_build_br(irb, parent_scope, node, cleanup_block, const_bool_false);7057 ir_build_br(irb, parent_scope, node, cleanup_block, const_bool_false);
70247058
7025 ir_set_cursor_at_end_and_append_block(irb, not_canceled_block);7059 ir_set_cursor_at_end_and_append_block(irb, not_canceled_block);
...@@ -7064,8 +7098,15 @@ static IrInstruction *ir_gen_suspend(IrBuilder *irb, Scope *parent_scope, AstNod...@@ -7064,8 +7098,15 @@ static IrInstruction *ir_gen_suspend(IrBuilder *irb, Scope *parent_scope, AstNod
7064 2, cases, const_bool_false, nullptr));7098 2, cases, const_bool_false, nullptr));
70657099
7066 ir_set_cursor_at_end_and_append_block(irb, cleanup_block);7100 ir_set_cursor_at_end_and_append_block(irb, cleanup_block);
7101 IrBasicBlock **incoming_blocks = allocate<IrBasicBlock *>(2);
7102 IrInstruction **incoming_values = allocate<IrInstruction *>(2);
7103 incoming_blocks[0] = post_canceled_block;
7104 incoming_values[0] = const_bool_true;
7105 incoming_blocks[1] = post_cancel_awaiter_block;
7106 incoming_values[1] = const_bool_false;
7107 IrInstruction *destroy_ourselves = ir_build_phi(irb, parent_scope, node, 2, incoming_blocks, incoming_values);
7067 ir_gen_defers_for_block(irb, parent_scope, outer_scope, true);7108 ir_gen_defers_for_block(irb, parent_scope, outer_scope, true);
7068 ir_mark_gen(ir_build_br(irb, parent_scope, node, irb->exec->coro_final_cleanup_block, const_bool_false));7109 ir_mark_gen(ir_build_cond_br(irb, parent_scope, node, destroy_ourselves, irb->exec->coro_final_cleanup_block, irb->exec->coro_early_final, const_bool_false));
70697110
7070 ir_set_cursor_at_end_and_append_block(irb, resume_block);7111 ir_set_cursor_at_end_and_append_block(irb, resume_block);
7071 return ir_mark_gen(ir_build_const_void(irb, parent_scope, node));7112 return ir_mark_gen(ir_build_const_void(irb, parent_scope, node));
...@@ -7450,7 +7491,7 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec...@@ -7450,7 +7491,7 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec
7450 ir_build_cond_br(irb, scope, node, resume_awaiter, resume_block, irb->exec->coro_suspend_block, const_bool_false);7491 ir_build_cond_br(irb, scope, node, resume_awaiter, resume_block, irb->exec->coro_suspend_block, const_bool_false);
74517492
7452 ir_set_cursor_at_end_and_append_block(irb, resume_block);7493 ir_set_cursor_at_end_and_append_block(irb, resume_block);
7453 ir_build_coro_resume(irb, scope, node, awaiter_handle);7494 ir_gen_resume_target(irb, scope, node, awaiter_handle);
7454 ir_build_br(irb, scope, node, irb->exec->coro_suspend_block, const_bool_false);7495 ir_build_br(irb, scope, node, irb->exec->coro_suspend_block, const_bool_false);
7455 }7496 }
74567497