aboutsummaryrefslogtreecommitdiff
path: root/src/llvm_backend_stmt.cpp
diff options
context:
space:
mode:
authorflysand7 <yyakut.ac@gmail.com>2023-12-06 00:23:41 +1100
committerflysand7 <yyakut.ac@gmail.com>2023-12-06 00:23:41 +1100
commit92d3a681cd6cc2aceb0865d4bffdf8a112f6f0d6 (patch)
tree6feb95445ee9f39f3c4e1dadc1ecb9d0410ec0c1 /src/llvm_backend_stmt.cpp
parentcb66ed52cefde3274b9b055a1fecbf938e4b5155 (diff)
parent65afe6f70d6baa2d4070791325701e38d6f2df61 (diff)
Merge branch 'master' into sys-linux-additions
Diffstat (limited to 'src/llvm_backend_stmt.cpp')
-rw-r--r--src/llvm_backend_stmt.cpp22
1 files changed, 19 insertions, 3 deletions
diff --git a/src/llvm_backend_stmt.cpp b/src/llvm_backend_stmt.cpp
index 9d688be6a..002fef881 100644
--- a/src/llvm_backend_stmt.cpp
+++ b/src/llvm_backend_stmt.cpp
@@ -1846,9 +1846,25 @@ gb_internal void lb_build_return_stmt_internal(lbProcedure *p, lbValue res) {
LLVMBuildRetVoid(p->builder);
} else {
LLVMValueRef ret_val = res.value;
- ret_val = OdinLLVMBuildTransmute(p, ret_val, p->abi_function_type->ret.type);
- if (p->abi_function_type->ret.cast_type != nullptr) {
- ret_val = OdinLLVMBuildTransmute(p, ret_val, p->abi_function_type->ret.cast_type);
+ LLVMTypeRef ret_type = p->abi_function_type->ret.type;
+ if (LLVMTypeRef cast_type = p->abi_function_type->ret.cast_type) {
+ ret_type = cast_type;
+ }
+
+ if (LLVMGetTypeKind(ret_type) == LLVMStructTypeKind) {
+ LLVMTypeRef src_type = LLVMTypeOf(ret_val);
+
+ if (p->temp_callee_return_struct_memory == nullptr) {
+ i64 max_align = gb_max(lb_alignof(ret_type), lb_alignof(src_type));
+ p->temp_callee_return_struct_memory = llvm_alloca(p, ret_type, max_align);
+ }
+ // reuse the temp return value memory where possible
+ LLVMValueRef ptr = p->temp_callee_return_struct_memory;
+ LLVMValueRef nptr = LLVMBuildPointerCast(p->builder, ptr, LLVMPointerType(src_type, 0), "");
+ LLVMBuildStore(p->builder, ret_val, nptr);
+ ret_val = LLVMBuildLoad2(p->builder, ret_type, ptr, "");
+ } else {
+ ret_val = OdinLLVMBuildTransmute(p, ret_val, ret_type);
}
lb_emit_defer_stmts(p, lbDeferExit_Return, nullptr);