| ... | ... | @@ -713,6 +713,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionAwaitBookkeeping |
| 713 | 713 | return IrInstructionIdAwaitBookkeeping; |
| 714 | 714 | } |
| 715 | 715 | |
| 716 | static constexpr IrInstructionId ir_instruction_id(IrInstructionSaveErrRetAddr *) { |
| 717 | return IrInstructionIdSaveErrRetAddr; |
| 718 | } |
| 719 | |
| 716 | 720 | template<typename T> |
| 717 | 721 | static T *ir_create_instruction(IrBuilder *irb, Scope *scope, AstNode *source_node) { |
| 718 | 722 | T *special_instruction = allocate<T>(1); |
| ... | ... | @@ -2678,6 +2682,11 @@ static IrInstruction *ir_build_await_bookkeeping(IrBuilder *irb, Scope *scope, A |
| 2678 | 2682 | return &instruction->base; |
| 2679 | 2683 | } |
| 2680 | 2684 | |
| 2685 | static IrInstruction *ir_build_save_err_ret_addr(IrBuilder *irb, Scope *scope, AstNode *source_node) { |
| 2686 | IrInstructionSaveErrRetAddr *instruction = ir_build_instruction<IrInstructionSaveErrRetAddr>(irb, scope, source_node); |
| 2687 | return &instruction->base; |
| 2688 | } |
| 2689 | |
| 2681 | 2690 | static void ir_count_defers(IrBuilder *irb, Scope *inner_scope, Scope *outer_scope, size_t *results) { |
| 2682 | 2691 | results[ReturnKindUnconditional] = 0; |
| 2683 | 2692 | results[ReturnKindError] = 0; |
| ... | ... | @@ -2750,16 +2759,16 @@ static ScopeDeferExpr *get_scope_defer_expr(Scope *scope) { |
| 2750 | 2759 | return nullptr; |
| 2751 | 2760 | } |
| 2752 | 2761 | |
| 2762 | static bool exec_is_async(IrExecutable *exec) { |
| 2763 | FnTableEntry *fn_entry = exec_fn_entry(exec); |
| 2764 | return fn_entry != nullptr && fn_entry->type_entry->data.fn.fn_type_id.cc == CallingConventionAsync; |
| 2765 | } |
| 2766 | |
| 2753 | 2767 | static IrInstruction *ir_gen_async_return(IrBuilder *irb, Scope *scope, AstNode *node, IrInstruction *return_value, |
| 2754 | 2768 | bool is_generated_code) |
| 2755 | 2769 | { |
| 2756 | | FnTableEntry *fn_entry = exec_fn_entry(irb->exec); |
| 2757 | | bool is_async = fn_entry != nullptr && fn_entry->type_entry->data.fn.fn_type_id.cc == CallingConventionAsync; |
| 2770 | bool is_async = exec_is_async(irb->exec); |
| 2758 | 2771 | if (!is_async) { |
| 2759 | | //if (irb->codegen->have_err_ret_tracing) { |
| 2760 | | // IrInstruction *stack_trace_ptr = ir_build_error_return_trace_nonnull(irb, scope, node); |
| 2761 | | // ir_build_save_err_ret_addr(irb, scope, node, stack_trace_ptr); |
| 2762 | | //} |
| 2763 | 2772 | IrInstruction *return_inst = ir_build_return(irb, scope, node, return_value); |
| 2764 | 2773 | return_inst->is_gen = is_generated_code; |
| 2765 | 2774 | return return_inst; |
| ... | ... | @@ -2781,21 +2790,33 @@ static IrInstruction *ir_gen_async_return(IrBuilder *irb, Scope *scope, AstNode |
| 2781 | 2790 | // the above blocks are rendered by ir_gen after the rest of codegen |
| 2782 | 2791 | } |
| 2783 | 2792 | |
| 2784 | | //static void ir_gen_save_err_ret_addr(IrBuilder *irb, Scope *scope, AstNode *node, bool is_async) { |
| 2785 | | // if (!irb->codegen->have_err_ret_tracing) |
| 2786 | | // return; |
| 2787 | | // |
| 2788 | | // if (is_async) { |
| 2789 | | // IrInstruction *err_ret_addr_ptr = ir_build_load_ptr(irb, scope, node, irb->exec->coro_err_ret_addr_ptr); |
| 2790 | | // IrInstruction *return_address_ptr = ir_build_return_address(irb, scope, node); |
| 2791 | | // IrInstruction *return_address_usize = ir_build_ptr_to_int(irb, scope, node, return_address_ptr); |
| 2792 | | // ir_build_store_ptr(irb, scope, node, err_ret_addr_ptr, return_address_usize); |
| 2793 | | // return; |
| 2794 | | // } |
| 2795 | | // |
| 2796 | | // IrInstruction *stack_trace_ptr = ir_build_error_return_trace_nonnull(irb, scope, node); |
| 2797 | | // ir_build_save_err_ret_addr(irb, scope, node, stack_trace_ptr); |
| 2798 | | //} |
| 2793 | static bool exec_have_err_ret_trace(CodeGen *g, IrExecutable *exec) { |
| 2794 | if (!g->have_err_ret_tracing) |
| 2795 | return false; |
| 2796 | FnTableEntry *fn_entry = exec_fn_entry(exec); |
| 2797 | if (fn_entry == nullptr) |
| 2798 | return false; |
| 2799 | if (exec->is_inline) |
| 2800 | return false; |
| 2801 | return type_can_fail(fn_entry->type_entry->data.fn.fn_type_id.return_type); |
| 2802 | } |
| 2803 | |
| 2804 | static void ir_gen_save_err_ret_addr(IrBuilder *irb, Scope *scope, AstNode *node) { |
| 2805 | if (!exec_have_err_ret_trace(irb->codegen, irb->exec)) |
| 2806 | return; |
| 2807 | |
| 2808 | bool is_async = exec_is_async(irb->exec); |
| 2809 | |
| 2810 | if (is_async) { |
| 2811 | //IrInstruction *err_ret_addr_ptr = ir_build_load_ptr(irb, scope, node, irb->exec->coro_err_ret_addr_ptr); |
| 2812 | //IrInstruction *return_address_ptr = ir_build_instr_addr(irb, scope, node); |
| 2813 | //IrInstruction *return_address_usize = ir_build_ptr_to_int(irb, scope, node, return_address_ptr); |
| 2814 | //ir_build_store_ptr(irb, scope, node, err_ret_addr_ptr, return_address_usize); |
| 2815 | return; |
| 2816 | } |
| 2817 | |
| 2818 | ir_build_save_err_ret_addr(irb, scope, node); |
| 2819 | } |
| 2799 | 2820 | |
| 2800 | 2821 | static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node, LVal lval) { |
| 2801 | 2822 | assert(node->type == NodeTypeReturnExpr); |
| ... | ... | @@ -2856,7 +2877,7 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node, |
| 2856 | 2877 | if (have_err_defers) { |
| 2857 | 2878 | ir_gen_defers_for_block(irb, scope, outer_scope, true); |
| 2858 | 2879 | } |
| 2859 | | //ir_gen_save_err_ret_addr(irb, scope, node, is_async); |
| 2880 | ir_gen_save_err_ret_addr(irb, scope, node); |
| 2860 | 2881 | ir_build_br(irb, scope, node, ret_stmt_block, is_comptime); |
| 2861 | 2882 | |
| 2862 | 2883 | ir_set_cursor_at_end_and_append_block(irb, ok_block); |
| ... | ... | @@ -2895,6 +2916,7 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node, |
| 2895 | 2916 | ir_set_cursor_at_end_and_append_block(irb, return_block); |
| 2896 | 2917 | ir_gen_defers_for_block(irb, scope, outer_scope, true); |
| 2897 | 2918 | IrInstruction *err_val = ir_build_unwrap_err_code(irb, scope, node, err_union_ptr); |
| 2919 | ir_gen_save_err_ret_addr(irb, scope, node); |
| 2898 | 2920 | ir_gen_async_return(irb, scope, node, err_val, false); |
| 2899 | 2921 | |
| 2900 | 2922 | ir_set_cursor_at_end_and_append_block(irb, continue_block); |
| ... | ... | @@ -6406,6 +6428,7 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec |
| 6406 | 6428 | return false; |
| 6407 | 6429 | |
| 6408 | 6430 | if (!instr_is_unreachable(result)) { |
| 6431 | // no need for save_err_ret_addr because this cannot return error |
| 6409 | 6432 | ir_gen_async_return(irb, scope, result->source_node, result, true); |
| 6410 | 6433 | } |
| 6411 | 6434 | |
| ... | ... | @@ -11464,13 +11487,17 @@ static TypeTableEntry *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructi |
| 11464 | 11487 | return ira->codegen->builtin_types.entry_void; |
| 11465 | 11488 | } |
| 11466 | 11489 | |
| 11490 | static bool exec_has_err_ret_trace(CodeGen *g, IrExecutable *exec) { |
| 11491 | FnTableEntry *fn_entry = exec_fn_entry(exec); |
| 11492 | return fn_entry != nullptr && fn_entry->calls_or_awaits_errorable_fn && g->have_err_ret_tracing; |
| 11493 | } |
| 11494 | |
| 11467 | 11495 | static TypeTableEntry *ir_analyze_instruction_error_return_trace(IrAnalyze *ira, |
| 11468 | 11496 | IrInstructionErrorReturnTrace *instruction) |
| 11469 | 11497 | { |
| 11470 | | FnTableEntry *fn_entry = exec_fn_entry(ira->new_irb.exec); |
| 11471 | 11498 | TypeTableEntry *ptr_to_stack_trace_type = get_ptr_to_stack_trace_type(ira->codegen); |
| 11472 | 11499 | TypeTableEntry *nullable_type = get_maybe_type(ira->codegen, ptr_to_stack_trace_type); |
| 11473 | | if (fn_entry == nullptr || !fn_entry->calls_or_awaits_errorable_fn || !ira->codegen->have_err_ret_tracing) { |
| 11500 | if (!exec_has_err_ret_trace(ira->codegen, ira->new_irb.exec)) { |
| 11474 | 11501 | ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base); |
| 11475 | 11502 | out_val->data.x_maybe = nullptr; |
| 11476 | 11503 | return nullable_type; |
| ... | ... | @@ -17775,6 +17802,14 @@ static TypeTableEntry *ir_analyze_instruction_await_bookkeeping(IrAnalyze *ira, |
| 17775 | 17802 | return out_val->type; |
| 17776 | 17803 | } |
| 17777 | 17804 | |
| 17805 | static TypeTableEntry *ir_analyze_instruction_save_err_ret_addr(IrAnalyze *ira, IrInstructionSaveErrRetAddr *instruction) { |
| 17806 | IrInstruction *result = ir_build_save_err_ret_addr(&ira->new_irb, instruction->base.scope, |
| 17807 | instruction->base.source_node); |
| 17808 | ir_link_new_instruction(result, &instruction->base); |
| 17809 | result->value.type = ira->codegen->builtin_types.entry_void; |
| 17810 | return result->value.type; |
| 17811 | } |
| 17812 | |
| 17778 | 17813 | static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstruction *instruction) { |
| 17779 | 17814 | switch (instruction->id) { |
| 17780 | 17815 | case IrInstructionIdInvalid: |
| ... | ... | @@ -18012,6 +18047,8 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi |
| 18012 | 18047 | return ir_analyze_instruction_promise_result_type(ira, (IrInstructionPromiseResultType *)instruction); |
| 18013 | 18048 | case IrInstructionIdAwaitBookkeeping: |
| 18014 | 18049 | return ir_analyze_instruction_await_bookkeeping(ira, (IrInstructionAwaitBookkeeping *)instruction); |
| 18050 | case IrInstructionIdSaveErrRetAddr: |
| 18051 | return ir_analyze_instruction_save_err_ret_addr(ira, (IrInstructionSaveErrRetAddr *)instruction); |
| 18015 | 18052 | } |
| 18016 | 18053 | zig_unreachable(); |
| 18017 | 18054 | } |
| ... | ... | @@ -18137,6 +18174,7 @@ bool ir_has_side_effects(IrInstruction *instruction) { |
| 18137 | 18174 | case IrInstructionIdCoroSave: |
| 18138 | 18175 | case IrInstructionIdCoroAllocHelper: |
| 18139 | 18176 | case IrInstructionIdAwaitBookkeeping: |
| 18177 | case IrInstructionIdSaveErrRetAddr: |
| 18140 | 18178 | return true; |
| 18141 | 18179 | |
| 18142 | 18180 | case IrInstructionIdPhi: |