summaryrefslogtreecommitdiffstats
path: root/clang/lib/CodeGen/CGCall.cpp
diff options
context:
space:
mode:
authorReid Kleckner <reid@kleckner.net>2014-10-31 17:10:41 +0000
committerReid Kleckner <reid@kleckner.net>2014-10-31 17:10:41 +0000
commite9f6a717dd9003b597defee48567431a7db7f9f4 (patch)
tree86216c56bf04dbd677475b810e77250b26a7297d /clang/lib/CodeGen/CGCall.cpp
parent47e7646ebbf1591120bb530fdc85504a1e47fafa (diff)
downloadbcm5719-llvm-e9f6a717dd9003b597defee48567431a7db7f9f4.tar.gz
bcm5719-llvm-e9f6a717dd9003b597defee48567431a7db7f9f4.zip
Fix ARM HVA classification of classes with non-virtual bases
Reuse the PPC64 HVA detection algorithm for ARM and AArch64. This is a nice code deduplication, since they are roughly identical. A few virtual method extension points are needed to understand how big an HVA can be and what element types it can have for a given architecture. Also make the record expansion code work in the presence of non-virtual bases. Reviewed By: uweigand, asl Differential Revision: http://reviews.llvm.org/D6045 llvm-svn: 220972
Diffstat (limited to 'clang/lib/CodeGen/CGCall.cpp')
-rw-r--r--clang/lib/CodeGen/CGCall.cpp51
1 files changed, 45 insertions, 6 deletions
diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp
index 085d702796e..ffa28c17694 100644
--- a/clang/lib/CodeGen/CGCall.cpp
+++ b/clang/lib/CodeGen/CGCall.cpp
@@ -549,10 +549,13 @@ struct ConstantArrayExpansion : TypeExpansion {
};
struct RecordExpansion : TypeExpansion {
+ SmallVector<const CXXBaseSpecifier *, 1> Bases;
+
SmallVector<const FieldDecl *, 1> Fields;
- RecordExpansion(SmallVector<const FieldDecl *, 1> &&Fields)
- : TypeExpansion(TEK_Record), Fields(Fields) {}
+ RecordExpansion(SmallVector<const CXXBaseSpecifier *, 1> &&Bases,
+ SmallVector<const FieldDecl *, 1> &&Fields)
+ : TypeExpansion(TEK_Record), Bases(Bases), Fields(Fields) {}
static bool classof(const TypeExpansion *TE) {
return TE->Kind == TEK_Record;
}
@@ -582,6 +585,7 @@ getTypeExpansion(QualType Ty, const ASTContext &Context) {
AT->getElementType(), AT->getSize().getZExtValue());
}
if (const RecordType *RT = Ty->getAs<RecordType>()) {
+ SmallVector<const CXXBaseSpecifier *, 1> Bases;
SmallVector<const FieldDecl *, 1> Fields;
const RecordDecl *RD = RT->getDecl();
assert(!RD->hasFlexibleArrayMember() &&
@@ -604,13 +608,21 @@ getTypeExpansion(QualType Ty, const ASTContext &Context) {
if (LargestFD)
Fields.push_back(LargestFD);
} else {
+ if (const auto *CXXRD = dyn_cast<CXXRecordDecl>(RD)) {
+ assert(!CXXRD->isDynamicClass() &&
+ "cannot expand vtable pointers in dynamic classes");
+ for (const CXXBaseSpecifier &BS : CXXRD->bases())
+ Bases.push_back(&BS);
+ }
+
for (const auto *FD : RD->fields()) {
assert(!FD->isBitField() &&
"Cannot expand structure with bit-field members.");
Fields.push_back(FD);
}
}
- return llvm::make_unique<RecordExpansion>(std::move(Fields));
+ return llvm::make_unique<RecordExpansion>(std::move(Bases),
+ std::move(Fields));
}
if (const ComplexType *CT = Ty->getAs<ComplexType>()) {
return llvm::make_unique<ComplexExpansion>(CT->getElementType());
@@ -625,6 +637,8 @@ static int getExpansionSize(QualType Ty, const ASTContext &Context) {
}
if (auto RExp = dyn_cast<RecordExpansion>(Exp.get())) {
int Res = 0;
+ for (auto BS : RExp->Bases)
+ Res += getExpansionSize(BS->getType(), Context);
for (auto FD : RExp->Fields)
Res += getExpansionSize(FD->getType(), Context);
return Res;
@@ -644,9 +658,10 @@ CodeGenTypes::getExpandedTypes(QualType Ty,
getExpandedTypes(CAExp->EltTy, TI);
}
} else if (auto RExp = dyn_cast<RecordExpansion>(Exp.get())) {
- for (auto FD : RExp->Fields) {
+ for (auto BS : RExp->Bases)
+ getExpandedTypes(BS->getType(), TI);
+ for (auto FD : RExp->Fields)
getExpandedTypes(FD->getType(), TI);
- }
} else if (auto CExp = dyn_cast<ComplexExpansion>(Exp.get())) {
llvm::Type *EltTy = ConvertType(CExp->EltTy);
*TI++ = EltTy;
@@ -670,6 +685,17 @@ void CodeGenFunction::ExpandTypeFromArgs(
ExpandTypeFromArgs(CAExp->EltTy, LV, AI);
}
} else if (auto RExp = dyn_cast<RecordExpansion>(Exp.get())) {
+ llvm::Value *This = LV.getAddress();
+ for (const CXXBaseSpecifier *BS : RExp->Bases) {
+ // Perform a single step derived-to-base conversion.
+ llvm::Value *Base =
+ GetAddressOfBaseClass(This, Ty->getAsCXXRecordDecl(), &BS, &BS + 1,
+ /*NullCheckValue=*/false, SourceLocation());
+ LValue SubLV = MakeAddrLValue(Base, BS->getType());
+
+ // Recurse onto bases.
+ ExpandTypeFromArgs(BS->getType(), SubLV, AI);
+ }
for (auto FD : RExp->Fields) {
// FIXME: What are the right qualifiers here?
LValue SubLV = EmitLValueForField(LV, FD);
@@ -701,7 +727,20 @@ void CodeGenFunction::ExpandTypeToArgs(
ExpandTypeToArgs(CAExp->EltTy, EltRV, IRFuncTy, IRCallArgs, IRCallArgPos);
}
} else if (auto RExp = dyn_cast<RecordExpansion>(Exp.get())) {
- LValue LV = MakeAddrLValue(RV.getAggregateAddr(), Ty);
+ llvm::Value *This = RV.getAggregateAddr();
+ for (const CXXBaseSpecifier *BS : RExp->Bases) {
+ // Perform a single step derived-to-base conversion.
+ llvm::Value *Base =
+ GetAddressOfBaseClass(This, Ty->getAsCXXRecordDecl(), &BS, &BS + 1,
+ /*NullCheckValue=*/false, SourceLocation());
+ RValue BaseRV = RValue::getAggregate(Base);
+
+ // Recurse onto bases.
+ ExpandTypeToArgs(BS->getType(), BaseRV, IRFuncTy, IRCallArgs,
+ IRCallArgPos);
+ }
+
+ LValue LV = MakeAddrLValue(This, Ty);
for (auto FD : RExp->Fields) {
RValue FldRV = EmitRValueForField(LV, FD, SourceLocation());
ExpandTypeToArgs(FD->getType(), FldRV, IRFuncTy, IRCallArgs,
OpenPOWER on IntegriCloud