| ... | ... | @@ -2394,24 +2394,31 @@ static LLVMValueRef ir_render_save_err_ret_addr(CodeGen *g, IrExecutable *execut |
| 2394 | 2394 | } |
| 2395 | 2395 | |
| 2396 | 2396 | static LLVMValueRef ir_render_return(CodeGen *g, IrExecutable *executable, IrInstructionReturn *return_instruction) { |
| 2397 | | if (return_instruction->value == nullptr) { |
| 2398 | | LLVMBuildRetVoid(g->builder); |
| 2399 | | return nullptr; |
| 2400 | | } |
| 2401 | | |
| 2402 | | ZigType *return_type = return_instruction->value->value.type; |
| 2403 | | |
| 2404 | 2397 | if (want_first_arg_sret(g, &g->cur_fn->type_entry->data.fn.fn_type_id)) { |
| 2398 | if (return_instruction->value == nullptr) { |
| 2399 | LLVMBuildRetVoid(g->builder); |
| 2400 | return nullptr; |
| 2401 | } |
| 2405 | 2402 | assert(g->cur_ret_ptr); |
| 2406 | 2403 | src_assert(return_instruction->value->value.special != ConstValSpecialRuntime, |
| 2407 | 2404 | return_instruction->base.source_node); |
| 2408 | 2405 | LLVMValueRef value = ir_llvm_value(g, return_instruction->value); |
| 2406 | ZigType *return_type = return_instruction->value->value.type; |
| 2409 | 2407 | gen_assign_raw(g, g->cur_ret_ptr, get_pointer_to_type(g, return_type, false), value); |
| 2410 | 2408 | LLVMBuildRetVoid(g->builder); |
| 2411 | | } else if (handle_is_ptr(return_type)) { |
| 2412 | | LLVMValueRef value = ir_llvm_value(g, return_instruction->value); |
| 2413 | | LLVMValueRef by_val_value = gen_load_untyped(g, value, 0, false, ""); |
| 2414 | | LLVMBuildRet(g->builder, by_val_value); |
| 2409 | } else if (g->cur_fn->type_entry->data.fn.fn_type_id.cc != CallingConventionAsync && |
| 2410 | handle_is_ptr(g->cur_fn->type_entry->data.fn.fn_type_id.return_type)) |
| 2411 | { |
| 2412 | if (return_instruction->value == nullptr) { |
| 2413 | LLVMValueRef by_val_value = gen_load_untyped(g, g->cur_ret_ptr, 0, false, ""); |
| 2414 | LLVMBuildRet(g->builder, by_val_value); |
| 2415 | } else { |
| 2416 | LLVMValueRef value = ir_llvm_value(g, return_instruction->value); |
| 2417 | LLVMValueRef by_val_value = gen_load_untyped(g, value, 0, false, ""); |
| 2418 | LLVMBuildRet(g->builder, by_val_value); |
| 2419 | } |
| 2420 | } else if (return_instruction->value == nullptr) { |
| 2421 | LLVMBuildRetVoid(g->builder); |
| 2415 | 2422 | } else { |
| 2416 | 2423 | LLVMValueRef value = ir_llvm_value(g, return_instruction->value); |
| 2417 | 2424 | LLVMBuildRet(g->builder, value); |
| ... | ... | @@ -3755,7 +3762,7 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr |
| 3755 | 3762 | bool prefix_arg_err_ret_stack = get_prefix_arg_err_ret_stack(g, fn_type_id); |
| 3756 | 3763 | bool is_var_args = fn_type_id->is_var_args; |
| 3757 | 3764 | ZigList<LLVMValueRef> gen_param_values = {}; |
| 3758 | | LLVMValueRef result_loc = (first_arg_ret || instruction->is_async) ? ir_llvm_value(g, instruction->result_loc) : nullptr; |
| 3765 | LLVMValueRef result_loc = instruction->result_loc ? ir_llvm_value(g, instruction->result_loc) : nullptr; |
| 3759 | 3766 | if (first_arg_ret) { |
| 3760 | 3767 | gen_param_values.append(result_loc); |
| 3761 | 3768 | } |
| ... | ... | @@ -6804,20 +6811,24 @@ static void do_code_gen(CodeGen *g) { |
| 6804 | 6811 | FnTypeId *fn_type_id = &fn_table_entry->type_entry->data.fn.fn_type_id; |
| 6805 | 6812 | CallingConvention cc = fn_type_id->cc; |
| 6806 | 6813 | bool is_c_abi = cc == CallingConventionC; |
| 6814 | bool want_sret = want_first_arg_sret(g, fn_type_id); |
| 6807 | 6815 | |
| 6808 | 6816 | LLVMValueRef fn = fn_llvm_value(g, fn_table_entry); |
| 6809 | 6817 | g->cur_fn = fn_table_entry; |
| 6810 | 6818 | g->cur_fn_val = fn; |
| 6811 | | ZigType *return_type = fn_type_id->return_type; |
| 6812 | | if (handle_is_ptr(return_type)) { |
| 6819 | |
| 6820 | build_all_basic_blocks(g, fn_table_entry); |
| 6821 | clear_debug_source_node(g); |
| 6822 | |
| 6823 | if (want_sret) { |
| 6813 | 6824 | g->cur_ret_ptr = LLVMGetParam(fn, 0); |
| 6825 | } else if (handle_is_ptr(fn_type_id->return_type)) { |
| 6826 | g->cur_ret_ptr = build_alloca(g, fn_type_id->return_type, "result", 0); |
| 6827 | // TODO add debug info variable for this |
| 6814 | 6828 | } else { |
| 6815 | 6829 | g->cur_ret_ptr = nullptr; |
| 6816 | 6830 | } |
| 6817 | 6831 | |
| 6818 | | build_all_basic_blocks(g, fn_table_entry); |
| 6819 | | clear_debug_source_node(g); |
| 6820 | | |
| 6821 | 6832 | uint32_t err_ret_trace_arg_index = get_err_ret_trace_arg_index(g, fn_table_entry); |
| 6822 | 6833 | bool have_err_ret_trace_arg = err_ret_trace_arg_index != UINT32_MAX; |
| 6823 | 6834 | if (have_err_ret_trace_arg) { |
| ... | ... | @@ -6863,8 +6874,7 @@ static void do_code_gen(CodeGen *g) { |
| 6863 | 6874 | } |
| 6864 | 6875 | |
| 6865 | 6876 | ZigType *import = get_scope_import(&fn_table_entry->fndef_scope->base); |
| 6866 | | |
| 6867 | | unsigned gen_i_init = want_first_arg_sret(g, fn_type_id) ? 1 : 0; |
| 6877 | unsigned gen_i_init = want_sret ? 1 : 0; |
| 6868 | 6878 | |
| 6869 | 6879 | // create debug variable declarations for variables and allocate all local variables |
| 6870 | 6880 | FnWalk fn_walk_var = {}; |