DavidTruby updated this revision to Diff 311906.
DavidTruby added a comment.
Herald added a project: LLVM.
Herald added a subscriber: llvm-commits.
Added extra tests for additional conditions and IR -> assembly tests.
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D92751/new/
https://reviews.llvm.org/D92751
Files:
clang/lib/CodeGen/CGCXXABI.cpp
clang/lib/CodeGen/CGCXXABI.h
clang/lib/CodeGen/MicrosoftCXXABI.cpp
clang/lib/CodeGen/TargetInfo.cpp
clang/test/CodeGenCXX/microsoft-abi-sret-and-byval.cpp
llvm/test/CodeGen/AArch64/arm64-windows-calls.ll
Index: llvm/test/CodeGen/AArch64/arm64-windows-calls.ll
===================================================================
--- llvm/test/CodeGen/AArch64/arm64-windows-calls.ll
+++ llvm/test/CodeGen/AArch64/arm64-windows-calls.ll
@@ -98,3 +98,41 @@
%this1 = load %class.C*, %class.C** %this.addr, align 8
ret void
}
+
+; The following tests correspond to tests in
+; clang/test/CodeGenCXX/microsoft-abi-sret-and-byval.cpp
+
+; Pod is a trivial HFA
+%struct.Pod = type { [2 x double] }
+; Not an aggregate according to C++14 spec => not HFA according to MSVC
+%struct.NotCXX14Aggregate = type { %struct.Pod }
+; NotPod is a C++14 aggregate. But not HFA, because it contains
+; NotCXX14Aggregate (which itself is not HFA because it's not a C++14
+; aggregate).
+%struct.NotPod = type { %struct.NotCXX14Aggregate }
+
+define dso_local %struct.Pod @copy_pod(%struct.Pod* %x) {
+ %x1 = load %struct.Pod, %struct.Pod* %x, align 8
+ ret %struct.Pod %x1
+; CHECK: ldp d0, d1, [x0]
+}
+
+declare void @llvm.memcpy.p0i8.p0i8.i64(i8* noalias nocapture writeonly, i8* noalias nocapture readonly, i64, i1 immarg)
+
+define dso_local void
+@copy_notcxx14aggregate(%struct.NotCXX14Aggregate* inreg noalias sret(%struct.NotCXX14Aggregate) align 8 %agg.result,
+ %struct.NotCXX14Aggregate* %x) {
+ %1 = bitcast %struct.NotCXX14Aggregate* %agg.result to i8*
+ %2 = bitcast %struct.NotCXX14Aggregate* %x to i8*
+ call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 %1, i8* align 8 %2, i64 16, i1 false)
+ ret void
+; CHECK: str q0, [x0]
+}
+
+define dso_local [2 x i64] @copy_notpod(%struct.NotPod* %x) {
+ %x1 = bitcast %struct.NotPod* %x to [2 x i64]*
+ %x2 = load [2 x i64], [2 x i64]* %x1
+ ret [2 x i64] %x2
+; CHECK: ldp x8, x1, [x0]
+; CHECK: mov x0, x8
+}
Index: clang/test/CodeGenCXX/microsoft-abi-sret-and-byval.cpp
===================================================================
--- clang/test/CodeGenCXX/microsoft-abi-sret-and-byval.cpp
+++ clang/test/CodeGenCXX/microsoft-abi-sret-and-byval.cpp
@@ -468,3 +468,41 @@
// WIN64-LABEL: define dso_local void @"?g@C@pr30293@@QEAAXXZ"(%"struct.pr30293::C"* {{[^,]*}} %this)
// WIN64: declare dso_local void @"?h@C@pr30293@@UEAAXUSmallWithDtor@@@Z"(i8*, i32)
}
+
+namespace pr47611 {
+// MSVC on Arm includes "isCXX14Aggregate" as part of its definition of
+// Homogeneous Floating-point Aggregate (HFA). Additionally, it has a different
+// handling of C++14 aggregates, which can lead to confusion.
+
+// Pod is a trivial HFA.
+struct Pod {
+ double b[2];
+};
+// Not an aggregate according to C++14 spec => not HFA according to MSVC.
+struct NotCXX14Aggregate {
+ NotCXX14Aggregate();
+ Pod p;
+};
+// NotPod is a C++14 aggregate. But not HFA, because it contains
+// NotCXX14Aggregate (which itself is not HFA because it's not a C++14
+// aggregate).
+struct NotPod {
+ NotCXX14Aggregate x;
+};
+struct Empty {};
+// A class with a base is returned in standard registers by MSVC
+struct HasEmptyBase : public Empty {
+ double b[2];
+};
+struct HasPodBase : public Pod {};
+// WOA64-LABEL: define dso_local %"struct.pr47611::Pod" @"?copy@pr47611@@YA?AUPod@1@PEAU21@@Z"(%"struct.pr47611::Pod"* %x)
+Pod copy(Pod *x) { return *x; } // MSVC: ldp d0,d1,[x0], Clang: ldp d0,d1,[x0]
+// WOA64-LABEL: define dso_local void @"?copy@pr47611@@YA?AUNotCXX14Aggregate@1@PEAU21@@Z"(%"struct.pr47611::NotCXX14Aggregate"* inreg noalias sret(%"struct.pr47611::NotCXX14Aggregate") align 8 %agg.result, %"struct.pr47611::NotCXX14Aggregate"* %x)
+NotCXX14Aggregate copy(NotCXX14Aggregate *x) { return *x; } // MSVC: stp x8,x9,[x0], Clang: str q0,[x0]
+// WOA64-LABEL: define dso_local [2 x i64] @"?copy@pr47611@@YA?AUNotPod@1@PEAU21@@Z"(%"struct.pr47611::NotPod"* %x)
+NotPod copy(NotPod *x) { return *x; }
+// WOA64-LABEL: define dso_local void @"?copy@pr47611@@YA?AUHasEmptyBase@1@PEAU21@@Z"(%"struct.pr47611::HasEmptyBase"* inreg noalias sret(%"struct.pr47611::HasEmptyBase") align 8 %agg.result, %"struct.pr47611::HasEmptyBase"* %x)
+HasEmptyBase copy(HasEmptyBase *x) { return *x; }
+// WOA64-LABEL: define dso_local void @"?copy@pr47611@@YA?AUHasPodBase@1@PEAU21@@Z"(%"struct.pr47611::HasPodBase"* inreg noalias sret(%"struct.pr47611::HasPodBase") align 8 %agg.result, %"struct.pr47611::HasPodBase"* %x)
+HasPodBase copy(HasPodBase *x) { return *x; }
+};
Index: clang/lib/CodeGen/TargetInfo.cpp
===================================================================
--- clang/lib/CodeGen/TargetInfo.cpp
+++ clang/lib/CodeGen/TargetInfo.cpp
@@ -5133,6 +5133,14 @@
Members += FldMembers;
}
+
+ const auto TT = CGT.getTarget().getTriple();
+ // MSVC Windows on Arm64 considers a type not HFA if it is not an
+ // aggregate according to the C++14 spec. This is not consistent with the
+ // AAPCS64, but is defacto spec on that platform.
+ if (TT.isAArch64() && TT.isWindowsMSVCEnvironment() &&
+ !CGCXXABI::isCXX14Aggregate(CXXRD))
+ return false;
}
for (const auto *FD : RD->fields()) {
Index: clang/lib/CodeGen/MicrosoftCXXABI.cpp
===================================================================
--- clang/lib/CodeGen/MicrosoftCXXABI.cpp
+++ clang/lib/CodeGen/MicrosoftCXXABI.cpp
@@ -1070,30 +1070,6 @@
return isDeletingDtor(GD);
}
-static bool isCXX14Aggregate(const CXXRecordDecl *RD) {
- // For AArch64, we use the C++14 definition of an aggregate, so we also
- // check for:
- // No private or protected non static data members.
- // No base classes
- // No virtual functions
- // Additionally, we need to ensure that there is a trivial copy assignment
- // operator, a trivial destructor and no user-provided constructors.
- if (RD->hasProtectedFields() || RD->hasPrivateFields())
- return false;
- if (RD->getNumBases() > 0)
- return false;
- if (RD->isPolymorphic())
- return false;
- if (RD->hasNonTrivialCopyAssignment())
- return false;
- for (const CXXConstructorDecl *Ctor : RD->ctors())
- if (Ctor->isUserProvided())
- return false;
- if (RD->hasNonTrivialDestructor())
- return false;
- return true;
-}
-
bool MicrosoftCXXABI::classifyReturnType(CGFunctionInfo &FI) const {
const CXXRecordDecl *RD = FI.getReturnType()->getAsCXXRecordDecl();
if (!RD)
Index: clang/lib/CodeGen/CGCXXABI.h
===================================================================
--- clang/lib/CodeGen/CGCXXABI.h
+++ clang/lib/CodeGen/CGCXXABI.h
@@ -625,6 +625,8 @@
virtual std::pair<llvm::Value *, const CXXRecordDecl *>
LoadVTablePtr(CodeGenFunction &CGF, Address This,
const CXXRecordDecl *RD) = 0;
+
+ static bool isCXX14Aggregate(const CXXRecordDecl *RD);
};
// Create an instance of a C++ ABI class:
Index: clang/lib/CodeGen/CGCXXABI.cpp
===================================================================
--- clang/lib/CodeGen/CGCXXABI.cpp
+++ clang/lib/CodeGen/CGCXXABI.cpp
@@ -310,3 +310,27 @@
return AddedStructorArgCounts(AddedArgs.Prefix.size(),
AddedArgs.Suffix.size());
}
+
+bool CGCXXABI::isCXX14Aggregate(const CXXRecordDecl *RD) {
+ // For AArch64, we use the C++14 definition of an aggregate, so we also
+ // check for:
+ // No private or protected non static data members.
+ // No base classes
+ // No virtual functions
+ // Additionally, we need to ensure that there is a trivial copy assignment
+ // operator, a trivial destructor and no user-provided constructors.
+ if (RD->hasProtectedFields() || RD->hasPrivateFields())
+ return false;
+ if (RD->getNumBases() > 0)
+ return false;
+ if (RD->isPolymorphic())
+ return false;
+ if (RD->hasNonTrivialCopyAssignment())
+ return false;
+ for (const CXXConstructorDecl *Ctor : RD->ctors())
+ if (Ctor->isUserProvided())
+ return false;
+ if (RD->hasNonTrivialDestructor())
+ return false;
+ return true;
+}
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits