[cfe-commits] r77352 - in /cfe/trunk: include/clang/AST/RecordLayout.h lib/AST/RecordLayoutBuilder.cpp lib/AST/RecordLayoutBuilder.h

Anders Carlsson andersca at mac.com
Tue Jul 28 12:24:15 PDT 2009


Author: andersca
Date: Tue Jul 28 14:24:15 2009
New Revision: 77352

URL: http://llvm.org/viewvc/llvm-project?rev=77352&view=rev
Log:
Add a field for C++ specific data to ASTRecordLayout. Use it to store the non-virtual size and alignment + base offsets.

Modified:
    cfe/trunk/include/clang/AST/RecordLayout.h
    cfe/trunk/lib/AST/RecordLayoutBuilder.cpp
    cfe/trunk/lib/AST/RecordLayoutBuilder.h

Modified: cfe/trunk/include/clang/AST/RecordLayout.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/RecordLayout.h?rev=77352&r1=77351&r2=77352&view=diff

==============================================================================
--- cfe/trunk/include/clang/AST/RecordLayout.h (original)
+++ cfe/trunk/include/clang/AST/RecordLayout.h Tue Jul 28 14:24:15 2009
@@ -20,6 +20,7 @@
   class ASTContext;
   class FieldDecl;
   class RecordDecl;
+  class CXXRecordDecl;
 
 /// ASTRecordLayout - 
 /// This class contains layout information for one RecordDecl,
