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.
This commit is contained in:
69
src/ir.cpp
69
src/ir.cpp
@@ -6412,60 +6412,61 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec
|
||||
VariableTableEntry *coro_size_var;
|
||||
if (is_async) {
|
||||
// create the coro promise
|
||||
const_bool_false = ir_build_const_bool(irb, scope, node, false);
|
||||
VariableTableEntry *promise_var = ir_create_var(irb, node, scope, nullptr, false, false, true, const_bool_false);
|
||||
Scope *coro_scope = create_coro_prelude_scope(node, scope);
|
||||
const_bool_false = ir_build_const_bool(irb, coro_scope, node, false);
|
||||
VariableTableEntry *promise_var = ir_create_var(irb, node, coro_scope, nullptr, false, false, true, const_bool_false);
|
||||
|
||||
return_type = fn_entry->type_entry->data.fn.fn_type_id.return_type;
|
||||
IrInstruction *promise_init = ir_build_const_promise_init(irb, scope, node, return_type);
|
||||
ir_build_var_decl(irb, scope, node, promise_var, nullptr, nullptr, promise_init);
|
||||
IrInstruction *coro_promise_ptr = ir_build_var_ptr(irb, scope, node, promise_var, false, false);
|
||||
IrInstruction *promise_init = ir_build_const_promise_init(irb, coro_scope, node, return_type);
|
||||
ir_build_var_decl(irb, coro_scope, node, promise_var, nullptr, nullptr, promise_init);
|
||||
IrInstruction *coro_promise_ptr = ir_build_var_ptr(irb, coro_scope, node, promise_var, false, false);
|
||||
|
||||
VariableTableEntry *await_handle_var = ir_create_var(irb, node, scope, nullptr, false, false, true, const_bool_false);
|
||||
IrInstruction *null_value = ir_build_const_null(irb, scope, node);
|
||||
IrInstruction *await_handle_type_val = ir_build_const_type(irb, scope, node,
|
||||
VariableTableEntry *await_handle_var = ir_create_var(irb, node, coro_scope, nullptr, false, false, true, const_bool_false);
|
||||
IrInstruction *null_value = ir_build_const_null(irb, coro_scope, node);
|
||||
IrInstruction *await_handle_type_val = ir_build_const_type(irb, coro_scope, node,
|
||||
get_maybe_type(irb->codegen, irb->codegen->builtin_types.entry_promise));
|
||||
ir_build_var_decl(irb, scope, node, await_handle_var, await_handle_type_val, nullptr, null_value);
|
||||
irb->exec->await_handle_var_ptr = ir_build_var_ptr(irb, scope, node,
|
||||
ir_build_var_decl(irb, coro_scope, node, await_handle_var, await_handle_type_val, nullptr, null_value);
|
||||
irb->exec->await_handle_var_ptr = ir_build_var_ptr(irb, coro_scope, node,
|
||||
await_handle_var, false, false);
|
||||
|
||||
u8_ptr_type = ir_build_const_type(irb, scope, node,
|
||||
u8_ptr_type = ir_build_const_type(irb, coro_scope, node,
|
||||
get_pointer_to_type(irb->codegen, irb->codegen->builtin_types.entry_u8, false));
|
||||
IrInstruction *promise_as_u8_ptr = ir_build_ptr_cast(irb, scope, node, u8_ptr_type, coro_promise_ptr);
|
||||
coro_id = ir_build_coro_id(irb, scope, node, promise_as_u8_ptr);
|
||||
coro_size_var = ir_create_var(irb, node, scope, nullptr, false, false, true, const_bool_false);
|
||||
IrInstruction *coro_size = ir_build_coro_size(irb, scope, node);
|
||||
ir_build_var_decl(irb, scope, node, coro_size_var, nullptr, nullptr, coro_size);
|
||||
IrInstruction *implicit_allocator_ptr = ir_build_get_implicit_allocator(irb, scope, node,
|
||||
IrInstruction *promise_as_u8_ptr = ir_build_ptr_cast(irb, coro_scope, node, u8_ptr_type, coro_promise_ptr);
|
||||
coro_id = ir_build_coro_id(irb, coro_scope, node, promise_as_u8_ptr);
|
||||
coro_size_var = ir_create_var(irb, node, coro_scope, nullptr, false, false, true, const_bool_false);
|
||||
IrInstruction *coro_size = ir_build_coro_size(irb, coro_scope, node);
|
||||
ir_build_var_decl(irb, coro_scope, node, coro_size_var, nullptr, nullptr, coro_size);
|
||||
IrInstruction *implicit_allocator_ptr = ir_build_get_implicit_allocator(irb, coro_scope, node,
|
||||
ImplicitAllocatorIdArg);
|
||||
irb->exec->coro_allocator_var = ir_create_var(irb, node, scope, nullptr, true, true, true, const_bool_false);
|
||||
ir_build_var_decl(irb, scope, node, irb->exec->coro_allocator_var, nullptr, nullptr, implicit_allocator_ptr);
|
||||
irb->exec->coro_allocator_var = ir_create_var(irb, node, coro_scope, nullptr, true, true, true, const_bool_false);
|
||||
ir_build_var_decl(irb, coro_scope, node, irb->exec->coro_allocator_var, nullptr, nullptr, implicit_allocator_ptr);
|
||||
Buf *alloc_field_name = buf_create_from_str(ASYNC_ALLOC_FIELD_NAME);
|
||||
IrInstruction *alloc_fn_ptr = ir_build_field_ptr(irb, scope, node, implicit_allocator_ptr, alloc_field_name);
|
||||
IrInstruction *alloc_fn = ir_build_load_ptr(irb, scope, node, alloc_fn_ptr);
|
||||
IrInstruction *maybe_coro_mem_ptr = ir_build_coro_alloc_helper(irb, scope, node, alloc_fn, coro_size);
|
||||
IrInstruction *alloc_result_is_ok = ir_build_test_nonnull(irb, scope, node, maybe_coro_mem_ptr);
|
||||
IrBasicBlock *alloc_err_block = ir_create_basic_block(irb, scope, "AllocError");
|
||||
IrBasicBlock *alloc_ok_block = ir_create_basic_block(irb, scope, "AllocOk");
|
||||
ir_build_cond_br(irb, scope, node, alloc_result_is_ok, alloc_ok_block, alloc_err_block, const_bool_false);
|
||||
IrInstruction *alloc_fn_ptr = ir_build_field_ptr(irb, coro_scope, node, implicit_allocator_ptr, alloc_field_name);
|
||||
IrInstruction *alloc_fn = ir_build_load_ptr(irb, coro_scope, node, alloc_fn_ptr);
|
||||
IrInstruction *maybe_coro_mem_ptr = ir_build_coro_alloc_helper(irb, coro_scope, node, alloc_fn, coro_size);
|
||||
IrInstruction *alloc_result_is_ok = ir_build_test_nonnull(irb, coro_scope, node, maybe_coro_mem_ptr);
|
||||
IrBasicBlock *alloc_err_block = ir_create_basic_block(irb, coro_scope, "AllocError");
|
||||
IrBasicBlock *alloc_ok_block = ir_create_basic_block(irb, coro_scope, "AllocOk");
|
||||
ir_build_cond_br(irb, coro_scope, node, alloc_result_is_ok, alloc_ok_block, alloc_err_block, const_bool_false);
|
||||
|
||||
ir_set_cursor_at_end_and_append_block(irb, alloc_err_block);
|
||||
// we can return undefined here, because the caller passes a pointer to the error struct field
|
||||
// in the error union result, and we populate it in case of allocation failure.
|
||||
IrInstruction *undef = ir_build_const_undefined(irb, scope, node);
|
||||
ir_build_return(irb, scope, node, undef);
|
||||
IrInstruction *undef = ir_build_const_undefined(irb, coro_scope, node);
|
||||
ir_build_return(irb, coro_scope, node, undef);
|
||||
|
||||
ir_set_cursor_at_end_and_append_block(irb, alloc_ok_block);
|
||||
IrInstruction *coro_mem_ptr = ir_build_ptr_cast(irb, scope, node, u8_ptr_type, maybe_coro_mem_ptr);
|
||||
irb->exec->coro_handle = ir_build_coro_begin(irb, scope, node, coro_id, coro_mem_ptr);
|
||||
IrInstruction *coro_mem_ptr = ir_build_ptr_cast(irb, coro_scope, node, u8_ptr_type, maybe_coro_mem_ptr);
|
||||
irb->exec->coro_handle = ir_build_coro_begin(irb, coro_scope, node, coro_id, coro_mem_ptr);
|
||||
|
||||
Buf *awaiter_handle_field_name = buf_create_from_str(AWAITER_HANDLE_FIELD_NAME);
|
||||
irb->exec->coro_awaiter_field_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr,
|
||||
irb->exec->coro_awaiter_field_ptr = ir_build_field_ptr(irb, coro_scope, node, coro_promise_ptr,
|
||||
awaiter_handle_field_name);
|
||||
Buf *result_field_name = buf_create_from_str(RESULT_FIELD_NAME);
|
||||
irb->exec->coro_result_field_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr, result_field_name);
|
||||
irb->exec->coro_result_field_ptr = ir_build_field_ptr(irb, coro_scope, node, coro_promise_ptr, result_field_name);
|
||||
result_ptr_field_name = buf_create_from_str(RESULT_PTR_FIELD_NAME);
|
||||
irb->exec->coro_result_ptr_field_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr, result_ptr_field_name);
|
||||
ir_build_store_ptr(irb, scope, node, irb->exec->coro_result_ptr_field_ptr, irb->exec->coro_result_field_ptr);
|
||||
irb->exec->coro_result_ptr_field_ptr = ir_build_field_ptr(irb, coro_scope, node, coro_promise_ptr, result_ptr_field_name);
|
||||
ir_build_store_ptr(irb, coro_scope, node, irb->exec->coro_result_ptr_field_ptr, irb->exec->coro_result_field_ptr);
|
||||
|
||||
|
||||
irb->exec->coro_early_final = ir_create_basic_block(irb, scope, "CoroEarlyFinal");
|
||||
|
||||
Reference in New Issue
Block a user