[cfe-commits] r98208 - in /cfe/trunk/lib/AST: RecordLayoutBuilder.cpp RecordLayoutBuilder.h

Anders Carlsson andersca at mac.com
Wed Mar 10 16:15:36 PST 2010


Author: andersca
Date: Wed Mar 10 18:15:35 2010
New Revision: 98208

URL: http://llvm.org/viewvc/llvm-project?rev=98208&view=rev
Log:
More cleanup and simplification of the record layout builder.

Modified:
    cfe/trunk/lib/AST/RecordLayoutBuilder.cpp
    cfe/trunk/lib/AST/RecordLayoutBuilder.h

Modified: cfe/trunk/lib/AST/RecordLayoutBuilder.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/RecordLayoutBuilder.cpp?rev=98208&r1=98207&r2=98208&view=diff
==============================================================================
--- cfe/trunk/lib/AST/RecordLayoutBuilder.cpp (original)
+++ cfe/trunk/lib/AST/RecordLayoutBuilder.cpp Wed Mar 10 18:15:35 2010
@@ -23,23 +23,7 @@
 ASTRecordLayoutBuilder::ASTRecordLayoutBuilder(ASTContext &Ctx)
   : Ctx(Ctx), Size(0), Alignment(8), Packed(false), UnfilledBitsInLastByte(0),
   MaxFieldAlignment(0), DataSize(0), IsUnion(false), NonVirtualSize(0), 
-  NonVirtualAlignment(8) { }
-
-/// LayoutVtable - Lay out the vtable and set PrimaryBase.
-void ASTRecordLayoutBuilder::LayoutVtable(const CXXRecordDecl *RD) {
-  if (!RD->isDynamicClass()) {
-    // There is no primary base in this case.
-    return;
-  }
-
-  SelectPrimaryBase(RD);
-  if (!PrimaryBase.getBase()) {
-    int AS = 0;
-    UpdateAlignment(Ctx.Target.getPointerAlign(AS));
-    Size += Ctx.Target.getPointerWidth(AS);
-    DataSize = Size;
-  }
-}
+  NonVirtualAlignment(8), FirstNearlyEmptyVBase(0) { }
 
 /// IsNearlyEmpty - Indicates when a class has a vtable pointer, but
 /// no other data.
@@ -78,8 +62,8 @@
 }
 
 void