@@ -29,26 +30,78 @@
 /// ObjCInterfaceDecl. FIXME - Find appropriate name.
 /// These objects are managed by ASTContext.
 class ASTRecordLayout {
-  uint64_t Size;        // Size of record in bits.
-  uint64_t DataSize;    // Size of record in bits without tail padding.
+  /// Size - Size of record in bits.
+  uint64_t Size;
+  
+  /// DataSize - Size of record in bits without tail padding.
+  uint64_t DataSize;
+  
+  /// FieldOffsets - Array of field offsets in bits.
   uint64_t *FieldOffsets;
-  unsigned Alignment;   // Alignment of record in bits.
-  unsigned FieldCount;  // Number of fields
+  
+  // Alignment - Alignment of record in bits.
+  unsigned Alignment;   
+  
+  // FieldCount - Number of fields.
+  unsigned FieldCount;
+
+  struct CXXRecordLayoutInfo {
+    /// NonVirtualSize - The non-virtual size (in bits) of an object, which is 
+    /// the size of the object without virtual bases.
+    uint64_t NonVirtualSize;
+    
+    /// NonVirtualAlign - The non-virtual alignment (in bits) of an object,
+    /// which is the alignment of the object without virtual bases.
+    uint64_t NonVirtualAlign;
+    
+    /// BaseOffsets - Contains a map from base classes to their offset.
+    /// FIXME: Does it make sense to store offsets for virtual base classes
+    /// here?
+    /// FIXME: This should really use a SmallPtrMap, once we have one in LLVM :)
+    llvm::DenseMap<const CXXRecordDecl *, uint64_t> BaseOffsets;
+  };
+  
+  /// CXXInfo - If the record layout is for a C++ record, this will have 
+  /// C++ specific information about the record.
+  CXXRecordLayoutInfo *CXXInfo;
+  
   friend class ASTContext;
   friend class ASTRecordLayoutBuilder;
 
   ASTRecordLayout(uint64_t size, unsigned alignment, unsigned datasize,
                   const uint64_t *fieldoffsets, unsigned fieldcount) 
   : Size(size), DataSize(datasize), FieldOffsets(0), Alignment(alignment),
-    FieldCount(fieldcount) {
+    FieldCount(fieldcount), CXXInfo(0) {
     if (FieldCount > 0)  {
       FieldOffsets = new uint64_t[FieldCount];
       for (unsigned i = 0; i < FieldCount; ++i)
         FieldOffsets[i] = fieldoffsets[i];
     }
   }
+  
+  // Constructor for C++ records.
+  ASTRecordLayout(uint64_t size, unsigned alignment, unsigned datasize,
+                  const uint64_t *fieldoffsets, unsigned fieldcount,
+                  uint64_t nonvirtualsize, unsigned nonvirtualalign,
+                  const CXXRecordDecl **bases, const uint64_t *baseoffsets,
+                  unsigned basecount)
+  : Size(size), DataSize(datasize), FieldOffsets(0), Alignment(alignment),
+  FieldCount(fieldcount), CXXInfo(new CXXRecordLayoutInfo) {
+    if (FieldCount > 0)  {
+      FieldOffsets = new uint64_t[FieldCount];
+      for (unsigned i = 0; i < FieldCount; ++i)
+        FieldOffsets[i] = fieldoffsets[i];
+    }
+    
+    CXXInfo->NonVirtualSize = nonvirtualsize;
+    CXXInfo->NonVirtualAlign = nonvirtualalign;
+    for (unsigned i = 0; i != basecount; ++i)
+      CXXInfo->BaseOffsets[bases[i]] = baseoffsets[i];
+  }
+  
   ~ASTRecordLayout() {
     delete [] FieldOffsets;
+    delete CXXInfo;
   }
 
   ASTRecordLayout(const ASTRecordLayout&);   // DO NOT IMPLEMENT
@@ -76,6 +129,30 @@
   uint64_t getDataSize() const {
     return DataSize;
   }
+  
+  /// getNonVirtualSize - Get the non-virtual size (in bits) of an object, 
+  /// which is the size of the object without virtual bases.
+  uint64_t getNonVirtualSize() const { 
+    assert(CXXInfo && "Record layout does not have C++ specific info!");
+    
+    return CXXInfo->NonVirtualSize;
+  }
+  
+  /// getNonVirtualSize - Get the non-virtual alignment (in bits) of an object,
+  /// which is the alignment of the object without virtual bases.
+  unsigned getNonVirtualAlign() const {
+    assert(CXXInfo && "Record layout does not have C++ specific info!");
+    
+    return CXXInfo->NonVirtualAlign;
+  }
+  
+  /// getBaseClassOffset - Get the offset, in bits, for the given base class.
+  uint64_t getBaseClassOffset(const CXXRecordDecl *Base) const {
+    assert(CXXInfo && "Record layout does not have C++ specific info!");
+    assert(CXXInfo->BaseOffsets.count(Base) && "Did not find base!");
+    
+    return CXXInfo->BaseOffsets[Base];
+  }
 };
 
 }  // end namespace clang

Modified: cfe/trunk/lib/AST/RecordLayoutBuilder.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/RecordLayoutBuilder.cpp?rev=77352&r1=77351&r2=77352&view=diff

==============================================================================
--- cfe/trunk/lib/AST/RecordLayoutBuilder.cpp (original)
+++ cfe/trunk/lib/AST/RecordLayoutBuilder.cpp Tue Jul 28 14:24:15 2009
@@ -22,7 +22,7 @@
 
 ASTRecordLayoutBuilder::ASTRecordLayoutBuilder(ASTContext &Ctx) 
   : Ctx(Ctx), Size(0), Alignment(8), StructPacking(0), NextOffset(0),
