[cfe-commits] r104787 - /cfe/trunk/lib/AST/RecordLayoutBuilder.cpp

Anders Carlsson andersca at mac.com
Wed May 26 17:07:01 PDT 2010


Author: andersca
Date: Wed May 26 19:07:01 2010
New Revision: 104787

URL: http://llvm.org/viewvc/llvm-project?rev=104787&view=rev
Log:
More work on the empty subobjects map.

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=104787&r1=104786&r2=104787&view=diff
==============================================================================
--- cfe/trunk/lib/AST/RecordLayoutBuilder.cpp (original)
+++ cfe/trunk/lib/AST/RecordLayoutBuilder.cpp Wed May 26 19:07:01 2010
@@ -42,8 +42,16 @@
   uint64_t SizeOfLargestEmptySubobject;
   
   EmptySubobjectMap(ASTContext &Context, const CXXRecordDecl *Class)
-    : Context(Context), Class(Class), SizeOfLargestEmptySubobject(0) { }
-                    
+    : Context(Context), Class(Class), SizeOfLargestEmptySubobject(0) {
+      ComputeEmptySubobjectSizes();
+  }
+
+  /// CanPlaceBaseAtOffset - Return whether the given base class can be placed
+  /// at the given offset.
+  /// Returns false if placing the record will result in two components 
+  /// (direct or indirect) of the same type having the same offset.
+  bool CanPlaceBaseAtOffset(const CXXRecordDecl *RD, bool BaseIsVirtual,
+                            uint64_t Offset);
 };
 
 void EmptySubobjectMap::ComputeEmptySubobjectSizes() {
@@ -95,6 +103,18 @@
   }
 }
 
+bool 
+EmptySubobjectMap::CanPlaceBaseAtOffset(const CXXRecordDecl *RD, 
+                                        bool BaseIsVirtual,
+                                        uint64_t Offset) {
+  // If we know this class doesn't have any empty subobjects we don't need to
+  // bother checking.
+  if (!SizeOfLargestEmptySubobject)
+    return true;
+
+  return true;
+}
+
 class RecordLayoutBuilder {
   // FIXME: Remove this and make the appropriate fields public.
   friend class clang::ASTContext;
@@ -163,8 +183,8 @@
   typedef std::multimap<uint64_t, const CXXRecordDecl *> EmptyClassOffsetsTy;
   EmptyClassOffsetsTy EmptyClassOffsets;
   
-  RecordLayoutBuilder(ASTContext &Context)
-    : Context(Context), EmptySubobjects(0), Size(0), Alignment(8),
+  RecordLayoutBuilder(ASTContext &Context, EmptySubobjectMap *EmptySubobjects)
+    : Context(Context), EmptySubobjects(EmptySubobjects), Size(0), Alignment(8),
     Packed(false), UnfilledBitsInLastByte(0), MaxFieldAlignment(0), DataSize(0), 
     IsUnion(false), NonVirtualSize(0), NonVirtualAlignment(8), PrimaryBase(0), 
     PrimaryBaseIsVirtual(false), FirstNearlyEmptyVBase(0) { }
@@ -199,7 +219,7 @@
   void LayoutNonVirtualBases(const CXXRecordDecl *RD);
 
   /// LayoutNonVirtualBase - Lays out a single non-virtual base.
-  void LayoutNonVirtualBase(const CXXRecordDecl *RD);
+  void LayoutNonVirtualBase(const CXXRecordDecl *Base);
 
   void AddPrimaryVirtualBaseOffsets(const CXXRecordDecl *RD, uint64_t Offset,
                                     const CXXRecordDecl *MostDerivedClass);
@@ -209,11 +229,11 @@
                           const CXXRecordDecl *MostDerivedClass);
 
   /// LayoutVirtualBase - Lays out a single virtual base.
-  void LayoutVirtualBase(const CXXRecordDecl *RD);
+  void LayoutVirtualBase(const CXXRecordDecl *Base);
 
   /// LayoutBase - Will lay out a base and return the offset where it was 
   /// placed, in bits.
-  uint64_t LayoutBase(const CXXRecordDecl *RD);
+  uint64_t LayoutBase(const CXXRecordDecl *Base, bool BaseIsVirtual);
 
   /// canPlaceRecordAtOffset - Return whether a record (either a base class
   /// or a field) can be placed at the given offset. 
@@ -250,10 +270,6 @@
   void operator=(const RecordLayoutBuilder&); // DO NOT IMPLEMENT
 public:
   static const CXXMethodDecl *ComputeKeyFunction(const CXXRecordDecl *RD);
-  
-  uint64_t getSizeOfLargestEmptySubobject() {
-    return EmptySubobjects->SizeOfLargestEmptySubobject;
-  }
 };
 } // end anonymous namespace
 
@@ -431,12 +447,12 @@
   }
 }
 
