authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-03-24 22:05:29-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-03-24 22:07:12-04:00
logaa2995ee395b2c1329a61513debcac6225fcb8a8
treeb96e44da1d55ee671538c775ca5aeb9d91f2c0a7
parenta43c7af3d1e41ccee73678f114bb3844febcaad6

fix invalid codegen for error return traces across suspend points

See #821 Now the code works correctly, but error return traces are missing the frames from coroutines.

6 files changed, 132 insertions(+), 50 deletions(-)

src/all_types.hpp+9-1
...@@ -1621,7 +1621,8 @@ struct CodeGen {...@@ -1621,7 +1621,8 @@ struct CodeGen {
1621 FnTableEntry *panic_fn;1621 FnTableEntry *panic_fn;
1622 LLVMValueRef cur_ret_ptr;1622 LLVMValueRef cur_ret_ptr;
1623 LLVMValueRef cur_fn_val;1623 LLVMValueRef cur_fn_val;
1624 LLVMValueRef cur_err_ret_trace_val;1624 LLVMValueRef cur_err_ret_trace_val_arg;
1625 LLVMValueRef cur_err_ret_trace_val_stack;
1625 bool c_want_stdint;1626 bool c_want_stdint;
1626 bool c_want_stdbool;1627 bool c_want_stdbool;
1627 AstNode *root_export_decl;1628 AstNode *root_export_decl;
...@@ -1760,6 +1761,7 @@ enum ScopeId {...@@ -1760,6 +1761,7 @@ enum ScopeId {
1760 ScopeIdLoop,1761 ScopeIdLoop,
1761 ScopeIdFnDef,1762 ScopeIdFnDef,
1762 ScopeIdCompTime,1763 ScopeIdCompTime,
1764 ScopeIdCoroPrelude,
1763};1765};
17641766
1765struct Scope {1767struct Scope {
...@@ -1867,6 +1869,12 @@ struct ScopeFnDef {...@@ -1867,6 +1869,12 @@ struct ScopeFnDef {
1867 FnTableEntry *fn_entry;1869 FnTableEntry *fn_entry;
1868};1870};
18691871
1872// This scope is created to indicate that the code in the scope
1873// is auto-generated coroutine prelude stuff.
1874struct ScopeCoroPrelude {
1875 Scope base;
1876};
1877
1870// synchronized with code in define_builtin_compile_vars1878// synchronized with code in define_builtin_compile_vars
1871enum AtomicOrder {1879enum AtomicOrder {
1872 AtomicOrderUnordered,1880 AtomicOrderUnordered,
src/analyze.cpp+7
...@@ -170,6 +170,12 @@ Scope *create_comptime_scope(AstNode *node, Scope *parent) {...@@ -170,6 +170,12 @@ Scope *create_comptime_scope(AstNode *node, Scope *parent) {
170 return &scope->base;170 return &scope->base;
171}171}
172172
173Scope *create_coro_prelude_scope(AstNode *node, Scope *parent) {
174 ScopeCoroPrelude *scope = allocate<ScopeCoroPrelude>(1);
175 init_scope(&scope->base, ScopeIdCoroPrelude, node, parent);
176 return &scope->base;
177}
178
173ImportTableEntry *get_scope_import(Scope *scope) {179ImportTableEntry *get_scope_import(Scope *scope) {
174 while (scope) {180 while (scope) {
175 if (scope->id == ScopeIdDecls) {181 if (scope->id == ScopeIdDecls) {
...@@ -3592,6 +3598,7 @@ FnTableEntry *scope_get_fn_if_root(Scope *scope) {...@@ -3592,6 +3598,7 @@ FnTableEntry *scope_get_fn_if_root(Scope *scope) {
3592 case ScopeIdCImport:3598 case ScopeIdCImport:
3593 case ScopeIdLoop:3599 case ScopeIdLoop:
3594 case ScopeIdCompTime:3600 case ScopeIdCompTime:
3601 case ScopeIdCoroPrelude:
3595 scope = scope->parent;3602 scope = scope->parent;
3596 continue;3603 continue;
3597 case ScopeIdFnDef:3604 case ScopeIdFnDef:
src/analyze.hpp+1
...@@ -107,6 +107,7 @@ ScopeLoop *create_loop_scope(AstNode *node, Scope *parent);...@@ -107,6 +107,7 @@ ScopeLoop *create_loop_scope(AstNode *node, Scope *parent);
107ScopeFnDef *create_fndef_scope(AstNode *node, Scope *parent, FnTableEntry *fn_entry);107ScopeFnDef *create_fndef_scope(AstNode *node, Scope *parent, FnTableEntry *fn_entry);
108ScopeDecls *create_decls_scope(AstNode *node, Scope *parent, TypeTableEntry *container_type, ImportTableEntry *import);108ScopeDecls *create_decls_scope(AstNode *node, Scope *parent, TypeTableEntry *container_type, ImportTableEntry *import);
109Scope *create_comptime_scope(AstNode *node, Scope *parent);109Scope *create_comptime_scope(AstNode *node, Scope *parent);
110Scope *create_coro_prelude_scope(AstNode *node, Scope *parent);
110111
111void init_const_str_lit(CodeGen *g, ConstExprValue *const_val, Buf *str);112void init_const_str_lit(CodeGen *g, ConstExprValue *const_val, Buf *str);
112ConstExprValue *create_const_str_lit(CodeGen *g, Buf *str);113ConstExprValue *create_const_str_lit(CodeGen *g, Buf *str);
src/codegen.cpp+50-15
...@@ -653,6 +653,7 @@ static ZigLLVMDIScope *get_di_scope(CodeGen *g, Scope *scope) {...@@ -653,6 +653,7 @@ static ZigLLVMDIScope *get_di_scope(CodeGen *g, Scope *scope) {
653 case ScopeIdDeferExpr:653 case ScopeIdDeferExpr:
654 case ScopeIdLoop:654 case ScopeIdLoop:
655 case ScopeIdCompTime:655 case ScopeIdCompTime:
656 case ScopeIdCoroPrelude:
656 return get_di_scope(g, scope->parent);657 return get_di_scope(g, scope->parent);
657 }658 }
658 zig_unreachable();659 zig_unreachable();
...@@ -1318,9 +1319,34 @@ static LLVMValueRef get_safety_crash_err_fn(CodeGen *g) {...@@ -1318,9 +1319,34 @@ static LLVMValueRef get_safety_crash_err_fn(CodeGen *g) {
1318 return fn_val;1319 return fn_val;
1319}1320}
13201321
1321static void gen_safety_crash_for_err(CodeGen *g, LLVMValueRef err_val) {1322static bool is_coro_prelude_scope(Scope *scope) {
1323 while (scope != nullptr) {
1324 if (scope->id == ScopeIdCoroPrelude) {
1325 return true;
1326 } else if (scope->id == ScopeIdFnDef) {
1327 break;
1328 }
1329 scope = scope->parent;
1330 }
1331 return false;
1332}
1333
1334static LLVMValueRef get_cur_err_ret_trace_val(CodeGen *g, Scope *scope) {
1335 if (!g->have_err_ret_tracing) {
1336 return nullptr;
1337 }
1338 if (g->cur_fn->type_entry->data.fn.fn_type_id.cc == CallingConventionAsync) {
1339 return is_coro_prelude_scope(scope) ? g->cur_err_ret_trace_val_arg : g->cur_err_ret_trace_val_stack;
1340 }
1341 if (g->cur_err_ret_trace_val_stack != nullptr) {
1342 return g->cur_err_ret_trace_val_stack;
1343 }
1344 return g->cur_err_ret_trace_val_arg;
1345}
1346
1347static void gen_safety_crash_for_err(CodeGen *g, LLVMValueRef err_val, Scope *scope) {
1322 LLVMValueRef safety_crash_err_fn = get_safety_crash_err_fn(g);1348 LLVMValueRef safety_crash_err_fn = get_safety_crash_err_fn(g);
1323 LLVMValueRef err_ret_trace_val = g->cur_err_ret_trace_val;1349 LLVMValueRef err_ret_trace_val = get_cur_err_ret_trace_val(g, scope);
1324 if (err_ret_trace_val == nullptr) {1350 if (err_ret_trace_val == nullptr) {
1325 TypeTableEntry *ptr_to_stack_trace_type = get_ptr_to_stack_trace_type(g);1351 TypeTableEntry *ptr_to_stack_trace_type = get_ptr_to_stack_trace_type(g);
1326 err_ret_trace_val = LLVMConstNull(ptr_to_stack_trace_type->type_ref);1352 err_ret_trace_val = LLVMConstNull(ptr_to_stack_trace_type->type_ref);
...@@ -1614,7 +1640,7 @@ static LLVMValueRef ir_render_save_err_ret_addr(CodeGen *g, IrExecutable *execut...@@ -1614,7 +1640,7 @@ static LLVMValueRef ir_render_save_err_ret_addr(CodeGen *g, IrExecutable *execut
16141640
1615 LLVMValueRef return_err_fn = get_return_err_fn(g);1641 LLVMValueRef return_err_fn = get_return_err_fn(g);
1616 LLVMValueRef args[] = {1642 LLVMValueRef args[] = {
1617 g->cur_err_ret_trace_val,1643 get_cur_err_ret_trace_val(g, save_err_ret_addr_instruction->base.scope),
1618 };1644 };
1619 LLVMValueRef call_instruction = ZigLLVMBuildCall(g->builder, return_err_fn, args, 1,1645 LLVMValueRef call_instruction = ZigLLVMBuildCall(g->builder, return_err_fn, args, 1,
1620 get_llvm_cc(g, CallingConventionUnspecified), ZigLLVM_FnInlineAuto, "");1646 get_llvm_cc(g, CallingConventionUnspecified), ZigLLVM_FnInlineAuto, "");
...@@ -2725,7 +2751,7 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr...@@ -2725,7 +2751,7 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr
2725 gen_param_index += 1;2751 gen_param_index += 1;
2726 }2752 }
2727 if (prefix_arg_err_ret_stack) {2753 if (prefix_arg_err_ret_stack) {
2728 gen_param_values[gen_param_index] = g->cur_err_ret_trace_val;2754 gen_param_values[gen_param_index] = get_cur_err_ret_trace_val(g, instruction->base.scope);
2729 gen_param_index += 1;2755 gen_param_index += 1;
2730 }2756 }
2731 if (instruction->is_async) {2757 if (instruction->is_async) {
...@@ -3292,11 +3318,12 @@ static LLVMValueRef ir_render_align_cast(CodeGen *g, IrExecutable *executable, I...@@ -3292,11 +3318,12 @@ static LLVMValueRef ir_render_align_cast(CodeGen *g, IrExecutable *executable, I
3292static LLVMValueRef ir_render_error_return_trace(CodeGen *g, IrExecutable *executable,3318static LLVMValueRef ir_render_error_return_trace(CodeGen *g, IrExecutable *executable,
3293 IrInstructionErrorReturnTrace *instruction)3319 IrInstructionErrorReturnTrace *instruction)
3294{3320{
3295 if (g->cur_err_ret_trace_val == nullptr) {3321 LLVMValueRef cur_err_ret_trace_val = get_cur_err_ret_trace_val(g, instruction->base.scope);
3322 if (cur_err_ret_trace_val == nullptr) {
3296 TypeTableEntry *ptr_to_stack_trace_type = get_ptr_to_stack_trace_type(g);3323 TypeTableEntry *ptr_to_stack_trace_type = get_ptr_to_stack_trace_type(g);
3297 return LLVMConstNull(ptr_to_stack_trace_type->type_ref);3324 return LLVMConstNull(ptr_to_stack_trace_type->type_ref);
3298 }3325 }
3299 return g->cur_err_ret_trace_val;3326 return cur_err_ret_trace_val;
3300}3327}
33013328
3302static LLVMValueRef ir_render_cancel(CodeGen *g, IrExecutable *executable, IrInstructionCancel *instruction) {3329static LLVMValueRef ir_render_cancel(CodeGen *g, IrExecutable *executable, IrInstructionCancel *instruction) {
...@@ -3726,7 +3753,7 @@ static LLVMValueRef ir_render_unwrap_err_payload(CodeGen *g, IrExecutable *execu...@@ -3726,7 +3753,7 @@ static LLVMValueRef ir_render_unwrap_err_payload(CodeGen *g, IrExecutable *execu
3726 LLVMBuildCondBr(g->builder, cond_val, ok_block, err_block);3753 LLVMBuildCondBr(g->builder, cond_val, ok_block, err_block);
37273754
3728 LLVMPositionBuilderAtEnd(g->builder, err_block);3755 LLVMPositionBuilderAtEnd(g->builder, err_block);
3729 gen_safety_crash_for_err(g, err_val);3756 gen_safety_crash_for_err(g, err_val, instruction->base.scope);
37303757
3731 LLVMPositionBuilderAtEnd(g->builder, ok_block);3758 LLVMPositionBuilderAtEnd(g->builder, ok_block);
3732 }3759 }
...@@ -3918,7 +3945,7 @@ static LLVMValueRef ir_render_container_init_list(CodeGen *g, IrExecutable *exec...@@ -3918,7 +3945,7 @@ static LLVMValueRef ir_render_container_init_list(CodeGen *g, IrExecutable *exec
3918}3945}
39193946
3920static LLVMValueRef ir_render_panic(CodeGen *g, IrExecutable *executable, IrInstructionPanic *instruction) {3947static LLVMValueRef ir_render_panic(CodeGen *g, IrExecutable *executable, IrInstructionPanic *instruction) {
3921 gen_panic(g, ir_llvm_value(g, instruction->msg), g->cur_err_ret_trace_val);3948 gen_panic(g, ir_llvm_value(g, instruction->msg), get_cur_err_ret_trace_val(g, instruction->base.scope));
3922 return nullptr;3949 return nullptr;
3923}3950}
39243951
...@@ -5279,9 +5306,17 @@ static void do_code_gen(CodeGen *g) {...@@ -5279,9 +5306,17 @@ static void do_code_gen(CodeGen *g) {
5279 clear_debug_source_node(g);5306 clear_debug_source_node(g);
52805307
5281 uint32_t err_ret_trace_arg_index = get_err_ret_trace_arg_index(g, fn_table_entry);5308 uint32_t err_ret_trace_arg_index = get_err_ret_trace_arg_index(g, fn_table_entry);
5282 if (err_ret_trace_arg_index != UINT32_MAX) {5309 bool have_err_ret_trace_arg = err_ret_trace_arg_index != UINT32_MAX;
5283 g->cur_err_ret_trace_val = LLVMGetParam(fn, err_ret_trace_arg_index);5310 if (have_err_ret_trace_arg) {
5284 } else if (g->have_err_ret_tracing && fn_table_entry->calls_or_awaits_errorable_fn) {5311 g->cur_err_ret_trace_val_arg = LLVMGetParam(fn, err_ret_trace_arg_index);
5312 } else {
5313 g->cur_err_ret_trace_val_arg = nullptr;
5314 }
5315
5316 bool is_async = fn_table_entry->type_entry->data.fn.fn_type_id.cc == CallingConventionAsync;
5317 bool have_err_ret_trace_stack = g->have_err_ret_tracing && fn_table_entry->calls_or_awaits_errorable_fn &&
5318 (is_async || !have_err_ret_trace_arg);
5319 if (have_err_ret_trace_stack) {
5285 // TODO call graph analysis to find out what this number needs to be for every function5320 // TODO call graph analysis to find out what this number needs to be for every function
5286 static const size_t stack_trace_ptr_count = 30;5321 static const size_t stack_trace_ptr_count = 30;
52875322
...@@ -5289,13 +5324,13 @@ static void do_code_gen(CodeGen *g) {...@@ -5289,13 +5324,13 @@ static void do_code_gen(CodeGen *g) {
5289 TypeTableEntry *array_type = get_array_type(g, usize, stack_trace_ptr_count);5324 TypeTableEntry *array_type = get_array_type(g, usize, stack_trace_ptr_count);
5290 LLVMValueRef err_ret_array_val = build_alloca(g, array_type, "error_return_trace_addresses",5325 LLVMValueRef err_ret_array_val = build_alloca(g, array_type, "error_return_trace_addresses",
5291 get_abi_alignment(g, array_type));5326 get_abi_alignment(g, array_type));
5292 g->cur_err_ret_trace_val = build_alloca(g, g->stack_trace_type, "error_return_trace", get_abi_alignment(g, g->stack_trace_type));5327 g->cur_err_ret_trace_val_stack = build_alloca(g, g->stack_trace_type, "error_return_trace", get_abi_alignment(g, g->stack_trace_type));
5293 size_t index_field_index = g->stack_trace_type->data.structure.fields[0].gen_index;5328 size_t index_field_index = g->stack_trace_type->data.structure.fields[0].gen_index;
5294 LLVMValueRef index_field_ptr = LLVMBuildStructGEP(g->builder, g->cur_err_ret_trace_val, (unsigned)index_field_index, "");5329 LLVMValueRef index_field_ptr = LLVMBuildStructGEP(g->builder, g->cur_err_ret_trace_val_stack, (unsigned)index_field_index, "");
5295 gen_store_untyped(g, LLVMConstNull(usize->type_ref), index_field_ptr, 0, false);5330 gen_store_untyped(g, LLVMConstNull(usize->type_ref), index_field_ptr, 0, false);
52965331
5297 size_t addresses_field_index = g->stack_trace_type->data.structure.fields[1].gen_index;5332 size_t addresses_field_index = g->stack_trace_type->data.structure.fields[1].gen_index;
5298 LLVMValueRef addresses_field_ptr = LLVMBuildStructGEP(g->builder, g->cur_err_ret_trace_val, (unsigned)addresses_field_index, "");5333 LLVMValueRef addresses_field_ptr = LLVMBuildStructGEP(g->builder, g->cur_err_ret_trace_val_stack, (unsigned)addresses_field_index, "");
52995334
5300 TypeTableEntry *slice_type = g->stack_trace_type->data.structure.fields[1].type_entry;5335 TypeTableEntry *slice_type = g->stack_trace_type->data.structure.fields[1].type_entry;
5301 size_t ptr_field_index = slice_type->data.structure.fields[slice_ptr_index].gen_index;5336 size_t ptr_field_index = slice_type->data.structure.fields[slice_ptr_index].gen_index;
...@@ -5311,7 +5346,7 @@ static void do_code_gen(CodeGen *g) {...@@ -5311,7 +5346,7 @@ static void do_code_gen(CodeGen *g) {
5311 LLVMValueRef len_field_ptr = LLVMBuildStructGEP(g->builder, addresses_field_ptr, (unsigned)len_field_index, "");5346 LLVMValueRef len_field_ptr = LLVMBuildStructGEP(g->builder, addresses_field_ptr, (unsigned)len_field_index, "");
5312 gen_store(g, LLVMConstInt(usize->type_ref, stack_trace_ptr_count, false), len_field_ptr, get_pointer_to_type(g, usize, false));5347 gen_store(g, LLVMConstInt(usize->type_ref, stack_trace_ptr_count, false), len_field_ptr, get_pointer_to_type(g, usize, false));
5313 } else {5348 } else {
5314 g->cur_err_ret_trace_val = nullptr;5349 g->cur_err_ret_trace_val_stack = nullptr;
5315 }5350 }
53165351
5317 // allocate temporary stack data5352 // allocate temporary stack data
src/ir.cpp+35-34
...@@ -6412,60 +6412,61 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec...@@ -6412,60 +6412,61 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec
6412 VariableTableEntry *coro_size_var;6412 VariableTableEntry *coro_size_var;
6413 if (is_async) {6413 if (is_async) {
6414 // create the coro promise6414 // create the coro promise
6415 const_bool_false = ir_build_const_bool(irb, scope, node, false);6415 Scope *coro_scope = create_coro_prelude_scope(node, scope);
6416 VariableTableEntry *promise_var = ir_create_var(irb, node, scope, nullptr, false, false, true, const_bool_false);6416 const_bool_false = ir_build_const_bool(irb, coro_scope, node, false);
6417 VariableTableEntry *promise_var = ir_create_var(irb, node, coro_scope, nullptr, false, false, true, const_bool_false);
64176418
6418 return_type = fn_entry->type_entry->data.fn.fn_type_id.return_type;6419 return_type = fn_entry->type_entry->data.fn.fn_type_id.return_type;
6419 IrInstruction *promise_init = ir_build_const_promise_init(irb, scope, node, return_type);6420 IrInstruction *promise_init = ir_build_const_promise_init(irb, coro_scope, node, return_type);
6420 ir_build_var_decl(irb, scope, node, promise_var, nullptr, nullptr, promise_init);6421 ir_build_var_decl(irb, coro_scope, node, promise_var, nullptr, nullptr, promise_init);
6421 IrInstruction *coro_promise_ptr = ir_build_var_ptr(irb, scope, node, promise_var, false, false);6422 IrInstruction *coro_promise_ptr = ir_build_var_ptr(irb, coro_scope, node, promise_var, false, false);
64226423
6423 VariableTableEntry *await_handle_var = ir_create_var(irb, node, scope, nullptr, false, false, true, const_bool_false);6424 VariableTableEntry *await_handle_var = ir_create_var(irb, node, coro_scope, nullptr, false, false, true, const_bool_false);
6424 IrInstruction *null_value = ir_build_const_null(irb, scope, node);6425 IrInstruction *null_value = ir_build_const_null(irb, coro_scope, node);
6425 IrInstruction *await_handle_type_val = ir_build_const_type(irb, scope, node,6426 IrInstruction *await_handle_type_val = ir_build_const_type(irb, coro_scope, node,
6426 get_maybe_type(irb->codegen, irb->codegen->builtin_types.entry_promise));6427 get_maybe_type(irb->codegen, irb->codegen->builtin_types.entry_promise));
6427 ir_build_var_decl(irb, scope, node, await_handle_var, await_handle_type_val, nullptr, null_value);6428 ir_build_var_decl(irb, coro_scope, node, await_handle_var, await_handle_type_val, nullptr, null_value);
6428 irb->exec->await_handle_var_ptr = ir_build_var_ptr(irb, scope, node,6429 irb->exec->await_handle_var_ptr = ir_build_var_ptr(irb, coro_scope, node,
6429 await_handle_var, false, false);6430 await_handle_var, false, false);
64306431
6431 u8_ptr_type = ir_build_const_type(irb, scope, node,6432 u8_ptr_type = ir_build_const_type(irb, coro_scope, node,
6432 get_pointer_to_type(irb->codegen, irb->codegen->builtin_types.entry_u8, false));6433 get_pointer_to_type(irb->codegen, irb->codegen->builtin_types.entry_u8, false));
6433 IrInstruction *promise_as_u8_ptr = ir_build_ptr_cast(irb, scope, node, u8_ptr_type, coro_promise_ptr);6434 IrInstruction *promise_as_u8_ptr = ir_build_ptr_cast(irb, coro_scope, node, u8_ptr_type, coro_promise_ptr);
6434 coro_id = ir_build_coro_id(irb, scope, node, promise_as_u8_ptr);6435 coro_id = ir_build_coro_id(irb, coro_scope, node, promise_as_u8_ptr);
6435 coro_size_var = ir_create_var(irb, node, scope, nullptr, false, false, true, const_bool_false);6436 coro_size_var = ir_create_var(irb, node, coro_scope, nullptr, false, false, true, const_bool_false);
6436 IrInstruction *coro_size = ir_build_coro_size(irb, scope, node);6437 IrInstruction *coro_size = ir_build_coro_size(irb, coro_scope, node);
6437 ir_build_var_decl(irb, scope, node, coro_size_var, nullptr, nullptr, coro_size);6438 ir_build_var_decl(irb, coro_scope, node, coro_size_var, nullptr, nullptr, coro_size);
6438 IrInstruction *implicit_allocator_ptr = ir_build_get_implicit_allocator(irb, scope, node,6439 IrInstruction *implicit_allocator_ptr = ir_build_get_implicit_allocator(irb, coro_scope, node,
6439 ImplicitAllocatorIdArg);6440 ImplicitAllocatorIdArg);
6440 irb->exec->coro_allocator_var = ir_create_var(irb, node, scope, nullptr, true, true, true, const_bool_false);6441 irb->exec->coro_allocator_var = ir_create_var(irb, node, coro_scope, nullptr, true, true, true, const_bool_false);
6441 ir_build_var_decl(irb, scope, node, irb->exec->coro_allocator_var, nullptr, nullptr, implicit_allocator_ptr);6442 ir_build_var_decl(irb, coro_scope, node, irb->exec->coro_allocator_var, nullptr, nullptr, implicit_allocator_ptr);
6442 Buf *alloc_field_name = buf_create_from_str(ASYNC_ALLOC_FIELD_NAME);6443 Buf *alloc_field_name = buf_create_from_str(ASYNC_ALLOC_FIELD_NAME);
6443 IrInstruction *alloc_fn_ptr = ir_build_field_ptr(irb, scope, node, implicit_allocator_ptr, alloc_field_name);6444 IrInstruction *alloc_fn_ptr = ir_build_field_ptr(irb, coro_scope, node, implicit_allocator_ptr, alloc_field_name);
6444 IrInstruction *alloc_fn = ir_build_load_ptr(irb, scope, node, alloc_fn_ptr);6445 IrInstruction *alloc_fn = ir_build_load_ptr(irb, coro_scope, node, alloc_fn_ptr);
6445 IrInstruction *maybe_coro_mem_ptr = ir_build_coro_alloc_helper(irb, scope, node, alloc_fn, coro_size);6446 IrInstruction *maybe_coro_mem_ptr = ir_build_coro_alloc_helper(irb, coro_scope, node, alloc_fn, coro_size);
6446 IrInstruction *alloc_result_is_ok = ir_build_test_nonnull(irb, scope, node, maybe_coro_mem_ptr);6447 IrInstruction *alloc_result_is_ok = ir_build_test_nonnull(irb, coro_scope, node, maybe_coro_mem_ptr);
6447 IrBasicBlock *alloc_err_block = ir_create_basic_block(irb, scope, "AllocError");6448 IrBasicBlock *alloc_err_block = ir_create_basic_block(irb, coro_scope, "AllocError");
6448 IrBasicBlock *alloc_ok_block = ir_create_basic_block(irb, scope, "AllocOk");6449 IrBasicBlock *alloc_ok_block = ir_create_basic_block(irb, coro_scope, "AllocOk");
6449 ir_build_cond_br(irb, scope, node, alloc_result_is_ok, alloc_ok_block, alloc_err_block, const_bool_false);6450 ir_build_cond_br(irb, coro_scope, node, alloc_result_is_ok, alloc_ok_block, alloc_err_block, const_bool_false);
64506451
6451 ir_set_cursor_at_end_and_append_block(irb, alloc_err_block);6452 ir_set_cursor_at_end_and_append_block(irb, alloc_err_block);
6452 // we can return undefined here, because the caller passes a pointer to the error struct field6453 // we can return undefined here, because the caller passes a pointer to the error struct field
6453 // in the error union result, and we populate it in case of allocation failure.6454 // in the error union result, and we populate it in case of allocation failure.
6454 IrInstruction *undef = ir_build_const_undefined(irb, scope, node);6455 IrInstruction *undef = ir_build_const_undefined(irb, coro_scope, node);
6455 ir_build_return(irb, scope, node, undef);6456 ir_build_return(irb, coro_scope, node, undef);
64566457
6457 ir_set_cursor_at_end_and_append_block(irb, alloc_ok_block);6458 ir_set_cursor_at_end_and_append_block(irb, alloc_ok_block);
6458 IrInstruction *coro_mem_ptr = ir_build_ptr_cast(irb, scope, node, u8_ptr_type, maybe_coro_mem_ptr);6459 IrInstruction *coro_mem_ptr = ir_build_ptr_cast(irb, coro_scope, node, u8_ptr_type, maybe_coro_mem_ptr);
6459 irb->exec->coro_handle = ir_build_coro_begin(irb, scope, node, coro_id, coro_mem_ptr);6460 irb->exec->coro_handle = ir_build_coro_begin(irb, coro_scope, node, coro_id, coro_mem_ptr);
64606461
6461 Buf *awaiter_handle_field_name = buf_create_from_str(AWAITER_HANDLE_FIELD_NAME);6462 Buf *awaiter_handle_field_name = buf_create_from_str(AWAITER_HANDLE_FIELD_NAME);
6462 irb->exec->coro_awaiter_field_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr,6463 irb->exec->coro_awaiter_field_ptr = ir_build_field_ptr(irb, coro_scope, node, coro_promise_ptr,
6463 awaiter_handle_field_name);6464 awaiter_handle_field_name);
6464 Buf *result_field_name = buf_create_from_str(RESULT_FIELD_NAME);6465 Buf *result_field_name = buf_create_from_str(RESULT_FIELD_NAME);
6465 irb->exec->coro_result_field_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr, result_field_name);6466 irb->exec->coro_result_field_ptr = ir_build_field_ptr(irb, coro_scope, node, coro_promise_ptr, result_field_name);
6466 result_ptr_field_name = buf_create_from_str(RESULT_PTR_FIELD_NAME);6467 result_ptr_field_name = buf_create_from_str(RESULT_PTR_FIELD_NAME);
6467 irb->exec->coro_result_ptr_field_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr, result_ptr_field_name);6468 irb->exec->coro_result_ptr_field_ptr = ir_build_field_ptr(irb, coro_scope, node, coro_promise_ptr, result_ptr_field_name);
6468 ir_build_store_ptr(irb, scope, node, irb->exec->coro_result_ptr_field_ptr, irb->exec->coro_result_field_ptr);6469 ir_build_store_ptr(irb, coro_scope, node, irb->exec->coro_result_ptr_field_ptr, irb->exec->coro_result_field_ptr);
64696470
64706471
6471 irb->exec->coro_early_final = ir_create_basic_block(irb, scope, "CoroEarlyFinal");6472 irb->exec->coro_early_final = ir_create_basic_block(irb, scope, "CoroEarlyFinal");
test/runtime_safety.zig+30
...@@ -281,4 +281,34 @@ pub fn addCases(cases: &tests.CompareOutputContext) void {...@@ -281,4 +281,34 @@ pub fn addCases(cases: &tests.CompareOutputContext) void {
281 \\ f.float = 12.34;281 \\ f.float = 12.34;
282 \\}282 \\}
283 );283 );
284
285 // This case makes sure that the code compiles and runs. There is not actually a special
286 // runtime safety check having to do specifically with error return traces across suspend points.
287 cases.addRuntimeSafety("error return trace across suspend points",
288 \\const std = @import("std");
289 \\
290 \\pub fn panic(message: []const u8, stack_trace: ?&@import("builtin").StackTrace) noreturn {
291 \\ std.os.exit(126);
292 \\}
293 \\
294 \\pub fn main() void {
295 \\ const p = nonFailing();
296 \\ resume p;
297 \\ const p2 = async<std.debug.global_allocator> printTrace(p) catch unreachable;
298 \\ cancel p2;
299 \\}
300 \\
301 \\fn nonFailing() promise->error!void {
302 \\ return async<std.debug.global_allocator> failing() catch unreachable;
303 \\}
304 \\
305 \\async fn failing() error!void {
306 \\ suspend;
307 \\ return error.Fail;
308 \\}
309 \\
310 \\async fn printTrace(p: promise->error!void) void {
311 \\ (await p) catch unreachable;
312 \\}
313 );
284}314}