| ... | ... | @@ -707,6 +707,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionPromiseResultTyp |
| 707 | 707 | return IrInstructionIdPromiseResultType; |
| 708 | 708 | } |
| 709 | 709 | |
| 710 | static constexpr IrInstructionId ir_instruction_id(IrInstructionAwaitBookkeeping *) { |
| 711 | return IrInstructionIdAwaitBookkeeping; |
| 712 | } |
| 713 | |
| 710 | 714 | template<typename T> |
| 711 | 715 | static T *ir_create_instruction(IrBuilder *irb, Scope *scope, AstNode *source_node) { |
| 712 | 716 | T *special_instruction = allocate<T>(1); |
| ... | ... | @@ -2656,6 +2660,17 @@ static IrInstruction *ir_build_promise_result_type(IrBuilder *irb, Scope *scope, |
| 2656 | 2660 | return &instruction->base; |
| 2657 | 2661 | } |
| 2658 | 2662 | |
| 2663 | static IrInstruction *ir_build_await_bookkeeping(IrBuilder *irb, Scope *scope, AstNode *source_node, |
| 2664 | IrInstruction *promise_result_type) |
| 2665 | { |
| 2666 | IrInstructionAwaitBookkeeping *instruction = ir_build_instruction<IrInstructionAwaitBookkeeping>(irb, scope, source_node); |
| 2667 | instruction->promise_result_type = promise_result_type; |
| 2668 | |
| 2669 | ir_ref_instruction(promise_result_type, irb->current_basic_block); |
| 2670 | |
| 2671 | return &instruction->base; |
| 2672 | } |
| 2673 | |
| 2659 | 2674 | static void ir_count_defers(IrBuilder *irb, Scope *inner_scope, Scope *outer_scope, size_t *results) { |
| 2660 | 2675 | results[ReturnKindUnconditional] = 0; |
| 2661 | 2676 | results[ReturnKindError] = 0; |
| ... | ... | @@ -2734,13 +2749,16 @@ static IrInstruction *ir_gen_async_return(IrBuilder *irb, Scope *scope, AstNode |
| 2734 | 2749 | FnTableEntry *fn_entry = exec_fn_entry(irb->exec); |
| 2735 | 2750 | bool is_async = fn_entry != nullptr && fn_entry->type_entry->data.fn.fn_type_id.cc == CallingConventionAsync; |
| 2736 | 2751 | if (!is_async) { |
| 2752 | //if (irb->codegen->have_err_ret_tracing) { |
| 2753 | // IrInstruction *stack_trace_ptr = ir_build_error_return_trace_nonnull(irb, scope, node); |
| 2754 | // ir_build_save_err_ret_addr(irb, scope, node, stack_trace_ptr); |
| 2755 | //} |
| 2737 | 2756 | IrInstruction *return_inst = ir_build_return(irb, scope, node, return_value); |
| 2738 | 2757 | return_inst->is_gen = is_generated_code; |
| 2739 | 2758 | return return_inst; |
| 2740 | 2759 | } |
| 2741 | 2760 | |
| 2742 | | IrInstruction *result_ptr = ir_build_load_ptr(irb, scope, node, irb->exec->coro_result_ptr_field_ptr); |
| 2743 | | ir_build_store_ptr(irb, scope, node, result_ptr, return_value); |
| 2761 | ir_build_store_ptr(irb, scope, node, irb->exec->coro_result_field_ptr, return_value); |
| 2744 | 2762 | IrInstruction *promise_type_val = ir_build_const_type(irb, scope, node, |
| 2745 | 2763 | get_maybe_type(irb->codegen, irb->codegen->builtin_types.entry_promise)); |
| 2746 | 2764 | // TODO replace replacement_value with @intToPtr(?promise, 0x1) when it doesn't crash zig |
| ... | ... | @@ -2756,6 +2774,22 @@ static IrInstruction *ir_gen_async_return(IrBuilder *irb, Scope *scope, AstNode |
| 2756 | 2774 | // the above blocks are rendered by ir_gen after the rest of codegen |
| 2757 | 2775 | } |
| 2758 | 2776 | |
| 2777 | //static void ir_gen_save_err_ret_addr(IrBuilder *irb, Scope *scope, AstNode *node, bool is_async) { |
| 2778 | // if (!irb->codegen->have_err_ret_tracing) |
| 2779 | // return; |
| 2780 | // |
| 2781 | // if (is_async) { |
| 2782 | // IrInstruction *err_ret_addr_ptr = ir_build_load_ptr(irb, scope, node, irb->exec->coro_err_ret_addr_ptr); |
| 2783 | // IrInstruction *return_address_ptr = ir_build_return_address(irb, scope, node); |
| 2784 | // IrInstruction *return_address_usize = ir_build_ptr_to_int(irb, scope, node, return_address_ptr); |
| 2785 | // ir_build_store_ptr(irb, scope, node, err_ret_addr_ptr, return_address_usize); |
| 2786 | // return; |
| 2787 | // } |
| 2788 | // |
| 2789 | // IrInstruction *stack_trace_ptr = ir_build_error_return_trace_nonnull(irb, scope, node); |
| 2790 | // ir_build_save_err_ret_addr(irb, scope, node, stack_trace_ptr); |
| 2791 | //} |
| 2792 | |
| 2759 | 2793 | static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node, LVal lval) { |
| 2760 | 2794 | assert(node->type == NodeTypeReturnExpr); |
| 2761 | 2795 | |
| ... | ... | @@ -2791,9 +2825,13 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node, |
| 2791 | 2825 | |
| 2792 | 2826 | size_t defer_counts[2]; |
| 2793 | 2827 | ir_count_defers(irb, scope, outer_scope, defer_counts); |
| 2794 | | if (defer_counts[ReturnKindError] > 0) { |
| 2828 | bool have_err_defers = defer_counts[ReturnKindError] > 0; |
| 2829 | if (have_err_defers || irb->codegen->have_err_ret_tracing) { |
| 2795 | 2830 | IrBasicBlock *err_block = ir_create_basic_block(irb, scope, "ErrRetErr"); |
| 2796 | 2831 | IrBasicBlock *ok_block = ir_create_basic_block(irb, scope, "ErrRetOk"); |
| 2832 | if (!have_err_defers) { |
| 2833 | ir_gen_defers_for_block(irb, scope, outer_scope, false); |
| 2834 | } |
| 2797 | 2835 | |
| 2798 | 2836 | IrInstruction *is_err = ir_build_test_err(irb, scope, node, return_value); |
| 2799 | 2837 | |
| ... | ... | @@ -2808,11 +2846,16 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node, |
| 2808 | 2846 | IrBasicBlock *ret_stmt_block = ir_create_basic_block(irb, scope, "RetStmt"); |
| 2809 | 2847 | |
| 2810 | 2848 | ir_set_cursor_at_end_and_append_block(irb, err_block); |
| 2811 | | ir_gen_defers_for_block(irb, scope, outer_scope, true); |
| 2849 | if (have_err_defers) { |
| 2850 | ir_gen_defers_for_block(irb, scope, outer_scope, true); |
| 2851 | } |
| 2852 | //ir_gen_save_err_ret_addr(irb, scope, node, is_async); |
| 2812 | 2853 | ir_build_br(irb, scope, node, ret_stmt_block, is_comptime); |
| 2813 | 2854 | |
| 2814 | 2855 | ir_set_cursor_at_end_and_append_block(irb, ok_block); |
| 2815 | | ir_gen_defers_for_block(irb, scope, outer_scope, false); |
| 2856 | if (have_err_defers) { |
| 2857 | ir_gen_defers_for_block(irb, scope, outer_scope, false); |
| 2858 | } |
| 2816 | 2859 | ir_build_br(irb, scope, node, ret_stmt_block, is_comptime); |
| 2817 | 2860 | |
| 2818 | 2861 | ir_set_cursor_at_end_and_append_block(irb, ret_stmt_block); |
| ... | ... | @@ -2834,7 +2877,12 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node, |
| 2834 | 2877 | |
| 2835 | 2878 | IrBasicBlock *return_block = ir_create_basic_block(irb, scope, "ErrRetReturn"); |
| 2836 | 2879 | IrBasicBlock *continue_block = ir_create_basic_block(irb, scope, "ErrRetContinue"); |
| 2837 | | IrInstruction *is_comptime = ir_build_const_bool(irb, scope, node, ir_should_inline(irb->exec, scope)); |
| 2880 | IrInstruction *is_comptime; |
| 2881 | if (ir_should_inline(irb->exec, scope)) { |
| 2882 | is_comptime = ir_build_const_bool(irb, scope, node, true); |
| 2883 | } else { |
| 2884 | is_comptime = ir_build_test_comptime(irb, scope, node, is_err_val); |
| 2885 | } |
| 2838 | 2886 | ir_mark_gen(ir_build_cond_br(irb, scope, node, is_err_val, return_block, continue_block, is_comptime)); |
| 2839 | 2887 | |
| 2840 | 2888 | ir_set_cursor_at_end_and_append_block(irb, return_block); |
| ... | ... | @@ -6002,6 +6050,7 @@ static IrInstruction *ir_gen_await_expr(IrBuilder *irb, Scope *parent_scope, Ast |
| 6002 | 6050 | IrInstruction *undefined_value = ir_build_const_undefined(irb, parent_scope, node); |
| 6003 | 6051 | IrInstruction *target_promise_type = ir_build_typeof(irb, parent_scope, node, target_inst); |
| 6004 | 6052 | IrInstruction *promise_result_type = ir_build_promise_result_type(irb, parent_scope, node, target_promise_type); |
| 6053 | ir_build_await_bookkeeping(irb, parent_scope, node, promise_result_type); |
| 6005 | 6054 | ir_build_var_decl(irb, parent_scope, node, result_var, promise_result_type, nullptr, undefined_value); |
| 6006 | 6055 | IrInstruction *my_result_var_ptr = ir_build_var_ptr(irb, parent_scope, node, result_var, false, false); |
| 6007 | 6056 | ir_build_store_ptr(irb, parent_scope, node, result_ptr_field_ptr, my_result_var_ptr); |
| ... | ... | @@ -6271,7 +6320,6 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec |
| 6271 | 6320 | IrInstruction *coro_id; |
| 6272 | 6321 | IrInstruction *u8_ptr_type; |
| 6273 | 6322 | IrInstruction *const_bool_false; |
| 6274 | | IrInstruction *coro_result_field_ptr; |
| 6275 | 6323 | TypeTableEntry *return_type; |
| 6276 | 6324 | Buf *result_ptr_field_name; |
| 6277 | 6325 | VariableTableEntry *coro_size_var; |
| ... | ... | @@ -6325,10 +6373,10 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec |
| 6325 | 6373 | irb->exec->coro_awaiter_field_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr, |
| 6326 | 6374 | awaiter_handle_field_name); |
| 6327 | 6375 | Buf *result_field_name = buf_create_from_str(RESULT_FIELD_NAME); |
| 6328 | | coro_result_field_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr, result_field_name); |
| 6376 | irb->exec->coro_result_field_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr, result_field_name); |
| 6329 | 6377 | result_ptr_field_name = buf_create_from_str(RESULT_PTR_FIELD_NAME); |
| 6330 | 6378 | irb->exec->coro_result_ptr_field_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr, result_ptr_field_name); |
| 6331 | | ir_build_store_ptr(irb, scope, node, irb->exec->coro_result_ptr_field_ptr, coro_result_field_ptr); |
| 6379 | ir_build_store_ptr(irb, scope, node, irb->exec->coro_result_ptr_field_ptr, irb->exec->coro_result_field_ptr); |
| 6332 | 6380 | |
| 6333 | 6381 | |
| 6334 | 6382 | irb->exec->coro_early_final = ir_create_basic_block(irb, scope, "CoroEarlyFinal"); |
| ... | ... | @@ -6368,14 +6416,11 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec |
| 6368 | 6416 | ir_build_unreachable(irb, scope, node); |
| 6369 | 6417 | |
| 6370 | 6418 | ir_set_cursor_at_end_and_append_block(irb, irb->exec->coro_normal_final); |
| 6371 | | ir_build_br(irb, scope, node, check_free_block, const_bool_false); |
| 6372 | | |
| 6373 | | ir_set_cursor_at_end_and_append_block(irb, irb->exec->coro_final_cleanup_block); |
| 6374 | 6419 | if (type_has_bits(return_type)) { |
| 6375 | 6420 | IrInstruction *result_ptr = ir_build_load_ptr(irb, scope, node, irb->exec->coro_result_ptr_field_ptr); |
| 6376 | 6421 | IrInstruction *result_ptr_as_u8_ptr = ir_build_ptr_cast(irb, scope, node, u8_ptr_type, result_ptr); |
| 6377 | 6422 | IrInstruction *return_value_ptr_as_u8_ptr = ir_build_ptr_cast(irb, scope, node, u8_ptr_type, |
| 6378 | | coro_result_field_ptr); |
| 6423 | irb->exec->coro_result_field_ptr); |
| 6379 | 6424 | IrInstruction *return_type_inst = ir_build_const_type(irb, scope, node, |
| 6380 | 6425 | fn_entry->type_entry->data.fn.fn_type_id.return_type); |
| 6381 | 6426 | IrInstruction *size_of_ret_val = ir_build_size_of(irb, scope, node, return_type_inst); |
| ... | ... | @@ -6383,6 +6428,9 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec |
| 6383 | 6428 | } |
| 6384 | 6429 | ir_build_br(irb, scope, node, check_free_block, const_bool_false); |
| 6385 | 6430 | |
| 6431 | ir_set_cursor_at_end_and_append_block(irb, irb->exec->coro_final_cleanup_block); |
| 6432 | ir_build_br(irb, scope, node, check_free_block, const_bool_false); |
| 6433 | |
| 6386 | 6434 | ir_set_cursor_at_end_and_append_block(irb, check_free_block); |
| 6387 | 6435 | IrBasicBlock **incoming_blocks = allocate<IrBasicBlock *>(2); |
| 6388 | 6436 | IrInstruction **incoming_values = allocate<IrInstruction *>(2); |
| ... | ... | @@ -11405,7 +11453,7 @@ static TypeTableEntry *ir_analyze_instruction_error_return_trace(IrAnalyze *ira, |
| 11405 | 11453 | FnTableEntry *fn_entry = exec_fn_entry(ira->new_irb.exec); |
| 11406 | 11454 | TypeTableEntry *ptr_to_stack_trace_type = get_ptr_to_stack_trace_type(ira->codegen); |
| 11407 | 11455 | TypeTableEntry *nullable_type = get_maybe_type(ira->codegen, ptr_to_stack_trace_type); |
| 11408 | | if (fn_entry == nullptr || !fn_entry->calls_errorable_function || !ira->codegen->have_err_ret_tracing) { |
| 11456 | if (fn_entry == nullptr || !fn_entry->calls_or_awaits_errorable_fn || !ira->codegen->have_err_ret_tracing) { |
| 11409 | 11457 | ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base); |
| 11410 | 11458 | out_val->data.x_maybe = nullptr; |
| 11411 | 11459 | return nullable_type; |
| ... | ... | @@ -12085,7 +12133,7 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal |
| 12085 | 12133 | |
| 12086 | 12134 | TypeTableEntry *return_type = impl_fn->type_entry->data.fn.fn_type_id.return_type; |
| 12087 | 12135 | if (fn_type_can_fail(&impl_fn->type_entry->data.fn.fn_type_id)) { |
| 12088 | | parent_fn_entry->calls_errorable_function = true; |
| 12136 | parent_fn_entry->calls_or_awaits_errorable_fn = true; |
| 12089 | 12137 | } |
| 12090 | 12138 | |
| 12091 | 12139 | size_t impl_param_count = impl_fn->type_entry->data.fn.fn_type_id.param_count; |
| ... | ... | @@ -12111,7 +12159,7 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal |
| 12111 | 12159 | assert(fn_type_id->return_type != nullptr); |
| 12112 | 12160 | assert(parent_fn_entry != nullptr); |
| 12113 | 12161 | if (fn_type_can_fail(fn_type_id)) { |
| 12114 | | parent_fn_entry->calls_errorable_function = true; |
| 12162 | parent_fn_entry->calls_or_awaits_errorable_fn = true; |
| 12115 | 12163 | } |
| 12116 | 12164 | |
| 12117 | 12165 | |
| ... | ... | @@ -17655,6 +17703,22 @@ static TypeTableEntry *ir_analyze_instruction_promise_result_type(IrAnalyze *ira |
| 17655 | 17703 | return ira->codegen->builtin_types.entry_type; |
| 17656 | 17704 | } |
| 17657 | 17705 | |
| 17706 | static TypeTableEntry *ir_analyze_instruction_await_bookkeeping(IrAnalyze *ira, IrInstructionAwaitBookkeeping *instruction) { |
| 17707 | TypeTableEntry *promise_result_type = ir_resolve_type(ira, instruction->promise_result_type->other); |
| 17708 | if (type_is_invalid(promise_result_type)) |
| 17709 | return ira->codegen->builtin_types.entry_invalid; |
| 17710 | |
| 17711 | FnTableEntry *fn_entry = exec_fn_entry(ira->new_irb.exec); |
| 17712 | assert(fn_entry != nullptr); |
| 17713 | |
| 17714 | if (type_can_fail(promise_result_type)) { |
| 17715 | fn_entry->calls_or_awaits_errorable_fn = true; |
| 17716 | } |
| 17717 | |
| 17718 | ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base); |
| 17719 | out_val->type = ira->codegen->builtin_types.entry_void; |
| 17720 | return out_val->type; |
| 17721 | } |
| 17658 | 17722 | |
| 17659 | 17723 | static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstruction *instruction) { |
| 17660 | 17724 | switch (instruction->id) { |
| ... | ... | @@ -17672,6 +17736,7 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi |
| 17672 | 17736 | case IrInstructionIdErrWrapPayload: |
| 17673 | 17737 | case IrInstructionIdCast: |
| 17674 | 17738 | zig_unreachable(); |
| 17739 | |
| 17675 | 17740 | case IrInstructionIdReturn: |
| 17676 | 17741 | return ir_analyze_instruction_return(ira, (IrInstructionReturn *)instruction); |
| 17677 | 17742 | case IrInstructionIdConst: |
| ... | ... | @@ -17890,6 +17955,8 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi |
| 17890 | 17955 | return ir_analyze_instruction_atomic_rmw(ira, (IrInstructionAtomicRmw *)instruction); |
| 17891 | 17956 | case IrInstructionIdPromiseResultType: |
| 17892 | 17957 | return ir_analyze_instruction_promise_result_type(ira, (IrInstructionPromiseResultType *)instruction); |
| 17958 | case IrInstructionIdAwaitBookkeeping: |
| 17959 | return ir_analyze_instruction_await_bookkeeping(ira, (IrInstructionAwaitBookkeeping *)instruction); |
| 17893 | 17960 | } |
| 17894 | 17961 | zig_unreachable(); |
| 17895 | 17962 | } |
| ... | ... | @@ -18014,6 +18081,7 @@ bool ir_has_side_effects(IrInstruction *instruction) { |
| 18014 | 18081 | case IrInstructionIdCoroResume: |
| 18015 | 18082 | case IrInstructionIdCoroSave: |
| 18016 | 18083 | case IrInstructionIdCoroAllocHelper: |
| 18084 | case IrInstructionIdAwaitBookkeeping: |
| 18017 | 18085 | return true; |
| 18018 | 18086 | |
| 18019 | 18087 | case IrInstructionIdPhi: |