This revision was automatically updated to reflect the committed changes.
Closed by commit rG3b3a16548568: [MS] On x86_32, pass overaligned, non-copyable 
arguments indirectly (authored by rnk).

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D87923/new/

https://reviews.llvm.org/D87923

Files:
  clang/lib/CodeGen/MicrosoftCXXABI.cpp
  clang/test/CodeGenCXX/inalloca-overaligned.cpp


Index: clang/test/CodeGenCXX/inalloca-overaligned.cpp
===================================================================
--- clang/test/CodeGenCXX/inalloca-overaligned.cpp
+++ clang/test/CodeGenCXX/inalloca-overaligned.cpp
@@ -4,11 +4,6 @@
 // MSVC passes overaligned types indirectly since MSVC 2015. Make sure that
 // works with inalloca.
 
-// FIXME: Pass non-trivial *and* overaligned types indirectly. Right now the 
C++
-// ABI rules say to use inalloca, and they take precedence, so it's not easy to
-// implement this.
-
-
 struct NonTrivial {
   NonTrivial();
   NonTrivial(const NonTrivial &o);
@@ -20,6 +15,12 @@
   int buf[16];
 };
 
+struct __declspec(align(8)) Both {
+  Both();
+  Both(const Both &o);
+  int x, y;
+};
+
 extern int gvi32;
 
 int receive_inalloca_overaligned(NonTrivial nt, OverAligned o) {
@@ -50,3 +51,37 @@
 // CHECK: getelementptr inbounds <{ %struct.NonTrivial, %struct.OverAligned* 
}>, <{ %struct.NonTrivial, %struct.OverAligned* }>* %{{.*}}, i32 0, i32 1
 // CHECK: store %struct.OverAligned* [[TMP]], %struct.OverAligned** %{{.*}}, 
align 4
 // CHECK: call i32 @"?receive_inalloca_overaligned@@Y{{.*}}"(<{ 
%struct.NonTrivial, %struct.OverAligned* }>* inalloca %argmem)
+
+int receive_both(Both o) {
+  return o.x + o.y;
+}
+
+// CHECK-LABEL: define dso_local i32 @"?receive_both@@Y{{.*}}"
+// CHECK-SAME: (%struct.Both* %o)
+
+int pass_both() {
+  gvi32 = receive_both(Both());
+  return gvi32;
+}
+
+// CHECK-LABEL: define dso_local i32 @"?pass_both@@Y{{.*}}"
+// CHECK: [[TMP:%[^ ]*]] = alloca %struct.Both, align 8
+// CHECK: call x86_thiscallcc %struct.Both* @"??0Both@@QAE@XZ"(%struct.Both* 
[[TMP]])
+// CHECK: call i32 @"?receive_both@@Y{{.*}}"(%struct.Both* [[TMP]])
+
+int receive_inalloca_both(NonTrivial nt, Both o) {
+  return nt.x + o.x + o.y;
+}
+
+// CHECK-LABEL: define dso_local i32 @"?receive_inalloca_both@@Y{{.*}}"
+// CHECK-SAME: (<{ %struct.NonTrivial, %struct.Both* }>* inalloca %0)
+
+int pass_inalloca_both() {
+  gvi32 = receive_inalloca_both(NonTrivial(), Both());
+  return gvi32;
+}
+
+// CHECK-LABEL: define dso_local i32 @"?pass_inalloca_both@@Y{{.*}}"
+// CHECK: [[TMP:%[^ ]*]] = alloca %struct.Both, align 8
+// CHECK: call x86_thiscallcc %struct.Both* @"??0Both@@QAE@XZ"(%struct.Both* 
[[TMP]])
+// CHECK: call i32 @"?receive_inalloca_both@@Y{{.*}}"(<{ %struct.NonTrivial, 
%struct.Both* }>* inalloca %argmem)
Index: clang/lib/CodeGen/MicrosoftCXXABI.cpp
===================================================================
--- clang/lib/CodeGen/MicrosoftCXXABI.cpp
+++ clang/lib/CodeGen/MicrosoftCXXABI.cpp
@@ -827,10 +827,14 @@
     // copy ctor.
     return !RD->canPassInRegisters() ? RAA_Indirect : RAA_Default;
 
-  case llvm::Triple::x86:
-    // All record arguments are passed in memory on x86.  Decide whether to
-    // construct the object directly in argument memory, or to construct the
-    // argument elsewhere and copy the bytes during the call.
+  case llvm::Triple::x86: {
+    // If the argument has *required* alignment greater than four bytes, pass
+    // it indirectly. Prior to MSVC version 19.14, passing overaligned
+    // arguments was not supported and resulted in a compiler error. In 19.14
+    // and later versions, such arguments are now passed indirectly.
+    TypeInfo Info = getContext().getTypeInfo(RD->getTypeForDecl());
+    if (Info.AlignIsRequired && Info.Align > 4)
+      return RAA_Indirect;
 
     // If C++ prohibits us from making a copy, construct the arguments directly
     // into argument memory.
@@ -840,6 +844,7 @@
     // Otherwise, construct the argument into a temporary and copy the bytes
     // into the outgoing argument memory.
     return RAA_Default;
+  }
 
   case llvm::Triple::x86_64:
   case llvm::Triple::aarch64:


