| ... | @@ -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 | } |
| 6688 | | 6688 | |
| 6689 | static IrInstruction *ir_gen_resume(IrBuilder *irb, Scope *parent_scope, AstNode *node) { | 6689 | static IrInstruction *ir_gen_resume(IrBuilder *irb, Scope *scope, AstNode *node) { |
| 6690 | assert(node->type == NodeTypeResume); | 6690 | assert(node->type == NodeTypeResume); |
| 6691 | | 6691 | |
| 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; |
| 6695 | | 6695 | |
| 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 | } |
| 6698 | | 6731 | |
| 6699 | static IrInstruction *ir_gen_await_expr(IrBuilder *irb, Scope *parent_scope, AstNode *node) { | 6732 | static IrInstruction *ir_gen_await_expr(IrBuilder *irb, Scope *scope, AstNode *node) { |
| 6700 | assert(node->type == NodeTypeAwaitExpr); | 6733 | assert(node->type == NodeTypeAwaitExpr); |
| 6701 | | 6734 | |
| 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; |
| 6705 | | 6738 | |
| ... | @@ -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 | } |
| 6715 | | 6748 | |
| 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 |
| 6724 | | 6757 | |
| 6725 | Scope *outer_scope = irb->exec->begin_scope; | 6758 | Scope *outer_scope = irb->exec->begin_scope; |
| 6726 | | 6759 | |
| 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); |
| 6730 | | 6763 | |
| 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 | } |
| 6737 | | 6770 | |
| 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); |
| 6741 | | 6774 | |
| 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); // 0b111 | 6792 | 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...000 | 6793 | 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); |
| 6767 | | 6800 | |
| 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); |
| 6783 | | 6816 | |
| 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"); |
| 6788 | | 6821 | |
| 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); |
| 6796 | | 6829 | |
| 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)); |
| 6800 | | 6833 | |
| 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); |
| 6803 | | 6836 | |
| 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 | } |
| 6807 | | 6840 | |
| 6808 | static IrInstruction *ir_gen_suspend(IrBuilder *irb, Scope *parent_scope, AstNode *node) { | 6841 | static IrInstruction *ir_gen_suspend(IrBuilder *irb, Scope *parent_scope, AstNode *node) { |