authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-07-29 23:25:40-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-07-29 23:25:40-04:00
log09304aab77a7b6af5693600fa6b3a35322f7469d
tree82528045894e188bd7c5a22a23eb6b5ed6aa8b7e
parent0d79e0381601404b844b4912d15d20f4b529e837

fix cancel and await semantics


2 files changed, 50 insertions(+), 25 deletions(-)

src/ir.cpp+38-23
......@@ -6663,7 +6663,9 @@ static IrInstruction *ir_gen_fn_proto(IrBuilder *irb, Scope *parent_scope, AstNo
66636663 async_allocator_type_value, is_var_args);
66646664}
66656665
6666static IrInstruction *ir_gen_cancel_target(IrBuilder *irb, Scope *scope, AstNode *node, IrInstruction *target_inst) {
6666static IrInstruction *ir_gen_cancel_target(IrBuilder *irb, Scope *scope, AstNode *node,
6667 IrInstruction *target_inst, bool cancel_non_suspended, bool cancel_awaited)
6668{
66676669 IrBasicBlock *done_block = ir_create_basic_block(irb, scope, "CancelDone");
66686670 IrBasicBlock *not_canceled_block = ir_create_basic_block(irb, scope, "NotCanceled");
66696671 IrBasicBlock *pre_return_block = ir_create_basic_block(irb, scope, "PreReturn");
......@@ -6691,7 +6693,7 @@ static IrInstruction *ir_gen_cancel_target(IrBuilder *irb, Scope *scope, AstNode
66916693 // set the is_canceled bit
66926694 IrInstruction *prev_atomic_value = ir_build_atomic_rmw(irb, scope, node,
66936695 usize_type_val, atomic_state_ptr, nullptr, is_canceled_mask, nullptr,
6694 AtomicRmwOp_and, AtomicOrderSeqCst);
6696 AtomicRmwOp_or, AtomicOrderSeqCst);
66956697
66966698 IrInstruction *is_canceled_value = ir_build_bin_op(irb, scope, node, IrBinOpBinAnd, prev_atomic_value, is_canceled_mask, false);
66976699 IrInstruction *is_canceled_bool = ir_build_bin_op(irb, scope, node, IrBinOpCmpNotEq, is_canceled_value, zero, false);
......@@ -6703,14 +6705,26 @@ static IrInstruction *ir_gen_cancel_target(IrBuilder *irb, Scope *scope, AstNode
67036705 ir_build_cond_br(irb, scope, node, is_returned_bool, post_return_block, pre_return_block, is_comptime);
67046706
67056707 ir_set_cursor_at_end_and_append_block(irb, post_return_block);
6706 IrInstruction *is_awaited_value = ir_build_bin_op(irb, scope, node, IrBinOpBinAnd, prev_atomic_value, await_mask, false);
6707 IrInstruction *is_awaited_bool = ir_build_bin_op(irb, scope, node, IrBinOpCmpNotEq, is_awaited_value, zero, false);
6708 ir_build_cond_br(irb, scope, node, is_awaited_bool, done_block, do_cancel_block, is_comptime);
6708 if (cancel_awaited) {
6709 ir_build_br(irb, scope, node, do_cancel_block, is_comptime);
6710 } else {
6711 IrInstruction *is_awaited_value = ir_build_bin_op(irb, scope, node, IrBinOpBinAnd, prev_atomic_value, await_mask, false);
6712 IrInstruction *is_awaited_bool = ir_build_bin_op(irb, scope, node, IrBinOpCmpNotEq, is_awaited_value, zero, false);
6713 ir_build_cond_br(irb, scope, node, is_awaited_bool, done_block, do_cancel_block, is_comptime);
6714 }
67096715
67106716 ir_set_cursor_at_end_and_append_block(irb, pre_return_block);
6711 IrInstruction *is_suspended_value = ir_build_bin_op(irb, scope, node, IrBinOpBinAnd, prev_atomic_value, is_suspended_mask, false);
6712 IrInstruction *is_suspended_bool = ir_build_bin_op(irb, scope, node, IrBinOpCmpNotEq, is_suspended_value, zero, false);
6713 ir_build_cond_br(irb, scope, node, is_suspended_bool, do_cancel_block, done_block, is_comptime);
6717 if (cancel_awaited) {
6718 if (cancel_non_suspended) {
6719 ir_build_br(irb, scope, node, do_cancel_block, is_comptime);
6720 } else {
6721 IrInstruction *is_suspended_value = ir_build_bin_op(irb, scope, node, IrBinOpBinAnd, prev_atomic_value, is_suspended_mask, false);
6722 IrInstruction *is_suspended_bool = ir_build_bin_op(irb, scope, node, IrBinOpCmpNotEq, is_suspended_value, zero, false);
6723 ir_build_cond_br(irb, scope, node, is_suspended_bool, do_cancel_block, done_block, is_comptime);
6724 }
6725 } else {
6726 ir_build_br(irb, scope, node, done_block, is_comptime);
6727 }
67146728
67156729 ir_set_cursor_at_end_and_append_block(irb, do_cancel_block);
67166730 ir_build_cancel(irb, scope, node, target_inst);
......@@ -6727,7 +6741,7 @@ static IrInstruction *ir_gen_cancel(IrBuilder *irb, Scope *scope, AstNode *node)
67276741 if (target_inst == irb->codegen->invalid_instruction)
67286742 return irb->codegen->invalid_instruction;
67296743
6730 return ir_gen_cancel_target(irb, scope, node, target_inst);
6744 return ir_gen_cancel_target(irb, scope, node, target_inst, false, true);
67316745}
67326746
67336747static IrInstruction *ir_gen_resume(IrBuilder *irb, Scope *scope, AstNode *node) {
......@@ -6872,15 +6886,19 @@ static IrInstruction *ir_gen_await_expr(IrBuilder *irb, Scope *scope, AstNode *n
68726886 ir_build_unreachable(irb, scope, node);
68736887
68746888 ir_set_cursor_at_end_and_append_block(irb, not_awaited_block);
6889 IrInstruction *await_handle_addr = ir_build_bin_op(irb, scope, node, IrBinOpBinAnd, prev_atomic_value, ptr_mask, false);
6890 IrInstruction *is_non_null = ir_build_bin_op(irb, scope, node, IrBinOpCmpNotEq, await_handle_addr, zero, false);
68756891 IrInstruction *is_canceled_value = ir_build_bin_op(irb, scope, node, IrBinOpBinAnd, prev_atomic_value, is_canceled_mask, false);
68766892 IrInstruction *is_canceled_bool = ir_build_bin_op(irb, scope, node, IrBinOpCmpNotEq, is_canceled_value, zero, false);
6877 ir_build_cond_br(irb, scope, node, is_canceled_bool, cleanup_block, not_canceled_block, const_bool_false);
6893 ir_build_cond_br(irb, scope, node, is_canceled_bool, cancel_target_block, not_canceled_block, const_bool_false);
68786894
68796895 ir_set_cursor_at_end_and_append_block(irb, not_canceled_block);
6880 IrInstruction *await_handle_addr = ir_build_bin_op(irb, scope, node, IrBinOpBinAnd, prev_atomic_value, ptr_mask, false);
6881 IrInstruction *is_non_null = ir_build_bin_op(irb, scope, node, IrBinOpCmpNotEq, await_handle_addr, zero, false);
68826896 ir_build_cond_br(irb, scope, node, is_non_null, no_suspend_block, yes_suspend_block, const_bool_false);
68836897
6898 ir_set_cursor_at_end_and_append_block(irb, cancel_target_block);
6899 ir_build_cancel(irb, scope, node, target_inst);
6900 ir_mark_gen(ir_build_br(irb, scope, node, cleanup_block, const_bool_false));
6901
68846902 ir_set_cursor_at_end_and_append_block(irb, no_suspend_block);
68856903 if (irb->codegen->have_err_ret_tracing) {
68866904 Buf *err_ret_trace_field_name = buf_create_from_str(ERR_RET_TRACE_FIELD_NAME);
......@@ -6897,6 +6915,7 @@ static IrInstruction *ir_gen_await_expr(IrBuilder *irb, Scope *scope, AstNode *n
68976915 ir_build_cancel(irb, scope, node, target_inst);
68986916 ir_build_br(irb, scope, node, merge_block, const_bool_false);
68996917
6918
69006919 ir_set_cursor_at_end_and_append_block(irb, yes_suspend_block);
69016920 IrInstruction *suspend_code = ir_build_coro_suspend(irb, scope, node, save_token, const_bool_false);
69026921
......@@ -6904,32 +6923,28 @@ static IrInstruction *ir_gen_await_expr(IrBuilder *irb, Scope *scope, AstNode *n
69046923 cases[0].value = ir_build_const_u8(irb, scope, node, 0);
69056924 cases[0].block = resume_block;
69066925 cases[1].value = ir_build_const_u8(irb, scope, node, 1);
6907 cases[1].block = cancel_target_block;
6926 cases[1].block = cleanup_block;
69086927 ir_build_switch_br(irb, scope, node, suspend_code, irb->exec->coro_suspend_block,
69096928 2, cases, const_bool_false, nullptr);
69106929
6911 ir_set_cursor_at_end_and_append_block(irb, cancel_target_block);
6912 IrInstruction *await_handle = ir_build_int_to_ptr(irb, scope, node, promise_type_val, await_handle_addr);
6913 ir_gen_cancel_target(irb, scope, node, await_handle);
6914 ir_mark_gen(ir_build_br(irb, scope, node, cleanup_block, const_bool_false));
6915
69166930 ir_set_cursor_at_end_and_append_block(irb, cleanup_block);
69176931 IrInstruction *my_mask_bits = ir_build_bin_op(irb, scope, node, IrBinOpBinOr, ptr_mask, is_canceled_mask, false);
69186932 IrInstruction *my_prev_atomic_value = ir_build_atomic_rmw(irb, scope, node,
69196933 usize_type_val, irb->exec->atomic_state_field_ptr, nullptr, my_mask_bits, nullptr,
69206934 AtomicRmwOp_or, AtomicOrderSeqCst);
69216935 IrInstruction *my_await_handle_addr = ir_build_bin_op(irb, scope, node, IrBinOpBinAnd, my_prev_atomic_value, ptr_mask, false);
6922 IrInstruction *have_my_await_handle = ir_build_bin_op(irb, scope, node, IrBinOpCmpNotEq, my_await_handle_addr, zero, false);
6923 ir_build_cond_br(irb, scope, node, have_my_await_handle, do_cancel_block, do_defers_block, const_bool_false);
6936 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);
6938 ir_build_cond_br(irb, scope, node, dont_have_my_await_handle, do_defers_block, do_cancel_block, const_bool_false);
69246939
69256940 ir_set_cursor_at_end_and_append_block(irb, do_cancel_block);
69266941 IrInstruction *my_await_handle = ir_build_int_to_ptr(irb, scope, node, promise_type_val, my_await_handle_addr);
6927 ir_gen_cancel_target(irb, scope, node, my_await_handle);
6942 ir_gen_cancel_target(irb, scope, node, my_await_handle, true, false);
69286943 ir_mark_gen(ir_build_br(irb, scope, node, do_defers_block, const_bool_false));
69296944
69306945 ir_set_cursor_at_end_and_append_block(irb, do_defers_block);
69316946 ir_gen_defers_for_block(irb, scope, outer_scope, true);
6932 ir_mark_gen(ir_build_br(irb, scope, node, irb->exec->coro_final_cleanup_block, const_bool_false));
6947 ir_mark_gen(ir_build_cond_br(irb, scope, node, dont_destroy_ourselves, irb->exec->coro_early_final, irb->exec->coro_final_cleanup_block, const_bool_false));
69336948
69346949 ir_set_cursor_at_end_and_append_block(irb, resume_block);
69356950 ir_build_br(irb, scope, node, merge_block, const_bool_false);
......@@ -7004,7 +7019,7 @@ static IrInstruction *ir_gen_suspend(IrBuilder *irb, Scope *parent_scope, AstNod
70047019
70057020 ir_set_cursor_at_end_and_append_block(irb, cancel_awaiter_block);
70067021 IrInstruction *await_handle = ir_build_int_to_ptr(irb, parent_scope, node, promise_type_val, await_handle_addr);
7007 ir_gen_cancel_target(irb, parent_scope, node, await_handle);
7022 ir_gen_cancel_target(irb, parent_scope, node, await_handle, true, false);
70087023 ir_build_br(irb, parent_scope, node, cleanup_block, const_bool_false);
70097024
70107025 ir_set_cursor_at_end_and_append_block(irb, not_canceled_block);
std/debug/index.zig+12-2
......@@ -27,7 +27,7 @@ pub fn warn(comptime fmt: []const u8, args: ...) void {
2727 const stderr = getStderrStream() catch return;
2828 stderr.print(fmt, args) catch return;
2929}
30fn getStderrStream() !*io.OutStream(io.FileOutStream.Error) {
30pub fn getStderrStream() !*io.OutStream(io.FileOutStream.Error) {
3131 if (stderr_stream) |st| {
3232 return st;
3333 } else {
......@@ -172,6 +172,16 @@ pub fn writeStackTrace(stack_trace: *const builtin.StackTrace, out_stream: var,
172172 }
173173}
174174
175pub inline fn getReturnAddress(frame_count: usize) usize {
176 var fp = @ptrToInt(@frameAddress());
177 var i: usize = 0;
178 while (fp != 0 and i < frame_count) {
179 fp = @intToPtr(*const usize, fp).*;
180 i += 1;
181 }
182 return @intToPtr(*const usize, fp + @sizeOf(usize)).*;
183}
184
175185pub fn writeCurrentStackTrace(out_stream: var, allocator: *mem.Allocator, debug_info: *ElfStackTrace, tty_color: bool, start_addr: ?usize) !void {
176186 const AddressState = union(enum) {
177187 NotLookingForStartAddress,
......@@ -205,7 +215,7 @@ pub fn writeCurrentStackTrace(out_stream: var, allocator: *mem.Allocator, debug_
205215 }
206216}
207217
208fn printSourceAtAddress(debug_info: *ElfStackTrace, out_stream: var, address: usize, tty_color: bool) !void {
218pub fn printSourceAtAddress(debug_info: *ElfStackTrace, out_stream: var, address: usize, tty_color: bool) !void {
209219 switch (builtin.os) {
210220 builtin.Os.windows => return error.UnsupportedDebugInfo,
211221 builtin.Os.macosx => {