-void RecordLayoutBuilder::LayoutNonVirtualBase(const CXXRecordDecl *RD) {
+void RecordLayoutBuilder::LayoutNonVirtualBase(const CXXRecordDecl *Base) {
   // Layout the base.
-  uint64_t Offset = LayoutBase(RD);
+  uint64_t Offset = LayoutBase(Base, /*BaseIsVirtual=*/false);
 
   // Add its base class offset.
-  if (!Bases.insert(std::make_pair(RD, Offset)).second)
+  if (!Bases.insert(std::make_pair(Base, Offset)).second)
     assert(false && "Added same base offset more than once!");
 }
 
@@ -544,22 +560,25 @@
   }
 }
 
-void RecordLayoutBuilder::LayoutVirtualBase(const CXXRecordDecl *RD) {
+void RecordLayoutBuilder::LayoutVirtualBase(const CXXRecordDecl *Base) {
   // Layout the base.
-  uint64_t Offset = LayoutBase(RD);
+  uint64_t Offset = LayoutBase(Base, /*BaseIsVirtual=*/true);
 
   // Add its base class offset.
-  if (!VBases.insert(std::make_pair(RD, Offset)).second)
+  if (!VBases.insert(std::make_pair(Base, Offset)).second)
     assert(false && "Added same vbase offset more than once!");
 }
 
-uint64_t RecordLayoutBuilder::LayoutBase(const CXXRecordDecl *RD) {
-  const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
+uint64_t RecordLayoutBuilder::LayoutBase(const CXXRecordDecl *Base,
+                                         bool BaseIsVirtual) {
+  const ASTRecordLayout &Layout = Context.getASTRecordLayout(Base);
 
   // If we have an empty base class, try to place it at offset 0.
-  if (RD->isEmpty() && canPlaceRecordAtOffset(RD, 0, /*CheckVBases=*/false)) {
+  if (Base->isEmpty() && 
+      EmptySubobjects->CanPlaceBaseAtOffset(Base, BaseIsVirtual, 0) &&
+      canPlaceRecordAtOffset(Base, 0, /*CheckVBases=*/false)) {
     // We were able to place the class at offset 0.
-    UpdateEmptyClassOffsets(RD, 0, /*UpdateVBases=*/false);
+    UpdateEmptyClassOffsets(Base, 0, /*UpdateVBases=*/false);
 
     Size = std::max(Size, Layout.getSize());
 
@@ -573,13 +592,14 @@
 
   // Try to place the base.
   while (true) {
-    if (canPlaceRecordAtOffset(RD, Offset, /*CheckVBases=*/false))
+    if (EmptySubobjects->CanPlaceBaseAtOffset(Base, BaseIsVirtual, Offset) &&
+        canPlaceRecordAtOffset(Base, Offset, /*CheckVBases=*/false))
       break;
 
     Offset += BaseAlign;
   }
 
-  if (!RD->isEmpty()) {
+  if (!Base->isEmpty()) {
     // Update the data size.
     DataSize = Offset + Layout.getNonVirtualSize();
 
@@ -590,7 +610,7 @@
   // Remember max struct/class alignment.
   UpdateAlignment(BaseAlign);
 
-  UpdateEmptyClassOffsets(RD, Offset, /*UpdateVBases=*/false);
+  UpdateEmptyClassOffsets(Base, Offset, /*UpdateVBases=*/false);
   return Offset;
 }
 
@@ -1125,7 +1145,8 @@
   const ASTRecordLayout *NewEntry;
 
   if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D)) {
-    RecordLayoutBuilder Builder(*this);
+    EmptySubobjectMap EmptySubobjects(*this, RD);
+    RecordLayoutBuilder Builder(*this, &EmptySubobjects);
     Builder.Layout(RD);
 
     // FIXME: This is not always correct. See the part about bitfields at
@@ -1145,12 +1166,12 @@
                                   Builder.FieldOffsets.size(),
                                   NonVirtualSize,
                                   Builder.NonVirtualAlignment,
-                                  Builder.getSizeOfLargestEmptySubobject(),
+                                  EmptySubobjects.SizeOfLargestEmptySubobject,
                                   Builder.PrimaryBase,
                                   Builder.PrimaryBaseIsVirtual,
                                   Builder.Bases, Builder.VBases);
   } else {
-    RecordLayoutBuilder Builder(*this);
+    RecordLayoutBuilder Builder(*this, /*EmptySubobjects=*/0);
     Builder.Layout(D);
   
     NewEntry =
@@ -1211,7 +1232,7 @@
       return getObjCLayout(D, 0);
   }
 
-  RecordLayoutBuilder Builder(*this);
+  RecordLayoutBuilder Builder(*this, /*EmptySubobjects=*/0);
   Builder.Layout(D);
 
   const ASTRecordLayout *NewEntry =





More information about the cfe-commits mailing list