From f697eab6ef409aa6206e979a9c1cc32f9f9902f5 Mon Sep 17 00:00:00 2001 From: hmelder Date: Sat, 13 Apr 2024 06:45:12 -0700 Subject: [PATCH 1/5] Use objc_msgSend_stret2_np when returning a non-trivial data type on woa64 --- clang/lib/CodeGen/CGCall.cpp | 5 +++++ clang/lib/CodeGen/CGObjCGNU.cpp | 21 +++++++++++++++++---- clang/lib/CodeGen/CodeGenModule.h | 3 +++ 3 files changed, 25 insertions(+), 4 deletions(-) diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp index 6c33cc17621f8..d2d92140b6b2a 100644 --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/lib/CodeGen/CGCall.cpp @@ -1585,6 +1585,11 @@ bool CodeGenModule::ReturnTypeUsesSRet(const CGFunctionInfo &FI) { return RI.isIndirect() || (RI.isInAlloca() && RI.getInAllocaSRet()); } +bool CodeGenModule::ReturnTypeHasInReg(const CGFunctionInfo &FI) { + const auto &RI = FI.getReturnInfo(); + return RI.getInReg(); +} + bool CodeGenModule::ReturnSlotInterferesWithArgs(const CGFunctionInfo &FI) { return ReturnTypeUsesSRet(FI) && getTargetCodeGenInfo().doesReturnSlotInterfereWithArgs(); diff --git a/clang/lib/CodeGen/CGObjCGNU.cpp b/clang/lib/CodeGen/CGObjCGNU.cpp index 4e7f777ba1d91..18d2f75b39428 100644 --- a/clang/lib/CodeGen/CGObjCGNU.cpp +++ b/clang/lib/CodeGen/CGObjCGNU.cpp @@ -2911,12 +2911,25 @@ CGObjCGNU::GenerateMessageSend(CodeGenFunction &CGF, "objc_msgSend_fpret") .getCallee(); } else if (CGM.ReturnTypeUsesSRet(MSI.CallInfo)) { + StringRef name = "objc_msgSend_stret"; + + // The address of the memory block is be passed in x8 for POD type, + // or in x0 for non-POD type (marked as inreg). + bool shouldCheckForInReg = + CGM.getContext() + .getTargetInfo() + .getTriple() + .isWindowsMSVCEnvironment() && + CGM.getContext().getTargetInfo().getTriple().isAArch64(); + if (shouldCheckForInReg && CGM.ReturnTypeHasInReg(MSI.CallInfo)) { + name = "objc_msgSend_stret2_np"; + } + // The actual types here don't matter - we're going to bitcast the // function anyway - imp = - CGM.CreateRuntimeFunction(llvm::FunctionType::get(IdTy, IdTy, true), - "objc_msgSend_stret") - .getCallee(); + CGM.CreateRuntimeFunction(llvm::FunctionType::get(IdTy, IdTy, true), + name) + .getCallee(); } else { imp = CGM.CreateRuntimeFunction( llvm::FunctionType::get(IdTy, IdTy, true), "objc_msgSend") diff --git a/clang/lib/CodeGen/CodeGenModule.h b/clang/lib/CodeGen/CodeGenModule.h index 1cc447765e2c9..be43a18fc6085 100644 --- a/clang/lib/CodeGen/CodeGenModule.h +++ b/clang/lib/CodeGen/CodeGenModule.h @@ -1241,6 +1241,9 @@ class CodeGenModule : public CodeGenTypeCache { /// Return true iff the given type uses 'sret' when used as a return type. bool ReturnTypeUsesSRet(const CGFunctionInfo &FI); + /// Return true iff the given type has `inreg` set. + bool ReturnTypeHasInReg(const CGFunctionInfo &FI); + /// Return true iff the given type uses an argument slot when 'sret' is used /// as a return type. bool ReturnSlotInterferesWithArgs(const CGFunctionInfo &FI); From c9db483967233f7889de97c4f950265f8d056d0c Mon Sep 17 00:00:00 2001 From: hmelder Date: Sat, 13 Apr 2024 08:38:12 -0700 Subject: [PATCH 2/5] Assign runtime function to imp --- clang/lib/CodeGen/CGObjCGNU.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/clang/lib/CodeGen/CGObjCGNU.cpp b/clang/lib/CodeGen/CGObjCGNU.cpp index 18d2f75b39428..5faecc6af3355 100644 --- a/clang/lib/CodeGen/CGObjCGNU.cpp +++ b/clang/lib/CodeGen/CGObjCGNU.cpp @@ -2927,9 +2927,9 @@ CGObjCGNU::GenerateMessageSend(CodeGenFunction &CGF, // The actual types here don't matter - we're going to bitcast the // function anyway - CGM.CreateRuntimeFunction(llvm::FunctionType::get(IdTy, IdTy, true), - name) - .getCallee(); + imp = CGM.CreateRuntimeFunction( + llvm::FunctionType::get(IdTy, IdTy, true), name) + .getCallee(); } else { imp = CGM.CreateRuntimeFunction( llvm::FunctionType::get(IdTy, IdTy, true), "objc_msgSend") From 333dbf5bd9d52a97a6bdb314a3211a9c52c9fe3c Mon Sep 17 00:00:00 2001 From: hmelder Date: Sat, 13 Apr 2024 09:59:16 -0700 Subject: [PATCH 3/5] Add ObjCXX unit test for stret on WoA64 --- clang/test/CodeGenObjCXX/msabi-stret-arm64.mm | 77 +++++++++++++++++++ 1 file changed, 77 insertions(+) create mode 100644 clang/test/CodeGenObjCXX/msabi-stret-arm64.mm diff --git a/clang/test/CodeGenObjCXX/msabi-stret-arm64.mm b/clang/test/CodeGenObjCXX/msabi-stret-arm64.mm new file mode 100644 index 0000000000000..0a17b5862b338 --- /dev/null +++ b/clang/test/CodeGenObjCXX/msabi-stret-arm64.mm @@ -0,0 +1,77 @@ +// RUN: %clang_cc1 -triple aarch64-pc-windows-msvc -fobjc-runtime=gnustep-2.2 -fobjc-dispatch-method=non-legacy -emit-llvm -o - %s | FileCheck %s + +// Pass and return for type size <= 8 bytes. +struct S1 { + int a[2]; +}; + +// Pass and return hfa <= 8 bytes +struct F1 { + float a[2]; +}; + +// Pass and return for type size > 16 bytes. +struct S2 { + int a[5]; +}; + +// Pass and return aggregate (of size < 16 bytes) with non-trivial destructor. +// Sret and inreg: Returned in x0 +struct S3 { + int a[3]; + ~S3(); +}; +S3::~S3() { +} + + +@interface MsgTest { id isa; } @end +@implementation MsgTest +- (S1) smallS1 { + S1 x; + x.a[0] = 0; + x.a[1] = 1; + return x; + +} +- (F1) smallF1 { + F1 x; + x.a[0] = 0.2f; + x.a[1] = 0.5f; + return x; +} +- (S2) stretS2 { + S2 x; + for (int i = 0; i < 5; i++) { + x.a[i] = i; + } + return x; +} +- (S3) stretInRegS3 { + S3 x; + for (int i = 0; i < 3; i++) { + x.a[i] = i; + } + return x; +} ++ (S3) msgTestStretInRegS3 { + S3 x; + for (int i = 0; i < 3; i++) { + x.a[i] = i; + } + return x; +} +@end + +void test0(MsgTest *t) { + // CHECK: call {{.*}} @objc_msgSend + S1 ret = [t smallS1]; + // CHECK: call {{.*}} @objc_msgSend + F1 ret2 = [t smallF1]; + // CHECK: call {{.*}} @objc_msgSend_stret + S2 ret3 = [t stretS2]; + // CHECK: call {{.*}} @objc_msgSend_stret2_np + S3 ret4 = [t stretInRegS3]; + // CHECK: call {{.*}} @objc_msgSend_stret2_np + S3 ret5 = [MsgTest msgTestStretInRegS3]; +} From 94902b224c1d921fe58f7c08524ed3e5b1b3d32d Mon Sep 17 00:00:00 2001 From: hmelder Date: Wed, 17 Apr 2024 14:47:14 -0700 Subject: [PATCH 4/5] Remove np suffix from objc_msgSend_stret2_np --- clang/lib/CodeGen/CGObjCGNU.cpp | 25 +++++++------------ clang/test/CodeGenObjCXX/msabi-stret-arm64.mm | 4 +-- 2 files changed, 11 insertions(+), 18 deletions(-) diff --git a/clang/lib/CodeGen/CGObjCGNU.cpp b/clang/lib/CodeGen/CGObjCGNU.cpp index 5faecc6af3355..90f620e2fa1de 100644 --- a/clang/lib/CodeGen/CGObjCGNU.cpp +++ b/clang/lib/CodeGen/CGObjCGNU.cpp @@ -2905,13 +2905,11 @@ CGObjCGNU::GenerateMessageSend(CodeGenFunction &CGF, break; case CodeGenOptions::Mixed: case CodeGenOptions::NonLegacy: + StringRef name = "objc_msgSend"; if (CGM.ReturnTypeUsesFPRet(ResultType)) { - imp = - CGM.CreateRuntimeFunction(llvm::FunctionType::get(IdTy, IdTy, true), - "objc_msgSend_fpret") - .getCallee(); + name = "objc_msgSend_fpret"; } else if (CGM.ReturnTypeUsesSRet(MSI.CallInfo)) { - StringRef name = "objc_msgSend_stret"; + name = "objc_msgSend_stret"; // The address of the memory block is be passed in x8 for POD type, // or in x0 for non-POD type (marked as inreg). @@ -2922,19 +2920,14 @@ CGObjCGNU::GenerateMessageSend(CodeGenFunction &CGF, .isWindowsMSVCEnvironment() && CGM.getContext().getTargetInfo().getTriple().isAArch64(); if (shouldCheckForInReg && CGM.ReturnTypeHasInReg(MSI.CallInfo)) { - name = "objc_msgSend_stret2_np"; + name = "objc_msgSend_stret2"; } - - // The actual types here don't matter - we're going to bitcast the - // function anyway - imp = CGM.CreateRuntimeFunction( - llvm::FunctionType::get(IdTy, IdTy, true), name) - .getCallee(); - } else { - imp = CGM.CreateRuntimeFunction( - llvm::FunctionType::get(IdTy, IdTy, true), "objc_msgSend") - .getCallee(); } + // The actual types here don't matter - we're going to bitcast the + // function anyway + imp = CGM.CreateRuntimeFunction( + llvm::FunctionType::get(IdTy, IdTy, true), name) + .getCallee(); } // Reset the receiver in case the lookup modified it diff --git a/clang/test/CodeGenObjCXX/msabi-stret-arm64.mm b/clang/test/CodeGenObjCXX/msabi-stret-arm64.mm index 0a17b5862b338..3bbdbebc5cb57 100644 --- a/clang/test/CodeGenObjCXX/msabi-stret-arm64.mm +++ b/clang/test/CodeGenObjCXX/msabi-stret-arm64.mm @@ -70,8 +70,8 @@ void test0(MsgTest *t) { F1 ret2 = [t smallF1]; // CHECK: call {{.*}} @objc_msgSend_stret S2 ret3 = [t stretS2]; - // CHECK: call {{.*}} @objc_msgSend_stret2_np + // CHECK: call {{.*}} @objc_msgSend_stret2 S3 ret4 = [t stretInRegS3]; - // CHECK: call {{.*}} @objc_msgSend_stret2_np + // CHECK: call {{.*}} @objc_msgSend_stret2 S3 ret5 = [MsgTest msgTestStretInRegS3]; } From b4d0255f63e59edba09155d3af8b1e5ef9be9df1 Mon Sep 17 00:00:00 2001 From: hmelder Date: Wed, 17 Apr 2024 14:53:35 -0700 Subject: [PATCH 5/5] Fix Formatting --- clang/lib/CodeGen/CGObjCGNU.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clang/lib/CodeGen/CGObjCGNU.cpp b/clang/lib/CodeGen/CGObjCGNU.cpp index 90f620e2fa1de..43dd38659518d 100644 --- a/clang/lib/CodeGen/CGObjCGNU.cpp +++ b/clang/lib/CodeGen/CGObjCGNU.cpp @@ -2925,8 +2925,8 @@ CGObjCGNU::GenerateMessageSend(CodeGenFunction &CGF, } // The actual types here don't matter - we're going to bitcast the // function anyway - imp = CGM.CreateRuntimeFunction( - llvm::FunctionType::get(IdTy, IdTy, true), name) + imp = CGM.CreateRuntimeFunction(llvm::FunctionType::get(IdTy, IdTy, true), + name) .getCallee(); }