summaryrefslogtreecommitdiffstats
path: root/clang/lib/CodeGen/TargetInfo.cpp
diff options
context:
space:
mode:
authorReid Kleckner <reid@kleckner.net>2014-05-13 22:05:45 +0000
committerReid Kleckner <reid@kleckner.net>2014-05-13 22:05:45 +0000
commit40ca913727f914b720b30d4e3ccc66250fb4aba2 (patch)
treea7b5b6ed63e525333c6fd2d0843082bb697b5537 /clang/lib/CodeGen/TargetInfo.cpp
parentb4892cd266dfafb9c6986ee46a8025c8031c3792 (diff)
downloadbcm5719-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.cpp145
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();
OpenPOWER on IntegriCloud