| ... | ... | @@ -3097,31 +3097,26 @@ static IrInstruction *ir_gen_async_return(IrBuilder *irb, Scope *scope, AstNode |
| 3097 | 3097 | return return_inst; |
| 3098 | 3098 | } |
| 3099 | 3099 | |
| 3100 | | IrBasicBlock *canceled_block = ir_create_basic_block(irb, scope, "Canceled"); |
| 3101 | | IrBasicBlock *not_canceled_block = ir_create_basic_block(irb, scope, "NotCanceled"); |
| 3102 | 3100 | IrBasicBlock *suspended_block = ir_create_basic_block(irb, scope, "Suspended"); |
| 3103 | 3101 | IrBasicBlock *not_suspended_block = ir_create_basic_block(irb, scope, "NotSuspended"); |
| 3102 | IrBasicBlock *store_awaiter_block = ir_create_basic_block(irb, scope, "StoreAwaiter"); |
| 3103 | IrBasicBlock *check_canceled_block = ir_create_basic_block(irb, scope, "CheckCanceled"); |
| 3104 | |
| 3105 | IrInstruction *inverted_ptr_mask = ir_build_const_usize(irb, scope, node, 0x7); // 0b111 |
| 3106 | IrInstruction *ptr_mask = ir_build_un_op(irb, scope, node, IrUnOpBinNot, inverted_ptr_mask); // 0b111...000 |
| 3107 | IrInstruction *is_canceled_mask = ir_build_const_usize(irb, scope, node, 0x1); // 0b001 |
| 3108 | IrInstruction *is_suspended_mask = ir_build_const_usize(irb, scope, node, 0x2); // 0b010 |
| 3109 | IrInstruction *promise_type_val = ir_build_const_type(irb, scope, node, irb->codegen->builtin_types.entry_promise); |
| 3110 | IrInstruction *is_comptime = ir_build_const_bool(irb, scope, node, false); |
| 3111 | IrInstruction *zero = ir_build_const_usize(irb, scope, node, 0); |
| 3104 | 3112 | |
| 3105 | 3113 | ir_build_store_ptr(irb, scope, node, irb->exec->coro_result_field_ptr, return_value); |
| 3106 | 3114 | IrInstruction *usize_type_val = ir_build_const_type(irb, scope, node, irb->codegen->builtin_types.entry_usize); |
| 3107 | | IrInstruction *replacement_value = ir_build_const_usize(irb, scope, node, 0xa); // 0b1010 |
| 3108 | 3115 | IrInstruction *prev_atomic_value = ir_build_atomic_rmw(irb, scope, node, |
| 3109 | | usize_type_val, irb->exec->coro_awaiter_field_ptr, nullptr, replacement_value, nullptr, |
| 3116 | usize_type_val, irb->exec->atomic_state_field_ptr, nullptr, ptr_mask, nullptr, |
| 3110 | 3117 | AtomicRmwOp_or, AtomicOrderSeqCst); |
| 3111 | 3118 | |
| 3112 | | IrInstruction *zero = ir_build_const_usize(irb, scope, node, 0); |
| 3113 | | IrInstruction *is_comptime = ir_build_const_bool(irb, scope, node, false); |
| 3114 | | IrInstruction *is_canceled_mask = ir_build_const_usize(irb, scope, node, 0x1); // 0b001 |
| 3115 | | IrInstruction *is_canceled_value = ir_build_bin_op(irb, scope, node, IrBinOpBinAnd, prev_atomic_value, is_canceled_mask, false); |
| 3116 | | IrInstruction *is_canceled_bool = ir_build_bin_op(irb, scope, node, IrBinOpCmpNotEq, is_canceled_value, zero, false); |
| 3117 | | ir_build_cond_br(irb, scope, node, is_canceled_bool, canceled_block, not_canceled_block, is_comptime); |
| 3118 | | |
| 3119 | | ir_set_cursor_at_end_and_append_block(irb, canceled_block); |
| 3120 | | ir_mark_gen(ir_build_br(irb, scope, node, irb->exec->coro_final_cleanup_block, is_comptime)); |
| 3121 | | |
| 3122 | | ir_set_cursor_at_end_and_append_block(irb, not_canceled_block); |
| 3123 | | IrInstruction *inverted_ptr_mask = ir_build_const_usize(irb, scope, node, 0x7); // 0b111 |
| 3124 | | IrInstruction *is_suspended_value = ir_build_bin_op(irb, scope, node, IrBinOpBinAnd, prev_atomic_value, inverted_ptr_mask, false); |
| 3119 | IrInstruction *is_suspended_value = ir_build_bin_op(irb, scope, node, IrBinOpBinAnd, prev_atomic_value, is_suspended_mask, false); |
| 3125 | 3120 | IrInstruction *is_suspended_bool = ir_build_bin_op(irb, scope, node, IrBinOpCmpNotEq, is_suspended_value, zero, false); |
| 3126 | 3121 | ir_build_cond_br(irb, scope, node, is_suspended_bool, suspended_block, not_suspended_block, is_comptime); |
| 3127 | 3122 | |
| ... | ... | @@ -3129,16 +3124,20 @@ static IrInstruction *ir_gen_async_return(IrBuilder *irb, Scope *scope, AstNode |
| 3129 | 3124 | ir_build_unreachable(irb, scope, node); |
| 3130 | 3125 | |
| 3131 | 3126 | ir_set_cursor_at_end_and_append_block(irb, not_suspended_block); |
| 3132 | | IrInstruction *ptr_mask = ir_build_un_op(irb, scope, node, IrUnOpBinNot, inverted_ptr_mask); // 0b111...000 |
| 3133 | 3127 | IrInstruction *await_handle_addr = ir_build_bin_op(irb, scope, node, IrBinOpBinAnd, prev_atomic_value, ptr_mask, false); |
| 3134 | | IrInstruction *promise_type_val = ir_build_const_type(irb, scope, node, irb->codegen->builtin_types.entry_promise); |
| 3135 | 3128 | // if we ever add null checking safety to the ptrtoint instruction, it needs to be disabled here |
| 3129 | IrInstruction *have_await_handle = ir_build_bin_op(irb, scope, node, IrBinOpCmpNotEq, await_handle_addr, zero, false); |
| 3130 | ir_build_cond_br(irb, scope, node, have_await_handle, store_awaiter_block, check_canceled_block, is_comptime); |
| 3131 | |
| 3132 | ir_set_cursor_at_end_and_append_block(irb, store_awaiter_block); |
| 3136 | 3133 | IrInstruction *await_handle = ir_build_int_to_ptr(irb, scope, node, promise_type_val, await_handle_addr); |
| 3137 | 3134 | ir_build_store_ptr(irb, scope, node, irb->exec->await_handle_var_ptr, await_handle); |
| 3138 | | IrInstruction *is_non_null = ir_build_bin_op(irb, scope, node, IrBinOpCmpNotEq, await_handle_addr, zero, false); |
| 3139 | | return ir_build_cond_br(irb, scope, node, is_non_null, irb->exec->coro_normal_final, |
| 3140 | | irb->exec->coro_early_final, is_comptime); |
| 3141 | | // the above blocks are rendered by ir_gen after the rest of codegen |
| 3135 | ir_build_br(irb, scope, node, irb->exec->coro_normal_final, is_comptime); |
| 3136 | |
| 3137 | ir_set_cursor_at_end_and_append_block(irb, check_canceled_block); |
| 3138 | IrInstruction *is_canceled_value = ir_build_bin_op(irb, scope, node, IrBinOpBinAnd, prev_atomic_value, is_canceled_mask, false); |
| 3139 | IrInstruction *is_canceled_bool = ir_build_bin_op(irb, scope, node, IrBinOpCmpNotEq, is_canceled_value, zero, false); |
| 3140 | return ir_build_cond_br(irb, scope, node, is_canceled_bool, irb->exec->coro_final_cleanup_block, irb->exec->coro_early_final, is_comptime); |
| 3142 | 3141 | } |
| 3143 | 3142 | |
| 3144 | 3143 | static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node, LVal lval) { |
| ... | ... | @@ -7120,10 +7119,10 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec |
| 7120 | 7119 | irb->exec->coro_handle = ir_build_coro_begin(irb, coro_scope, node, coro_id, coro_mem_ptr); |
| 7121 | 7120 | |
| 7122 | 7121 | Buf *atomic_state_field_name = buf_create_from_str(ATOMIC_STATE_FIELD_NAME); |
| 7123 | | irb->exec->coro_awaiter_field_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr, |
| 7122 | irb->exec->atomic_state_field_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr, |
| 7124 | 7123 | atomic_state_field_name); |
| 7125 | 7124 | IrInstruction *zero = ir_build_const_usize(irb, scope, node, 0); |
| 7126 | | ir_build_store_ptr(irb, scope, node, irb->exec->coro_awaiter_field_ptr, zero); |
| 7125 | ir_build_store_ptr(irb, scope, node, irb->exec->atomic_state_field_ptr, zero); |
| 7127 | 7126 | Buf *result_field_name = buf_create_from_str(RESULT_FIELD_NAME); |
| 7128 | 7127 | irb->exec->coro_result_field_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr, result_field_name); |
| 7129 | 7128 | result_ptr_field_name = buf_create_from_str(RESULT_PTR_FIELD_NAME); |