[cfe-commits] r105102 - /cfe/trunk/lib/AST/RecordLayoutBuilder.cpp
Anders Carlsson
andersca at mac.com
Sat May 29 10:35:14 PDT 2010
Author: andersca
Date: Sat May 29 12:35:14 2010
New Revision: 105102
URL: http://llvm.org/viewvc/llvm-project?rev=105102&view=rev
Log:
Move computing the base subobject info for a class into the RecordLayoutBuilder because we're going to need it to be able to correctly add offsets for primary virtual bases.
Modified:
cfe/trunk/lib/AST/RecordLayoutBuilder.cpp
Modified: cfe/trunk/lib/AST/RecordLayoutBuilder.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/RecordLayoutBuilder.cpp?rev=105102&r1=105101&r2=105102&view=diff
==============================================================================
--- cfe/trunk/lib/AST/RecordLayoutBuilder.cpp (original)
+++ cfe/trunk/lib/AST/RecordLayoutBuilder.cpp Sat May 29 12:35:14 2010
@@ -44,9 +44,9 @@
/// Bases - Information about the base subobjects.
llvm::SmallVector<BaseSubobjectInfo*, 4> Bases;
- /// PrimaryVirtualBase - Holds the base info for the primary virtual base of
- /// this base info (if one exists).
- const CXXRecordDecl *PrimaryVirtualBase;
+ /// PrimaryVirtualBaseInfo - Holds the base info for the primary virtual base
+ /// of this base info (if one exists).
+ BaseSubobjectInfo *PrimaryVirtualBaseInfo;
// FIXME: Document.
const BaseSubobjectInfo *Derived;
@@ -68,13 +68,6 @@
/// ComputeEmptySubobjectSizes - Compute the size of the largest base or
/// member subobject that is empty.
void ComputeEmptySubobjectSizes();
-
- llvm::DenseMap<const CXXRecordDecl *, BaseSubobjectInfo *> VirtualBaseInfo;
- llvm::DenseMap<const CXXRecordDecl *, BaseSubobjectInfo *> NonVirtualBaseInfo;
-
- BaseSubobjectInfo *ComputeBaseInfo(const CXXRecordDecl *RD, bool IsVirtual,
- const BaseSubobjectInfo *Derived);
- void ComputeBaseInfo();
bool CanPlaceSubobjectAtOffset(const CXXRecordDecl *RD, uint64_t Offset);
void AddSubobjectAtOffset(const CXXRecordDecl *RD, uint64_t Offset);
@@ -104,8 +97,6 @@
EmptySubobjectMap(ASTContext &Context, const CXXRecordDecl *Class)
: Context(Context), Class(Class), SizeOfLargestEmptySubobject(0) {
ComputeEmptySubobjectSizes();
-
- ComputeBaseInfo();
}
/// CanPlaceBaseAtOffset - Return whether the given base class can be placed
@@ -169,74 +160,6 @@
}
}
-BaseSubobjectInfo *
-EmptySubobjectMap::ComputeBaseInfo(const CXXRecordDecl *RD, bool IsVirtual,
- const BaseSubobjectInfo *Derived) {
- BaseSubobjectInfo *Info;
-
- if (IsVirtual) {
- BaseSubobjectInfo *&InfoSlot = VirtualBaseInfo[RD];
- if (InfoSlot) {
- assert(InfoSlot->Class == RD && "Wrong class for virtual base info!");
- return InfoSlot;
- }
-
- InfoSlot = new (Context) BaseSubobjectInfo;
- Info = InfoSlot;
- } else {
- Info = new (Context) BaseSubobjectInfo;
- }
-
- Info->Class = RD;
- Info->IsVirtual = IsVirtual;
- Info->Derived = Derived;
- Info->PrimaryVirtualBase = 0;
-
- if (RD->getNumVBases()) {
- // Check if this class has a primary virtual base.
- const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
- if (Layout.getPrimaryBaseWasVirtual()) {
- Info->PrimaryVirtualBase = Layout.getPrimaryBase();
- assert(Info->PrimaryVirtualBase &&
- "Didn't have a primary virtual base!");
- }
- }
-
- for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(),
- E = RD->bases_end(); I != E; ++I) {
- bool IsVirtual = I->isVirtual();
-
- const CXXRecordDecl *BaseDecl =
- cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl());
-
- Info->Bases.push_back(ComputeBaseInfo(BaseDecl, IsVirtual, Info));
- }
-
- return Info;
-}
-
-void EmptySubobjectMap::ComputeBaseInfo() {
- for (CXXRecordDecl::base_class_const_iterator I = Class->bases_begin(),
- E = Class->bases_end(); I != E; ++I) {
- bool IsVirtual = I->isVirtual();
-
- const CXXRecordDecl *BaseDecl =
- cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl());
-
- BaseSubobjectInfo *Info =
- ComputeBaseInfo(BaseDecl, IsVirtual, /*Derived=*/0);
- if (IsVirtual) {
- // ComputeBaseInfo has already added this base for us.
- continue;
- }
-
- // Add the base info to the map of non-virtual bases.
- assert(!NonVirtualBaseInfo.count(BaseDecl) &&
- "Non-virtual base already exists!");
- NonVirtualBaseInfo.insert(std::make_pair(BaseDecl, Info));
- }
-}
-
bool
EmptySubobjectMap::CanPlaceSubobjectAtOffset(const CXXRecordDecl *RD,
uint64_t Offset) {
@@ -288,10 +211,8 @@
return false;
}
- if (Info->PrimaryVirtualBase) {
- BaseSubobjectInfo *PrimaryVirtualBaseInfo =
- VirtualBaseInfo.lookup(Info->PrimaryVirtualBase);
- assert(PrimaryVirtualBaseInfo && "Didn't find base info!");
+ if (Info->PrimaryVirtualBaseInfo) {
+ BaseSubobjectInfo *PrimaryVirtualBaseInfo = Info->PrimaryVirtualBaseInfo;
if (Info == PrimaryVirtualBaseInfo->Derived) {
if (!CanPlaceBaseSubobjectAtOffset(PrimaryVirtualBaseInfo, Offset))
@@ -332,10 +253,8 @@
UpdateEmptyBaseSubobjects(Base, BaseOffset);
}
- if (Info->PrimaryVirtualBase) {
- BaseSubobjectInfo *PrimaryVirtualBaseInfo =
- VirtualBaseInfo.lookup(Info->PrimaryVirtualBase);
- assert(PrimaryVirtualBaseInfo && "Didn't find base info!");
+ if (Info->PrimaryVirtualBaseInfo) {
+ BaseSubobjectInfo *PrimaryVirtualBaseInfo = Info->PrimaryVirtualBaseInfo;
if (Info == PrimaryVirtualBaseInfo->Derived)
UpdateEmptyBaseSubobjects(PrimaryVirtualBaseInfo, Offset);
@@ -363,19 +282,22 @@
if (!SizeOfLargestEmptySubobject)
return true;
+ // FIXME: Re-enable this.
+#if 0
BaseSubobjectInfo *Info;
-
+
if (BaseIsVirtual)
Info = VirtualBaseInfo.lookup(RD);
else
Info = NonVirtualBaseInfo.lookup(RD);
-
+
if (!CanPlaceBaseSubobjectAtOffset(Info, Offset))
return false;
// We are able to place the base at this offset. Make sure to update the
// empty base subobject map.
UpdateEmptyBaseSubobjects(Info, Offset);
+#endif
return true;
}
@@ -606,9 +528,29 @@
void LayoutWideBitField(uint64_t FieldSize, uint64_t TypeSize);
void LayoutBitField(const FieldDecl *D);
- /// ComputeEmptySubobjectSizes - Compute the size of the largest base or
- /// member subobject that is empty.
- void ComputeEmptySubobjectSizes(const CXXRecordDecl *RD);
+ /// BaseSubobjectInfoAllocator - Allocator for BaseSubobjectInfo objects.
+ llvm::SpecificBumpPtrAllocator<BaseSubobjectInfo> BaseSubobjectInfoAllocator;
+
+ typedef llvm::DenseMap<const CXXRecordDecl *, BaseSubobjectInfo *>
+ BaseSubobjectInfoMapTy;
+
+ /// VirtualBaseInfo - Map from all the (direct or indirect) virtual bases
+ /// of the class we're laying out to their base subobject info.
+ BaseSubobjectInfoMapTy VirtualBaseInfo;
+
+ /// NonVirtualBaseInfo - Map from all the direct non-virtual bases of the
+ /// class we're laying out to their base subobject info.
+ BaseSubobjectInfoMapTy NonVirtualBaseInfo;
+
+ /// ComputeBaseSubobjectInfo - Compute the base subobject information for the
+ /// bases of the given class.
+ void ComputeBaseSubobjectInfo(const CXXRecordDecl *RD);
+
+ /// ComputeBaseSubobjectInfo - Compute the base subobject information for a
+ /// single class and all of its base classes.
+ BaseSubobjectInfo *ComputeBaseSubobjectInfo(const CXXRecordDecl *RD,
+ bool IsVirtual,
+ BaseSubobjectInfo *Derived);
/// DeterminePrimaryBase - Determine the primary base of the given class.
void DeterminePrimaryBase(const CXXRecordDecl *RD);
@@ -815,14 +757,127 @@
UpdateAlignment(Context.Target.getPointerAlign(0));
}
+BaseSubobjectInfo *
+RecordLayoutBuilder::ComputeBaseSubobjectInfo(const CXXRecordDecl *RD,
+ bool IsVirtual,
+ BaseSubobjectInfo *Derived) {
+ BaseSubobjectInfo *Info;
+
+ if (IsVirtual) {
+ // Check if we already have info about this virtual base.
+ BaseSubobjectInfo *&InfoSlot = VirtualBaseInfo[RD];
+ if (InfoSlot) {
+ assert(InfoSlot->Class == RD && "Wrong class for virtual base info!");
+ return InfoSlot;
+ }
+
+ // We don't, create it.
+ InfoSlot = new (BaseSubobjectInfoAllocator.Allocate()) BaseSubobjectInfo;
+ Info = InfoSlot;
+ } else {
+ Info = new (BaseSubobjectInfoAllocator.Allocate()) BaseSubobjectInfo;
+ }
+
+ Info->Class = RD;
+ Info->IsVirtual = IsVirtual;
+ Info->Derived = 0;
+ Info->PrimaryVirtualBaseInfo = 0;
+
+ const CXXRecordDecl *PrimaryVirtualBase = 0;
+ BaseSubobjectInfo *PrimaryVirtualBaseInfo = 0;
+
+ // Check if this base has a primary virtual base.
+ if (RD->getNumVBases()) {
+ const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
+ if (Layout.getPrimaryBaseWasVirtual()) {
+ // This base does have a primary virtual base.
+ PrimaryVirtualBase = Layout.getPrimaryBase();
+ assert(PrimaryVirtualBase && "Didn't have a primary virtual base!");
+
+ // Now check if we have base subobject info about this primary base.
+ PrimaryVirtualBaseInfo = VirtualBaseInfo.lookup(PrimaryVirtualBase);
+
+ if (PrimaryVirtualBaseInfo) {
+ if (PrimaryVirtualBaseInfo->Derived) {
+ // We did have info about this primary base, and it turns out that it
+ // has already been claimed as a primary virtual base for another
+ // base.
+ PrimaryVirtualBase = 0;
+ } else {
+ // We can claim this base as our primary base.
+ Info->PrimaryVirtualBaseInfo = PrimaryVirtualBaseInfo;
+ PrimaryVirtualBaseInfo->Derived = Info;
+ }
+ }
+ }
+ }
+
+ // Now go through all direct bases.
+ for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(),
+ E = RD->bases_end(); I != E; ++I) {
+ bool IsVirtual = I->isVirtual();
+
+ const CXXRecordDecl *BaseDecl =
+ cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl());
+
+ Info->Bases.push_back(ComputeBaseSubobjectInfo(BaseDecl, IsVirtual, Info));
+ }
+
+ if (PrimaryVirtualBase && !PrimaryVirtualBaseInfo) {
+ // Traversing the bases must have created the base info for our primary
+ // virtual base.
+ PrimaryVirtualBaseInfo = VirtualBaseInfo.lookup(PrimaryVirtualBase);
+ assert(PrimaryVirtualBaseInfo &&
+ "Did not create a primary virtual base!");
+
+ // Claim the primary virtual base as our primary virtual base.
+ Info->PrimaryVirtualBaseInfo = PrimaryVirtualBaseInfo;
+ PrimaryVirtualBaseInfo->Derived = Info;
+ }
+
+ return Info;
+}
+
+void RecordLayoutBuilder::ComputeBaseSubobjectInfo(const CXXRecordDecl *RD) {
+ for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(),
+ E = RD->bases_end(); I != E; ++I) {
+ bool IsVirtual = I->isVirtual();
+
+ const CXXRecordDecl *BaseDecl =
+ cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl());
+
+ // Compute the base subobject info for this base.
+ BaseSubobjectInfo *Info = ComputeBaseSubobjectInfo(BaseDecl, IsVirtual, 0);
+
+ if (IsVirtual) {
+ // ComputeBaseInfo has already added this base for us.
+ assert(VirtualBaseInfo.count(BaseDecl) &&
+ "Did not add virtual base!");
+ } else {
+ // Add the base info to the map of non-virtual bases.
+ assert(!NonVirtualBaseInfo.count(BaseDecl) &&
+ "Non-virtual base already exists!");
+ NonVirtualBaseInfo.insert(std::make_pair(BaseDecl, Info));
+ }
+ }
+}
+
void
RecordLayoutBuilder::LayoutNonVirtualBases(const CXXRecordDecl *RD) {
- // First, determine the primary base class.
+ // Then, determine the primary base class.
DeterminePrimaryBase(RD);
+ // Compute base subobject info.
+ ComputeBaseSubobjectInfo(RD);
+
// If we have a primary base class, lay it out.
if (PrimaryBase) {
if (PrimaryBaseIsVirtual) {
+ // If the primary virtual base was a primary virtual base of some other
+ // base class we'll have to steal it.
+ BaseSubobjectInfo *PrimaryBaseInfo = VirtualBaseInfo.lookup(PrimaryBase);
+ PrimaryBaseInfo->Derived = 0;
+
// We have a virtual primary base, insert it as an indirect primary base.
IndirectPrimaryBases.insert(PrimaryBase);
More information about the cfe-commits
mailing list