diff options
author | Reid Kleckner <reid@kleckner.net> | 2014-05-02 00:51:20 +0000 |
---|---|---|
committer | Reid Kleckner <reid@kleckner.net> | 2014-05-02 00:51:20 +0000 |
commit | 9005f418372a66ef5657b3683b1c975af88ec1c3 (patch) | |
tree | 701c511e3e34148c578a2356c33481084f4d44fb /clang/lib/CodeGen/TargetInfo.cpp | |
parent | f0066ad07fadc7c1386c65572e6d988dfd26610d (diff) | |
download | bcm5719-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.cpp | 29 |
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()) |