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
66866686 return ir_build_cancel(irb, parent_scope, node, target_inst);
66876687}
66886688
6689static IrInstruction *ir_gen_resume(IrBuilder *irb, Scope *parent_scope, AstNode *node) {
6689static IrInstruction *ir_gen_resume(IrBuilder *irb, Scope *scope, AstNode *node) {
66906690 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);
66936693 if (target_inst == irb->codegen->invalid_instruction)
66946694 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);
66976730}
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) {
67006733 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);
67036736 if (target_inst == irb->codegen->invalid_instruction)
67046737 return irb->codegen->invalid_instruction;
67056738
......@@ -6713,7 +6746,7 @@ static IrInstruction *ir_gen_await_expr(IrBuilder *irb, Scope *parent_scope, Ast
67136746 return irb->codegen->invalid_instruction;
67146747 }
67156748
6716 ScopeDeferExpr *scope_defer_expr = get_scope_defer_expr(parent_scope);
6749 ScopeDeferExpr *scope_defer_expr = get_scope_defer_expr(scope);
67176750 if (scope_defer_expr) {
67186751 if (!scope_defer_expr->reported_err) {
67196752 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
67246757
67256758 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);
67286761 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
67316764 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);
67336766 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);
6735 ir_build_store_ptr(irb, parent_scope, node, err_ret_trace_ptr_field_ptr, err_ret_trace_ptr);
6767 IrInstruction *err_ret_trace_ptr_field_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr, err_ret_trace_ptr_field_name);
6768 ir_build_store_ptr(irb, scope, node, err_ret_trace_ptr_field_ptr, err_ret_trace_ptr);
67366769 }
67376770
67386771 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,
67406773 atomic_state_field_name);
67416774
6742 IrInstruction *const_bool_false = ir_build_const_bool(irb, parent_scope, node, false);
6743 VariableTableEntry *result_var = ir_create_var(irb, node, parent_scope, nullptr,
6775 IrInstruction *const_bool_false = ir_build_const_bool(irb, scope, node, false);
6776 VariableTableEntry *result_var = ir_create_var(irb, node, scope, nullptr,
67446777 false, false, true, const_bool_false);
6745 IrInstruction *undefined_value = ir_build_const_undefined(irb, parent_scope, node);
6746 IrInstruction *target_promise_type = ir_build_typeof(irb, parent_scope, node, target_inst);
6747 IrInstruction *promise_result_type = ir_build_promise_result_type(irb, parent_scope, node, target_promise_type);
6748 ir_build_await_bookkeeping(irb, parent_scope, node, promise_result_type);
6749 ir_build_var_decl(irb, parent_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);
6751 ir_build_store_ptr(irb, parent_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);
6753 IrInstruction *usize_type_val = ir_build_const_type(irb, parent_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);
6755 IrInstruction *prev_atomic_value = ir_build_atomic_rmw(irb, parent_scope, node,
6778 IrInstruction *undefined_value = ir_build_const_undefined(irb, scope, node);
6779 IrInstruction *target_promise_type = ir_build_typeof(irb, scope, node, target_inst);
6780 IrInstruction *promise_result_type = ir_build_promise_result_type(irb, scope, node, target_promise_type);
6781 ir_build_await_bookkeeping(irb, scope, node, promise_result_type);
6782 ir_build_var_decl(irb, scope, node, result_var, promise_result_type, nullptr, undefined_value);
6783 IrInstruction *my_result_var_ptr = ir_build_var_ptr(irb, scope, node, result_var);
6784 ir_build_store_ptr(irb, scope, node, result_ptr_field_ptr, my_result_var_ptr);
6785 IrInstruction *save_token = ir_build_coro_save(irb, scope, node, irb->exec->coro_handle);
6786 IrInstruction *usize_type_val = ir_build_const_type(irb, scope, node, irb->codegen->builtin_types.entry_usize);
6787 IrInstruction *coro_handle_addr = ir_build_ptr_to_int(irb, scope, node, irb->exec->coro_handle);
6788 IrInstruction *prev_atomic_value = ir_build_atomic_rmw(irb, scope, node,
67566789 usize_type_val, atomic_state_ptr, nullptr, coro_handle_addr, nullptr,
67576790 AtomicRmwOp_or, AtomicOrderSeqCst);
6758 IrInstruction *zero = ir_build_const_usize(irb, parent_scope, node, 0);
6759 IrInstruction *inverted_ptr_mask = ir_build_const_usize(irb, parent_scope, node, 0x7); // 0b111
6760 IrInstruction *ptr_mask = ir_build_un_op(irb, parent_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);
6762 IrInstruction *is_non_null = ir_build_bin_op(irb, parent_scope, node, IrBinOpCmpNotEq, await_handle_addr, zero, false);
6763 IrBasicBlock *yes_suspend_block = ir_create_basic_block(irb, parent_scope, "YesSuspend");
6764 IrBasicBlock *no_suspend_block = ir_create_basic_block(irb, parent_scope, "NoSuspend");
6765 IrBasicBlock *merge_block = ir_create_basic_block(irb, parent_scope, "MergeSuspend");
6766 ir_build_cond_br(irb, parent_scope, node, is_non_null, no_suspend_block, yes_suspend_block, const_bool_false);
6791 IrInstruction *zero = ir_build_const_usize(irb, scope, node, 0);
6792 IrInstruction *inverted_ptr_mask = ir_build_const_usize(irb, scope, node, 0x7); // 0b111
6793 IrInstruction *ptr_mask = ir_build_un_op(irb, scope, node, IrUnOpBinNot, inverted_ptr_mask); // 0b111...000
6794 IrInstruction *await_handle_addr = ir_build_bin_op(irb, scope, node, IrBinOpBinAnd, prev_atomic_value, ptr_mask, false);
6795 IrInstruction *is_non_null = ir_build_bin_op(irb, scope, node, IrBinOpCmpNotEq, await_handle_addr, zero, false);
6796 IrBasicBlock *yes_suspend_block = ir_create_basic_block(irb, scope, "YesSuspend");
6797 IrBasicBlock *no_suspend_block = ir_create_basic_block(irb, scope, "NoSuspend");
6798 IrBasicBlock *merge_block = ir_create_basic_block(irb, scope, "MergeSuspend");
6799 ir_build_cond_br(irb, scope, node, is_non_null, no_suspend_block, yes_suspend_block, const_bool_false);
67676800
67686801 ir_set_cursor_at_end_and_append_block(irb, no_suspend_block);
67696802 if (irb->codegen->have_err_ret_tracing) {
67706803 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);
6772 IrInstruction *dest_err_ret_trace_ptr = ir_build_error_return_trace(irb, parent_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);
6804 IrInstruction *src_err_ret_trace_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr, err_ret_trace_field_name);
6805 IrInstruction *dest_err_ret_trace_ptr = ir_build_error_return_trace(irb, scope, node, IrInstructionErrorReturnTrace::NonNull);
6806 ir_build_merge_err_ret_traces(irb, scope, node, coro_promise_ptr, src_err_ret_trace_ptr, dest_err_ret_trace_ptr);
67746807 }
67756808 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);
67776810 // If the type of the result handle_is_ptr then this does not actually perform a load. But we need it to,
67786811 // 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);
6780 ir_build_store_ptr(irb, parent_scope, node, my_result_var_ptr, no_suspend_result);
6781 ir_build_cancel(irb, parent_scope, node, target_inst);
6782 ir_build_br(irb, parent_scope, node, merge_block, const_bool_false);
6812 IrInstruction *no_suspend_result = ir_build_load_ptr(irb, scope, node, promise_result_ptr);
6813 ir_build_store_ptr(irb, scope, node, my_result_var_ptr, no_suspend_result);
6814 ir_build_cancel(irb, scope, node, target_inst);
6815 ir_build_br(irb, scope, node, merge_block, const_bool_false);
67836816
67846817 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);
6786 IrBasicBlock *cleanup_block = ir_create_basic_block(irb, parent_scope, "SuspendCleanup");
6787 IrBasicBlock *resume_block = ir_create_basic_block(irb, parent_scope, "SuspendResume");
6818 IrInstruction *suspend_code = ir_build_coro_suspend(irb, scope, node, save_token, const_bool_false);
6819 IrBasicBlock *cleanup_block = ir_create_basic_block(irb, scope, "SuspendCleanup");
6820 IrBasicBlock *resume_block = ir_create_basic_block(irb, scope, "SuspendResume");
67886821
67896822 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);
67916824 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);
67936826 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,
67956828 2, cases, const_bool_false, nullptr);
67966829
67976830 ir_set_cursor_at_end_and_append_block(irb, cleanup_block);
6798 ir_gen_defers_for_block(irb, parent_scope, outer_scope, true);
6799 ir_mark_gen(ir_build_br(irb, parent_scope, node, irb->exec->coro_final_cleanup_block, const_bool_false));
6831 ir_gen_defers_for_block(irb, scope, outer_scope, true);
6832 ir_mark_gen(ir_build_br(irb, scope, node, irb->exec->coro_final_cleanup_block, const_bool_false));
68006833
68016834 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
68046837 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);
68066839}
68076840
68086841static IrInstruction *ir_gen_suspend(IrBuilder *irb, Scope *parent_scope, AstNode *node) {