Index: clang/test/CodeGenCXX/inalloca-overaligned.cpp
===================================================================
--- clang/test/CodeGenCXX/inalloca-overaligned.cpp
+++ clang/test/CodeGenCXX/inalloca-overaligned.cpp
@@ -4,11 +4,6 @@
 // MSVC passes overaligned types indirectly since MSVC 2015. Make sure that
 // works with inalloca.
 
-// FIXME: Pass non-trivial *and* overaligned types indirectly. Right now the C++
-// ABI rules say to use inalloca, and they take precedence, so it's not easy to
-// implement this.
-
-
 struct NonTrivial {
   NonTrivial();
   NonTrivial(const NonTrivial &o);
@@ -20,6 +15,12 @@
   int buf[16];
 };
 
+struct __declspec(align(8)) Both {
+  Both();
+  Both(const Both &o);
+  int x, y;
+};
+
 extern int gvi32;
 
 int receive_inalloca_overaligned(NonTrivial nt, OverAligned o) {
@@ -50,3 +51,37 @@
 // CHECK: getelementptr inbounds <{ %struct.NonTrivial, %struct.OverAligned* }>, <{ %struct.NonTrivial, %struct.OverAligned* }>* %{{.*}}, i32 0, i32 1
 // CHECK: store %struct.OverAligned* [[TMP]], %struct.OverAligned** %{{.*}}, align 4
 // CHECK: call i32 @"?receive_inalloca_overaligned@@Y{{.*}}"(<{ %struct.NonTrivial, %struct.OverAligned* }>* inalloca %argmem)
+
+int receive_both(Both o) {
+  return o.x + o.y;
+}
+
+// CHECK-LABEL: define dso_local i32 @"?receive_both@@Y{{.*}}"
+// CHECK-SAME: (%struct.Both* %o)
+
+int pass_both() {
+  gvi32 = receive_both(Both());
+  return gvi32;
+}
+
+// CHECK-LABEL: define dso_local i32 @"?pass_both@@Y{{.*}}"
+// CHECK: [[TMP:%[^ ]*]] = alloca %struct.Both, align 8
+// CHECK: call x86_thiscallcc %struct.Both* @"??0Both@@QAE@XZ"(%struct.Both* [[TMP]])
+// CHECK: call i32 @"?receive_both@@Y{{.*}}"(%struct.Both* [[TMP]])
+
+int receive_inalloca_both(NonTrivial nt, Both o) {
+  return nt.x + o.x + o.y;
+}
+
+// CHECK-LABEL: define dso_local i32 @"?receive_inalloca_both@@Y{{.*}}"
+// CHECK-SAME: (<{ %struct.NonTrivial, %struct.Both* }>* inalloca %0)
+
+int pass_inalloca_both() {
+  gvi32 = receive_inalloca_both(NonTrivial(), Both());
+  return gvi32;
+}
+
+// CHECK-LABEL: define dso_local i32 @"?pass_inalloca_both@@Y{{.*}}"
+// CHECK: [[TMP:%[^ ]*]] = alloca %struct.Both, align 8
+// CHECK: call x86_thiscallcc %struct.Both* @"??0Both@@QAE@XZ"(%struct.Both* [[TMP]])
+// CHECK: call i32 @"?receive_inalloca_both@@Y{{.*}}"(<{ %struct.NonTrivial, %struct.Both* }>* inalloca %argmem)
Index: clang/lib/CodeGen/MicrosoftCXXABI.cpp
===================================================================
--- clang/lib/CodeGen/MicrosoftCXXABI.cpp
+++ clang/lib/CodeGen/MicrosoftCXXABI.cpp
@@ -827,10 +827,14 @@
     // copy ctor.
     return !RD->canPassInRegisters() ? RAA_Indirect : RAA_Default;
 
-  case llvm::Triple::x86:
-    // All record arguments are passed in memory on x86.  Decide whether to
-    // construct the object directly in argument memory, or to construct the
-    // argument elsewhere and copy the bytes during the call.
+  case llvm::Triple::x86: {
+    // If the argument has *required* alignment greater than four bytes, pass
+    // it indirectly. Prior to MSVC version 19.14, passing overaligned
+    // arguments was not supported and resulted in a compiler error. In 19.14
+    // and later versions, such arguments are now passed indirectly.
+    TypeInfo Info = getContext().getTypeInfo(RD->getTypeForDecl());
+    if (Info.AlignIsRequired && Info.Align > 4)
+      return RAA_Indirect;
 
     // If C++ prohibits us from making a copy, construct the arguments directly
     // into argument memory.
@@ -840,6 +844,7 @@
     // Otherwise, construct the argument into a temporary and copy the bytes
     // into the outgoing argument memory.
     return RAA_Default;
+  }
 
   case llvm::Triple::x86_64:
   case llvm::Triple::aarch64:
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to