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