| ... | ... | @@ -298,7 +298,7 @@ static LLVMLinkage to_llvm_linkage(GlobalLinkageId id) { |
| 298 | 298 | } |
| 299 | 299 | |
| 300 | 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 | 302 | // [0] *ReturnType |
| 303 | 303 | // [1] ReturnType |
| 304 | 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 | 307 | |
| 308 | 308 | // label (grep this): [coro_frame_struct_layout] |
| 309 | 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); |
| 311 | | // [0] *StackTrace |
| 312 | | // [1] StackTrace |
| 313 | | // [2] [stack_trace_ptr_count]usize |
| 314 | | uint32_t trace_field_count = have_stack_trace ? 3 : 0; |
| 315 | | return frame_index_trace(g, fn_type_id) + trace_field_count; |
| 310 | bool have_stack_trace = codegen_fn_has_err_ret_tracing_arg(g, fn_type_id->return_type); |
| 311 | // [0] StackTrace |
| 312 | // [1] [stack_trace_ptr_count]usize |
| 313 | uint32_t trace_field_count = have_stack_trace ? 2 : 0; |
| 314 | return frame_index_trace_arg(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 | 329 | static uint32_t get_err_ret_trace_arg_index(CodeGen *g, ZigFn *fn_table_entry) { |
| 319 | 330 | if (!g->have_err_ret_tracing) { |
| 320 | 331 | return UINT32_MAX; |
| ... | ... | @@ -1287,9 +1298,6 @@ static LLVMValueRef get_cur_err_ret_trace_val(CodeGen *g, Scope *scope) { |
| 1287 | 1298 | if (!g->have_err_ret_tracing) { |
| 1288 | 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 | 1301 | if (g->cur_err_ret_trace_val_stack != nullptr) { |
| 1294 | 1302 | return g->cur_err_ret_trace_val_stack; |
| 1295 | 1303 | } |
| ... | ... | @@ -3441,6 +3449,10 @@ static void render_async_spills(CodeGen *g) { |
| 3441 | 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 | 3456 | for (size_t alloca_i = 0; alloca_i < g->cur_fn->alloca_gen_list.length; alloca_i += 1) { |
| 3445 | 3457 | IrInstructionAllocaGen *instruction = g->cur_fn->alloca_gen_list.at(alloca_i); |
| 3446 | 3458 | ZigType *ptr_type = instruction->base.value.type; |
| ... | ... | @@ -3525,7 +3537,7 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr |
| 3525 | 3537 | CallingConvention cc = fn_type->data.fn.fn_type_id.cc; |
| 3526 | 3538 | |
| 3527 | 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 | 3541 | bool is_var_args = fn_type_id->is_var_args; |
| 3530 | 3542 | ZigList<LLVMValueRef> gen_param_values = {}; |
| 3531 | 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 | 3584 | } |
| 3573 | 3585 | } |
| 3574 | 3586 | |
| 3575 | | if (prefix_arg_err_ret_stack) { |
| 3576 | | uint32_t trace_field_index = frame_index_trace(g, fn_type_id); |
| 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 | | } |
| 3587 | // even if prefix_arg_err_ret_stack is true, let the async function do its own |
| 3588 | // initialization. |
| 3597 | 3589 | } else if (callee_is_async) { |
| 3598 | 3590 | frame_result_loc = ir_llvm_value(g, instruction->frame_result_loc); |
| 3599 | 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 | 3599 | } |
| 3608 | 3600 | } |
| 3609 | 3601 | |
| 3610 | | if (prefix_arg_err_ret_stack) { |
| 3611 | | uint32_t trace_field_index = frame_index_trace(g, fn_type_id); |
| 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 | | |
| 3602 | // even if prefix_arg_err_ret_stack is true, let the async function do its |
| 3603 | // error return tracing normally, and then we'll invoke merge_error_return_traces like normal. |
| 3617 | 3604 | } |
| 3618 | 3605 | if (instruction->is_async || callee_is_async) { |
| 3619 | 3606 | assert(frame_result_loc != nullptr); |
| ... | ... | @@ -6790,9 +6777,16 @@ static void do_code_gen(CodeGen *g) { |
| 6790 | 6777 | g->cur_async_awaiter_ptr = LLVMBuildStructGEP(g->builder, g->cur_ret_ptr, coro_awaiter_index, ""); |
| 6791 | 6778 | LLVMValueRef resume_index_ptr = LLVMBuildStructGEP(g->builder, g->cur_ret_ptr, coro_resume_index, ""); |
| 6792 | 6779 | g->cur_async_resume_index_ptr = resume_index_ptr; |
| 6793 | | if (codegen_fn_has_err_ret_tracing(g, fn_type_id->return_type)) { |
| 6794 | | uint32_t field_index = frame_index_trace(g, fn_type_id); |
| 6795 | | g->cur_err_ret_trace_val_arg = LLVMBuildStructGEP(g->builder, g->cur_ret_ptr, field_index, ""); |
| 6780 | LLVMValueRef err_ret_trace_val = nullptr; |
| 6781 | uint32_t trace_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 | 6792 | LLVMValueRef resume_index = LLVMBuildLoad(g->builder, resume_index_ptr, ""); |
| ... | ... | @@ -6804,6 +6798,24 @@ static void do_code_gen(CodeGen *g) { |
| 6804 | 6798 | LLVMAddCase(switch_instr, zero, entry_block->llvm_block); |
| 6805 | 6799 | g->cur_resume_block_count += 1; |
| 6806 | 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 | 6819 | render_async_var_decls(g, entry_block->instruction_list.at(0)->scope); |
| 6808 | 6820 | } else { |
| 6809 | 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 | 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 | 9723 | return g->have_err_ret_tracing && |
| 9712 | 9724 | (return_type->id == ZigTypeIdErrorUnion || |
| 9713 | 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 | } |