]> granicus.if.org Git - clang/commitdiff
Scaffolding for supporting empty bases/fields.
authorAnders Carlsson <andersca@mac.com>
Thu, 24 Sep 2009 03:13:30 +0000 (03:13 +0000)
committerAnders Carlsson <andersca@mac.com>
Thu, 24 Sep 2009 03:13:30 +0000 (03:13 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@82678 91177308-0d34-0410-b5e6-96231b3b80d8

lib/AST/RecordLayoutBuilder.cpp
lib/AST/RecordLayoutBuilder.h

index 8a3e08965f4d8952359c567702ddf682dc938bb1..78598b795626f395cc76f237b6d8122054689ab3 100644 (file)
@@ -219,8 +219,18 @@ void ASTRecordLayoutBuilder::LayoutVirtualBases(const CXXRecordDecl *RD,
   }
 }
 
-void ASTRecordLayoutBuilder::LayoutBaseNonVirtually(const CXXRecordDecl *RD,
-  bool IsVirtualBase) {
+bool ASTRecordLayoutBuilder::canPlaceRecordAtOffset(const CXXRecordDecl *RD, 
+                                                    uint64_t Offset) const {
+  // FIXME: Implement.
+  return true;
+}
+
+void ASTRecordLayoutBuilder::UpdateEmptyClassOffsets(const CXXRecordDecl *RD,
+                                                     uint64_t Offset) {
+  // FIXME: Implement.
+}
+
+uint64_t ASTRecordLayoutBuilder::LayoutBase(const CXXRecordDecl *RD) {
   const ASTRecordLayout &BaseInfo = Ctx.getASTRecordLayout(RD);
   if (!Bases.empty()) {
     assert(BaseInfo.getDataSize() > 0 &&
@@ -229,15 +239,32 @@ void ASTRecordLayoutBuilder::LayoutBaseNonVirtually(const CXXRecordDecl *RD,
   
   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);
+  uint64_t Offset = llvm::RoundUpToAlignment(Size, BaseAlign);
+  
+  // Reserve space for this base.
+  Size = Offset + BaseSize;
+  
+  // Remember the next available offset.
+  NextOffset = Size;
+  
+  // Remember max struct/class alignment.
+  UpdateAlignment(BaseAlign);
+  
+  return Offset;
+}
+
+void ASTRecordLayoutBuilder::LayoutBaseNonVirtually(const CXXRecordDecl *RD,
+  bool IsVirtualBase) {
+  // Layout the base.
+  unsigned Offset = LayoutBase(RD);
 
   // Add base class offsets.
   if (IsVirtualBase) 
-    VBases.push_back(std::make_pair(RD, Size));
+    VBases.push_back(std::make_pair(RD, Offset));
   else
-    Bases.push_back(std::make_pair(RD, Size));
+    Bases.push_back(std::make_pair(RD, Offset));
 
 #if 0
   // And now add offsets for all our primary virtual bases as well, so
@@ -254,15 +281,6 @@ void ASTRecordLayoutBuilder::LayoutBaseNonVirtually(const CXXRecordDecl *RD,
       L = &Ctx.getASTRecordLayout(PB);
   }
 #endif
-
-  // Reserve space for this base.
-  Size += BaseSize;
-
-  // Remember the next available offset.
-  NextOffset = Size;
-
-  // Remember max struct/class alignment.
-  UpdateAlignment(BaseAlign);
 }
 
 void ASTRecordLayoutBuilder::Layout(const RecordDecl *D) {
@@ -408,7 +426,7 @@ void ASTRecordLayoutBuilder::LayoutField(const FieldDecl *D) {
       FieldAlign = std::min(FieldAlign, MaxFieldAlignment);
 
     // Round up the current record size to the field's alignment boundary.
-    FieldOffset = (FieldOffset + (FieldAlign-1)) & ~(FieldAlign-1);
+    FieldOffset = llvm::RoundUpToAlignment(FieldOffset, FieldAlign);
   }
 
   // Place this field at the current location.
index efc309155f0c3147d8671517912dffd0a7d8e212..43563c6729b9fac2c6df039a559e64d14db1c5e7 100644 (file)
@@ -13,6 +13,7 @@
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/ADT/SmallSet.h"
 #include "llvm/Support/DataTypes.h"
+#include <map>
 
 namespace clang {
   class ASTContext;
@@ -53,6 +54,10 @@ class ASTRecordLayoutBuilder {
   /// primary base classes for some other direct or indirect base class.
   llvm::SmallSet<const CXXRecordDecl*, 32> IndirectPrimaryBases;
   
+  /// EmptyClassOffsets - A map from offsets to empty record decls.
+  typedef std::multimap<uint64_t, const CXXRecordDecl *> EmptyClassOffsetsTy;
+  EmptyClassOffsetsTy EmptyClassOffsets;
+  
   ASTRecordLayoutBuilder(ASTContext &Ctx);
 
   void Layout(const RecordDecl *D);
@@ -79,6 +84,10 @@ class ASTRecordLayoutBuilder {
   
   bool IsNearlyEmpty(const CXXRecordDecl *RD) const;
   
+  /// 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);
   void LayoutNonVirtualBases(const CXXRecordDecl *RD);
   void LayoutBaseNonVirtually(const CXXRecordDecl *RD, bool IsVBase);
@@ -88,6 +97,18 @@ class ASTRecordLayoutBuilder {
                                  llvm::SmallSet<const CXXRecordDecl*, 32> &mark,
                      llvm::SmallSet<const CXXRecordDecl*, 32> &IndirectPrimary);
 
+  /// canPlaceRecordAtOffset - Return whether a record (either a base class
+  /// or a field) 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 canPlaceRecordAtOffset(const CXXRecordDecl *RD, uint64_t Offset) const;
+
+  /// UpdateEmptyClassOffsets - Called after a record (either a base class
+  /// or a field) has been placed at the given offset. Will update the
+  /// EmptyClassOffsets map if the class is empty or has any empty bases or
+  /// fields.
+  void UpdateEmptyClassOffsets(const CXXRecordDecl *RD, uint64_t Offset);
+  
   /// FinishLayout - Finalize record layout. Adjust record size based on the
   /// alignment.
   void FinishLayout();