-  IsUnion(false) {}
+  IsUnion(false), NonVirtualSize(0), NonVirtualAlignment(8) {}
 
 void 
 ASTRecordLayoutBuilder::LayoutNonVirtualBases(const CXXRecordDecl *RD) {
@@ -44,15 +44,16 @@
     assert(BaseInfo.getDataSize() > 0 && 
            "FIXME: Handle empty classes.");
   
-  // FIXME: Should get the non-virtual alignment of the base.
-  unsigned BaseAlign = BaseInfo.getAlignment();
-  
-  // FIXME: Should get the non-virtual size of the base.
-  uint64_t BaseSize = BaseInfo.getDataSize();
+  unsigned BaseAlign = BaseInfo.getNonVirtualAlign();
+  uint64_t BaseSize = BaseInfo.getNonVirtualSize();
   
   // Round up the current record size to the base's alignment boundary.
   Size = (Size + (BaseAlign-1)) & ~(BaseAlign-1);
 
+  // Add base class offsets.
+  Bases.push_back(RD);
+  BaseOffsets.push_back(Size);
+
   // Non-virtual base class has offset too.
   FieldOffsets.push_back(Size);
 
@@ -81,6 +82,9 @@
 
   LayoutFields(D);
   
+  NonVirtualSize = Size;
+  NonVirtualAlignment = Alignment;
+  
   // Finally, round the size of the total struct up to the alignment of the
   // struct itself.
   FinishLayout();
@@ -238,22 +242,33 @@
 
   Builder.Layout(D);
 
-  bool IsPODForThePurposeOfLayout;
-  if (!Ctx.getLangOptions().CPlusPlus) {
-    // In C, all record types are POD.
-    IsPODForThePurposeOfLayout = true;
-  } else {
-    // FIXME: This is not always correct. See the part about bitfields at
-    // http://www.codesourcery.com/public/cxx-abi/abi.html#POD for more info.
-    IsPODForThePurposeOfLayout = cast<CXXRecordDecl>(D)->isPOD();
-  }
+  if (!isa<CXXRecordDecl>(D))
+    return new ASTRecordLayout(Builder.Size, Builder.Alignment, Builder.Size,
+                               Builder.FieldOffsets.data(), 
+                               Builder.FieldOffsets.size());
+  
+  // FIXME: This is not always correct. See the part about bitfields at
+  // http://www.codesourcery.com/public/cxx-abi/abi.html#POD for more info.
+  // FIXME: IsPODForThePurposeOfLayout should be stored in the record layout.
+  bool IsPODForThePurposeOfLayout = cast<CXXRecordDecl>(D)->isPOD();
   
+  assert(Builder.Bases.size() == Builder.BaseOffsets.size() && 
+         "Base offsets vector must be same size as bases vector!");
+
+  // FIXME: This should be done in FinalizeLayout.
   uint64_t DataSize = 
     IsPODForThePurposeOfLayout ? Builder.Size : Builder.NextOffset;
+  uint64_t NonVirtualSize = 
+    IsPODForThePurposeOfLayout ? DataSize : Builder.NonVirtualSize;
   
   return new ASTRecordLayout(Builder.Size, Builder.Alignment, DataSize,
                              Builder.FieldOffsets.data(), 
-                             Builder.FieldOffsets.size());
+                             Builder.FieldOffsets.size(),
+                             NonVirtualSize,
+                             Builder.NonVirtualAlignment,
+                             Builder.Bases.data(),
+                             Builder.BaseOffsets.data(),
+                             Builder.Bases.size());
 }
 
 const ASTRecordLayout *

Modified: cfe/trunk/lib/AST/RecordLayoutBuilder.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/RecordLayoutBuilder.h?rev=77352&r1=77351&r2=77352&view=diff

==============================================================================
--- cfe/trunk/lib/AST/RecordLayoutBuilder.h (original)
+++ cfe/trunk/lib/AST/RecordLayoutBuilder.h Tue Jul 28 14:24:15 2009
@@ -26,13 +26,18 @@
   ASTContext &Ctx;
 
   uint64_t Size;
-  uint64_t Alignment;
+  unsigned Alignment;
   llvm::SmallVector<uint64_t, 16> FieldOffsets;
   
   unsigned StructPacking;
   unsigned NextOffset;
   bool IsUnion;
   
+  uint64_t NonVirtualSize;
+  unsigned NonVirtualAlignment;
+  llvm::SmallVector<const CXXRecordDecl *, 4> Bases;
+  llvm::SmallVector<uint64_t, 4> BaseOffsets;
+  
   ASTRecordLayoutBuilder(ASTContext &Ctx);
   
   void Layout(const RecordDecl *D);





More information about the cfe-commits mailing list