[clang] Fix Objective-C++ Sret of non-trivial data types on Windows ARM64 (PR #88671)

Hugo Melder via cfe-commits cfe-commits at lists.llvm.org
Wed Apr 17 07:03:29 PDT 2024


https://github.com/hmelder updated https://github.com/llvm/llvm-project/pull/88671

>From 293c507c1257fa37935c4ec78788c25e702d1fb1 Mon Sep 17 00:00:00 2001
From: hmelder <service at hugomelder.com>
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 7a0bc6fa77b889..5ea26b0f594815 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 4e7f777ba1d916..18d2f75b39428d 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 1cc447765e2c97..be43a18fc60856 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 67fbc247f3e9bce5c98efdbb7e90988cbc9fc8ad Mon Sep 17 00:00:00 2001
From: hmelder <service at hugomelder.com>
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 18d2f75b39428d..5faecc6af33556 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 f8e46397e11b98638b2274c4b36f2c2df38aa615 Mon Sep 17 00:00:00 2001
From: hmelder <service at hugomelder.com>
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 00000000000000..0a17b5862b338e
--- /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() {
+}
+
+
+ at interface MsgTest { id isa; } @end
+ at 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;
+}
+ at 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 547dd8b6117c478ea0dff03e89a1c5534e98e614 Mon Sep 17 00:00:00 2001
From: hmelder <service at hugomelder.com>
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 5faecc6af33556..90f620e2fa1de1 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 0a17b5862b338e..3bbdbebc5cb576 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 de9e2166e1da7c93cad2dfe77454c4e638e294cc Mon Sep 17 00:00:00 2001
From: hmelder <service at hugomelder.com>
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 90f620e2fa1de1..43dd38659518d1 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();
     }
 



More information about the cfe-commits mailing list