]> granicus.if.org Git - clang/commitdiff
Add a SizeOfLargestEmptySubobject member to ASTRecordLayout. For C++ classes this...
authorAnders Carlsson <andersca@mac.com>
Sat, 8 May 2010 22:35:05 +0000 (22:35 +0000)
committerAnders Carlsson <andersca@mac.com>
Sat, 8 May 2010 22:35:05 +0000 (22:35 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@103359 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/AST/RecordLayout.h
lib/AST/RecordLayout.cpp
lib/AST/RecordLayoutBuilder.cpp
lib/AST/RecordLayoutBuilder.h

index e78476ef51bb8a72539ccc3002ee3bb26717ba80..0b05614a193bad03f2f343d70bb1183cf9e91956 100644 (file)
@@ -109,6 +109,11 @@ private:
     /// which is the alignment of the object without virtual bases.
     uint64_t NonVirtualAlign;
 
+    /// SizeOfLargestEmptySubobject - The size of the largest empty subobject
+    /// (either a base or a member). Will be zero if the class doesn't contain
+    /// any empty subobjects.
+    uint64_t SizeOfLargestEmptySubobject;
+    
     /// PrimaryBase - The primary base info for this record.
     PrimaryBaseInfo PrimaryBase;
     
@@ -139,6 +144,7 @@ private:
                   uint64_t size, unsigned alignment, uint64_t datasize,
                   const uint64_t *fieldoffsets, unsigned fieldcount,
                   uint64_t nonvirtualsize, unsigned nonvirtualalign,
+                  uint64_t SizeOfLargestEmptySubobject,
                   const PrimaryBaseInfo &PrimaryBase,
                   const BaseOffsetsMapTy& BaseOffsets,
                   const BaseOffsetsMapTy& VBaseOffsets);
index ade2483722ef819ddab760d429e6225de4ef8bd1..2cf7e4a1cb390da13d9cc173b794ebd60454099c 100644 (file)
@@ -44,6 +44,7 @@ ASTRecordLayout::ASTRecordLayout(ASTContext &Ctx,
                                  unsigned fieldcount,
                                  uint64_t nonvirtualsize,
                                  unsigned nonvirtualalign,
+                                 uint64_t SizeOfLargestEmptySubobject,
                                  const PrimaryBaseInfo &PrimaryBase,
                                  const BaseOffsetsMapTy& BaseOffsets,
                                  const BaseOffsetsMapTy& VBaseOffsets)
