| author | |
| committer | |
| log | 17199b087915661c935f0970cc1e4eb29968a68d |
| tree | 8bac40ee50c809720fee1bbfbd23bbc4347500a1 |
| parent | 400500a3afafca8178f13a7e4e1cd0ae7808aff2 |
| signature |
5 files changed, 114 insertions(+), 95 deletions(-)
src/all_types.hpp+1-1| ... | @@ -1718,7 +1718,7 @@ struct CodeGen { | ... | @@ -1718,7 +1718,7 @@ struct CodeGen { |
| 1718 | LLVMTargetMachineRef target_machine; | 1718 | LLVMTargetMachineRef target_machine; |
| 1719 | ZigLLVMDIFile *dummy_di_file; | 1719 | ZigLLVMDIFile *dummy_di_file; |
| 1720 | LLVMValueRef cur_ret_ptr; | 1720 | LLVMValueRef cur_ret_ptr; |
| 1721 | LLVMValueRef cur_ret_ptr_ptr; | 1721 | LLVMValueRef cur_frame_ptr; |
| 1722 | LLVMValueRef cur_fn_val; | 1722 | LLVMValueRef cur_fn_val; |
| 1723 | LLVMValueRef cur_async_switch_instr; | 1723 | LLVMValueRef cur_async_switch_instr; |
| 1724 | LLVMValueRef cur_async_resume_index_ptr; | 1724 | LLVMValueRef cur_async_resume_index_ptr; |
src/analyze.cpp+5| ... | @@ -5160,6 +5160,8 @@ static ZigType *get_async_fn_type(CodeGen *g, ZigType *orig_fn_type) { | ... | @@ -5160,6 +5160,8 @@ static ZigType *get_async_fn_type(CodeGen *g, ZigType *orig_fn_type) { |
| 5160 | } | 5160 | } |
| 5161 | 5161 | ||
| 5162 | static Error resolve_coro_frame(CodeGen *g, ZigType *frame_type) { | 5162 | static Error resolve_coro_frame(CodeGen *g, ZigType *frame_type) { |
| 5163 | Error err; | ||
| 5164 | |||
| 5163 | if (frame_type->data.frame.locals_struct != nullptr) | 5165 | if (frame_type->data.frame.locals_struct != nullptr) |
| 5164 | return ErrorNone; | 5166 | return ErrorNone; |
| 5165 | 5167 | ||
| ... | @@ -5286,6 +5288,9 @@ static Error resolve_coro_frame(CodeGen *g, ZigType *frame_type) { | ... | @@ -5286,6 +5288,9 @@ static Error resolve_coro_frame(CodeGen *g, ZigType *frame_type) { |
| 5286 | continue; | 5288 | continue; |
| 5287 | } | 5289 | } |
| 5288 | } | 5290 | } |
| 5291 | if ((err = type_resolve(g, child_type, ResolveStatusSizeKnown))) { | ||
| 5292 | return err; | ||
| 5293 | } | ||
| 5289 | const char *name; | 5294 | const char *name; |
| 5290 | if (*instruction->name_hint == 0) { | 5295 | if (*instruction->name_hint == 0) { |
| 5291 | name = buf_ptr(buf_sprintf("@local%" ZIG_PRI_usize, alloca_i)); | 5296 | name = buf_ptr(buf_sprintf("@local%" ZIG_PRI_usize, alloca_i)); |
src/codegen.cpp+37-31| ... | @@ -2088,17 +2088,19 @@ static LLVMValueRef gen_resume(CodeGen *g, LLVMValueRef fn_val, LLVMValueRef tar | ... | @@ -2088,17 +2088,19 @@ static LLVMValueRef gen_resume(CodeGen *g, LLVMValueRef fn_val, LLVMValueRef tar |
| 2088 | static LLVMValueRef ir_render_return_begin(CodeGen *g, IrExecutable *executable, | 2088 | static LLVMValueRef ir_render_return_begin(CodeGen *g, IrExecutable *executable, |
| 2089 | IrInstructionReturnBegin *instruction) | 2089 | IrInstructionReturnBegin *instruction) |
| 2090 | { | 2090 | { |
| 2091 | if (!fn_is_async(g->cur_fn)) return nullptr; | 2091 | bool ret_type_has_bits = instruction->operand != nullptr && |
| 2092 | type_has_bits(instruction->operand->value.type); | ||
| 2093 | |||
| 2094 | if (!fn_is_async(g->cur_fn)) { | ||
| 2095 | return ret_type_has_bits ? ir_llvm_value(g, instruction->operand) : nullptr; | ||
| 2096 | } | ||
| 2092 | 2097 | ||
| 2093 | LLVMTypeRef usize_type_ref = g->builtin_types.entry_usize->llvm_type; | 2098 | LLVMTypeRef usize_type_ref = g->builtin_types.entry_usize->llvm_type; |
| 2094 | 2099 | ||
| 2095 | bool ret_type_has_bits = instruction->operand != nullptr && | ||
| 2096 | type_has_bits(instruction->operand->value.type); | ||
| 2097 | ZigType *ret_type = ret_type_has_bits ? instruction->operand->value.type : nullptr; | 2100 | ZigType *ret_type = ret_type_has_bits ? instruction->operand->value.type : nullptr; |
| 2098 | if (ret_type_has_bits && !handle_is_ptr(ret_type)) { | 2101 | if (ret_type_has_bits && !handle_is_ptr(ret_type)) { |
| 2099 | // It's a scalar, so it didn't get written to the result ptr. Do that before the atomic rmw. | 2102 | // It's a scalar, so it didn't get written to the result ptr. Do that before the atomic rmw. |
| 2100 | LLVMValueRef result_ptr = LLVMBuildLoad(g->builder, g->cur_ret_ptr_ptr, ""); | 2103 | LLVMBuildStore(g->builder, ir_llvm_value(g, instruction->operand), g->cur_ret_ptr); |
| 2101 | LLVMBuildStore(g->builder, ir_llvm_value(g, instruction->operand), result_ptr); | ||
| 2102 | } | 2104 | } |
| 2103 | 2105 | ||
| 2104 | // Prepare to be suspended. We might end up not having to suspend though. | 2106 | // Prepare to be suspended. We might end up not having to suspend though. |
| ... | @@ -2147,7 +2149,11 @@ static LLVMValueRef ir_render_return_begin(CodeGen *g, IrExecutable *executable, | ... | @@ -2147,7 +2149,11 @@ static LLVMValueRef ir_render_return_begin(CodeGen *g, IrExecutable *executable, |
| 2147 | LLVMBasicBlockRef incoming_blocks[] = { after_resume_block, switch_bb }; | 2149 | LLVMBasicBlockRef incoming_blocks[] = { after_resume_block, switch_bb }; |
| 2148 | LLVMAddIncoming(g->cur_async_prev_val, incoming_values, incoming_blocks, 2); | 2150 | LLVMAddIncoming(g->cur_async_prev_val, incoming_values, incoming_blocks, 2); |
| 2149 | 2151 | ||
| 2150 | return nullptr; | 2152 | if (!ret_type_has_bits) { |
| 2153 | return nullptr; | ||
| 2154 | } | ||
| 2155 | |||
| 2156 | return get_handle_value(g, g->cur_ret_ptr, ret_type, get_pointer_to_type(g, ret_type, true)); | ||
| 2151 | } | 2157 | } |
| 2152 | 2158 | ||
| 2153 | static LLVMValueRef ir_render_return(CodeGen *g, IrExecutable *executable, IrInstructionReturn *instruction) { | 2159 | static LLVMValueRef ir_render_return(CodeGen *g, IrExecutable *executable, IrInstructionReturn *instruction) { |
| ... | @@ -2166,17 +2172,16 @@ static LLVMValueRef ir_render_return(CodeGen *g, IrExecutable *executable, IrIns | ... | @@ -2166,17 +2172,16 @@ static LLVMValueRef ir_render_return(CodeGen *g, IrExecutable *executable, IrIns |
| 2166 | // If the awaiter result pointer is non-null, we need to copy the result to there. | 2172 | // If the awaiter result pointer is non-null, we need to copy the result to there. |
| 2167 | LLVMBasicBlockRef copy_block = LLVMAppendBasicBlock(g->cur_fn_val, "CopyResult"); | 2173 | LLVMBasicBlockRef copy_block = LLVMAppendBasicBlock(g->cur_fn_val, "CopyResult"); |
| 2168 | LLVMBasicBlockRef copy_end_block = LLVMAppendBasicBlock(g->cur_fn_val, "CopyResultEnd"); | 2174 | LLVMBasicBlockRef copy_end_block = LLVMAppendBasicBlock(g->cur_fn_val, "CopyResultEnd"); |
| 2169 | LLVMValueRef awaiter_ret_ptr_ptr = LLVMBuildStructGEP(g->builder, g->cur_ret_ptr, coro_ret_start + 1, ""); | 2175 | LLVMValueRef awaiter_ret_ptr_ptr = LLVMBuildStructGEP(g->builder, g->cur_frame_ptr, coro_ret_start + 1, ""); |
| 2170 | LLVMValueRef awaiter_ret_ptr = LLVMBuildLoad(g->builder, awaiter_ret_ptr_ptr, ""); | 2176 | LLVMValueRef awaiter_ret_ptr = LLVMBuildLoad(g->builder, awaiter_ret_ptr_ptr, ""); |
| 2171 | LLVMValueRef zero_ptr = LLVMConstNull(LLVMTypeOf(awaiter_ret_ptr)); | 2177 | LLVMValueRef zero_ptr = LLVMConstNull(LLVMTypeOf(awaiter_ret_ptr)); |
| 2172 | LLVMValueRef need_copy_bit = LLVMBuildICmp(g->builder, LLVMIntNE, awaiter_ret_ptr, zero_ptr, ""); | 2178 | LLVMValueRef need_copy_bit = LLVMBuildICmp(g->builder, LLVMIntNE, awaiter_ret_ptr, zero_ptr, ""); |
| 2173 | LLVMBuildCondBr(g->builder, need_copy_bit, copy_block, copy_end_block); | 2179 | LLVMBuildCondBr(g->builder, need_copy_bit, copy_block, copy_end_block); |
| 2174 | 2180 | ||
| 2175 | LLVMPositionBuilderAtEnd(g->builder, copy_block); | 2181 | LLVMPositionBuilderAtEnd(g->builder, copy_block); |
| 2176 | LLVMValueRef ret_ptr = LLVMBuildLoad(g->builder, g->cur_ret_ptr_ptr, ""); | ||
| 2177 | LLVMTypeRef ptr_u8 = LLVMPointerType(LLVMInt8Type(), 0); | 2182 | LLVMTypeRef ptr_u8 = LLVMPointerType(LLVMInt8Type(), 0); |
| 2178 | LLVMValueRef dest_ptr_casted = LLVMBuildBitCast(g->builder, awaiter_ret_ptr, ptr_u8, ""); | 2183 | LLVMValueRef dest_ptr_casted = LLVMBuildBitCast(g->builder, awaiter_ret_ptr, ptr_u8, ""); |
| 2179 | LLVMValueRef src_ptr_casted = LLVMBuildBitCast(g->builder, ret_ptr, ptr_u8, ""); | 2184 | LLVMValueRef src_ptr_casted = LLVMBuildBitCast(g->builder, g->cur_ret_ptr, ptr_u8, ""); |
| 2180 | bool is_volatile = false; | 2185 | bool is_volatile = false; |
| 2181 | uint32_t abi_align = get_abi_alignment(g, ret_type); | 2186 | uint32_t abi_align = get_abi_alignment(g, ret_type); |
| 2182 | LLVMValueRef byte_count_val = LLVMConstInt(usize_type_ref, type_size(g, ret_type), false); | 2187 | LLVMValueRef byte_count_val = LLVMConstInt(usize_type_ref, type_size(g, ret_type), false); |
| ... | @@ -3385,10 +3390,6 @@ static LLVMValueRef ir_render_return_ptr(CodeGen *g, IrExecutable *executable, | ... | @@ -3385,10 +3390,6 @@ static LLVMValueRef ir_render_return_ptr(CodeGen *g, IrExecutable *executable, |
| 3385 | if (!type_has_bits(instruction->base.value.type)) | 3390 | if (!type_has_bits(instruction->base.value.type)) |
| 3386 | return nullptr; | 3391 | return nullptr; |
| 3387 | src_assert(g->cur_ret_ptr != nullptr, instruction->base.source_node); | 3392 | src_assert(g->cur_ret_ptr != nullptr, instruction->base.source_node); |
| 3388 | if (fn_is_async(g->cur_fn)) { | ||
| 3389 | LLVMValueRef ptr_ptr = LLVMBuildStructGEP(g->builder, g->cur_ret_ptr, coro_ret_start, ""); | ||
| 3390 | return LLVMBuildLoad(g->builder, ptr_ptr, ""); | ||
| 3391 | } | ||
| 3392 | return g->cur_ret_ptr; | 3393 | return g->cur_ret_ptr; |
| 3393 | } | 3394 | } |
| 3394 | 3395 | ||
| ... | @@ -3547,7 +3548,7 @@ static void render_async_spills(CodeGen *g) { | ... | @@ -3547,7 +3548,7 @@ static void render_async_spills(CodeGen *g) { |
| 3547 | continue; | 3548 | continue; |
| 3548 | } | 3549 | } |
| 3549 | 3550 | ||
| 3550 | var->value_ref = LLVMBuildStructGEP(g->builder, g->cur_ret_ptr, async_var_index, | 3551 | var->value_ref = LLVMBuildStructGEP(g->builder, g->cur_frame_ptr, async_var_index, |
| 3551 | buf_ptr(&var->name)); | 3552 | buf_ptr(&var->name)); |
| 3552 | async_var_index += 1; | 3553 | async_var_index += 1; |
| 3553 | if (var->decl_node) { | 3554 | if (var->decl_node) { |
| ... | @@ -3578,7 +3579,7 @@ static void render_async_spills(CodeGen *g) { | ... | @@ -3578,7 +3579,7 @@ static void render_async_spills(CodeGen *g) { |
| 3578 | continue; | 3579 | continue; |
| 3579 | } | 3580 | } |
| 3580 | } | 3581 | } |
| 3581 | instruction->base.llvm_value = LLVMBuildStructGEP(g->builder, g->cur_ret_ptr, async_var_index, | 3582 | instruction->base.llvm_value = LLVMBuildStructGEP(g->builder, g->cur_frame_ptr, async_var_index, |
| 3582 | instruction->name_hint); | 3583 | instruction->name_hint); |
| 3583 | async_var_index += 1; | 3584 | async_var_index += 1; |
| 3584 | } | 3585 | } |
| ... | @@ -3697,7 +3698,7 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr | ... | @@ -3697,7 +3698,7 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr |
| 3697 | // initialization. | 3698 | // initialization. |
| 3698 | } else if (callee_is_async) { | 3699 | } else if (callee_is_async) { |
| 3699 | frame_result_loc = ir_llvm_value(g, instruction->frame_result_loc); | 3700 | frame_result_loc = ir_llvm_value(g, instruction->frame_result_loc); |
| 3700 | awaiter_init_val = LLVMBuildPtrToInt(g->builder, g->cur_ret_ptr, usize_type_ref, ""); // caller's own frame pointer | 3701 | awaiter_init_val = LLVMBuildPtrToInt(g->builder, g->cur_frame_ptr, usize_type_ref, ""); // caller's own frame pointer |
| 3701 | if (ret_has_bits) { | 3702 | if (ret_has_bits) { |
| 3702 | if (result_loc == nullptr) { | 3703 | if (result_loc == nullptr) { |
| 3703 | // return type is a scalar, but we still need a pointer to it. Use the async fn frame. | 3704 | // return type is a scalar, but we still need a pointer to it. Use the async fn frame. |
| ... | @@ -4850,7 +4851,7 @@ static LLVMValueRef ir_render_frame_address(CodeGen *g, IrExecutable *executable | ... | @@ -4850,7 +4851,7 @@ static LLVMValueRef ir_render_frame_address(CodeGen *g, IrExecutable *executable |
| 4850 | } | 4851 | } |
| 4851 | 4852 | ||
| 4852 | static LLVMValueRef ir_render_handle(CodeGen *g, IrExecutable *executable, IrInstructionFrameHandle *instruction) { | 4853 | static LLVMValueRef ir_render_handle(CodeGen *g, IrExecutable *executable, IrInstructionFrameHandle *instruction) { |
| 4853 | return g->cur_ret_ptr; | 4854 | return g->cur_frame_ptr; |
| 4854 | } | 4855 | } |
| 4855 | 4856 | ||
| 4856 | static LLVMValueRef render_shl_with_overflow(CodeGen *g, IrInstructionOverflowOp *instruction) { | 4857 | static LLVMValueRef render_shl_with_overflow(CodeGen *g, IrInstructionOverflowOp *instruction) { |
| ... | @@ -5335,7 +5336,7 @@ static LLVMValueRef ir_render_await(CodeGen *g, IrExecutable *executable, IrInst | ... | @@ -5335,7 +5336,7 @@ static LLVMValueRef ir_render_await(CodeGen *g, IrExecutable *executable, IrInst |
| 5335 | } | 5336 | } |
| 5336 | 5337 | ||
| 5337 | // caller's own frame pointer | 5338 | // caller's own frame pointer |
| 5338 | LLVMValueRef awaiter_init_val = LLVMBuildPtrToInt(g->builder, g->cur_ret_ptr, usize_type_ref, ""); | 5339 | LLVMValueRef awaiter_init_val = LLVMBuildPtrToInt(g->builder, g->cur_frame_ptr, usize_type_ref, ""); |
| 5339 | LLVMValueRef awaiter_ptr = LLVMBuildStructGEP(g->builder, target_frame_ptr, coro_awaiter_index, ""); | 5340 | LLVMValueRef awaiter_ptr = LLVMBuildStructGEP(g->builder, target_frame_ptr, coro_awaiter_index, ""); |
| 5340 | LLVMValueRef prev_val = LLVMBuildAtomicRMW(g->builder, LLVMAtomicRMWBinOpXchg, awaiter_ptr, awaiter_init_val, | 5341 | LLVMValueRef prev_val = LLVMBuildAtomicRMW(g->builder, LLVMAtomicRMWBinOpXchg, awaiter_ptr, awaiter_init_val, |
| 5341 | LLVMAtomicOrderingRelease, g->is_single_threaded); | 5342 | LLVMAtomicOrderingRelease, g->is_single_threaded); |
| ... | @@ -6710,13 +6711,17 @@ static void do_code_gen(CodeGen *g) { | ... | @@ -6710,13 +6711,17 @@ static void do_code_gen(CodeGen *g) { |
| 6710 | 6711 | ||
| 6711 | bool is_async = fn_is_async(fn_table_entry); | 6712 | bool is_async = fn_is_async(fn_table_entry); |
| 6712 | 6713 | ||
| 6713 | if (want_sret || is_async) { | 6714 | if (is_async) { |
| 6714 | g->cur_ret_ptr = LLVMGetParam(fn, 0); | 6715 | g->cur_frame_ptr = LLVMGetParam(fn, 0); |
| 6715 | } else if (handle_is_ptr(fn_type_id->return_type)) { | ||
| 6716 | g->cur_ret_ptr = build_alloca(g, fn_type_id->return_type, "result", 0); | ||
| 6717 | // TODO add debug info variable for this | ||
| 6718 | } else { | 6716 | } else { |
| 6719 | g->cur_ret_ptr = nullptr; | 6717 | if (want_sret) { |
| 6718 | g->cur_ret_ptr = LLVMGetParam(fn, 0); | ||
| 6719 | } else if (handle_is_ptr(fn_type_id->return_type)) { | ||
| 6720 | g->cur_ret_ptr = build_alloca(g, fn_type_id->return_type, "result", 0); | ||
| 6721 | // TODO add debug info variable for this | ||
| 6722 | } else { | ||
| 6723 | g->cur_ret_ptr = nullptr; | ||
| 6724 | } | ||
| 6720 | } | 6725 | } |
| 6721 | 6726 | ||
| 6722 | uint32_t err_ret_trace_arg_index = get_err_ret_trace_arg_index(g, fn_table_entry); | 6727 | uint32_t err_ret_trace_arg_index = get_err_ret_trace_arg_index(g, fn_table_entry); |
| ... | @@ -6870,21 +6875,22 @@ static void do_code_gen(CodeGen *g) { | ... | @@ -6870,21 +6875,22 @@ static void do_code_gen(CodeGen *g) { |
| 6870 | 6875 | ||
| 6871 | LLVMPositionBuilderAtEnd(g->builder, g->cur_preamble_llvm_block); | 6876 | LLVMPositionBuilderAtEnd(g->builder, g->cur_preamble_llvm_block); |
| 6872 | render_async_spills(g); | 6877 | render_async_spills(g); |
| 6873 | g->cur_async_awaiter_ptr = LLVMBuildStructGEP(g->builder, g->cur_ret_ptr, coro_awaiter_index, ""); | 6878 | g->cur_async_awaiter_ptr = LLVMBuildStructGEP(g->builder, g->cur_frame_ptr, coro_awaiter_index, ""); |
| 6874 | LLVMValueRef resume_index_ptr = LLVMBuildStructGEP(g->builder, g->cur_ret_ptr, coro_resume_index, ""); | 6879 | LLVMValueRef resume_index_ptr = LLVMBuildStructGEP(g->builder, g->cur_frame_ptr, coro_resume_index, ""); |
| 6875 | g->cur_async_resume_index_ptr = resume_index_ptr; | 6880 | g->cur_async_resume_index_ptr = resume_index_ptr; |
| 6876 | 6881 | ||
| 6877 | if (type_has_bits(fn_type_id->return_type)) { | 6882 | if (type_has_bits(fn_type_id->return_type)) { |
| 6878 | g->cur_ret_ptr_ptr = LLVMBuildStructGEP(g->builder, g->cur_ret_ptr, coro_ret_start, ""); | 6883 | LLVMValueRef cur_ret_ptr_ptr = LLVMBuildStructGEP(g->builder, g->cur_frame_ptr, coro_ret_start, ""); |
| 6884 | g->cur_ret_ptr = LLVMBuildLoad(g->builder, cur_ret_ptr_ptr, ""); | ||
| 6879 | } | 6885 | } |
| 6880 | if (codegen_fn_has_err_ret_tracing_arg(g, fn_type_id->return_type)) { | 6886 | if (codegen_fn_has_err_ret_tracing_arg(g, fn_type_id->return_type)) { |
| 6881 | uint32_t trace_field_index = frame_index_trace_arg(g, fn_type_id->return_type); | 6887 | uint32_t trace_field_index = frame_index_trace_arg(g, fn_type_id->return_type); |
| 6882 | g->cur_err_ret_trace_val_arg = LLVMBuildStructGEP(g->builder, g->cur_ret_ptr, trace_field_index, ""); | 6888 | g->cur_err_ret_trace_val_arg = LLVMBuildStructGEP(g->builder, g->cur_frame_ptr, trace_field_index, ""); |
| 6883 | } | 6889 | } |
| 6884 | uint32_t trace_field_index_stack = UINT32_MAX; | 6890 | uint32_t trace_field_index_stack = UINT32_MAX; |
| 6885 | if (codegen_fn_has_err_ret_tracing_stack(g, fn_table_entry, true)) { | 6891 | if (codegen_fn_has_err_ret_tracing_stack(g, fn_table_entry, true)) { |
| 6886 | trace_field_index_stack = frame_index_trace_stack(g, fn_type_id); | 6892 | trace_field_index_stack = frame_index_trace_stack(g, fn_type_id); |
| 6887 | g->cur_err_ret_trace_val_stack = LLVMBuildStructGEP(g->builder, g->cur_ret_ptr, | 6893 | g->cur_err_ret_trace_val_stack = LLVMBuildStructGEP(g->builder, g->cur_frame_ptr, |
| 6888 | trace_field_index_stack, ""); | 6894 | trace_field_index_stack, ""); |
| 6889 | } | 6895 | } |
| 6890 | 6896 | ||
| ... | @@ -6898,9 +6904,9 @@ static void do_code_gen(CodeGen *g) { | ... | @@ -6898,9 +6904,9 @@ static void do_code_gen(CodeGen *g) { |
| 6898 | g->cur_resume_block_count += 1; | 6904 | g->cur_resume_block_count += 1; |
| 6899 | LLVMPositionBuilderAtEnd(g->builder, entry_block->llvm_block); | 6905 | LLVMPositionBuilderAtEnd(g->builder, entry_block->llvm_block); |
| 6900 | if (trace_field_index_stack != UINT32_MAX) { | 6906 | if (trace_field_index_stack != UINT32_MAX) { |
| 6901 | LLVMValueRef trace_field_ptr = LLVMBuildStructGEP(g->builder, g->cur_ret_ptr, | 6907 | LLVMValueRef trace_field_ptr = LLVMBuildStructGEP(g->builder, g->cur_frame_ptr, |
| 6902 | trace_field_index_stack, ""); | 6908 | trace_field_index_stack, ""); |
| 6903 | LLVMValueRef trace_field_addrs = LLVMBuildStructGEP(g->builder, g->cur_ret_ptr, | 6909 | LLVMValueRef trace_field_addrs = LLVMBuildStructGEP(g->builder, g->cur_frame_ptr, |
| 6904 | trace_field_index_stack + 1, ""); | 6910 | trace_field_index_stack + 1, ""); |
| 6905 | 6911 | ||
| 6906 | LLVMValueRef index_ptr = LLVMBuildStructGEP(g->builder, trace_field_ptr, 0, ""); | 6912 | LLVMValueRef index_ptr = LLVMBuildStructGEP(g->builder, trace_field_ptr, 0, ""); |
src/ir.cpp+37-29| ... | @@ -1129,8 +1129,6 @@ static IrInstruction *ir_build_return_begin(IrBuilder *irb, Scope *scope, AstNod | ... | @@ -1129,8 +1129,6 @@ static IrInstruction *ir_build_return_begin(IrBuilder *irb, Scope *scope, AstNod |
| 1129 | IrInstruction *operand) | 1129 | IrInstruction *operand) |
| 1130 | { | 1130 | { |
| 1131 | IrInstructionReturnBegin *return_instruction = ir_build_instruction<IrInstructionReturnBegin>(irb, scope, source_node); | 1131 | IrInstructionReturnBegin *return_instruction = ir_build_instruction<IrInstructionReturnBegin>(irb, scope, source_node); |
| 1132 | return_instruction->base.value.type = irb->codegen->builtin_types.entry_void; | ||
| 1133 | return_instruction->base.value.special = ConstValSpecialStatic; | ||
| 1134 | return_instruction->operand = operand; | 1132 | return_instruction->operand = operand; |
| 1135 | 1133 | ||
| 1136 | ir_ref_instruction(operand, irb->current_basic_block); | 1134 | ir_ref_instruction(operand, irb->current_basic_block); |
| ... | @@ -3480,7 +3478,8 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node, | ... | @@ -3480,7 +3478,8 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node, |
| 3480 | return_value = ir_build_const_void(irb, scope, node); | 3478 | return_value = ir_build_const_void(irb, scope, node); |
| 3481 | } | 3479 | } |
| 3482 | 3480 | ||
| 3483 | ir_build_return_begin(irb, scope, node, return_value); | 3481 | ir_mark_gen(ir_build_add_implicit_return_type(irb, scope, node, return_value)); |
| 3482 | return_value = ir_build_return_begin(irb, scope, node, return_value); | ||
| 3484 | 3483 | ||
| 3485 | size_t defer_counts[2]; | 3484 | size_t defer_counts[2]; |
| 3486 | ir_count_defers(irb, scope, outer_scope, defer_counts); | 3485 | ir_count_defers(irb, scope, outer_scope, defer_counts); |
| ... | @@ -3514,14 +3513,12 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node, | ... | @@ -3514,14 +3513,12 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node, |
| 3514 | ir_build_br(irb, scope, node, ret_stmt_block, is_comptime); | 3513 | ir_build_br(irb, scope, node, ret_stmt_block, is_comptime); |
| 3515 | 3514 | ||
| 3516 | ir_set_cursor_at_end_and_append_block(irb, ret_stmt_block); | 3515 | ir_set_cursor_at_end_and_append_block(irb, ret_stmt_block); |
| 3517 | ir_mark_gen(ir_build_add_implicit_return_type(irb, scope, node, return_value)); | ||
| 3518 | IrInstruction *result = ir_build_return(irb, scope, node, return_value); | 3516 | IrInstruction *result = ir_build_return(irb, scope, node, return_value); |
| 3519 | result_loc_ret->base.source_instruction = result; | 3517 | result_loc_ret->base.source_instruction = result; |
| 3520 | return result; | 3518 | return result; |
| 3521 | } else { | 3519 | } else { |
| 3522 | // generate unconditional defers | 3520 | // generate unconditional defers |
| 3523 | ir_gen_defers_for_block(irb, scope, outer_scope, false); | 3521 | ir_gen_defers_for_block(irb, scope, outer_scope, false); |
| 3524 | ir_mark_gen(ir_build_add_implicit_return_type(irb, scope, node, return_value)); | ||
| 3525 | IrInstruction *result = ir_build_return(irb, scope, node, return_value); | 3522 | IrInstruction *result = ir_build_return(irb, scope, node, return_value); |
| 3526 | result_loc_ret->base.source_instruction = result; | 3523 | result_loc_ret->base.source_instruction = result; |
| 3527 | return result; | 3524 | return result; |
| ... | @@ -3549,7 +3546,8 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node, | ... | @@ -3549,7 +3546,8 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node, |
| 3549 | ir_set_cursor_at_end_and_append_block(irb, return_block); | 3546 | ir_set_cursor_at_end_and_append_block(irb, return_block); |
| 3550 | IrInstruction *err_val_ptr = ir_build_unwrap_err_code(irb, scope, node, err_union_ptr); | 3547 | IrInstruction *err_val_ptr = ir_build_unwrap_err_code(irb, scope, node, err_union_ptr); |
| 3551 | IrInstruction *err_val = ir_build_load_ptr(irb, scope, node, err_val_ptr); | 3548 | IrInstruction *err_val = ir_build_load_ptr(irb, scope, node, err_val_ptr); |
| 3552 | ir_build_return_begin(irb, scope, node, err_val); | 3549 | ir_mark_gen(ir_build_add_implicit_return_type(irb, scope, node, err_val)); |
| 3550 | err_val = ir_build_return_begin(irb, scope, node, err_val); | ||
| 3553 | if (!ir_gen_defers_for_block(irb, scope, outer_scope, true)) { | 3551 | if (!ir_gen_defers_for_block(irb, scope, outer_scope, true)) { |
| 3554 | ResultLocReturn *result_loc_ret = allocate<ResultLocReturn>(1); | 3552 | ResultLocReturn *result_loc_ret = allocate<ResultLocReturn>(1); |
| 3555 | result_loc_ret->base.id = ResultLocIdReturn; | 3553 | result_loc_ret->base.id = ResultLocIdReturn; |
| ... | @@ -3559,7 +3557,6 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node, | ... | @@ -3559,7 +3557,6 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node, |
| 3559 | if (irb->codegen->have_err_ret_tracing && !should_inline) { | 3557 | if (irb->codegen->have_err_ret_tracing && !should_inline) { |
| 3560 | ir_build_save_err_ret_addr(irb, scope, node); | 3558 | ir_build_save_err_ret_addr(irb, scope, node); |
| 3561 | } | 3559 | } |
| 3562 | ir_mark_gen(ir_build_add_implicit_return_type(irb, scope, node, err_val)); | ||
| 3563 | IrInstruction *ret_inst = ir_build_return(irb, scope, node, err_val); | 3560 | IrInstruction *ret_inst = ir_build_return(irb, scope, node, err_val); |
| 3564 | result_loc_ret->base.source_instruction = ret_inst; | 3561 | result_loc_ret->base.source_instruction = ret_inst; |
| 3565 | } | 3562 | } |
| ... | @@ -4972,7 +4969,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo | ... | @@ -4972,7 +4969,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo |
| 4972 | return ir_lval_wrap(irb, scope, ir_build_frame_address(irb, scope, node), lval, result_loc); | 4969 | return ir_lval_wrap(irb, scope, ir_build_frame_address(irb, scope, node), lval, result_loc); |
| 4973 | case BuiltinFnIdFrameHandle: | 4970 | case BuiltinFnIdFrameHandle: |
| 4974 | if (!irb->exec->fn_entry) { | 4971 | if (!irb->exec->fn_entry) { |
| 4975 | add_node_error(irb->codegen, node, buf_sprintf("@handle() called outside of function definition")); | 4972 | add_node_error(irb->codegen, node, buf_sprintf("@frame() called outside of function definition")); |
| 4976 | return irb->codegen->invalid_instruction; | 4973 | return irb->codegen->invalid_instruction; |
| 4977 | } | 4974 | } |
| 4978 | return ir_lval_wrap(irb, scope, ir_build_handle(irb, scope, node), lval, result_loc); | 4975 | return ir_lval_wrap(irb, scope, ir_build_handle(irb, scope, node), lval, result_loc); |
| ... | @@ -8101,9 +8098,9 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec | ... | @@ -8101,9 +8098,9 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec |
| 8101 | return false; | 8098 | return false; |
| 8102 | 8099 | ||
| 8103 | if (!instr_is_unreachable(result)) { | 8100 | if (!instr_is_unreachable(result)) { |
| 8104 | ir_mark_gen(ir_build_return_begin(irb, scope, node, result)); | ||
| 8105 | // no need for save_err_ret_addr because this cannot return error | ||
| 8106 | ir_mark_gen(ir_build_add_implicit_return_type(irb, scope, result->source_node, result)); | 8101 | ir_mark_gen(ir_build_add_implicit_return_type(irb, scope, result->source_node, result)); |
| 8102 | result = ir_mark_gen(ir_build_return_begin(irb, scope, node, result)); | ||
| 8103 | // no need for save_err_ret_addr because this cannot return error | ||
| 8107 | ir_mark_gen(ir_build_return(irb, scope, result->source_node, result)); | 8104 | ir_mark_gen(ir_build_return(irb, scope, result->source_node, result)); |
| 8108 | } | 8105 | } |
| 8109 | 8106 | ||
| ... | @@ -9789,6 +9786,8 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT | ... | @@ -9789,6 +9786,8 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT |
| 9789 | 9786 | ||
| 9790 | ZigType *prev_err_set_type = (err_set_type == nullptr) ? prev_type->data.error_union.err_set_type : err_set_type; | 9787 | ZigType *prev_err_set_type = (err_set_type == nullptr) ? prev_type->data.error_union.err_set_type : err_set_type; |
| 9791 | ZigType *cur_err_set_type = cur_type->data.error_union.err_set_type; | 9788 | ZigType *cur_err_set_type = cur_type->data.error_union.err_set_type; |
| 9789 | if (prev_err_set_type == cur_err_set_type) | ||
| 9790 | continue; | ||
| 9792 | 9791 | ||
| 9793 | if (!resolve_inferred_error_set(ira->codegen, prev_err_set_type, cur_inst->source_node)) { | 9792 | if (!resolve_inferred_error_set(ira->codegen, prev_err_set_type, cur_inst->source_node)) { |
| 9794 | return ira->codegen->builtin_types.entry_invalid; | 9793 | return ira->codegen->builtin_types.entry_invalid; |
| ... | @@ -12614,6 +12613,14 @@ static IrInstruction *ir_analyze_instruction_return_begin(IrAnalyze *ira, IrInst | ... | @@ -12614,6 +12613,14 @@ static IrInstruction *ir_analyze_instruction_return_begin(IrAnalyze *ira, IrInst |
| 12614 | if (type_is_invalid(operand->value.type)) | 12613 | if (type_is_invalid(operand->value.type)) |
| 12615 | return ira->codegen->invalid_instruction; | 12614 | return ira->codegen->invalid_instruction; |
| 12616 | 12615 | ||
| 12616 | if (!instr_is_comptime(operand) && handle_is_ptr(ira->explicit_return_type)) { | ||
| 12617 | // result location mechanism took care of it. | ||
| 12618 | IrInstruction *result = ir_build_return_begin(&ira->new_irb, instruction->base.scope, | ||
| 12619 | instruction->base.source_node, operand); | ||
| 12620 | copy_const_val(&result->value, &operand->value, true); | ||
| 12621 | return result; | ||
| 12622 | } | ||
| 12623 | |||
| 12617 | IrInstruction *casted_operand = ir_implicit_cast(ira, operand, ira->explicit_return_type); | 12624 | IrInstruction *casted_operand = ir_implicit_cast(ira, operand, ira->explicit_return_type); |
| 12618 | if (type_is_invalid(casted_operand->value.type)) { | 12625 | if (type_is_invalid(casted_operand->value.type)) { |
| 12619 | AstNode *source_node = ira->explicit_return_type_source_node; | 12626 | AstNode *source_node = ira->explicit_return_type_source_node; |
| ... | @@ -12625,8 +12632,18 @@ static IrInstruction *ir_analyze_instruction_return_begin(IrAnalyze *ira, IrInst | ... | @@ -12625,8 +12632,18 @@ static IrInstruction *ir_analyze_instruction_return_begin(IrAnalyze *ira, IrInst |
| 12625 | return ir_unreach_error(ira); | 12632 | return ir_unreach_error(ira); |
| 12626 | } | 12633 | } |
| 12627 | 12634 | ||
| 12628 | return ir_build_return_begin(&ira->new_irb, instruction->base.scope, instruction->base.source_node, | 12635 | if (casted_operand->value.special == ConstValSpecialRuntime && |
| 12629 | casted_operand); | 12636 | casted_operand->value.type->id == ZigTypeIdPointer && |
| 12637 | casted_operand->value.data.rh_ptr == RuntimeHintPtrStack) | ||
| 12638 | { | ||
| 12639 | ir_add_error(ira, casted_operand, buf_sprintf("function returns address of local variable")); | ||
| 12640 | return ir_unreach_error(ira); | ||
| 12641 | } | ||
| 12642 | |||
| 12643 | IrInstruction *result = ir_build_return_begin(&ira->new_irb, instruction->base.scope, | ||
| 12644 | instruction->base.source_node, casted_operand); | ||
| 12645 | copy_const_val(&result->value, &casted_operand->value, true); | ||
| 12646 | return result; | ||
| 12630 | } | 12647 | } |
| 12631 | 12648 | ||
| 12632 | static IrInstruction *ir_analyze_instruction_return(IrAnalyze *ira, IrInstructionReturn *instruction) { | 12649 | static IrInstruction *ir_analyze_instruction_return(IrAnalyze *ira, IrInstructionReturn *instruction) { |
| ... | @@ -12642,21 +12659,8 @@ static IrInstruction *ir_analyze_instruction_return(IrAnalyze *ira, IrInstructio | ... | @@ -12642,21 +12659,8 @@ static IrInstruction *ir_analyze_instruction_return(IrAnalyze *ira, IrInstructio |
| 12642 | return ir_finish_anal(ira, result); | 12659 | return ir_finish_anal(ira, result); |
| 12643 | } | 12660 | } |
| 12644 | 12661 | ||
| 12645 | IrInstruction *casted_operand = ir_implicit_cast(ira, operand, ira->explicit_return_type); | ||
| 12646 | if (type_is_invalid(casted_operand->value.type)) { | ||
| 12647 | // error already reported by IrInstructionReturnBegin | ||
| 12648 | return ir_unreach_error(ira); | ||
| 12649 | } | ||
| 12650 | |||
| 12651 | if (casted_operand->value.special == ConstValSpecialRuntime && | ||
| 12652 | casted_operand->value.type->id == ZigTypeIdPointer && | ||
| 12653 | casted_operand->value.data.rh_ptr == RuntimeHintPtrStack) | ||
| 12654 | { | ||
| 12655 | ir_add_error(ira, casted_operand, buf_sprintf("function returns address of local variable")); | ||
| 12656 | return ir_unreach_error(ira); | ||
| 12657 | } | ||
| 12658 | IrInstruction *result = ir_build_return(&ira->new_irb, instruction->base.scope, | 12662 | IrInstruction *result = ir_build_return(&ira->new_irb, instruction->base.scope, |
| 12659 | instruction->base.source_node, casted_operand); | 12663 | instruction->base.source_node, operand); |
| 12660 | result->value.type = ira->codegen->builtin_types.entry_unreachable; | 12664 | result->value.type = ira->codegen->builtin_types.entry_unreachable; |
| 12661 | return ir_finish_anal(ira, result); | 12665 | return ir_finish_anal(ira, result); |
| 12662 | } | 12666 | } |
| ... | @@ -14612,8 +14616,12 @@ static IrInstruction *ir_resolve_result_raw(IrAnalyze *ira, IrInstruction *suspe | ... | @@ -14612,8 +14616,12 @@ static IrInstruction *ir_resolve_result_raw(IrAnalyze *ira, IrInstruction *suspe |
| 14612 | if ((err = type_resolve(ira->codegen, ira->explicit_return_type, ResolveStatusZeroBitsKnown))) { | 14616 | if ((err = type_resolve(ira->codegen, ira->explicit_return_type, ResolveStatusZeroBitsKnown))) { |
| 14613 | return ira->codegen->invalid_instruction; | 14617 | return ira->codegen->invalid_instruction; |
| 14614 | } | 14618 | } |
| 14615 | if (!type_has_bits(ira->explicit_return_type) || !handle_is_ptr(ira->explicit_return_type)) | 14619 | if (!type_has_bits(ira->explicit_return_type) || !handle_is_ptr(ira->explicit_return_type)) { |
| 14616 | return nullptr; | 14620 | ZigFn *fn_entry = exec_fn_entry(ira->new_irb.exec); |
| 14621 | if (fn_entry == nullptr || fn_entry->inferred_async_node == nullptr) { | ||
| 14622 | return nullptr; | ||
| 14623 | } | ||
| 14624 | } | ||
| 14617 | 14625 | ||
| 14618 | ZigType *ptr_return_type = get_pointer_to_type(ira->codegen, ira->explicit_return_type, false); | 14626 | ZigType *ptr_return_type = get_pointer_to_type(ira->codegen, ira->explicit_return_type, false); |
| 14619 | result_loc->written = true; | 14627 | result_loc->written = true; |
| ... | @@ -24510,7 +24518,7 @@ static IrInstruction *ir_analyze_instruction_await(IrAnalyze *ira, IrInstruction | ... | @@ -24510,7 +24518,7 @@ static IrInstruction *ir_analyze_instruction_await(IrAnalyze *ira, IrInstruction |
| 24510 | IrInstruction *result_loc; | 24518 | IrInstruction *result_loc; |
| 24511 | if (type_has_bits(result_type)) { | 24519 | if (type_has_bits(result_type)) { |
| 24512 | result_loc = ir_resolve_result(ira, &instruction->base, instruction->result_loc, | 24520 | result_loc = ir_resolve_result(ira, &instruction->base, instruction->result_loc, |
| 24513 | result_type, nullptr, true, false, true); | 24521 | result_type, nullptr, true, true, true); |
| 24514 | if (result_loc != nullptr && (type_is_invalid(result_loc->value.type) || instr_is_unreachable(result_loc))) | 24522 | if (result_loc != nullptr && (type_is_invalid(result_loc->value.type) || instr_is_unreachable(result_loc))) |
| 24515 | return result_loc; | 24523 | return result_loc; |
| 24516 | } else { | 24524 | } else { |
test/stage1/behavior/coroutines.zig+34-34| ... | @@ -334,40 +334,40 @@ test "async fn with inferred error set" { | ... | @@ -334,40 +334,40 @@ test "async fn with inferred error set" { |
| 334 | S.doTheTest(); | 334 | S.doTheTest(); |
| 335 | } | 335 | } |
| 336 | 336 | ||
| 337 | //test "error return trace across suspend points - early return" { | 337 | test "error return trace across suspend points - early return" { |
| 338 | // const p = nonFailing(); | 338 | const p = nonFailing(); |
| 339 | // resume p; | 339 | resume p; |
| 340 | // const p2 = async printTrace(p); | 340 | const p2 = async printTrace(p); |
| 341 | //} | 341 | } |
| 342 | // | 342 | |
| 343 | //test "error return trace across suspend points - async return" { | 343 | test "error return trace across suspend points - async return" { |
| 344 | // const p = nonFailing(); | 344 | const p = nonFailing(); |
| 345 | // const p2 = async printTrace(p); | 345 | const p2 = async printTrace(p); |
| 346 | // resume p; | 346 | resume p; |
| 347 | //} | 347 | } |
| 348 | // | 348 | |
| 349 | //fn nonFailing() (anyframe->anyerror!void) { | 349 | fn nonFailing() (anyframe->anyerror!void) { |
| 350 | // const Static = struct { | 350 | const Static = struct { |
| 351 | // var frame: @Frame(suspendThenFail) = undefined; | 351 | var frame: @Frame(suspendThenFail) = undefined; |
| 352 | // }; | 352 | }; |
| 353 | // Static.frame = async suspendThenFail(); | 353 | Static.frame = async suspendThenFail(); |
| 354 | // return &Static.frame; | 354 | return &Static.frame; |
| 355 | //} | 355 | } |
| 356 | //async fn suspendThenFail() anyerror!void { | 356 | async fn suspendThenFail() anyerror!void { |
| 357 | // suspend; | 357 | suspend; |
| 358 | // return error.Fail; | 358 | return error.Fail; |
| 359 | //} | 359 | } |
| 360 | //async fn printTrace(p: anyframe->(anyerror!void)) void { | 360 | async fn printTrace(p: anyframe->(anyerror!void)) void { |
| 361 | // (await p) catch |e| { | 361 | (await p) catch |e| { |
| 362 | // std.testing.expect(e == error.Fail); | 362 | std.testing.expect(e == error.Fail); |
| 363 | // if (@errorReturnTrace()) |trace| { | 363 | if (@errorReturnTrace()) |trace| { |
| 364 | // expect(trace.index == 1); | 364 | expect(trace.index == 1); |
| 365 | // } else switch (builtin.mode) { | 365 | } else switch (builtin.mode) { |
| 366 | // .Debug, .ReleaseSafe => @panic("expected return trace"), | 366 | .Debug, .ReleaseSafe => @panic("expected return trace"), |
| 367 | // .ReleaseFast, .ReleaseSmall => {}, | 367 | .ReleaseFast, .ReleaseSmall => {}, |
| 368 | // } | 368 | } |
| 369 | // }; | 369 | }; |
| 370 | //} | 370 | } |
| 371 | 371 | ||
| 372 | test "break from suspend" { | 372 | test "break from suspend" { |
| 373 | var my_result: i32 = 1; | 373 | var my_result: i32 = 1; |