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 {...@@ -3037,7 +3037,8 @@ struct IrInstructionMergeErrRetTraces {
3037 IrInstruction base;3037 IrInstruction base;
30383038
3039 IrInstruction *coro_promise_ptr;3039 IrInstruction *coro_promise_ptr;
3040 IrInstruction *err_ret_trace_ptr;3040 IrInstruction *src_err_ret_trace_ptr;
3041 IrInstruction *dest_err_ret_trace_ptr;
3041};3042};
30423043
3043struct IrInstructionMarkErrRetTracePtr {3044struct IrInstructionMarkErrRetTracePtr {
...@@ -3058,13 +3059,16 @@ static const size_t err_union_payload_index = 1;...@@ -3058,13 +3059,16 @@ static const size_t err_union_payload_index = 1;
3058// TODO call graph analysis to find out what this number needs to be for every function3059// TODO call graph analysis to find out what this number needs to be for every function
3059static const size_t stack_trace_ptr_count = 30;3060static 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"
3061#define ASYNC_ALLOC_FIELD_NAME "allocFn"3066#define ASYNC_ALLOC_FIELD_NAME "allocFn"
3062#define ASYNC_FREE_FIELD_NAME "freeFn"3067#define ASYNC_FREE_FIELD_NAME "freeFn"
3063#define AWAITER_HANDLE_FIELD_NAME "awaiter_handle"3068#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"
3065#define RESULT_PTR_FIELD_NAME "result_ptr"3071#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
3070enum FloatMode {3074enum FloatMode {
src/analyze.cpp+2-1
...@@ -474,6 +474,7 @@ TypeTableEntry *get_promise_frame_type(CodeGen *g, TypeTableEntry *return_type)...@@ -474,6 +474,7 @@ TypeTableEntry *get_promise_frame_type(CodeGen *g, TypeTableEntry *return_type)
474 field_names.append(RESULT_FIELD_NAME);474 field_names.append(RESULT_FIELD_NAME);
475 field_names.append(RESULT_PTR_FIELD_NAME);475 field_names.append(RESULT_PTR_FIELD_NAME);
476 if (g->have_err_ret_tracing) {476 if (g->have_err_ret_tracing) {
477 field_names.append(ERR_RET_TRACE_PTR_FIELD_NAME);
477 field_names.append(ERR_RET_TRACE_FIELD_NAME);478 field_names.append(ERR_RET_TRACE_FIELD_NAME);
478 field_names.append(RETURN_ADDRESSES_FIELD_NAME);479 field_names.append(RETURN_ADDRESSES_FIELD_NAME);
479 }480 }
...@@ -483,7 +484,7 @@ TypeTableEntry *get_promise_frame_type(CodeGen *g, TypeTableEntry *return_type)...@@ -483,7 +484,7 @@ TypeTableEntry *get_promise_frame_type(CodeGen *g, TypeTableEntry *return_type)
483 field_types.append(return_type);484 field_types.append(return_type);
484 field_types.append(result_ptr_type);485 field_types.append(result_ptr_type);
485 if (g->have_err_ret_tracing) {486 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));
487 field_types.append(g->stack_trace_type);488 field_types.append(g->stack_trace_type);
488 field_types.append(get_array_type(g, g->builtin_types.entry_usize, stack_trace_ptr_count));489 field_types.append(get_array_type(g, g->builtin_types.entry_usize, stack_trace_ptr_count));
489 }490 }
src/codegen.cpp+2-2
...@@ -4383,8 +4383,8 @@ static LLVMValueRef ir_render_merge_err_ret_traces(CodeGen *g, IrExecutable *exe...@@ -4383,8 +4383,8 @@ static LLVMValueRef ir_render_merge_err_ret_traces(CodeGen *g, IrExecutable *exe
4383{4383{
4384 assert(g->have_err_ret_tracing);4384 assert(g->have_err_ret_tracing);
43854385
4386 LLVMValueRef src_trace_ptr = ir_llvm_value(g, instruction->err_ret_trace_ptr);4386 LLVMValueRef src_trace_ptr = ir_llvm_value(g, instruction->src_err_ret_trace_ptr);
4387 LLVMValueRef dest_trace_ptr = get_cur_err_ret_trace_val(g, instruction->base.scope);4387 LLVMValueRef dest_trace_ptr = ir_llvm_value(g, instruction->dest_err_ret_trace_ptr);
43884388
4389 LLVMValueRef args[] = { dest_trace_ptr, src_trace_ptr };4389 LLVMValueRef args[] = { dest_trace_ptr, src_trace_ptr };
4390 ZigLLVMBuildCall(g->builder, get_merge_err_ret_traces_fn_val(g), args, 2, get_llvm_cc(g, CallingConventionUnspecified), ZigLLVM_FnInlineAuto, "");4390 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...@@ -2708,14 +2708,16 @@ static IrInstruction *ir_build_add_implicit_return_type(IrBuilder *irb, Scope *s
2708}2708}
27092709
2710static IrInstruction *ir_build_merge_err_ret_traces(IrBuilder *irb, Scope *scope, AstNode *source_node,2710static 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)
2712{2712{
2713 IrInstructionMergeErrRetTraces *instruction = ir_build_instruction<IrInstructionMergeErrRetTraces>(irb, scope, source_node);2713 IrInstructionMergeErrRetTraces *instruction = ir_build_instruction<IrInstructionMergeErrRetTraces>(irb, scope, source_node);
2714 instruction->coro_promise_ptr = coro_promise_ptr;2714 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
2717 ir_ref_instruction(coro_promise_ptr, irb->current_basic_block);2718 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
2720 return &instruction->base;2722 return &instruction->base;
2721}2723}
...@@ -6115,6 +6117,13 @@ static IrInstruction *ir_gen_await_expr(IrBuilder *irb, Scope *parent_scope, Ast...@@ -6115,6 +6117,13 @@ static IrInstruction *ir_gen_await_expr(IrBuilder *irb, Scope *parent_scope, Ast
6115 Buf *result_ptr_field_name = buf_create_from_str(RESULT_PTR_FIELD_NAME);6117 Buf *result_ptr_field_name = buf_create_from_str(RESULT_PTR_FIELD_NAME);
6116 IrInstruction *result_ptr_field_ptr = ir_build_field_ptr(irb, parent_scope, node, coro_promise_ptr, result_ptr_field_name);6118 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
6118 Buf *awaiter_handle_field_name = buf_create_from_str(AWAITER_HANDLE_FIELD_NAME);6127 Buf *awaiter_handle_field_name = buf_create_from_str(AWAITER_HANDLE_FIELD_NAME);
6119 IrInstruction *awaiter_field_ptr = ir_build_field_ptr(irb, parent_scope, node, coro_promise_ptr,6128 IrInstruction *awaiter_field_ptr = ir_build_field_ptr(irb, parent_scope, node, coro_promise_ptr,
6120 awaiter_handle_field_name);6129 awaiter_handle_field_name);
...@@ -6144,8 +6153,9 @@ static IrInstruction *ir_gen_await_expr(IrBuilder *irb, Scope *parent_scope, Ast...@@ -6144,8 +6153,9 @@ static IrInstruction *ir_gen_await_expr(IrBuilder *irb, Scope *parent_scope, Ast
6144 ir_set_cursor_at_end_and_append_block(irb, no_suspend_block);6153 ir_set_cursor_at_end_and_append_block(irb, no_suspend_block);
6145 if (irb->codegen->have_err_ret_tracing) {6154 if (irb->codegen->have_err_ret_tracing) {
6146 Buf *err_ret_trace_field_name = buf_create_from_str(ERR_RET_TRACE_FIELD_NAME);6155 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);6156 IrInstruction *src_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);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);
6149 }6159 }
6150 Buf *result_field_name = buf_create_from_str(RESULT_FIELD_NAME);6160 Buf *result_field_name = buf_create_from_str(RESULT_FIELD_NAME);
6151 IrInstruction *promise_result_ptr = ir_build_field_ptr(irb, parent_scope, node, coro_promise_ptr, result_field_name);6161 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...@@ -6402,6 +6412,8 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec
6402 IrInstruction *coro_id;6412 IrInstruction *coro_id;
6403 IrInstruction *u8_ptr_type;6413 IrInstruction *u8_ptr_type;
6404 IrInstruction *const_bool_false;6414 IrInstruction *const_bool_false;
6415 IrInstruction *coro_promise_ptr;
6416 IrInstruction *err_ret_trace_ptr;
6405 TypeTableEntry *return_type;6417 TypeTableEntry *return_type;
6406 Buf *result_ptr_field_name;6418 Buf *result_ptr_field_name;
6407 VariableTableEntry *coro_size_var;6419 VariableTableEntry *coro_size_var;
...@@ -6417,7 +6429,7 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec...@@ -6417,7 +6429,7 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec
6417 IrInstruction *coro_frame_type_value = ir_build_const_type(irb, coro_scope, node, coro_frame_type);6429 IrInstruction *coro_frame_type_value = ir_build_const_type(irb, coro_scope, node, coro_frame_type);
6418 // TODO mark this var decl as "no safety" e.g. disable initializing the undef value to 0xaa6430 // TODO mark this var decl as "no safety" e.g. disable initializing the undef value to 0xaa
6419 ir_build_var_decl(irb, coro_scope, node, promise_var, coro_frame_type_value, nullptr, undef);6431 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
6422 VariableTableEntry *await_handle_var = ir_create_var(irb, node, coro_scope, nullptr, false, false, true, const_bool_false);6434 VariableTableEntry *await_handle_var = ir_create_var(irb, node, coro_scope, nullptr, false, false, true, const_bool_false);
6423 IrInstruction *null_value = ir_build_const_null(irb, coro_scope, node);6435 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...@@ -6471,7 +6483,7 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec
6471 IrInstruction *return_addresses_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr, return_addresses_field_name);6483 IrInstruction *return_addresses_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr, return_addresses_field_name);
64726484
6473 Buf *err_ret_trace_field_name = buf_create_from_str(ERR_RET_TRACE_FIELD_NAME);6485 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);
6475 ir_build_mark_err_ret_trace_ptr(irb, scope, node, err_ret_trace_ptr);6487 ir_build_mark_err_ret_trace_ptr(irb, scope, node, err_ret_trace_ptr);
64766488
6477 // coordinate with builtin.zig6489 // coordinate with builtin.zig
...@@ -6536,6 +6548,12 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec...@@ -6536,6 +6548,12 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec
6536 IrInstruction *size_of_ret_val = ir_build_size_of(irb, scope, node, return_type_inst);6548 IrInstruction *size_of_ret_val = ir_build_size_of(irb, scope, node, return_type_inst);
6537 ir_build_memcpy(irb, scope, node, result_ptr_as_u8_ptr, return_value_ptr_as_u8_ptr, size_of_ret_val);6549 ir_build_memcpy(irb, scope, node, result_ptr_as_u8_ptr, return_value_ptr_as_u8_ptr, size_of_ret_val);
6538 }6550 }
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 }
6539 ir_build_br(irb, scope, node, check_free_block, const_bool_false);6557 ir_build_br(irb, scope, node, check_free_block, const_bool_false);
65406558
6541 ir_set_cursor_at_end_and_append_block(irb, irb->exec->coro_final_cleanup_block);6559 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,...@@ -13098,6 +13116,7 @@ static IrInstruction *ir_analyze_container_member_access_inner(IrAnalyze *ira,
13098{13116{
13099 if (!is_slice(bare_struct_type)) {13117 if (!is_slice(bare_struct_type)) {
13100 ScopeDecls *container_scope = get_container_scope(bare_struct_type);13118 ScopeDecls *container_scope = get_container_scope(bare_struct_type);
13119 assert(container_scope != nullptr);
13101 auto entry = container_scope->decl_table.maybe_get(field_name);13120 auto entry = container_scope->decl_table.maybe_get(field_name);
13102 Tld *tld = entry ? entry->value : nullptr;13121 Tld *tld = entry ? entry->value : nullptr;
13103 if (tld && tld->id == TldIdFn) {13122 if (tld && tld->id == TldIdFn) {
...@@ -17948,12 +17967,16 @@ static TypeTableEntry *ir_analyze_instruction_merge_err_ret_traces(IrAnalyze *ir...@@ -17948,12 +17967,16 @@ static TypeTableEntry *ir_analyze_instruction_merge_err_ret_traces(IrAnalyze *ir
17948 return out_val->type;17967 return out_val->type;
17949 }17968 }
1795017969
17951 IrInstruction *err_ret_trace_ptr = instruction->err_ret_trace_ptr->other;17970 IrInstruction *src_err_ret_trace_ptr = instruction->src_err_ret_trace_ptr->other;
17952 if (type_is_invalid(err_ret_trace_ptr->value.type))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))
17953 return ira->codegen->builtin_types.entry_invalid;17976 return ira->codegen->builtin_types.entry_invalid;
1795417977
17955 IrInstruction *result = ir_build_merge_err_ret_traces(&ira->new_irb, instruction->base.scope,17978 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);
17957 ir_link_new_instruction(result, &instruction->base);17980 ir_link_new_instruction(result, &instruction->base);
17958 result->value.type = ira->codegen->builtin_types.entry_void;17981 result->value.type = ira->codegen->builtin_types.entry_void;
17959 return result->value.type;17982 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...@@ -1192,7 +1192,9 @@ static void ir_print_merge_err_ret_traces(IrPrint *irp, IrInstructionMergeErrRet
1192 fprintf(irp->f, "@mergeErrRetTraces(");1192 fprintf(irp->f, "@mergeErrRetTraces(");
1193 ir_print_other_instruction(irp, instruction->coro_promise_ptr);1193 ir_print_other_instruction(irp, instruction->coro_promise_ptr);
1194 fprintf(irp->f, ",");1194 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);
1196 fprintf(irp->f, ")");1198 fprintf(irp->f, ")");
1197}1199}
11981200
test/cases/coroutines.zig+8-1
...@@ -191,13 +191,20 @@ async fn failing() !void {...@@ -191,13 +191,20 @@ async fn failing() !void {
191 return error.Fail;191 return error.Fail;
192}192}
193193
194test "error return trace across suspend points" {194test "error return trace across suspend points - early return" {
195 const p = nonFailing();195 const p = nonFailing();
196 resume p;196 resume p;
197 const p2 = try async<std.debug.global_allocator> printTrace(p);197 const p2 = try async<std.debug.global_allocator> printTrace(p);
198 cancel p2;198 cancel p2;
199}199}
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
201fn nonFailing() promise->error!void {208fn nonFailing() promise->error!void {
202 return async<std.debug.global_allocator> suspendThenFail() catch unreachable;209 return async<std.debug.global_allocator> suspendThenFail() catch unreachable;
203}210}