authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-04-08 17:44:29-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-04-08 17:44:29-04:00
logee1a4f4c1d888d1485d8bb13ee0fa756bf729b08
tree151da8064d7f08e1f56b13c4a2ef73d2148aa450
parent9e98ea552dcf03a4a05a920c8f027d09130dd688

error return traces work with async return case


6 files changed, 56 insertions(+), 19 deletions(-)

src/all_types.hpp+8-4
......@@ -3037,7 +3037,8 @@ struct IrInstructionMergeErrRetTraces {
30373037 IrInstruction base;
30383038
30393039 IrInstruction *coro_promise_ptr;
3040 IrInstruction *err_ret_trace_ptr;
3040 IrInstruction *src_err_ret_trace_ptr;
3041 IrInstruction *dest_err_ret_trace_ptr;
30413042};
30423043
30433044struct IrInstructionMarkErrRetTracePtr {
......@@ -3058,13 +3059,16 @@ static const size_t err_union_payload_index = 1;
30583059// TODO call graph analysis to find out what this number needs to be for every function
30593060static const size_t stack_trace_ptr_count = 30;
30603061
3062// these belong to the async function
3063#define RETURN_ADDRESSES_FIELD_NAME "return_addresses"
3064#define ERR_RET_TRACE_FIELD_NAME "err_ret_trace"
3065#define RESULT_FIELD_NAME "result"
30613066#define ASYNC_ALLOC_FIELD_NAME "allocFn"
30623067#define ASYNC_FREE_FIELD_NAME "freeFn"
30633068#define AWAITER_HANDLE_FIELD_NAME "awaiter_handle"
3064#define RESULT_FIELD_NAME "result"
3069// these point to data belonging to the awaiter
3070#define ERR_RET_TRACE_PTR_FIELD_NAME "err_ret_trace_ptr"
30653071#define RESULT_PTR_FIELD_NAME "result_ptr"
3066#define RETURN_ADDRESSES_FIELD_NAME "return_addresses"
3067#define ERR_RET_TRACE_FIELD_NAME "err_ret_trace"
30683072
30693073
30703074enum FloatMode {
src/analyze.cpp+2-1
......@@ -474,6 +474,7 @@ TypeTableEntry *get_promise_frame_type(CodeGen *g, TypeTableEntry *return_type)
474474 field_names.append(RESULT_FIELD_NAME);
475475 field_names.append(RESULT_PTR_FIELD_NAME);
476476 if (g->have_err_ret_tracing) {
477 field_names.append(ERR_RET_TRACE_PTR_FIELD_NAME);
477478 field_names.append(ERR_RET_TRACE_FIELD_NAME);
478479 field_names.append(RETURN_ADDRESSES_FIELD_NAME);
479480 }
......@@ -483,7 +484,7 @@ TypeTableEntry *get_promise_frame_type(CodeGen *g, TypeTableEntry *return_type)
483484 field_types.append(return_type);
484485 field_types.append(result_ptr_type);
485486 if (g->have_err_ret_tracing) {
486 get_ptr_to_stack_trace_type(g);
487 field_types.append(get_ptr_to_stack_trace_type(g));
487488 field_types.append(g->stack_trace_type);
488489 field_types.append(get_array_type(g, g->builtin_types.entry_usize, stack_trace_ptr_count));
489490 }
src/codegen.cpp+2-2
......@@ -4383,8 +4383,8 @@ static LLVMValueRef ir_render_merge_err_ret_traces(CodeGen *g, IrExecutable *exe
43834383{
43844384 assert(g->have_err_ret_tracing);
43854385
4386 LLVMValueRef src_trace_ptr = ir_llvm_value(g, instruction->err_ret_trace_ptr);
4387 LLVMValueRef dest_trace_ptr = get_cur_err_ret_trace_val(g, instruction->base.scope);
4386 LLVMValueRef src_trace_ptr = ir_llvm_value(g, instruction->src_err_ret_trace_ptr);
4387 LLVMValueRef dest_trace_ptr = ir_llvm_value(g, instruction->dest_err_ret_trace_ptr);
43884388
43894389 LLVMValueRef args[] = { dest_trace_ptr, src_trace_ptr };
43904390 ZigLLVMBuildCall(g->builder, get_merge_err_ret_traces_fn_val(g), args, 2, get_llvm_cc(g, CallingConventionUnspecified), ZigLLVM_FnInlineAuto, "");
src/ir.cpp+33-10
......@@ -2708,14 +2708,16 @@ static IrInstruction *ir_build_add_implicit_return_type(IrBuilder *irb, Scope *s
27082708}
27092709
27102710static IrInstruction *ir_build_merge_err_ret_traces(IrBuilder *irb, Scope *scope, AstNode *source_node,
2711 IrInstruction *coro_promise_ptr, IrInstruction *err_ret_trace_ptr)
2711 IrInstruction *coro_promise_ptr, IrInstruction *src_err_ret_trace_ptr, IrInstruction *dest_err_ret_trace_ptr)
27122712{
27132713 IrInstructionMergeErrRetTraces *instruction = ir_build_instruction<IrInstructionMergeErrRetTraces>(irb, scope, source_node);
27142714 instruction->coro_promise_ptr = coro_promise_ptr;
2715 instruction->err_ret_trace_ptr = err_ret_trace_ptr;
2715 instruction->src_err_ret_trace_ptr = src_err_ret_trace_ptr;
2716 instruction->dest_err_ret_trace_ptr = dest_err_ret_trace_ptr;
27162717
27172718 ir_ref_instruction(coro_promise_ptr, irb->current_basic_block);
2718 ir_ref_instruction(err_ret_trace_ptr, irb->current_basic_block);
2719 ir_ref_instruction(src_err_ret_trace_ptr, irb->current_basic_block);
2720 ir_ref_instruction(dest_err_ret_trace_ptr, irb->current_basic_block);
27192721
27202722 return &instruction->base;
27212723}
......@@ -6115,6 +6117,13 @@ static IrInstruction *ir_gen_await_expr(IrBuilder *irb, Scope *parent_scope, Ast
61156117 Buf *result_ptr_field_name = buf_create_from_str(RESULT_PTR_FIELD_NAME);
61166118 IrInstruction *result_ptr_field_ptr = ir_build_field_ptr(irb, parent_scope, node, coro_promise_ptr, result_ptr_field_name);
61176119
6120 if (irb->codegen->have_err_ret_tracing) {
6121 IrInstruction *err_ret_trace_ptr = ir_build_error_return_trace(irb, parent_scope, node, IrInstructionErrorReturnTrace::NonNull);
6122 Buf *err_ret_trace_ptr_field_name = buf_create_from_str(ERR_RET_TRACE_PTR_FIELD_NAME);
6123 IrInstruction *err_ret_trace_ptr_field_ptr = ir_build_field_ptr(irb, parent_scope, node, coro_promise_ptr, err_ret_trace_ptr_field_name);
6124 ir_build_store_ptr(irb, parent_scope, node, err_ret_trace_ptr_field_ptr, err_ret_trace_ptr);
6125 }
6126
61186127 Buf *awaiter_handle_field_name = buf_create_from_str(AWAITER_HANDLE_FIELD_NAME);
61196128 IrInstruction *awaiter_field_ptr = ir_build_field_ptr(irb, parent_scope, node, coro_promise_ptr,
61206129 awaiter_handle_field_name);
......@@ -6144,8 +6153,9 @@ static IrInstruction *ir_gen_await_expr(IrBuilder *irb, Scope *parent_scope, Ast
61446153 ir_set_cursor_at_end_and_append_block(irb, no_suspend_block);
61456154 if (irb->codegen->have_err_ret_tracing) {
61466155 Buf *err_ret_trace_field_name = buf_create_from_str(ERR_RET_TRACE_FIELD_NAME);
6147 IrInstruction *err_ret_trace_ptr = ir_build_field_ptr(irb, parent_scope, node, coro_promise_ptr, err_ret_trace_field_name);
6148 ir_build_merge_err_ret_traces(irb, parent_scope, node, coro_promise_ptr, err_ret_trace_ptr);
6156 IrInstruction *src_err_ret_trace_ptr = ir_build_field_ptr(irb, parent_scope, node, coro_promise_ptr, err_ret_trace_field_name);
6157 IrInstruction *dest_err_ret_trace_ptr = ir_build_error_return_trace(irb, parent_scope, node, IrInstructionErrorReturnTrace::NonNull);
6158 ir_build_merge_err_ret_traces(irb, parent_scope, node, coro_promise_ptr, src_err_ret_trace_ptr, dest_err_ret_trace_ptr);
61496159 }
61506160 Buf *result_field_name = buf_create_from_str(RESULT_FIELD_NAME);
61516161 IrInstruction *promise_result_ptr = ir_build_field_ptr(irb, parent_scope, node, coro_promise_ptr, result_field_name);
......@@ -6402,6 +6412,8 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec
64026412 IrInstruction *coro_id;
64036413 IrInstruction *u8_ptr_type;
64046414 IrInstruction *const_bool_false;
6415 IrInstruction *coro_promise_ptr;
6416 IrInstruction *err_ret_trace_ptr;
64056417 TypeTableEntry *return_type;
64066418 Buf *result_ptr_field_name;
64076419 VariableTableEntry *coro_size_var;
......@@ -6417,7 +6429,7 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec
64176429 IrInstruction *coro_frame_type_value = ir_build_const_type(irb, coro_scope, node, coro_frame_type);
64186430 // TODO mark this var decl as "no safety" e.g. disable initializing the undef value to 0xaa
64196431 ir_build_var_decl(irb, coro_scope, node, promise_var, coro_frame_type_value, nullptr, undef);
6420 IrInstruction *coro_promise_ptr = ir_build_var_ptr(irb, coro_scope, node, promise_var, false, false);
6432 coro_promise_ptr = ir_build_var_ptr(irb, coro_scope, node, promise_var, false, false);
64216433
64226434 VariableTableEntry *await_handle_var = ir_create_var(irb, node, coro_scope, nullptr, false, false, true, const_bool_false);
64236435 IrInstruction *null_value = ir_build_const_null(irb, coro_scope, node);
......@@ -6471,7 +6483,7 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec
64716483 IrInstruction *return_addresses_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr, return_addresses_field_name);
64726484
64736485 Buf *err_ret_trace_field_name = buf_create_from_str(ERR_RET_TRACE_FIELD_NAME);
6474 IrInstruction *err_ret_trace_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr, err_ret_trace_field_name);
6486 err_ret_trace_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr, err_ret_trace_field_name);
64756487 ir_build_mark_err_ret_trace_ptr(irb, scope, node, err_ret_trace_ptr);
64766488
64776489 // coordinate with builtin.zig
......@@ -6536,6 +6548,12 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec
65366548 IrInstruction *size_of_ret_val = ir_build_size_of(irb, scope, node, return_type_inst);
65376549 ir_build_memcpy(irb, scope, node, result_ptr_as_u8_ptr, return_value_ptr_as_u8_ptr, size_of_ret_val);
65386550 }
6551 if (irb->codegen->have_err_ret_tracing) {
6552 Buf *err_ret_trace_ptr_field_name = buf_create_from_str(ERR_RET_TRACE_PTR_FIELD_NAME);
6553 IrInstruction *err_ret_trace_ptr_field_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr, err_ret_trace_ptr_field_name);
6554 IrInstruction *dest_err_ret_trace_ptr = ir_build_load_ptr(irb, scope, node, err_ret_trace_ptr_field_ptr);
6555 ir_build_merge_err_ret_traces(irb, scope, node, coro_promise_ptr, err_ret_trace_ptr, dest_err_ret_trace_ptr);
6556 }
65396557 ir_build_br(irb, scope, node, check_free_block, const_bool_false);
65406558
65416559 ir_set_cursor_at_end_and_append_block(irb, irb->exec->coro_final_cleanup_block);
......@@ -13098,6 +13116,7 @@ static IrInstruction *ir_analyze_container_member_access_inner(IrAnalyze *ira,
1309813116{
1309913117 if (!is_slice(bare_struct_type)) {
1310013118 ScopeDecls *container_scope = get_container_scope(bare_struct_type);
13119 assert(container_scope != nullptr);
1310113120 auto entry = container_scope->decl_table.maybe_get(field_name);
1310213121 Tld *tld = entry ? entry->value : nullptr;
1310313122 if (tld && tld->id == TldIdFn) {
......@@ -17948,12 +17967,16 @@ static TypeTableEntry *ir_analyze_instruction_merge_err_ret_traces(IrAnalyze *ir
1794817967 return out_val->type;
1794917968 }
1795017969
17951 IrInstruction *err_ret_trace_ptr = instruction->err_ret_trace_ptr->other;
17952 if (type_is_invalid(err_ret_trace_ptr->value.type))
17970 IrInstruction *src_err_ret_trace_ptr = instruction->src_err_ret_trace_ptr->other;
17971 if (type_is_invalid(src_err_ret_trace_ptr->value.type))
17972 return ira->codegen->builtin_types.entry_invalid;
17973
17974 IrInstruction *dest_err_ret_trace_ptr = instruction->dest_err_ret_trace_ptr->other;
17975 if (type_is_invalid(dest_err_ret_trace_ptr->value.type))
1795317976 return ira->codegen->builtin_types.entry_invalid;
1795417977
1795517978 IrInstruction *result = ir_build_merge_err_ret_traces(&ira->new_irb, instruction->base.scope,
17956 instruction->base.source_node, coro_promise_ptr, err_ret_trace_ptr);
17979 instruction->base.source_node, coro_promise_ptr, src_err_ret_trace_ptr, dest_err_ret_trace_ptr);
1795717980 ir_link_new_instruction(result, &instruction->base);
1795817981 result->value.type = ira->codegen->builtin_types.entry_void;
1795917982 return result->value.type;
src/ir_print.cpp+3-1
......@@ -1192,7 +1192,9 @@ static void ir_print_merge_err_ret_traces(IrPrint *irp, IrInstructionMergeErrRet
11921192 fprintf(irp->f, "@mergeErrRetTraces(");
11931193 ir_print_other_instruction(irp, instruction->coro_promise_ptr);
11941194 fprintf(irp->f, ",");
1195 ir_print_other_instruction(irp, instruction->err_ret_trace_ptr);
1195 ir_print_other_instruction(irp, instruction->src_err_ret_trace_ptr);
1196 fprintf(irp->f, ",");
1197 ir_print_other_instruction(irp, instruction->dest_err_ret_trace_ptr);
11961198 fprintf(irp->f, ")");
11971199}
11981200
test/cases/coroutines.zig+8-1
......@@ -191,13 +191,20 @@ async fn failing() !void {
191191 return error.Fail;
192192}
193193
194test "error return trace across suspend points" {
194test "error return trace across suspend points - early return" {
195195 const p = nonFailing();
196196 resume p;
197197 const p2 = try async<std.debug.global_allocator> printTrace(p);
198198 cancel p2;
199199}
200200
201test "error return trace across suspend points - async return" {
202 const p = nonFailing();
203 const p2 = try async<std.debug.global_allocator> printTrace(p);
204 resume p;
205 cancel p2;
206}
207
201208fn nonFailing() promise->error!void {
202209 return async<std.debug.global_allocator> suspendThenFail() catch unreachable;
203210}