authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-07-27 17:00:41-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-07-27 17:00:41-04:00
log10764ee0e66e5d9a815073340d8f16a58e225422
treef90a9c4e0c81ceb2bd45ef5cbf4c082a9c425ae4
parent7113f109a4111acadf0533ca84e529d229892c8c

resume clears suspend bit


1 files changed, 85 insertions(+), 52 deletions(-)

src/ir.cpp+85-52
...@@ -6686,20 +6686,53 @@ static IrInstruction *ir_gen_cancel(IrBuilder *irb, Scope *parent_scope, AstNode...@@ -6686,20 +6686,53 @@ static IrInstruction *ir_gen_cancel(IrBuilder *irb, Scope *parent_scope, AstNode
6686 return ir_build_cancel(irb, parent_scope, node, target_inst);6686 return ir_build_cancel(irb, parent_scope, node, target_inst);
6687}6687}
66886688
6689static IrInstruction *ir_gen_resume(IrBuilder *irb, Scope *parent_scope, AstNode *node) {6689static IrInstruction *ir_gen_resume(IrBuilder *irb, Scope *scope, AstNode *node) {
6690 assert(node->type == NodeTypeResume);6690 assert(node->type == NodeTypeResume);
66916691
6692 IrInstruction *target_inst = ir_gen_node(irb, node->data.resume_expr.expr, parent_scope);6692 IrInstruction *target_inst = ir_gen_node(irb, node->data.resume_expr.expr, scope);
6693 if (target_inst == irb->codegen->invalid_instruction)6693 if (target_inst == irb->codegen->invalid_instruction)
6694 return irb->codegen->invalid_instruction;6694 return irb->codegen->invalid_instruction;
66956695
6696 return ir_build_coro_resume(irb, parent_scope, node, target_inst);6696 IrBasicBlock *done_block = ir_create_basic_block(irb, scope, "ResumeDone");
6697 IrBasicBlock *not_canceled_block = ir_create_basic_block(irb, scope, "NotCanceled");
6698
6699 IrInstruction *inverted_mask = ir_build_const_usize(irb, scope, node, 0x2); // 0b010
6700 IrInstruction *mask = ir_build_un_op(irb, scope, node, IrUnOpBinNot, inverted_mask);
6701 IrInstruction *is_canceled_mask = ir_build_const_usize(irb, scope, node, 0x1); // 0b001
6702 IrInstruction *is_comptime = ir_build_const_bool(irb, scope, node, false);
6703 IrInstruction *usize_type_val = ir_build_const_type(irb, scope, node, irb->codegen->builtin_types.entry_usize);
6704 IrInstruction *zero = ir_build_const_usize(irb, scope, node, 0);
6705 IrInstruction *promise_T_type_val = ir_build_const_type(irb, scope, node,
6706 get_promise_type(irb->codegen, irb->codegen->builtin_types.entry_void));
6707
6708 // TODO relies on Zig not re-ordering fields
6709 IrInstruction *casted_target_inst = ir_build_ptr_cast(irb, scope, node, promise_T_type_val, target_inst);
6710 IrInstruction *coro_promise_ptr = ir_build_coro_promise(irb, scope, node, casted_target_inst);
6711 Buf *atomic_state_field_name = buf_create_from_str(ATOMIC_STATE_FIELD_NAME);
6712 IrInstruction *atomic_state_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr,
6713 atomic_state_field_name);
6714
6715 // clear the is_suspended bit
6716 IrInstruction *prev_atomic_value = ir_build_atomic_rmw(irb, scope, node,
6717 usize_type_val, atomic_state_ptr, nullptr, mask, nullptr,
6718 AtomicRmwOp_and, AtomicOrderSeqCst);
6719
6720 IrInstruction *is_canceled_value = ir_build_bin_op(irb, scope, node, IrBinOpBinAnd, prev_atomic_value, is_canceled_mask, false);
6721 IrInstruction *is_canceled_bool = ir_build_bin_op(irb, scope, node, IrBinOpCmpNotEq, is_canceled_value, zero, false);
6722 ir_build_cond_br(irb, scope, node, is_canceled_bool, done_block, not_canceled_block, is_comptime);
6723
6724 ir_set_cursor_at_end_and_append_block(irb, not_canceled_block);
6725 ir_build_coro_resume(irb, scope, node, target_inst);
6726 ir_build_br(irb, scope, node, done_block, is_comptime);
6727
6728 ir_set_cursor_at_end_and_append_block(irb, done_block);
6729 return ir_build_const_void(irb, scope, node);
6697}6730}
66986731
6699static IrInstruction *ir_gen_await_expr(IrBuilder *irb, Scope *parent_scope, AstNode *node) {6732static IrInstruction *ir_gen_await_expr(IrBuilder *irb, Scope *scope, AstNode *node) {
6700 assert(node->type == NodeTypeAwaitExpr);6733 assert(node->type == NodeTypeAwaitExpr);
67016734
6702 IrInstruction *target_inst = ir_gen_node(irb, node->data.await_expr.expr, parent_scope);6735 IrInstruction *target_inst = ir_gen_node(irb, node->data.await_expr.expr, scope);
6703 if (target_inst == irb->codegen->invalid_instruction)6736 if (target_inst == irb->codegen->invalid_instruction)
6704 return irb->codegen->invalid_instruction;6737 return irb->codegen->invalid_instruction;
67056738
...@@ -6713,7 +6746,7 @@ static IrInstruction *ir_gen_await_expr(IrBuilder *irb, Scope *parent_scope, Ast...@@ -6713,7 +6746,7 @@ static IrInstruction *ir_gen_await_expr(IrBuilder *irb, Scope *parent_scope, Ast
6713 return irb->codegen->invalid_instruction;6746 return irb->codegen->invalid_instruction;
6714 }6747 }
67156748
6716 ScopeDeferExpr *scope_defer_expr = get_scope_defer_expr(parent_scope);6749 ScopeDeferExpr *scope_defer_expr = get_scope_defer_expr(scope);
6717 if (scope_defer_expr) {6750 if (scope_defer_expr) {
6718 if (!scope_defer_expr->reported_err) {6751 if (!scope_defer_expr->reported_err) {
6719 add_node_error(irb->codegen, node, buf_sprintf("cannot await inside defer expression"));6752 add_node_error(irb->codegen, node, buf_sprintf("cannot await inside defer expression"));
...@@ -6724,85 +6757,85 @@ static IrInstruction *ir_gen_await_expr(IrBuilder *irb, Scope *parent_scope, Ast...@@ -6724,85 +6757,85 @@ static IrInstruction *ir_gen_await_expr(IrBuilder *irb, Scope *parent_scope, Ast
67246757
6725 Scope *outer_scope = irb->exec->begin_scope;6758 Scope *outer_scope = irb->exec->begin_scope;
67266759
6727 IrInstruction *coro_promise_ptr = ir_build_coro_promise(irb, parent_scope, node, target_inst);6760 IrInstruction *coro_promise_ptr = ir_build_coro_promise(irb, scope, node, target_inst);
6728 Buf *result_ptr_field_name = buf_create_from_str(RESULT_PTR_FIELD_NAME);6761 Buf *result_ptr_field_name = buf_create_from_str(RESULT_PTR_FIELD_NAME);
6729 IrInstruction *result_ptr_field_ptr = ir_build_field_ptr(irb, parent_scope, node, coro_promise_ptr, result_ptr_field_name);6762 IrInstruction *result_ptr_field_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr, result_ptr_field_name);
67306763
6731 if (irb->codegen->have_err_ret_tracing) {6764 if (irb->codegen->have_err_ret_tracing) {
6732 IrInstruction *err_ret_trace_ptr = ir_build_error_return_trace(irb, parent_scope, node, IrInstructionErrorReturnTrace::NonNull);6765 IrInstruction *err_ret_trace_ptr = ir_build_error_return_trace(irb, scope, node, IrInstructionErrorReturnTrace::NonNull);
6733 Buf *err_ret_trace_ptr_field_name = buf_create_from_str(ERR_RET_TRACE_PTR_FIELD_NAME);6766 Buf *err_ret_trace_ptr_field_name = buf_create_from_str(ERR_RET_TRACE_PTR_FIELD_NAME);
6734 IrInstruction *err_ret_trace_ptr_field_ptr = ir_build_field_ptr(irb, parent_scope, node, coro_promise_ptr, err_ret_trace_ptr_field_name);6767 IrInstruction *err_ret_trace_ptr_field_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr, err_ret_trace_ptr_field_name);
6735 ir_build_store_ptr(irb, parent_scope, node, err_ret_trace_ptr_field_ptr, err_ret_trace_ptr);6768 ir_build_store_ptr(irb, scope, node, err_ret_trace_ptr_field_ptr, err_ret_trace_ptr);
6736 }6769 }
67376770
6738 Buf *atomic_state_field_name = buf_create_from_str(ATOMIC_STATE_FIELD_NAME);6771 Buf *atomic_state_field_name = buf_create_from_str(ATOMIC_STATE_FIELD_NAME);
6739 IrInstruction *atomic_state_ptr = ir_build_field_ptr(irb, parent_scope, node, coro_promise_ptr,6772 IrInstruction *atomic_state_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr,
6740 atomic_state_field_name);6773 atomic_state_field_name);
67416774
6742 IrInstruction *const_bool_false = ir_build_const_bool(irb, parent_scope, node, false);6775 IrInstruction *const_bool_false = ir_build_const_bool(irb, scope, node, false);
6743 VariableTableEntry *result_var = ir_create_var(irb, node, parent_scope, nullptr,6776 VariableTableEntry *result_var = ir_create_var(irb, node, scope, nullptr,
6744 false, false, true, const_bool_false);6777 false, false, true, const_bool_false);
6745 IrInstruction *undefined_value = ir_build_const_undefined(irb, parent_scope, node);6778 IrInstruction *undefined_value = ir_build_const_undefined(irb, scope, node);
6746 IrInstruction *target_promise_type = ir_build_typeof(irb, parent_scope, node, target_inst);6779 IrInstruction *target_promise_type = ir_build_typeof(irb, scope, node, target_inst);
6747 IrInstruction *promise_result_type = ir_build_promise_result_type(irb, parent_scope, node, target_promise_type);6780 IrInstruction *promise_result_type = ir_build_promise_result_type(irb, scope, node, target_promise_type);
6748 ir_build_await_bookkeeping(irb, parent_scope, node, promise_result_type);6781 ir_build_await_bookkeeping(irb, scope, node, promise_result_type);
6749 ir_build_var_decl(irb, parent_scope, node, result_var, promise_result_type, nullptr, undefined_value);6782 ir_build_var_decl(irb, scope, node, result_var, promise_result_type, nullptr, undefined_value);
6750 IrInstruction *my_result_var_ptr = ir_build_var_ptr(irb, parent_scope, node, result_var);6783 IrInstruction *my_result_var_ptr = ir_build_var_ptr(irb, scope, node, result_var);
6751 ir_build_store_ptr(irb, parent_scope, node, result_ptr_field_ptr, my_result_var_ptr);6784 ir_build_store_ptr(irb, scope, node, result_ptr_field_ptr, my_result_var_ptr);
6752 IrInstruction *save_token = ir_build_coro_save(irb, parent_scope, node, irb->exec->coro_handle);6785 IrInstruction *save_token = ir_build_coro_save(irb, scope, node, irb->exec->coro_handle);
6753 IrInstruction *usize_type_val = ir_build_const_type(irb, parent_scope, node, irb->codegen->builtin_types.entry_usize);6786 IrInstruction *usize_type_val = ir_build_const_type(irb, scope, node, irb->codegen->builtin_types.entry_usize);
6754 IrInstruction *coro_handle_addr = ir_build_ptr_to_int(irb, parent_scope, node, irb->exec->coro_handle);6787 IrInstruction *coro_handle_addr = ir_build_ptr_to_int(irb, scope, node, irb->exec->coro_handle);
6755 IrInstruction *prev_atomic_value = ir_build_atomic_rmw(irb, parent_scope, node, 6788 IrInstruction *prev_atomic_value = ir_build_atomic_rmw(irb, scope, node,
6756 usize_type_val, atomic_state_ptr, nullptr, coro_handle_addr, nullptr,6789 usize_type_val, atomic_state_ptr, nullptr, coro_handle_addr, nullptr,
6757 AtomicRmwOp_or, AtomicOrderSeqCst);6790 AtomicRmwOp_or, AtomicOrderSeqCst);
6758 IrInstruction *zero = ir_build_const_usize(irb, parent_scope, node, 0);6791 IrInstruction *zero = ir_build_const_usize(irb, scope, node, 0);
6759 IrInstruction *inverted_ptr_mask = ir_build_const_usize(irb, parent_scope, node, 0x7); // 0b1116792 IrInstruction *inverted_ptr_mask = ir_build_const_usize(irb, scope, node, 0x7); // 0b111
6760 IrInstruction *ptr_mask = ir_build_un_op(irb, parent_scope, node, IrUnOpBinNot, inverted_ptr_mask); // 0b111...0006793 IrInstruction *ptr_mask = ir_build_un_op(irb, scope, node, IrUnOpBinNot, inverted_ptr_mask); // 0b111...000
6761 IrInstruction *await_handle_addr = ir_build_bin_op(irb, parent_scope, node, IrBinOpBinAnd, prev_atomic_value, ptr_mask, false);6794 IrInstruction *await_handle_addr = ir_build_bin_op(irb, scope, node, IrBinOpBinAnd, prev_atomic_value, ptr_mask, false);
6762 IrInstruction *is_non_null = ir_build_bin_op(irb, parent_scope, node, IrBinOpCmpNotEq, await_handle_addr, zero, false);6795 IrInstruction *is_non_null = ir_build_bin_op(irb, scope, node, IrBinOpCmpNotEq, await_handle_addr, zero, false);
6763 IrBasicBlock *yes_suspend_block = ir_create_basic_block(irb, parent_scope, "YesSuspend");6796 IrBasicBlock *yes_suspend_block = ir_create_basic_block(irb, scope, "YesSuspend");
6764 IrBasicBlock *no_suspend_block = ir_create_basic_block(irb, parent_scope, "NoSuspend");6797 IrBasicBlock *no_suspend_block = ir_create_basic_block(irb, scope, "NoSuspend");
6765 IrBasicBlock *merge_block = ir_create_basic_block(irb, parent_scope, "MergeSuspend");6798 IrBasicBlock *merge_block = ir_create_basic_block(irb, scope, "MergeSuspend");
6766 ir_build_cond_br(irb, parent_scope, node, is_non_null, no_suspend_block, yes_suspend_block, const_bool_false);6799 ir_build_cond_br(irb, scope, node, is_non_null, no_suspend_block, yes_suspend_block, const_bool_false);
67676800
6768 ir_set_cursor_at_end_and_append_block(irb, no_suspend_block);6801 ir_set_cursor_at_end_and_append_block(irb, no_suspend_block);
6769 if (irb->codegen->have_err_ret_tracing) {6802 if (irb->codegen->have_err_ret_tracing) {
6770 Buf *err_ret_trace_field_name = buf_create_from_str(ERR_RET_TRACE_FIELD_NAME);6803 Buf *err_ret_trace_field_name = buf_create_from_str(ERR_RET_TRACE_FIELD_NAME);
6771 IrInstruction *src_err_ret_trace_ptr = ir_build_field_ptr(irb, parent_scope, node, coro_promise_ptr, err_ret_trace_field_name);6804 IrInstruction *src_err_ret_trace_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr, err_ret_trace_field_name);
6772 IrInstruction *dest_err_ret_trace_ptr = ir_build_error_return_trace(irb, parent_scope, node, IrInstructionErrorReturnTrace::NonNull);6805 IrInstruction *dest_err_ret_trace_ptr = ir_build_error_return_trace(irb, scope, node, IrInstructionErrorReturnTrace::NonNull);
6773 ir_build_merge_err_ret_traces(irb, parent_scope, node, coro_promise_ptr, src_err_ret_trace_ptr, dest_err_ret_trace_ptr);6806 ir_build_merge_err_ret_traces(irb, scope, node, coro_promise_ptr, src_err_ret_trace_ptr, dest_err_ret_trace_ptr);
6774 }6807 }
6775 Buf *result_field_name = buf_create_from_str(RESULT_FIELD_NAME);6808 Buf *result_field_name = buf_create_from_str(RESULT_FIELD_NAME);
6776 IrInstruction *promise_result_ptr = ir_build_field_ptr(irb, parent_scope, node, coro_promise_ptr, result_field_name);6809 IrInstruction *promise_result_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr, result_field_name);
6777 // If the type of the result handle_is_ptr then this does not actually perform a load. But we need it to,6810 // If the type of the result handle_is_ptr then this does not actually perform a load. But we need it to,
6778 // because we're about to destroy the memory. So we store it into our result variable.6811 // because we're about to destroy the memory. So we store it into our result variable.
6779 IrInstruction *no_suspend_result = ir_build_load_ptr(irb, parent_scope, node, promise_result_ptr);6812 IrInstruction *no_suspend_result = ir_build_load_ptr(irb, scope, node, promise_result_ptr);
6780 ir_build_store_ptr(irb, parent_scope, node, my_result_var_ptr, no_suspend_result);6813 ir_build_store_ptr(irb, scope, node, my_result_var_ptr, no_suspend_result);
6781 ir_build_cancel(irb, parent_scope, node, target_inst);6814 ir_build_cancel(irb, scope, node, target_inst);
6782 ir_build_br(irb, parent_scope, node, merge_block, const_bool_false);6815 ir_build_br(irb, scope, node, merge_block, const_bool_false);
67836816
6784 ir_set_cursor_at_end_and_append_block(irb, yes_suspend_block);6817 ir_set_cursor_at_end_and_append_block(irb, yes_suspend_block);
6785 IrInstruction *suspend_code = ir_build_coro_suspend(irb, parent_scope, node, save_token, const_bool_false);6818 IrInstruction *suspend_code = ir_build_coro_suspend(irb, scope, node, save_token, const_bool_false);
6786 IrBasicBlock *cleanup_block = ir_create_basic_block(irb, parent_scope, "SuspendCleanup");6819 IrBasicBlock *cleanup_block = ir_create_basic_block(irb, scope, "SuspendCleanup");
6787 IrBasicBlock *resume_block = ir_create_basic_block(irb, parent_scope, "SuspendResume");6820 IrBasicBlock *resume_block = ir_create_basic_block(irb, scope, "SuspendResume");
67886821
6789 IrInstructionSwitchBrCase *cases = allocate<IrInstructionSwitchBrCase>(2);6822 IrInstructionSwitchBrCase *cases = allocate<IrInstructionSwitchBrCase>(2);
6790 cases[0].value = ir_build_const_u8(irb, parent_scope, node, 0);6823 cases[0].value = ir_build_const_u8(irb, scope, node, 0);
6791 cases[0].block = resume_block;6824 cases[0].block = resume_block;
6792 cases[1].value = ir_build_const_u8(irb, parent_scope, node, 1);6825 cases[1].value = ir_build_const_u8(irb, scope, node, 1);
6793 cases[1].block = cleanup_block;6826 cases[1].block = cleanup_block;
6794 ir_build_switch_br(irb, parent_scope, node, suspend_code, irb->exec->coro_suspend_block,6827 ir_build_switch_br(irb, scope, node, suspend_code, irb->exec->coro_suspend_block,
6795 2, cases, const_bool_false, nullptr);6828 2, cases, const_bool_false, nullptr);
67966829
6797 ir_set_cursor_at_end_and_append_block(irb, cleanup_block);6830 ir_set_cursor_at_end_and_append_block(irb, cleanup_block);
6798 ir_gen_defers_for_block(irb, parent_scope, outer_scope, true);6831 ir_gen_defers_for_block(irb, scope, outer_scope, true);
6799 ir_mark_gen(ir_build_br(irb, parent_scope, node, irb->exec->coro_final_cleanup_block, const_bool_false));6832 ir_mark_gen(ir_build_br(irb, scope, node, irb->exec->coro_final_cleanup_block, const_bool_false));
68006833
6801 ir_set_cursor_at_end_and_append_block(irb, resume_block);6834 ir_set_cursor_at_end_and_append_block(irb, resume_block);
6802 ir_build_br(irb, parent_scope, node, merge_block, const_bool_false);6835 ir_build_br(irb, scope, node, merge_block, const_bool_false);
68036836
6804 ir_set_cursor_at_end_and_append_block(irb, merge_block);6837 ir_set_cursor_at_end_and_append_block(irb, merge_block);
6805 return ir_build_load_ptr(irb, parent_scope, node, my_result_var_ptr);6838 return ir_build_load_ptr(irb, scope, node, my_result_var_ptr);
6806}6839}
68076840
6808static IrInstruction *ir_gen_suspend(IrBuilder *irb, Scope *parent_scope, AstNode *node) {6841static IrInstruction *ir_gen_suspend(IrBuilder *irb, Scope *parent_scope, AstNode *node) {