]> granicus.if.org Git - clang/commitdiff
Actually compute the empty subobject sizes. No functionality change yet.
authorAnders Carlsson <andersca@mac.com>
Sat, 8 May 2010 23:06:26 +0000 (23:06 +0000)
committerAnders Carlsson <andersca@mac.com>
Sat, 8 May 2010 23:06:26 +0000 (23:06 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@103363 91177308-0d34-0410-b5e6-96231b3b80d8

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

index 0b05614a193bad03f2f343d70bb1183cf9e91956..817f0384357970fd6bc7c1dfce6996df277e9ea2 100644 (file)
@@ -228,6 +228,11 @@ public:
     return CXXInfo->VBaseOffsets[VBase];
   }
   
+  uint64_t getSizeOfLargestEmptySubobject() const {
+    assert(CXXInfo && "Record layout does not have C++ specific info!");
+    return CXXInfo->SizeOfLargestEmptySubobject;
+  }
+
   primary_base_info_iterator primary_base_begin() const {
     assert(CXXInfo && "Record layout does not have C++ specific info!");
   
index 745e68f38f199dedcbce0b11c2d4fdc83733b057..2d4b769735549819f43dbc1e8890d8ae981c615a 100644 (file)
@@ -24,8 +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),
-  SizeOfLargestEmptySubobject(0), NonVirtualSize(0), NonVirtualAlignment(8),
-  FirstNearlyEmptyVBase(0) { }
+  NonVirtualSize(0), NonVirtualAlignment(8), FirstNearlyEmptyVBase(0),
+  SizeOfLargestEmptySubobject(0) { }
 
 /// IsNearlyEmpty - Indicates when a class has a vtable pointer, but
 /// no other data.
@@ -39,6 +39,56 @@ bool ASTRecordLayoutBuilder::IsNearlyEmpty(const CXXRecordDecl *RD) const {
   return false;
 }
 
+void 
+ASTRecordLayoutBuilder::ComputeEmptySubobjectSizes(const CXXRecordDecl *RD) {
+  // Check the bases.
+  for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(),
+       E = RD->bases_end(); I != E; ++I) {
+    const CXXRecordDecl *BaseDecl =
+      cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl());
+
+    uint64_t EmptySize = 0;
+    const ASTRecordLayout &Layout = Context.getASTRecordLayout(BaseDecl);
+    if (BaseDecl->isEmpty()) {
+      // If the class decl is empty, get its size.
+      EmptySize = Layout.getSize();
+    } else {
+      // Otherwise, we get the largest empty subobject for the decl.
+      EmptySize = Layout.getSizeOfLargestEmptySubobject();
+    }
+    
+    SizeOfLargestEmptySubobject = std::max(SizeOfLargestEmptySubobject, 
+                                           EmptySize);
+  }
+
+  // Check the fields.
+  for (CXXRecordDecl::field_iterator I = RD->field_begin(), E = RD->field_end();
+       I != E; ++I) {
+    const FieldDecl *FD = *I;
+    
+    const RecordType *RT = 
+      Context.getBaseElementType(FD->getType())->getAs<RecordType>();
+    
+    // We only care about record types.
+    if (!RT)
+      continue;
+
+    uint64_t EmptySize = 0;
+    const CXXRecordDecl *MemberDecl = cast<CXXRecordDecl>(RT->getDecl());
+    const ASTRecordLayout &Layout = Context.getASTRecordLayout(MemberDecl);
+    if (MemberDecl->isEmpty()) {
+      // If the class decl is empty, get its size.
+      EmptySize = Layout.getSize();
+    } else {
+      // Otherwise, we get the largest empty subobject for the decl.
+      EmptySize = Layout.getSizeOfLargestEmptySubobject();
+    }
+      
+   SizeOfLargestEmptySubobject = std::max(SizeOfLargestEmptySubobject, 
+                                          EmptySize);
+  }
+}
+
 void ASTRecordLayoutBuilder::IdentifyPrimaryBases(const CXXRecordDecl *RD) {
   const ASTRecordLayout::PrimaryBaseInfo &BaseInfo =
     Context.getASTRecordLayout(RD).getPrimaryBaseInfo();
@@ -522,8 +572,10 @@ void ASTRecordLayoutBuilder::Layout(const RecordDecl *D) {
 
   // If this is a C++ class, lay out the vtable and the non-virtual bases.
   const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D);
-  if (RD)
+  if (RD) {
+    ComputeEmptySubobjectSizes(RD);
     LayoutNonVirtualBases(RD);
+  }
 
   LayoutFields(D);
 
index acbee9e1dc6a644adbfc07a74bbb69b9ef73028f..f3da315ead886fd78d8d2cad5a62aa2cf148f3ca 100644 (file)
@@ -77,7 +77,7 @@ class ASTRecordLayoutBuilder {
   /// VisitedVirtualBases - A set of all the visited virtual bases, used to
   /// 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.
@@ -99,6 +99,10 @@ class ASTRecordLayoutBuilder {
   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);
+
   /// DeterminePrimaryBase - Determine the primary base of the given class.
   void DeterminePrimaryBase(const CXXRecordDecl *RD);