-ASTRecordLayoutBuilder::SelectPrimaryVBase(const CXXRecordDecl *RD,
-                                           const CXXRecordDecl *&FirstPrimary) {
+ASTRecordLayoutBuilder::SelectPrimaryVBase(const CXXRecordDecl *RD) {
+
   for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(),
          e = RD->bases_end(); i != e; ++i) {
     assert(!i->getType()->isDependentType() &&
@@ -87,35 +71,42 @@
     const CXXRecordDecl *Base =
       cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
     if (!i->isVirtual()) {
-      SelectPrimaryVBase(Base, FirstPrimary);
+      SelectPrimaryVBase(Base);
       if (PrimaryBase.getBase())
         return;
       continue;
     }
     if (IsNearlyEmpty(Base)) {
-      if (FirstPrimary==0)
-        FirstPrimary = Base;
+      // Is this the first nearly empty primary virtual base?
+      if (!FirstNearlyEmptyVBase)
+        FirstNearlyEmptyVBase = Base;
+
       if (!IndirectPrimaryBases.count(Base)) {
-        setPrimaryBase(Base, /*IsVirtual=*/true);
+        PrimaryBase = ASTRecordLayout::PrimaryBaseInfo(Base,
+                                                       /*IsVirtual=*/true);
         return;
       }
     }
+    
     assert(i->isVirtual());
-    SelectPrimaryVBase(Base, FirstPrimary);
+    SelectPrimaryVBase(Base);
     if (PrimaryBase.getBase())
       return;
   }
 }
 
-/// SelectPrimaryBase - Selects the primary base for the given class and
-/// record that with setPrimaryBase.  We also calculate the IndirectPrimaries.
-void ASTRecordLayoutBuilder::SelectPrimaryBase(const CXXRecordDecl *RD) {
+/// DeterminePrimaryBase - Determine the primary base of the given class.
+void ASTRecordLayoutBuilder::DeterminePrimaryBase(const CXXRecordDecl *RD) {
+  // If the class isn't dynamic, it won't have a primary base.
+  if (!RD->isDynamicClass())
+    return;
+  
   // Compute all the primary virtual bases for all of our direct and
   // indirect bases, and record all their primary virtual base classes.
   for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(),
        e = RD->bases_end(); i != e; ++i) {
     assert(!i->getType()->isDependentType() &&
-           "Cannot layout class with dependent bases.");
+           "Cannot lay out class with dependent bases.");
     const CXXRecordDecl *Base =
       cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
     IdentifyPrimaryBases(Base);
@@ -142,20 +133,32 @@
 
   // Otherwise, it is the first nearly empty virtual base that is not an
   // indirect primary virtual base class, if one exists.
+  if (RD->getNumVBases() != 0) {
+    SelectPrimaryVBase(RD);
+    if (PrimaryBase.getBase())
+      return;
+  }
 
-  // If we have no virtual bases at this point, bail out as the searching below
-  // is expensive.
-  if (RD->getNumVBases() == 0)
+  // Otherwise, it is the first nearly empty virtual base that is not an
+  // indirect primary virtual base class, if one exists.
+  if (FirstNearlyEmptyVBase) {
+    PrimaryBase = 
+      ASTRecordLayout::PrimaryBaseInfo(FirstNearlyEmptyVBase, /*IsVirtual=*/true);
     return;
+  }
   
-  // Then we can search for the first nearly empty virtual base itself.
-  const CXXRecordDecl *FirstPrimary = 0;
-  SelectPrimaryVBase(RD, FirstPrimary);
-
-  // Otherwise if is the first nearly empty virtual base, if one exists,
-  // otherwise there is no primary base class.
-  if (!PrimaryBase.getBase())
-    setPrimaryBase(FirstPrimary, /*IsVirtual=*/true);
+  // Otherwise there is no primary base class.
+  assert(!PrimaryBase.getBase() && "Should not get here with a primary base!");
+
+  // Allocate the virtual table pointer at offset zero.
+  assert(DataSize == 0 && "Vtable pointer must be at offset zero!");
+           
+  // Update the size.
+  Size += Ctx.Target.getPointerWidth(0);
+  DataSize = Size;
+
+  // Update the alignment.
+  UpdateAlignment(Ctx.Target.getPointerAlign(0));
 }
 
 uint64_t ASTRecordLayoutBuilder::getBaseOffset(const CXXRecordDecl *Base) {
@@ -173,19 +176,38 @@
 
 void
 ASTRecordLayoutBuilder::LayoutNonVirtualBases(const CXXRecordDecl *RD) {
-  for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(),
-       e = RD->bases_end(); i != e; ++i) {
-    if (!i->isVirtual()) {
-      assert(!i->getType()->isDependentType() &&
-             "Cannot layout class with dependent bases.");
-      const CXXRecordDecl *Base =
-      cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
-      // Skip the PrimaryBase here, as it is laid down first.
-      if (Base != PrimaryBase.getBase() || PrimaryBase.isVirtual()) {
-        // Lay out the base.
-        LayoutNonVirtualBase(Base);
-      }
-    }
+  // First, determine the primary base class.
+  DeterminePrimaryBase(RD);
+  
+  // If we have a primary base class, lay it out.
+  if (const CXXRecordDecl *Base = PrimaryBase.getBase()) {
+    printf("found primary base %s\n", Base->getQualifiedNameAsString().c_str());
+    if (PrimaryBase.isVirtual()) {
+      // We have a virtual primary base, insert it as an indirect primary base.
+      IndirectPrimaryBases.insert(Base);
+      
+      LayoutVirtualBase(Base);
+    } else
+      LayoutNonVirtualBase(Base);
+  }
+  
+  // Now lay out the non-virtual bases.
+  for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(),
+       E = RD->bases_end(); I != E; ++I) {
+
+    // Ignore virtual bases.
+    if (I->isVirtual())
+      continue;
+
+    const CXXRecordDecl *Base =
+      cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl());
+
+    // Skip the primary base.
+    if (Base == PrimaryBase.getBase() && !PrimaryBase.isVirtual())
+      continue;
+
+    // Lay out the base.
+    LayoutNonVirtualBase(Base);
   }
 }
 
