| ... | @@ -298,7 +298,7 @@ static LLVMLinkage to_llvm_linkage(GlobalLinkageId id) { | ... | @@ -298,7 +298,7 @@ static LLVMLinkage to_llvm_linkage(GlobalLinkageId id) { |
| 298 | } | 298 | } |
| 299 | | 299 | |
| 300 | // label (grep this): [coro_frame_struct_layout] | 300 | // label (grep this): [coro_frame_struct_layout] |
| 301 | static uint32_t frame_index_trace(CodeGen *g, FnTypeId *fn_type_id) { | 301 | static uint32_t frame_index_trace_arg(CodeGen *g, FnTypeId *fn_type_id) { |
| 302 | // [0] *ReturnType | 302 | // [0] *ReturnType |
| 303 | // [1] ReturnType | 303 | // [1] ReturnType |
| 304 | uint32_t return_field_count = type_has_bits(fn_type_id->return_type) ? 2 : 0; | 304 | uint32_t return_field_count = type_has_bits(fn_type_id->return_type) ? 2 : 0; |
| ... | @@ -307,14 +307,25 @@ static uint32_t frame_index_trace(CodeGen *g, FnTypeId *fn_type_id) { | ... | @@ -307,14 +307,25 @@ static uint32_t frame_index_trace(CodeGen *g, FnTypeId *fn_type_id) { |
| 307 | | 307 | |
| 308 | // label (grep this): [coro_frame_struct_layout] | 308 | // label (grep this): [coro_frame_struct_layout] |
| 309 | static uint32_t frame_index_arg(CodeGen *g, FnTypeId *fn_type_id) { | 309 | static uint32_t frame_index_arg(CodeGen *g, FnTypeId *fn_type_id) { |
| 310 | bool have_stack_trace = g->have_err_ret_tracing && codegen_fn_has_err_ret_tracing(g, fn_type_id->return_type); | 310 | bool have_stack_trace = codegen_fn_has_err_ret_tracing_arg(g, fn_type_id->return_type); |
| 311 | // [0] *StackTrace | 311 | // [0] StackTrace |
| 312 | // [1] StackTrace | 312 | // [1] [stack_trace_ptr_count]usize |
| 313 | // [2] [stack_trace_ptr_count]usize | 313 | uint32_t trace_field_count = have_stack_trace ? 2 : 0; |
| 314 | uint32_t trace_field_count = have_stack_trace ? 3 : 0; | 314 | return frame_index_trace_arg(g, fn_type_id) + trace_field_count; |
| 315 | return frame_index_trace(g, fn_type_id) + trace_field_count; | | |
| 316 | } | 315 | } |
| 317 | | 316 | |
| | 317 | // label (grep this): [coro_frame_struct_layout] |
| | 318 | static uint32_t frame_index_trace_stack(CodeGen *g, FnTypeId *fn_type_id) { |
| | 319 | uint32_t result = frame_index_arg(g, fn_type_id); |
| | 320 | for (size_t i = 0; i < fn_type_id->param_count; i += 1) { |
| | 321 | if (type_has_bits(fn_type_id->param_info->type)) { |
| | 322 | result += 1; |
| | 323 | } |
| | 324 | } |
| | 325 | return result; |
| | 326 | } |
| | 327 | |
| | 328 | |
| 318 | static uint32_t get_err_ret_trace_arg_index(CodeGen *g, ZigFn *fn_table_entry) { | 329 | static uint32_t get_err_ret_trace_arg_index(CodeGen *g, ZigFn *fn_table_entry) { |
| 319 | if (!g->have_err_ret_tracing) { | 330 | if (!g->have_err_ret_tracing) { |
| 320 | return UINT32_MAX; | 331 | return UINT32_MAX; |
| ... | @@ -1287,9 +1298,6 @@ static LLVMValueRef get_cur_err_ret_trace_val(CodeGen *g, Scope *scope) { | ... | @@ -1287,9 +1298,6 @@ static LLVMValueRef get_cur_err_ret_trace_val(CodeGen *g, Scope *scope) { |
| 1287 | if (!g->have_err_ret_tracing) { | 1298 | if (!g->have_err_ret_tracing) { |
| 1288 | return nullptr; | 1299 | return nullptr; |
| 1289 | } | 1300 | } |
| 1290 | if (fn_is_async(g->cur_fn)) { | | |
| 1291 | return LLVMBuildLoad(g->builder, g->cur_err_ret_trace_val_arg, ""); | | |
| 1292 | } | | |
| 1293 | if (g->cur_err_ret_trace_val_stack != nullptr) { | 1301 | if (g->cur_err_ret_trace_val_stack != nullptr) { |
| 1294 | return g->cur_err_ret_trace_val_stack; | 1302 | return g->cur_err_ret_trace_val_stack; |
| 1295 | } | 1303 | } |
| ... | @@ -3441,6 +3449,10 @@ static void render_async_spills(CodeGen *g) { | ... | @@ -3441,6 +3449,10 @@ static void render_async_spills(CodeGen *g) { |
| 3441 | gen_var_debug_decl(g, var); | 3449 | gen_var_debug_decl(g, var); |
| 3442 | } | 3450 | } |
| 3443 | } | 3451 | } |
| | 3452 | // label (grep this): [coro_frame_struct_layout] |
| | 3453 | if (codegen_fn_has_err_ret_tracing_stack(g, g->cur_fn)) { |
| | 3454 | async_var_index += 2; |
| | 3455 | } |
| 3444 | for (size_t alloca_i = 0; alloca_i < g->cur_fn->alloca_gen_list.length; alloca_i += 1) { | 3456 | for (size_t alloca_i = 0; alloca_i < g->cur_fn->alloca_gen_list.length; alloca_i += 1) { |
| 3445 | IrInstructionAllocaGen *instruction = g->cur_fn->alloca_gen_list.at(alloca_i); | 3457 | IrInstructionAllocaGen *instruction = g->cur_fn->alloca_gen_list.at(alloca_i); |
| 3446 | ZigType *ptr_type = instruction->base.value.type; | 3458 | ZigType *ptr_type = instruction->base.value.type; |
| ... | @@ -3525,7 +3537,7 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr | ... | @@ -3525,7 +3537,7 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr |
| 3525 | CallingConvention cc = fn_type->data.fn.fn_type_id.cc; | 3537 | CallingConvention cc = fn_type->data.fn.fn_type_id.cc; |
| 3526 | | 3538 | |
| 3527 | bool first_arg_ret = ret_has_bits && want_first_arg_sret(g, fn_type_id); | 3539 | bool first_arg_ret = ret_has_bits && want_first_arg_sret(g, fn_type_id); |
| 3528 | bool prefix_arg_err_ret_stack = codegen_fn_has_err_ret_tracing(g, fn_type_id->return_type); | 3540 | bool prefix_arg_err_ret_stack = codegen_fn_has_err_ret_tracing_arg(g, fn_type_id->return_type); |
| 3529 | bool is_var_args = fn_type_id->is_var_args; | 3541 | bool is_var_args = fn_type_id->is_var_args; |
| 3530 | ZigList<LLVMValueRef> gen_param_values = {}; | 3542 | ZigList<LLVMValueRef> gen_param_values = {}; |
| 3531 | LLVMValueRef result_loc = instruction->result_loc ? ir_llvm_value(g, instruction->result_loc) : nullptr; | 3543 | LLVMValueRef result_loc = instruction->result_loc ? ir_llvm_value(g, instruction->result_loc) : nullptr; |
| ... | @@ -3572,28 +3584,8 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr | ... | @@ -3572,28 +3584,8 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr |
| 3572 | } | 3584 | } |
| 3573 | } | 3585 | } |
| 3574 | | 3586 | |
| 3575 | if (prefix_arg_err_ret_stack) { | 3587 | // even if prefix_arg_err_ret_stack is true, let the async function do its own |
| 3576 | uint32_t trace_field_index = frame_index_trace(g, fn_type_id); | 3588 | // initialization. |
| 3577 | LLVMValueRef trace_field_ptr_ptr = LLVMBuildStructGEP(g->builder, frame_result_loc, | | |
| 3578 | trace_field_index, ""); | | |
| 3579 | LLVMValueRef trace_field_ptr = LLVMBuildStructGEP(g->builder, frame_result_loc, | | |
| 3580 | trace_field_index + 1, ""); | | |
| 3581 | LLVMValueRef trace_field_addrs = LLVMBuildStructGEP(g->builder, frame_result_loc, | | |
| 3582 | trace_field_index + 2, ""); | | |
| 3583 | LLVMBuildStore(g->builder, trace_field_ptr, trace_field_ptr_ptr); | | |
| 3584 | | | |
| 3585 | LLVMValueRef index_ptr = LLVMBuildStructGEP(g->builder, trace_field_ptr, 0, ""); | | |
| 3586 | LLVMBuildStore(g->builder, zero, index_ptr); | | |
| 3587 | | | |
| 3588 | LLVMValueRef addrs_slice_ptr = LLVMBuildStructGEP(g->builder, trace_field_ptr, 1, ""); | | |
| 3589 | LLVMValueRef addrs_ptr_ptr = LLVMBuildStructGEP(g->builder, addrs_slice_ptr, slice_ptr_index, ""); | | |
| 3590 | LLVMValueRef indices[] = { LLVMConstNull(usize_type_ref), LLVMConstNull(usize_type_ref) }; | | |
| 3591 | LLVMValueRef trace_field_addrs_as_ptr = LLVMBuildInBoundsGEP(g->builder, trace_field_addrs, indices, 2, ""); | | |
| 3592 | LLVMBuildStore(g->builder, trace_field_addrs_as_ptr, addrs_ptr_ptr); | | |
| 3593 | | | |
| 3594 | LLVMValueRef addrs_len_ptr = LLVMBuildStructGEP(g->builder, addrs_slice_ptr, slice_len_index, ""); | | |
| 3595 | LLVMBuildStore(g->builder, LLVMConstInt(usize_type_ref, stack_trace_ptr_count, false), addrs_len_ptr); | | |
| 3596 | } | | |
| 3597 | } else if (callee_is_async) { | 3589 | } else if (callee_is_async) { |
| 3598 | frame_result_loc = ir_llvm_value(g, instruction->frame_result_loc); | 3590 | frame_result_loc = ir_llvm_value(g, instruction->frame_result_loc); |
| 3599 | awaiter_init_val = LLVMBuildPtrToInt(g->builder, g->cur_ret_ptr, usize_type_ref, ""); // caller's own frame pointer | 3591 | awaiter_init_val = LLVMBuildPtrToInt(g->builder, g->cur_ret_ptr, usize_type_ref, ""); // caller's own frame pointer |
| ... | @@ -3607,13 +3599,8 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr | ... | @@ -3607,13 +3599,8 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr |
| 3607 | } | 3599 | } |
| 3608 | } | 3600 | } |
| 3609 | | 3601 | |
| 3610 | if (prefix_arg_err_ret_stack) { | 3602 | // even if prefix_arg_err_ret_stack is true, let the async function do its |
| 3611 | uint32_t trace_field_index = frame_index_trace(g, fn_type_id); | 3603 | // error return tracing normally, and then we'll invoke merge_error_return_traces like normal. |
| 3612 | LLVMValueRef trace_field_ptr = LLVMBuildStructGEP(g->builder, frame_result_loc, trace_field_index, ""); | | |
| 3613 | LLVMValueRef err_trace_val = get_cur_err_ret_trace_val(g, instruction->base.scope); | | |
| 3614 | LLVMBuildStore(g->builder, err_trace_val, trace_field_ptr); | | |
| 3615 | } | | |
| 3616 | | | |
| 3617 | } | 3604 | } |
| 3618 | if (instruction->is_async || callee_is_async) { | 3605 | if (instruction->is_async || callee_is_async) { |
| 3619 | assert(frame_result_loc != nullptr); | 3606 | assert(frame_result_loc != nullptr); |
| ... | @@ -6790,9 +6777,16 @@ static void do_code_gen(CodeGen *g) { | ... | @@ -6790,9 +6777,16 @@ static void do_code_gen(CodeGen *g) { |
| 6790 | g->cur_async_awaiter_ptr = LLVMBuildStructGEP(g->builder, g->cur_ret_ptr, coro_awaiter_index, ""); | 6777 | g->cur_async_awaiter_ptr = LLVMBuildStructGEP(g->builder, g->cur_ret_ptr, coro_awaiter_index, ""); |
| 6791 | LLVMValueRef resume_index_ptr = LLVMBuildStructGEP(g->builder, g->cur_ret_ptr, coro_resume_index, ""); | 6778 | LLVMValueRef resume_index_ptr = LLVMBuildStructGEP(g->builder, g->cur_ret_ptr, coro_resume_index, ""); |
| 6792 | g->cur_async_resume_index_ptr = resume_index_ptr; | 6779 | g->cur_async_resume_index_ptr = resume_index_ptr; |
| 6793 | if (codegen_fn_has_err_ret_tracing(g, fn_type_id->return_type)) { | 6780 | LLVMValueRef err_ret_trace_val = nullptr; |
| 6794 | uint32_t field_index = frame_index_trace(g, fn_type_id); | 6781 | uint32_t trace_field_index; |
| 6795 | g->cur_err_ret_trace_val_arg = LLVMBuildStructGEP(g->builder, g->cur_ret_ptr, field_index, ""); | 6782 | if (codegen_fn_has_err_ret_tracing_arg(g, fn_type_id->return_type)) { |
| | 6783 | trace_field_index = frame_index_trace_arg(g, fn_type_id); |
| | 6784 | err_ret_trace_val = LLVMBuildStructGEP(g->builder, g->cur_ret_ptr, trace_field_index, ""); |
| | 6785 | g->cur_err_ret_trace_val_arg = err_ret_trace_val; |
| | 6786 | } else if (codegen_fn_has_err_ret_tracing_stack(g, fn_table_entry)) { |
| | 6787 | trace_field_index = frame_index_trace_stack(g, fn_type_id); |
| | 6788 | err_ret_trace_val = LLVMBuildStructGEP(g->builder, g->cur_ret_ptr, trace_field_index, ""); |
| | 6789 | g->cur_err_ret_trace_val_stack = err_ret_trace_val; |
| 6796 | } | 6790 | } |
| 6797 | | 6791 | |
| 6798 | LLVMValueRef resume_index = LLVMBuildLoad(g->builder, resume_index_ptr, ""); | 6792 | LLVMValueRef resume_index = LLVMBuildLoad(g->builder, resume_index_ptr, ""); |
| ... | @@ -6804,6 +6798,24 @@ static void do_code_gen(CodeGen *g) { | ... | @@ -6804,6 +6798,24 @@ static void do_code_gen(CodeGen *g) { |
| 6804 | LLVMAddCase(switch_instr, zero, entry_block->llvm_block); | 6798 | LLVMAddCase(switch_instr, zero, entry_block->llvm_block); |
| 6805 | g->cur_resume_block_count += 1; | 6799 | g->cur_resume_block_count += 1; |
| 6806 | LLVMPositionBuilderAtEnd(g->builder, entry_block->llvm_block); | 6800 | LLVMPositionBuilderAtEnd(g->builder, entry_block->llvm_block); |
| | 6801 | if (err_ret_trace_val != nullptr) { |
| | 6802 | LLVMValueRef trace_field_ptr = LLVMBuildStructGEP(g->builder, g->cur_ret_ptr, |
| | 6803 | trace_field_index, ""); |
| | 6804 | LLVMValueRef trace_field_addrs = LLVMBuildStructGEP(g->builder, g->cur_ret_ptr, |
| | 6805 | trace_field_index + 1, ""); |
| | 6806 | |
| | 6807 | LLVMValueRef index_ptr = LLVMBuildStructGEP(g->builder, trace_field_ptr, 0, ""); |
| | 6808 | LLVMBuildStore(g->builder, zero, index_ptr); |
| | 6809 | |
| | 6810 | LLVMValueRef addrs_slice_ptr = LLVMBuildStructGEP(g->builder, trace_field_ptr, 1, ""); |
| | 6811 | LLVMValueRef addrs_ptr_ptr = LLVMBuildStructGEP(g->builder, addrs_slice_ptr, slice_ptr_index, ""); |
| | 6812 | LLVMValueRef indices[] = { LLVMConstNull(usize_type_ref), LLVMConstNull(usize_type_ref) }; |
| | 6813 | LLVMValueRef trace_field_addrs_as_ptr = LLVMBuildInBoundsGEP(g->builder, trace_field_addrs, indices, 2, ""); |
| | 6814 | LLVMBuildStore(g->builder, trace_field_addrs_as_ptr, addrs_ptr_ptr); |
| | 6815 | |
| | 6816 | LLVMValueRef addrs_len_ptr = LLVMBuildStructGEP(g->builder, addrs_slice_ptr, slice_len_index, ""); |
| | 6817 | LLVMBuildStore(g->builder, LLVMConstInt(usize_type_ref, stack_trace_ptr_count, false), addrs_len_ptr); |
| | 6818 | } |
| 6807 | render_async_var_decls(g, entry_block->instruction_list.at(0)->scope); | 6819 | render_async_var_decls(g, entry_block->instruction_list.at(0)->scope); |
| 6808 | } else { | 6820 | } else { |
| 6809 | // create debug variable declarations for parameters | 6821 | // create debug variable declarations for parameters |
| ... | @@ -9707,8 +9719,13 @@ CodeGen *codegen_create(Buf *main_pkg_path, Buf *root_src_path, const ZigTarget | ... | @@ -9707,8 +9719,13 @@ CodeGen *codegen_create(Buf *main_pkg_path, Buf *root_src_path, const ZigTarget |
| 9707 | return g; | 9719 | return g; |
| 9708 | } | 9720 | } |
| 9709 | | 9721 | |
| 9710 | bool codegen_fn_has_err_ret_tracing(CodeGen *g, ZigType *return_type) { | 9722 | bool codegen_fn_has_err_ret_tracing_arg(CodeGen *g, ZigType *return_type) { |
| 9711 | return g->have_err_ret_tracing && | 9723 | return g->have_err_ret_tracing && |
| 9712 | (return_type->id == ZigTypeIdErrorUnion || | 9724 | (return_type->id == ZigTypeIdErrorUnion || |
| 9713 | return_type->id == ZigTypeIdErrorSet); | 9725 | return_type->id == ZigTypeIdErrorSet); |
| 9714 | } | 9726 | } |
| | 9727 | |
| | 9728 | bool codegen_fn_has_err_ret_tracing_stack(CodeGen *g, ZigFn *fn) { |
| | 9729 | return g->have_err_ret_tracing && fn->calls_or_awaits_errorable_fn && |
| | 9730 | !codegen_fn_has_err_ret_tracing_arg(g, fn->type_entry->data.fn.fn_type_id.return_type); |
| | 9731 | } |