diff options
author | Reid Kleckner <reid@kleckner.net> | 2014-10-31 17:10:41 +0000 |
---|---|---|
committer | Reid Kleckner <reid@kleckner.net> | 2014-10-31 17:10:41 +0000 |
commit | e9f6a717dd9003b597defee48567431a7db7f9f4 (patch) | |
tree | 86216c56bf04dbd677475b810e77250b26a7297d /clang/lib/CodeGen/CGCall.cpp | |
parent | 47e7646ebbf1591120bb530fdc85504a1e47fafa (diff) | |
download | bcm5719-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.cpp | 51 |
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, |