@@ -458,20 +480,8 @@
 
   // If this is a C++ class, lay out the vtable and the non-virtual bases.
   const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D);
-  if (RD) {
-    LayoutVtable(RD);
-    // PrimaryBase goes first.
-    if (PrimaryBase.getBase()) {
-      if (PrimaryBase.isVirtual()) {
-        IndirectPrimaryBases.insert(PrimaryBase.getBase());
-        
-        LayoutVirtualBase(PrimaryBase.getBase());
-      } else {
-        LayoutNonVirtualBase(PrimaryBase.getBase());
-      }
-    }
+  if (RD)
     LayoutNonVirtualBases(RD);
-  }
 
   LayoutFields(D);
 

Modified: cfe/trunk/lib/AST/RecordLayoutBuilder.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/RecordLayoutBuilder.h?rev=98208&r1=98207&r2=98208&view=diff
==============================================================================
--- cfe/trunk/lib/AST/RecordLayoutBuilder.h (original)
+++ cfe/trunk/lib/AST/RecordLayoutBuilder.h Wed Mar 10 18:15:35 2010
@@ -56,6 +56,8 @@
   uint64_t NonVirtualSize;
   unsigned NonVirtualAlignment;
   
+  /// PrimaryBase - the primary base class (if one exists) of the class
+  /// we're laying out.
   ASTRecordLayout::PrimaryBaseInfo PrimaryBase;
 
   typedef llvm::SmallVector<std::pair<const CXXRecordDecl *, 
@@ -71,6 +73,10 @@
   /// primary base classes for some other direct or indirect base class.
   llvm::SmallSet<const CXXRecordDecl*, 32> IndirectPrimaryBases;
   
+  /// FirstNearlyEmptyVBase - The first nearly empty virtual base class in
+  /// inheritance graph order. Used for determining the primary base class.
+  const CXXRecordDecl *FirstNearlyEmptyVBase;
+
   /// EmptyClassOffsets - A map from offsets to empty record decls.
   typedef std::multimap<uint64_t, const CXXRecordDecl *> EmptyClassOffsetsTy;
   EmptyClassOffsetsTy EmptyClassOffsets;
@@ -86,19 +92,16 @@
   void LayoutField(const FieldDecl *D);
   void LayoutBitField(const FieldDecl *D);
 
-  void SelectPrimaryBase(const CXXRecordDecl *RD);
-  void SelectPrimaryVBase(const CXXRecordDecl *RD,
-                          const CXXRecordDecl *&FirstPrimary);
+  /// DeterminePrimaryBase - Determine the primary base of the given class.
+  void DeterminePrimaryBase(const CXXRecordDecl *RD);
+
+  void SelectPrimaryVBase(const CXXRecordDecl *RD);
   
   /// IdentifyPrimaryBases - Identify all virtual base classes, direct or 
   /// indirect, that are primary base classes for some other direct or indirect 
   /// base class.
   void IdentifyPrimaryBases(const CXXRecordDecl *RD);
   
-  void setPrimaryBase(const CXXRecordDecl *Base, bool IsVirtual) {
-    PrimaryBase = ASTRecordLayout::PrimaryBaseInfo(Base, IsVirtual);
-  }
-  
   bool IsNearlyEmpty(const CXXRecordDecl *RD) const;
   
   /// LayoutNonVirtualBases - Determines the primary base class (if any) and 
@@ -120,8 +123,6 @@
   /// LayoutBase - Will lay out a base and return the offset where it was 
   /// placed, in bits.
   uint64_t LayoutBase(const CXXRecordDecl *RD);
-  
-  void LayoutVtable(const CXXRecordDecl *RD);
 
   /// canPlaceRecordAtOffset - Return whether a record (either a base class
   /// or a field) can be placed at the given offset. 





More information about the cfe-commits mailing list