@@ -58,6 +59,7 @@ ASTRecordLayout::ASTRecordLayout(ASTContext &Ctx,
   CXXInfo->PrimaryBase = PrimaryBase;
   CXXInfo->NonVirtualSize = nonvirtualsize;
   CXXInfo->NonVirtualAlign = nonvirtualalign;
+  CXXInfo->SizeOfLargestEmptySubobject = SizeOfLargestEmptySubobject;
   CXXInfo->BaseOffsets = BaseOffsets;
   CXXInfo->VBaseOffsets = VBaseOffsets;
 
index 3782985e53029edcc62a47882bce51998a17f679..745e68f38f199dedcbce0b11c2d4fdc83733b057 100644 (file)
@@ -24,7 +24,8 @@ using namespace clang;
 ASTRecordLayoutBuilder::ASTRecordLayoutBuilder(ASTContext &Context)
   : Context(Context), Size(0), Alignment(8), Packed(false), 
   UnfilledBitsInLastByte(0), MaxFieldAlignment(0), DataSize(0), IsUnion(false),
-  NonVirtualSize(0), NonVirtualAlignment(8), FirstNearlyEmptyVBase(0) { }
+  SizeOfLargestEmptySubobject(0), NonVirtualSize(0), NonVirtualAlignment(8),
+  FirstNearlyEmptyVBase(0) { }
 
 /// IsNearlyEmpty - Indicates when a class has a vtable pointer, but
 /// no other data.
@@ -321,19 +322,19 @@ void ASTRecordLayoutBuilder::LayoutVirtualBase(const CXXRecordDecl *RD) {
 }
 
 uint64_t ASTRecordLayoutBuilder::LayoutBase(const CXXRecordDecl *RD) {
-  const ASTRecordLayout &BaseInfo = Context.getASTRecordLayout(RD);
+  const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
 
   // If we have an empty base class, try to place it at offset 0.
   if (RD->isEmpty() && canPlaceRecordAtOffset(RD, 0)) {
     // We were able to place the class at offset 0.
     UpdateEmptyClassOffsets(RD, 0);
 
-    Size = std::max(Size, BaseInfo.getSize());
+    Size = std::max(Size, Layout.getSize());
 
     return 0;
   }
 
-  unsigned BaseAlign = BaseInfo.getNonVirtualAlign();
+  unsigned BaseAlign = Layout.getNonVirtualAlign();
 
   // Round up the current record size to the base's alignment boundary.
   uint64_t Offset = llvm::RoundUpToAlignment(DataSize, BaseAlign);
@@ -348,11 +349,11 @@ uint64_t ASTRecordLayoutBuilder::LayoutBase(const CXXRecordDecl *RD) {
 
   if (!RD->isEmpty()) {
     // Update the data size.
-    DataSize = Offset + BaseInfo.getNonVirtualSize();
+    DataSize = Offset + Layout.getNonVirtualSize();
 
     Size = std::max(Size, DataSize);
   } else
-    Size = std::max(Size, Offset + BaseInfo.getSize());
+    Size = std::max(Size, Offset + Layout.getSize());
 
   // Remember max struct/class alignment.
   UpdateAlignment(BaseAlign);
@@ -424,7 +425,7 @@ bool ASTRecordLayoutBuilder::canPlaceFieldAtOffset(const FieldDecl *FD,
     if (!RD)
       return true;
 
-    const ASTRecordLayout &Info = Context.getASTRecordLayout(RD);
+    const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
 
     uint64_t NumElements = Context.getConstantArrayElementCount(AT);
     uint64_t ElementOffset = Offset;
@@ -432,7 +433,7 @@ bool ASTRecordLayoutBuilder::canPlaceFieldAtOffset(const FieldDecl *FD,
       if (!canPlaceRecordAtOffset(RD, ElementOffset))
         return false;
 
-      ElementOffset += Info.getSize();
+      ElementOffset += Layout.getSize();
     }
   }
 
@@ -444,7 +445,7 @@ void ASTRecordLayoutBuilder::UpdateEmptyClassOffsets(const CXXRecordDecl *RD,
   if (RD->isEmpty())
     EmptyClassOffsets.insert(std::make_pair(Offset, RD));
 
-  const ASTRecordLayout &Info = Context.getASTRecordLayout(RD);
+  const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
 
   // Update bases.
   for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(),
@@ -457,7 +458,7 @@ void ASTRecordLayoutBuilder::UpdateEmptyClassOffsets(const CXXRecordDecl *RD,
     const CXXRecordDecl *Base =
       cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl());
 
-    uint64_t BaseClassOffset = Info.getBaseClassOffset(Base);
+    uint64_t BaseClassOffset = Layout.getBaseClassOffset(Base);
     UpdateEmptyClassOffsets(Base, Offset + BaseClassOffset);
   }
 
@@ -467,7 +468,7 @@ void ASTRecordLayoutBuilder::UpdateEmptyClassOffsets(const CXXRecordDecl *RD,
        I != E; ++I, ++FieldNo) {
     const FieldDecl *FD = *I;
 
-    uint64_t FieldOffset = Info.getFieldOffset(FieldNo);
+    uint64_t FieldOffset = Layout.getFieldOffset(FieldNo);
     UpdateEmptyClassOffsets(FD, Offset + FieldOffset);
   }
 
@@ -838,6 +839,7 @@ ASTRecordLayoutBuilder::ComputeLayout(ASTContext &Ctx,
                                    Builder.FieldOffsets.size(),
                                    NonVirtualSize,
                                    Builder.NonVirtualAlignment,
+                                   Builder.SizeOfLargestEmptySubobject,
                                    Builder.PrimaryBase,
                                    Builder.Bases, Builder.VBases);
 }
index f277c29398b336604e81e39f3c7fb86b7eb87aab..acbee9e1dc6a644adbfc07a74bbb69b9ef73028f 100644 (file)
@@ -78,6 +78,11 @@ class ASTRecordLayoutBuilder {
   /// avoid visiting virtual bases more than once.
   llvm::SmallPtrSet<const CXXRecordDecl *, 4> VisitedVirtualBases;
   
+  /// SizeOfLargestEmptySubobject - When laying out C++ classes, this holds the
+  /// size of the largest empty subobject (either a base or a member).
+  /// Will be zero if the record being built doesn't contain any empty classes.
+  uint64_t SizeOfLargestEmptySubobject;
+  
   /// EmptyClassOffsets - A map from offsets to empty record decls.
   typedef std::multimap<uint64_t, const CXXRecordDecl *> EmptyClassOffsetsTy;
   EmptyClassOffsetsTy EmptyClassOffsets;