summaryrefslogtreecommitdiffstats
path: root/clang/lib/CodeGen/TargetInfo.cpp
diff options
context:
space:
mode:
authorReid Kleckner <reid@kleckner.net>2014-05-02 00:51:20 +0000
committerReid Kleckner <reid@kleckner.net>2014-05-02 00:51:20 +0000
commit9005f418372a66ef5657b3683b1c975af88ec1c3 (patch)
tree701c511e3e34148c578a2356c33481084f4d44fb /clang/lib/CodeGen/TargetInfo.cpp
parentf0066ad07fadc7c1386c65572e6d988dfd26610d (diff)
downloadbcm5719-llvm-9005f418372a66ef5657b3683b1c975af88ec1c3.tar.gz
bcm5719-llvm-9005f418372a66ef5657b3683b1c975af88ec1c3.zip
Win64: Pass member pointers larger than 8 bytes by reference
The Win64 ABI docs on MSDN say that arguments bigger than 8 bytes are passed by reference. Prior to this change, we were only applying this logic to RecordType arguments. This affects both the Itanium and Microsoft C++ ABIs. Reviewers: majnemer Differential Revision: http://reviews.llvm.org/D3587 llvm-svn: 207817
Diffstat (limited to 'clang/lib/CodeGen/TargetInfo.cpp')
-rw-r--r--clang/lib/CodeGen/TargetInfo.cpp29
1 files changed, 23 insertions, 6 deletions
diff --git a/clang/lib/CodeGen/TargetInfo.cpp b/clang/lib/CodeGen/TargetInfo.cpp
index 436e887d593..e45195dd261 100644
--- a/clang/lib/CodeGen/TargetInfo.cpp
+++ b/clang/lib/CodeGen/TargetInfo.cpp
@@ -2717,7 +2717,8 @@ ABIArgInfo WinX86_64ABIInfo::classify(QualType Ty, bool IsReturnType) const {
uint64_t Size = getContext().getTypeSize(Ty);
- if (const RecordType *RT = Ty->getAs<RecordType>()) {
+ const RecordType *RT = Ty->getAs<RecordType>();
+ if (RT) {
if (IsReturnType) {
if (isRecordReturnIndirect(RT, getCXXABI()))
return ABIArgInfo::getIndirect(0, false);
@@ -2733,15 +2734,31 @@ ABIArgInfo WinX86_64ABIInfo::classify(QualType Ty, bool IsReturnType) const {
if (Size == 128 && getTarget().getTriple().isWindowsGNUEnvironment())
return ABIArgInfo::getDirect(llvm::IntegerType::get(getVMContext(),
Size));
+ }
+
+ if (const auto *MPT = Ty->getAs<MemberPointerType>()) {
+ // If the member pointer is not an aggregate, pass it directly.
+ if (getTarget().getCXXABI().isMicrosoft()) {
+ // For Microsoft, check with the inheritance model.
+ const CXXRecordDecl *RD = MPT->getClass()->getAsCXXRecordDecl();
+ if (MSInheritanceAttr::hasOnlyOneField(MPT->isMemberFunctionPointer(),
+ RD->getMSInheritanceModel()))
+ return ABIArgInfo::getDirect();
+ } else {
+ // For Itanium, data pointers are simple and function pointers are big.
+ if (MPT->isMemberDataPointer())
+ return ABIArgInfo::getDirect();
+ }
+ }
+ if (RT || Ty->isMemberPointerType()) {
// MS x64 ABI requirement: "Any argument that doesn't fit in 8 bytes, or is
// not 1, 2, 4, or 8 bytes, must be passed by reference."
- if (Size <= 64 &&
- (Size & (Size - 1)) == 0)
- return ABIArgInfo::getDirect(llvm::IntegerType::get(getVMContext(),
- Size));
+ if (Size > 64 || !llvm::isPowerOf2_64(Size))
+ return ABIArgInfo::getIndirect(0, /*ByVal=*/false);
- return ABIArgInfo::getIndirect(0, /*ByVal=*/false);
+ // Otherwise, coerce it to a small integer.
+ return ABIArgInfo::getDirect(llvm::IntegerType::get(getVMContext(), Size));
}
if (Ty->isPromotableIntegerType())
OpenPOWER on IntegriCloud