diff options
author | Reid Kleckner <reid@kleckner.net> | 2014-05-13 22:05:45 +0000 |
---|---|---|
committer | Reid Kleckner <reid@kleckner.net> | 2014-05-13 22:05:45 +0000 |
commit | 40ca913727f914b720b30d4e3ccc66250fb4aba2 (patch) | |
tree | a7b5b6ed63e525333c6fd2d0843082bb697b5537 /clang/lib/CodeGen/TargetInfo.cpp | |
parent | b4892cd266dfafb9c6986ee46a8025c8031c3792 (diff) | |
download | bcm5719-llvm-40ca913727f914b720b30d4e3ccc66250fb4aba2.tar.gz bcm5719-llvm-40ca913727f914b720b30d4e3ccc66250fb4aba2.zip |
Push record return type classification into CGCXXABI
In the Microsoft C++ ABI, instance methods always return records
indirectly via the second hidden parameter. This was implemented in
X86_32ABIInfo, but not WinX86_64ABIInfo.
Rather than exposing a handful of boolean methods in the CGCXXABI
interface, we can expose a single method that applies C++ ABI return
value classification rules.
llvm-svn: 208733
Diffstat (limited to 'clang/lib/CodeGen/TargetInfo.cpp')
-rw-r--r-- | clang/lib/CodeGen/TargetInfo.cpp | 145 |
1 files changed, 43 insertions, 102 deletions
diff --git a/clang/lib/CodeGen/TargetInfo.cpp b/clang/lib/CodeGen/TargetInfo.cpp index 6f0df6bda11..5dc1a913fb4 100644 --- a/clang/lib/CodeGen/TargetInfo.cpp +++ b/clang/lib/CodeGen/TargetInfo.cpp @@ -48,22 +48,6 @@ static bool isAggregateTypeForABI(QualType T) { ABIInfo::~ABIInfo() {} -static bool isRecordReturnIndirect(const RecordType *RT, - CGCXXABI &CXXABI) { - const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(RT->getDecl()); - if (!RD) - return false; - return CXXABI.isReturnTypeIndirect(RD); -} - - -static bool isRecordReturnIndirect(QualType T, CGCXXABI &CXXABI) { - const RecordType *RT = T->getAs<RecordType>(); - if (!RT) - return false; - return isRecordReturnIndirect(RT, CXXABI); -} - static CGCXXABI::RecordArgABI getRecordArgABI(const RecordType *RT, CGCXXABI &CXXABI) { const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(RT->getDecl()); @@ -370,7 +354,8 @@ public: ABIArgInfo classifyArgumentType(QualType RetTy) const; void computeInfo(CGFunctionInfo &FI) const override { - FI.getReturnInfo() = classifyReturnType(FI.getReturnType()); + if (!getCXXABI().classifyReturnType(FI)) + FI.getReturnInfo() = classifyReturnType(FI.getReturnType()); for (auto &I : FI.arguments()) I.info = classifyArgumentType(I.type); } @@ -391,14 +376,8 @@ llvm::Value *DefaultABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty, } ABIArgInfo DefaultABIInfo::classifyArgumentType(QualType Ty) const { - if (isAggregateTypeForABI(Ty)) { - // Records with non-trivial destructors/constructors should not be passed - // by value. - if (isRecordReturnIndirect(Ty, getCXXABI())) - return ABIArgInfo::getIndirect(0, /*ByVal=*/false); - + if (isAggregateTypeForABI(Ty)) return ABIArgInfo::getIndirect(0); - } // Treat an enum type as its underlying type. if (const EnumType *EnumTy = Ty->getAs<EnumType>()) @@ -449,11 +428,12 @@ class PNaClTargetCodeGenInfo : public TargetCodeGenInfo { }; void PNaClABIInfo::computeInfo(CGFunctionInfo &FI) const { + if (!getCXXABI().classifyReturnType(FI)) FI.getReturnInfo() = classifyReturnType(FI.getReturnType()); - for (auto &I : FI.arguments()) - I.info = classifyArgumentType(I.type); - } + for (auto &I : FI.arguments()) + I.info = classifyArgumentType(I.type); +} llvm::Value *PNaClABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty, CodeGenFunction &CGF) const { @@ -550,8 +530,7 @@ class X86_32ABIInfo : public ABIInfo { return (Size == 8 || Size == 16 || Size == 32 || Size == 64); } - bool shouldReturnTypeInRegister(QualType Ty, ASTContext &Context, - bool IsInstanceMethod) const; + bool shouldReturnTypeInRegister(QualType Ty, ASTContext &Context) const; /// getIndirectResult - Give a source type \arg Ty, return a suitable result /// such that the argument will be passed in memory. @@ -563,8 +542,7 @@ class X86_32ABIInfo : public ABIInfo { unsigned getTypeStackAlignInBytes(QualType Ty, unsigned Align) const; Class classify(QualType Ty) const; - ABIArgInfo classifyReturnType(QualType RetTy, CCState &State, - bool IsInstanceMethod) const; + ABIArgInfo classifyReturnType(QualType RetTy, CCState &State) const; ABIArgInfo classifyArgumentType(QualType RetTy, CCState &State) const; bool shouldUseInReg(QualType Ty, CCState &State, bool &NeedsPadding) const; @@ -630,8 +608,8 @@ public: /// shouldReturnTypeInRegister - Determine if the given type should be /// passed in a register (for the Darwin ABI). -bool X86_32ABIInfo::shouldReturnTypeInRegister(QualType Ty, ASTContext &Context, - bool IsInstanceMethod) const { +bool X86_32ABIInfo::shouldReturnTypeInRegister(QualType Ty, + ASTContext &Context) const { uint64_t Size = Context.getTypeSize(Ty); // Type must be register sized. @@ -656,8 +634,7 @@ bool X86_32ABIInfo::shouldReturnTypeInRegister(QualType Ty, ASTContext &Context, // Arrays are treated like records. if (const ConstantArrayType *AT = Context.getAsConstantArrayType(Ty)) - return shouldReturnTypeInRegister(AT->getElementType(), Context, - IsInstanceMethod); + return shouldReturnTypeInRegister(AT->getElementType(), Context); // Otherwise, it must be a record type. const RecordType *RT = Ty->getAs<RecordType>(); @@ -665,11 +642,6 @@ bool X86_32ABIInfo::shouldReturnTypeInRegister(QualType Ty, ASTContext &Context, // FIXME: Traverse bases here too. - // For thiscall conventions, structures will never be returned in - // a register. This is for compatibility with the MSVC ABI - if (IsWin32StructABI && IsInstanceMethod && RT->isStructureType()) - return false; - // Structure types are passed in register if all fields would be // passed in a register. for (const auto *FD : RT->getDecl()->fields()) { @@ -678,7 +650,7 @@ bool X86_32ABIInfo::shouldReturnTypeInRegister(QualType Ty, ASTContext &Context, continue; // Check fields recursively. - if (!shouldReturnTypeInRegister(FD->getType(), Context, IsInstanceMethod)) + if (!shouldReturnTypeInRegister(FD->getType(), Context)) return false; } return true; @@ -694,8 +666,7 @@ ABIArgInfo X86_32ABIInfo::getIndirectReturnResult(CCState &State) const { return ABIArgInfo::getIndirect(/*Align=*/0, /*ByVal=*/false); } -ABIArgInfo X86_32ABIInfo::classifyReturnType(QualType RetTy, CCState &State, - bool IsInstanceMethod) const { +ABIArgInfo X86_32ABIInfo::classifyReturnType(QualType RetTy, CCState &State) const { if (RetTy->isVoidType()) return ABIArgInfo::getIgnore(); @@ -726,9 +697,6 @@ ABIArgInfo X86_32ABIInfo::classifyReturnType(QualType RetTy, CCState &State, if (isAggregateTypeForABI(RetTy)) { if (const RecordType *RT = RetTy->getAs<RecordType>()) { - if (isRecordReturnIndirect(RT, getCXXABI())) - return getIndirectReturnResult(State); - // Structures with flexible arrays are always indirect. if (RT->getDecl()->hasFlexibleArrayMember()) return getIndirectReturnResult(State); @@ -740,7 +708,7 @@ ABIArgInfo X86_32ABIInfo::classifyReturnType(QualType RetTy, CCState &State, // Small structures which are register sized are generally returned // in a register. - if (shouldReturnTypeInRegister(RetTy, getContext(), IsInstanceMethod)) { + if (shouldReturnTypeInRegister(RetTy, getContext())) { uint64_t Size = getContext().getTypeSize(RetTy); // As a special-case, if the struct is a "single-element" struct, and @@ -989,16 +957,8 @@ void X86_32ABIInfo::computeInfo(CGFunctionInfo &FI) const { else State.FreeRegs = DefaultNumRegisterParameters; - FI.getReturnInfo() = - classifyReturnType(FI.getReturnType(), State, FI.isInstanceMethod()); - - // On win32, swap the order of the first two parameters for instance methods - // which are sret behind the scenes to match MSVC. - if (IsWin32StructABI && FI.isInstanceMethod() && - FI.getReturnInfo().isIndirect()) { - assert(FI.arg_size() >= 1 && "instance method should have this"); - FI.getReturnInfo().setSRetAfterThis(true); - } + if (!getCXXABI().classifyReturnType(FI)) + FI.getReturnInfo() = classifyReturnType(FI.getReturnType(), State); bool UsedInAlloca = false; for (auto &I : FI.arguments()) { @@ -2451,7 +2411,8 @@ ABIArgInfo X86_64ABIInfo::classifyArgumentType( void X86_64ABIInfo::computeInfo(CGFunctionInfo &FI) const { - FI.getReturnInfo() = classifyReturnType(FI.getReturnType()); + if (!getCXXABI().classifyReturnType(FI)) + FI.getReturnInfo() = classifyReturnType(FI.getReturnType()); // Keep track of the number of assigned registers. unsigned freeIntRegs = 6, freeSSERegs = 8; @@ -2722,10 +2683,7 @@ ABIArgInfo WinX86_64ABIInfo::classify(QualType Ty, bool IsReturnType) const { const RecordType *RT = Ty->getAs<RecordType>(); if (RT) { - if (IsReturnType) { - if (isRecordReturnIndirect(RT, getCXXABI())) - return ABIArgInfo::getIndirect(0, false); - } else { + if (!IsReturnType) { if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(RT, getCXXABI())) return ABIArgInfo::getIndirect(0, RAA == CGCXXABI::RAA_DirectInMemory); } @@ -2764,17 +2722,8 @@ ABIArgInfo WinX86_64ABIInfo::classify(QualType Ty, bool IsReturnType) const { } void WinX86_64ABIInfo::computeInfo(CGFunctionInfo &FI) const { - - QualType RetTy = FI.getReturnType(); - FI.getReturnInfo() = classify(RetTy, true); - - // On win64, swap the order of the first two parameters for instance methods - // which are sret behind the scenes to match MSVC. - if (FI.getReturnInfo().isIndirect() && FI.isInstanceMethod() && - getCXXABI().isSRetParameterAfterThis()) { - assert(FI.arg_size() >= 1 && "instance method should have this"); - FI.getReturnInfo().setSRetAfterThis(true); - } + if (!getCXXABI().classifyReturnType(FI)) + FI.getReturnInfo() = classify(FI.getReturnType(), true); for (auto &I : FI.arguments()) I.info = classify(I.type, false); @@ -2919,7 +2868,8 @@ public: // entry. This would require changing the logic in PPCISelLowering // when lowering the parameters in the caller and args in the callee. void computeInfo(CGFunctionInfo &FI) const override { - FI.getReturnInfo() = classifyReturnType(FI.getReturnType()); + if (!getCXXABI().classifyReturnType(FI)) + FI.getReturnInfo() = classifyReturnType(FI.getReturnType()); for (auto &I : FI.arguments()) { // We rely on the default argument classification for the most part. // One exception: An aggregate containing a single floating-point @@ -3203,7 +3153,8 @@ private: FI.getRequiredArgs().getNumRequiredArgs() : FI.arg_size()); - FI.getReturnInfo() = classifyReturnType(FI.getReturnType()); + if (!getCXXABI().classifyReturnType(FI)) + FI.getReturnInfo() = classifyReturnType(FI.getReturnType()); for (CGFunctionInfo::arg_iterator it = FI.arg_begin(), ie = FI.arg_end(); it != ie; ++it) { unsigned PreAllocation = AllocatedVFP, PreGPR = AllocatedGPR; @@ -3340,9 +3291,10 @@ ABIArgInfo ARM64ABIInfo::classifyArgumentType(QualType Ty, // Structures with either a non-trivial destructor or a non-trivial // copy constructor are always indirect. - if (isRecordReturnIndirect(Ty, getCXXABI())) { + if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(Ty, getCXXABI())) { AllocatedGPR++; - return ABIArgInfo::getIndirect(0, /*ByVal=*/false); + return ABIArgInfo::getIndirect(0, /*ByVal=*/RAA == + CGCXXABI::RAA_DirectInMemory); } // Empty records are always ignored on Darwin, but actually passed in C++ mode @@ -3412,11 +3364,6 @@ ABIArgInfo ARM64ABIInfo::classifyReturnType(QualType RetTy) const { : ABIArgInfo::getDirect()); } - // Structures with either a non-trivial destructor or a non-trivial - // copy constructor are always indirect. - if (isRecordReturnIndirect(RetTy, getCXXABI())) - return ABIArgInfo::getIndirect(0, /*ByVal=*/false); - if (isEmptyRecord(getContext(), RetTy, true)) return ABIArgInfo::getIgnore(); @@ -3905,7 +3852,12 @@ void ARMABIInfo::computeInfo(CGFunctionInfo &FI) const { // unallocated are marked as unavailable. resetAllocatedRegs(); - FI.getReturnInfo() = classifyReturnType(FI.getReturnType(), FI.isVariadic()); + if (getCXXABI().classifyReturnType(FI)) { + if (FI.getReturnInfo().isIndirect()) + markAllocatedGPRs(1, 1); + } else { + FI.getReturnInfo() = classifyReturnType(FI.getReturnType(), FI.isVariadic()); + } for (auto &I : FI.arguments()) { unsigned PreAllocationVFPs = AllocatedVFPs; unsigned PreAllocationGPRs = AllocatedGPRs; @@ -4368,13 +4320,6 @@ ABIArgInfo ARMABIInfo::classifyReturnType(QualType RetTy, ABIArgInfo::getExtend() : ABIArgInfo::getDirect()); } - // Structures with either a non-trivial destructor or a non-trivial - // copy constructor are always indirect. - if (isRecordReturnIndirect(RetTy, getCXXABI())) { - markAllocatedGPRs(1, 1); - return ABIArgInfo::getIndirect(0, /*ByVal=*/false); - } - // Are we following APCS? if (getABIKind() == APCS) { if (isEmptyRecord(getContext(), RetTy, false)) @@ -4834,7 +4779,8 @@ ABIArgInfo NVPTXABIInfo::classifyArgumentType(QualType Ty) const { } void NVPTXABIInfo::computeInfo(CGFunctionInfo &FI) const { - FI.getReturnInfo() = classifyReturnType(FI.getReturnType()); + if (!getCXXABI().classifyReturnType(FI)) + FI.getReturnInfo() = classifyReturnType(FI.getReturnType()); for (auto &I : FI.arguments()) I.info = classifyArgumentType(I.type); @@ -4931,7 +4877,8 @@ public: ABIArgInfo classifyArgumentType(QualType ArgTy) const; void computeInfo(CGFunctionInfo &FI) const override { - FI.getReturnInfo() = classifyReturnType(FI.getReturnType()); + if (!getCXXABI().classifyReturnType(FI)) + FI.getReturnInfo() = classifyReturnType(FI.getReturnType()); for (auto &I : FI.arguments()) I.info = classifyArgumentType(I.type); } @@ -5500,9 +5447,6 @@ ABIArgInfo MipsABIInfo::classifyReturnType(QualType RetTy) const { return ABIArgInfo::getIgnore(); if (isAggregateTypeForABI(RetTy) || RetTy->isVectorType()) { - if (isRecordReturnIndirect(RetTy, getCXXABI())) - return ABIArgInfo::getIndirect(0); - if (Size <= 128) { if (RetTy->isAnyComplexType()) return ABIArgInfo::getDirect(); @@ -5528,7 +5472,8 @@ ABIArgInfo MipsABIInfo::classifyReturnType(QualType RetTy) const { void MipsABIInfo::computeInfo(CGFunctionInfo &FI) const { ABIArgInfo &RetInfo = FI.getReturnInfo(); - RetInfo = classifyReturnType(FI.getReturnType()); + if (!getCXXABI().classifyReturnType(FI)) + RetInfo = classifyReturnType(FI.getReturnType()); // Check if a pointer to an aggregate is passed as a hidden argument. uint64_t Offset = RetInfo.isIndirect() ? MinABIStackAlignInBytes : 0; @@ -5696,7 +5641,8 @@ public: } void HexagonABIInfo::computeInfo(CGFunctionInfo &FI) const { - FI.getReturnInfo() = classifyReturnType(FI.getReturnType()); + if (!getCXXABI().classifyReturnType(FI)) + FI.getReturnInfo() = classifyReturnType(FI.getReturnType()); for (auto &I : FI.arguments()) I.info = classifyArgumentType(I.type); } @@ -5749,11 +5695,6 @@ ABIArgInfo HexagonABIInfo::classifyReturnType(QualType RetTy) const { ABIArgInfo::getExtend() : ABIArgInfo::getDirect()); } - // Structures with either a non-trivial destructor or a non-trivial - // copy constructor are always indirect. - if (isRecordReturnIndirect(RetTy, getCXXABI())) - return ABIArgInfo::getIndirect(0, /*ByVal=*/false); - if (isEmptyRecord(getContext(), RetTy, true)) return ABIArgInfo::getIgnore(); |