| ... | @@ -713,6 +713,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionAwaitBookkeeping | ... | @@ -713,6 +713,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionAwaitBookkeeping |
| 713 | return IrInstructionIdAwaitBookkeeping; | 713 | return IrInstructionIdAwaitBookkeeping; |
| 714 | } | 714 | } |
| 715 | | 715 | |
| | 716 | static constexpr IrInstructionId ir_instruction_id(IrInstructionSaveErrRetAddr *) { |
| | 717 | return IrInstructionIdSaveErrRetAddr; |
| | 718 | } |
| | 719 | |
| 716 | template<typename T> | 720 | template<typename T> |
| 717 | static T *ir_create_instruction(IrBuilder *irb, Scope *scope, AstNode *source_node) { | 721 | static T *ir_create_instruction(IrBuilder *irb, Scope *scope, AstNode *source_node) { |
| 718 | T *special_instruction = allocate<T>(1); | 722 | T *special_instruction = allocate<T>(1); |
| ... | @@ -2678,6 +2682,11 @@ static IrInstruction *ir_build_await_bookkeeping(IrBuilder *irb, Scope *scope, A | ... | @@ -2678,6 +2682,11 @@ static IrInstruction *ir_build_await_bookkeeping(IrBuilder *irb, Scope *scope, A |
| 2678 | return &instruction->base; | 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 | static void ir_count_defers(IrBuilder *irb, Scope *inner_scope, Scope *outer_scope, size_t *results) { | 2690 | static void ir_count_defers(IrBuilder *irb, Scope *inner_scope, Scope *outer_scope, size_t *results) { |
| 2682 | results[ReturnKindUnconditional] = 0; | 2691 | results[ReturnKindUnconditional] = 0; |
| 2683 | results[ReturnKindError] = 0; | 2692 | results[ReturnKindError] = 0; |
| ... | @@ -2750,16 +2759,16 @@ static ScopeDeferExpr *get_scope_defer_expr(Scope *scope) { | ... | @@ -2750,16 +2759,16 @@ static ScopeDeferExpr *get_scope_defer_expr(Scope *scope) { |
| 2750 | return nullptr; | 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 | static IrInstruction *ir_gen_async_return(IrBuilder *irb, Scope *scope, AstNode *node, IrInstruction *return_value, | 2767 | static IrInstruction *ir_gen_async_return(IrBuilder *irb, Scope *scope, AstNode *node, IrInstruction *return_value, |
| 2754 | bool is_generated_code) | 2768 | bool is_generated_code) |
| 2755 | { | 2769 | { |
| 2756 | FnTableEntry *fn_entry = exec_fn_entry(irb->exec); | 2770 | bool is_async = exec_is_async(irb->exec); |
| 2757 | bool is_async = fn_entry != nullptr && fn_entry->type_entry->data.fn.fn_type_id.cc == CallingConventionAsync; | | |
| 2758 | if (!is_async) { | 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 | IrInstruction *return_inst = ir_build_return(irb, scope, node, return_value); | 2772 | IrInstruction *return_inst = ir_build_return(irb, scope, node, return_value); |
| 2764 | return_inst->is_gen = is_generated_code; | 2773 | return_inst->is_gen = is_generated_code; |
| 2765 | return return_inst; | 2774 | return return_inst; |
| ... | @@ -2781,21 +2790,33 @@ static IrInstruction *ir_gen_async_return(IrBuilder *irb, Scope *scope, AstNode | ... | @@ -2781,21 +2790,33 @@ static IrInstruction *ir_gen_async_return(IrBuilder *irb, Scope *scope, AstNode |
| 2781 | // the above blocks are rendered by ir_gen after the rest of codegen | 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) { | 2793 | static bool exec_have_err_ret_trace(CodeGen *g, IrExecutable *exec) { |
| 2785 | // if (!irb->codegen->have_err_ret_tracing) | 2794 | if (!g->have_err_ret_tracing) |
| 2786 | // return; | 2795 | return false; |
| 2787 | // | 2796 | FnTableEntry *fn_entry = exec_fn_entry(exec); |
| 2788 | // if (is_async) { | 2797 | if (fn_entry == nullptr) |
| 2789 | // IrInstruction *err_ret_addr_ptr = ir_build_load_ptr(irb, scope, node, irb->exec->coro_err_ret_addr_ptr); | 2798 | return false; |
| 2790 | // IrInstruction *return_address_ptr = ir_build_return_address(irb, scope, node); | 2799 | if (exec->is_inline) |
| 2791 | // IrInstruction *return_address_usize = ir_build_ptr_to_int(irb, scope, node, return_address_ptr); | 2800 | return false; |
| 2792 | // ir_build_store_ptr(irb, scope, node, err_ret_addr_ptr, return_address_usize); | 2801 | return type_can_fail(fn_entry->type_entry->data.fn.fn_type_id.return_type); |
| 2793 | // return; | 2802 | } |
| 2794 | // } | 2803 | |
| 2795 | // | 2804 | static void ir_gen_save_err_ret_addr(IrBuilder *irb, Scope *scope, AstNode *node) { |
| 2796 | // IrInstruction *stack_trace_ptr = ir_build_error_return_trace_nonnull(irb, scope, node); | 2805 | if (!exec_have_err_ret_trace(irb->codegen, irb->exec)) |
| 2797 | // ir_build_save_err_ret_addr(irb, scope, node, stack_trace_ptr); | 2806 | return; |
| 2798 | //} | 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 | static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node, LVal lval) { | 2821 | static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node, LVal lval) { |
| 2801 | assert(node->type == NodeTypeReturnExpr); | 2822 | assert(node->type == NodeTypeReturnExpr); |
| ... | @@ -2856,7 +2877,7 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node, | ... | @@ -2856,7 +2877,7 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node, |
| 2856 | if (have_err_defers) { | 2877 | if (have_err_defers) { |
| 2857 | ir_gen_defers_for_block(irb, scope, outer_scope, true); | 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 | ir_build_br(irb, scope, node, ret_stmt_block, is_comptime); | 2881 | ir_build_br(irb, scope, node, ret_stmt_block, is_comptime); |
| 2861 | | 2882 | |
| 2862 | ir_set_cursor_at_end_and_append_block(irb, ok_block); | 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,6 +2916,7 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node, |
| 2895 | ir_set_cursor_at_end_and_append_block(irb, return_block); | 2916 | ir_set_cursor_at_end_and_append_block(irb, return_block); |
| 2896 | ir_gen_defers_for_block(irb, scope, outer_scope, true); | 2917 | ir_gen_defers_for_block(irb, scope, outer_scope, true); |
| 2897 | IrInstruction *err_val = ir_build_unwrap_err_code(irb, scope, node, err_union_ptr); | 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 | ir_gen_async_return(irb, scope, node, err_val, false); | 2920 | ir_gen_async_return(irb, scope, node, err_val, false); |
| 2899 | | 2921 | |
| 2900 | ir_set_cursor_at_end_and_append_block(irb, continue_block); | 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,6 +6428,7 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec |
| 6406 | return false; | 6428 | return false; |
| 6407 | | 6429 | |
| 6408 | if (!instr_is_unreachable(result)) { | 6430 | if (!instr_is_unreachable(result)) { |
| | 6431 | // no need for save_err_ret_addr because this cannot return error |
| 6409 | ir_gen_async_return(irb, scope, result->source_node, result, true); | 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,13 +11487,17 @@ static TypeTableEntry *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructi |
| 11464 | return ira->codegen->builtin_types.entry_void; | 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 | static TypeTableEntry *ir_analyze_instruction_error_return_trace(IrAnalyze *ira, | 11495 | static TypeTableEntry *ir_analyze_instruction_error_return_trace(IrAnalyze *ira, |
| 11468 | IrInstructionErrorReturnTrace *instruction) | 11496 | IrInstructionErrorReturnTrace *instruction) |
| 11469 | { | 11497 | { |
| 11470 | FnTableEntry *fn_entry = exec_fn_entry(ira->new_irb.exec); | | |
| 11471 | TypeTableEntry *ptr_to_stack_trace_type = get_ptr_to_stack_trace_type(ira->codegen); | 11498 | TypeTableEntry *ptr_to_stack_trace_type = get_ptr_to_stack_trace_type(ira->codegen); |
| 11472 | TypeTableEntry *nullable_type = get_maybe_type(ira->codegen, ptr_to_stack_trace_type); | 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 | ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base); | 11501 | ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base); |
| 11475 | out_val->data.x_maybe = nullptr; | 11502 | out_val->data.x_maybe = nullptr; |
| 11476 | return nullable_type; | 11503 | return nullable_type; |
| ... | @@ -17775,6 +17802,14 @@ static TypeTableEntry *ir_analyze_instruction_await_bookkeeping(IrAnalyze *ira, | ... | @@ -17775,6 +17802,14 @@ static TypeTableEntry *ir_analyze_instruction_await_bookkeeping(IrAnalyze *ira, |
| 17775 | return out_val->type; | 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 | static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstruction *instruction) { | 17813 | static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstruction *instruction) { |
| 17779 | switch (instruction->id) { | 17814 | switch (instruction->id) { |
| 17780 | case IrInstructionIdInvalid: | 17815 | case IrInstructionIdInvalid: |
| ... | @@ -18012,6 +18047,8 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi | ... | @@ -18012,6 +18047,8 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi |
| 18012 | return ir_analyze_instruction_promise_result_type(ira, (IrInstructionPromiseResultType *)instruction); | 18047 | return ir_analyze_instruction_promise_result_type(ira, (IrInstructionPromiseResultType *)instruction); |
| 18013 | case IrInstructionIdAwaitBookkeeping: | 18048 | case IrInstructionIdAwaitBookkeeping: |
| 18014 | return ir_analyze_instruction_await_bookkeeping(ira, (IrInstructionAwaitBookkeeping *)instruction); | 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 | zig_unreachable(); | 18053 | zig_unreachable(); |
| 18017 | } | 18054 | } |
| ... | @@ -18137,6 +18174,7 @@ bool ir_has_side_effects(IrInstruction *instruction) { | ... | @@ -18137,6 +18174,7 @@ bool ir_has_side_effects(IrInstruction *instruction) { |
| 18137 | case IrInstructionIdCoroSave: | 18174 | case IrInstructionIdCoroSave: |
| 18138 | case IrInstructionIdCoroAllocHelper: | 18175 | case IrInstructionIdCoroAllocHelper: |
| 18139 | case IrInstructionIdAwaitBookkeeping: | 18176 | case IrInstructionIdAwaitBookkeeping: |
| | 18177 | case IrInstructionIdSaveErrRetAddr: |
| 18140 | return true; | 18178 | return true; |
| 18141 | | 18179 | |
| 18142 | case IrInstructionIdPhi: | 18180 | case IrInstructionIdPhi: |