[cfe-commits] r142694 - in /cfe/trunk: include/clang/AST/RecordLayout.h lib/AST/RecordLayout.cpp lib/AST/RecordLayoutBuilder.cpp test/Sema/ms_class_layout.cpp

Eli Friedman eli.friedman at gmail.com
Fri Oct 21 15:49:56 PDT 2011


Author: efriedma
Date: Fri Oct 21 17:49:56 2011
New Revision: 142694

URL: http://llvm.org/viewvc/llvm-project?rev=142694&view=rev
Log:
More ASTRecordLayout changes for MS ABI; based on patch by r4start.


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

Modified: cfe/trunk/include/clang/AST/RecordLayout.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/RecordLayout.h?rev=142694&r1=142693&r2=142694&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/RecordLayout.h (original)
+++ cfe/trunk/include/clang/AST/RecordLayout.h Fri Oct 21 17:49:56 2011
@@ -62,8 +62,11 @@
     /// (either a base or a member). Will be zero if the class doesn't contain
     /// any empty subobjects.
     CharUnits SizeOfLargestEmptySubobject;
-    
-    /// VBPtrOffset - Virtual base table offset.
+
+    /// VFPtrOffset - Virtual function table offset (Microsoft-only).
+    CharUnits VFPtrOffset;
+
+    /// VBPtrOffset - Virtual base table offset (Microsoft-only).
     CharUnits VBPtrOffset;
     
     /// PrimaryBase - The primary base info for this record.
@@ -92,7 +95,8 @@
   // Constructor for C++ records.
   typedef CXXRecordLayoutInfo::BaseOffsetsMapTy BaseOffsetsMapTy;
   ASTRecordLayout(const ASTContext &Ctx,
-                  CharUnits size, CharUnits alignment, CharUnits vbptroffset,
+                  CharUnits size, CharUnits alignment,
+                  CharUnits vfptroffset, CharUnits vbptroffset,
                   CharUnits datasize,
                   const uint64_t *fieldoffsets, unsigned fieldcount,
                   CharUnits nonvirtualsize, CharUnits nonvirtualalign,
@@ -204,7 +208,17 @@
     return CXXInfo->SizeOfLargestEmptySubobject;
   }
 
+  /// getVFPtrOffset - Get the offset for virtual function table pointer.
+  /// This is only meaningful with the Microsoft ABI.
+  CharUnits getVFPtrOffset() const {
+    assert(CXXInfo && "Record layout does not have C++ specific info!");
+    return CXXInfo->VFPtrOffset;
+  }
+
+  /// getVBPtrOffset - Get the offset for virtual base table pointer.
+  /// This is only meaningful with the Microsoft ABI.
   CharUnits getVBPtrOffset() const {
+    assert(CXXInfo && "Record layout does not have C++ specific info!");
     return CXXInfo->VBPtrOffset;
   }
 };

Modified: cfe/trunk/lib/AST/RecordLayout.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/RecordLayout.cpp?rev=142694&r1=142693&r2=142694&view=diff
==============================================================================
--- cfe/trunk/lib/AST/RecordLayout.cpp (original)
+++ cfe/trunk/lib/AST/RecordLayout.cpp Fri Oct 21 17:49:56 2011
@@ -43,7 +43,8 @@
 // Constructor for C++ records.
 ASTRecordLayout::ASTRecordLayout(const ASTContext &Ctx,
                                  CharUnits size, CharUnits alignment,
-                                 CharUnits vbptroffset, CharUnits datasize,
+                                 CharUnits vfptroffset, CharUnits vbptroffset,
+                                 CharUnits datasize,
                                  const uint64_t *fieldoffsets,
                                  unsigned fieldcount,
                                  CharUnits nonvirtualsize,
@@ -68,6 +69,7 @@
   CXXInfo->SizeOfLargestEmptySubobject = SizeOfLargestEmptySubobject;
   CXXInfo->BaseOffsets = BaseOffsets;
   CXXInfo->VBaseOffsets = VBaseOffsets;
+  CXXInfo->VFPtrOffset = vfptroffset;
   CXXInfo->VBPtrOffset = vbptroffset;
 
 #ifndef NDEBUG

Modified: cfe/trunk/lib/AST/RecordLayoutBuilder.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/RecordLayoutBuilder.cpp?rev=142694&r1=142693&r2=142694&view=diff
==============================================================================
--- cfe/trunk/lib/AST/RecordLayoutBuilder.cpp (original)
+++ cfe/trunk/lib/AST/RecordLayoutBuilder.cpp Fri Oct 21 17:49:56 2011
@@ -592,6 +592,9 @@
   /// out is virtual.
   bool PrimaryBaseIsVirtual;
 
+  /// VFPtrOffset - Virtual function table offset. Only for MS layout.
+  CharUnits VFPtrOffset;
+
   /// VBPtrOffset - Virtual base table offset. Only for MS layout.
   CharUnits VBPtrOffset;
 
@@ -625,7 +628,9 @@
       DataSize(0), NonVirtualSize(CharUnits::Zero()), 
       NonVirtualAlignment(CharUnits::One()), 
       ZeroLengthBitfield(0), PrimaryBase(0), 
-      PrimaryBaseIsVirtual(false), VBPtrOffset(CharUnits::fromQuantity(-1)),
+      PrimaryBaseIsVirtual(false),
+      VFPtrOffset(CharUnits::fromQuantity(-1)),
+      VBPtrOffset(CharUnits::fromQuantity(-1)),
       FirstNearlyEmptyVBase(0) { }
 
   void Layout(const RecordDecl *D);
@@ -669,7 +674,7 @@
 
   void SelectPrimaryVBase(const CXXRecordDecl *RD);
 
-  void EnsureVTablePointerAlignment();
+  void EnsureVTablePointerAlignment(CharUnits UnpackedBaseAlign);
 
   /// LayoutNonVirtualBases - Determines the primary base class (if any) and
   /// lays it out. Will then proceed to lay out all non-virtual base clasess.
@@ -739,8 +744,6 @@
   static const CXXMethodDecl *ComputeKeyFunction(const CXXRecordDecl *RD);
 
   virtual ~RecordLayoutBuilder() { }
-
-  CharUnits GetVBPtrOffset() const { return VBPtrOffset; }
 };
 } // end anonymous namespace
 
@@ -937,9 +940,7 @@
 }
 
 void
-RecordLayoutBuilder::EnsureVTablePointerAlignment() {
-  CharUnits UnpackedBaseAlign = 
-    Context.toCharUnitsFromBits(Context.getTargetInfo().getPointerAlign(0));
+RecordLayoutBuilder::EnsureVTablePointerAlignment(CharUnits UnpackedBaseAlign) {
   CharUnits BaseAlign = (Packed) ? CharUnits::One() : UnpackedBaseAlign;
 
   // The maximum field alignment overrides base align.
@@ -949,7 +950,8 @@
   }
 
   // Round up the current record size to pointer alignment.
-  setDataSize(getDataSize().RoundUpToAlignment(BaseAlign));
+  setSize(getSize().RoundUpToAlignment(BaseAlign));
+  setDataSize(getSize());
 
   // Update the alignment.
   UpdateAlignment(BaseAlign, UnpackedBaseAlign);
@@ -994,9 +996,11 @@
     // Under the Itanium ABI, a dynamic class without a primary base has a
     // vtable pointer.  It is placed at offset 0.
     assert(DataSize == 0 && "Vtable pointer must be at offset zero!");
-    EnsureVTablePointerAlignment();
     CharUnits PtrWidth = 
       Context.toCharUnitsFromBits(Context.getTargetInfo().getPointerWidth(0));
+    CharUnits PtrAlign = 
+      Context.toCharUnitsFromBits(Context.getTargetInfo().getPointerAlign(0));
+    EnsureVTablePointerAlignment(PtrAlign);
     setSize(getSize() + PtrWidth);
     setDataSize(getSize());
   }
@@ -1032,15 +1036,19 @@
     // after any base classes.
     CharUnits PtrWidth = 
       Context.toCharUnitsFromBits(Context.getTargetInfo().getPointerWidth(0));
+    CharUnits PtrAlign = 
+      Context.toCharUnitsFromBits(Context.getTargetInfo().getPointerAlign(0));
+    PtrAlign = std::max(PtrAlign, Alignment);
     if (HasNewVirtualFunction(RD) &&
         (!PrimaryBase || !BaseHasVFPtr(PrimaryBase))) {
-      EnsureVTablePointerAlignment();
+      EnsureVTablePointerAlignment(PtrAlign);
+      VFPtrOffset = getSize();
       setSize(getSize() + PtrWidth);
       setDataSize(getSize());
     }
     if (RD->getNumVBases() &&
         (!PrimaryBase || !PrimaryBase->getNumVBases())) {
-      EnsureVTablePointerAlignment();
+      EnsureVTablePointerAlignment(PtrAlign);
       VBPtrOffset = getSize();
       setSize(getSize() + PtrWidth);
       setDataSize(getSize());
@@ -2030,7 +2038,7 @@
     
     Builder->Layout(RD);
 
-    TargetAlign = Builder->getAligment();
+    TargetAlign = Builder->NonVirtualAlignment;
     
     if (getTargetInfo().getCXXABI() == CXXABI_Microsoft &&
         TargetAlign.getQuantity() > 4) {
@@ -2053,7 +2061,7 @@
     // FIXME: IsPODForThePurposeOfLayout should be stored in the record layout.
     // This does not affect the calculations of MSVC layouts
     bool IsPODForThePurposeOfLayout = 
-      (getTargetInfo().getCXXABI() == CXXABI_Microsoft) ||
+      (getTargetInfo().getCXXABI() != CXXABI_Microsoft) &&
       cast<CXXRecordDecl>(D)->isPOD();
 
     // FIXME: This should be done in FinalizeLayout.
@@ -2065,7 +2073,8 @@
     NewEntry =
       new (*this) ASTRecordLayout(*this, Builder->getSize(), 
                                   Builder->Alignment,
-                                  Builder->GetVBPtrOffset(),
+                                  Builder->VFPtrOffset,
+                                  Builder->VBPtrOffset,
                                   DataSize, 
                                   Builder->FieldOffsets.data(),
                                   Builder->FieldOffsets.size(),
@@ -2175,22 +2184,16 @@
   IndentLevel++;
 
   const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase();
+  bool HasVfptr = Layout.getVFPtrOffset() != CharUnits::fromQuantity(-1);
   bool HasVbptr = Layout.getVBPtrOffset() != CharUnits::fromQuantity(-1);
 
   // Vtable pointer.
-  if (RD->isDynamicClass() && !PrimaryBase) {
+  if (RD->isDynamicClass() && !PrimaryBase &&
+      C.getTargetInfo().getCXXABI() != CXXABI_Microsoft) {
     PrintOffset(OS, Offset, IndentLevel);
     OS << '(' << *RD << " vtable pointer)\n";
   }
   
-  if (HasVbptr && !PrimaryBase) {
-    PrintOffset(OS, Offset + Layout.getVBPtrOffset(), IndentLevel);
-    OS << '(' << *RD << " vbtable pointer)\n";
-
-    // one vbtable per class
-    HasVbptr = false;
-  }
-
   // Dump (non-virtual) bases
   for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(),
          E = RD->bases_end(); I != E; ++I) {
@@ -2208,7 +2211,12 @@
                         Base == PrimaryBase ? "(primary base)" : "(base)",
                         /*IncludeVirtualBases=*/false);
   }
-  // vbptr
+
+  // vfptr and vbptr (for Microsoft C++ ABI)
+  if (HasVfptr) {
+    PrintOffset(OS, Offset + Layout.getVFPtrOffset(), IndentLevel);
+    OS << '(' << *RD << " vftable pointer)\n";
+  }
   if (HasVbptr) {
     PrintOffset(OS, Offset + Layout.getVBPtrOffset(), IndentLevel);
     OS << '(' << *RD << " vbtable pointer)\n";

Modified: cfe/trunk/test/Sema/ms_class_layout.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/ms_class_layout.cpp?rev=142694&r1=142693&r2=142694&view=diff
==============================================================================
--- cfe/trunk/test/Sema/ms_class_layout.cpp (original)
+++ cfe/trunk/test/Sema/ms_class_layout.cpp Fri Oct 21 17:49:56 2011
@@ -61,6 +61,12 @@
 {
 };
 
+struct I : public virtual D
+{
+  virtual ~I(){}
+  double q;
+};
+
 #pragma pack(pop)
 
 // This needs only for building layouts. 
@@ -72,18 +78,19 @@
   DerivedStruct* v;
   H* g;
   BaseStruct* u;
+  I* i;
   return 0;
 }
 
 // CHECK:       0 | class D
-// CHECK-NEXT:  0 |   (D vtable pointer)
+// CHECK-NEXT:  0 |   (D vftable pointer)
 // CHECK-NEXT:  8 |   double a
 
 // CHECK-NEXT: sizeof=16, dsize=16, align=8
 // CHECK-NEXT: nvsize=16, nvalign=8
 
 // CHECK:       0 | class B
-// CHECK-NEXT:  0 |   (B vtable pointer)
+// CHECK-NEXT:  0 |   (B vftable pointer)
 // CHECK-NEXT:  4 |   int b_field
 
 // CHECK-NEXT: sizeof=8, dsize=8, align=4
@@ -91,7 +98,7 @@
 
 // CHECK:       0 | class A
 // CHECK-NEXT:  0 |   class B (primary base)
-// CHECK-NEXT:  0 |     (B vtable pointer)
+// CHECK-NEXT:  0 |     (B vftable pointer)
 // CHECK-NEXT:  4 |     int b_field
 // CHECK-NEXT:  8 |   int a_field
 // CHECK-NEXT: 12 |   char one
@@ -101,10 +108,10 @@
 
 // CHECK:       0 | class C
 // CHECK-NEXT:  0 |   class D (primary base)
-// CHECK-NEXT:  0 |     (D vtable pointer)
+// CHECK-NEXT:  0 |     (D vftable pointer)
 // CHECK-NEXT:  8 |     double a
 // CHECK-NEXT: 16 |   class B (base)
-// CHECK-NEXT: 16 |     (B vtable pointer)
+// CHECK-NEXT: 16 |     (B vftable pointer)
 // CHECK-NEXT: 20 |     int b_field
 // CHECK-NEXT: 24 |   (C vbtable pointer)
 // CHECK-NEXT: 32 |   double c1_field
@@ -113,23 +120,23 @@
 // CHECK-NEXT: 56 |   int c4_field
 // CHECK-NEXT: 64 |   class A (virtual base)
 // CHECK-NEXT: 64 |     class B (primary base)
-// CHECK-NEXT: 64 |       (B vtable pointer)
+// CHECK-NEXT: 64 |       (B vftable pointer)
 // CHECK-NEXT: 68 |       int b_field
 // CHECK-NEXT: 72 |     int a_field
 // CHECK-NEXT: 76 |     char one
 
 // CHECK-NEXT: sizeof=80, dsize=80, align=8
-// CHECK-NEXT: nvsize=80, nvalign=8
+// CHECK-NEXT: nvsize=64, nvalign=8
  
 // CHECK:       0 | struct BaseStruct
 // CHECK-NEXT:  0 |   double v0
 // CHECK-NEXT:  8 |   float v1
 // CHECK-NEXT: 16 |   class C fg
 // CHECK-NEXT: 16 |     class D (primary base)
-// CHECK-NEXT: 16 |       (D vtable pointer)
+// CHECK-NEXT: 16 |       (D vftable pointer)
 // CHECK-NEXT: 24 |       double a
 // CHECK-NEXT: 32 |     class B (base)
-// CHECK-NEXT: 32 |       (B vtable pointer)
+// CHECK-NEXT: 32 |       (B vftable pointer)
 // CHECK-NEXT: 36 |       int b_field
 // CHECK-NEXT: 40 |     (C vbtable pointer)
 // CHECK-NEXT: 48 |     double c1_field
@@ -138,13 +145,13 @@
 // CHECK-NEXT: 72 |     int c4_field
 // CHECK-NEXT: 80 |     class A (virtual base)
 // CHECK-NEXT: 80 |       class B (primary base)
-// CHECK-NEXT: 80 |         (B vtable pointer)
+// CHECK-NEXT: 80 |         (B vftable pointer)
 // CHECK-NEXT: 84 |         int b_field
 // CHECK-NEXT: 88 |       int a_field
 // CHECK-NEXT: 92 |       char one
 
 // CHECK-NEXT: sizeof=80, dsize=80, align=8
-// CHECK-NEXT: nvsize=80, nvalign=8
+// CHECK-NEXT: nvsize=64, nvalign=8
 
 // CHECK: sizeof=96, dsize=96, align=8
 // CHECK-NEXT: nvsize=96, nvalign=8
@@ -155,10 +162,10 @@
 // CHECK-NEXT:  8 |     float v1
 // CHECK-NEXT: 16 |     class C fg
 // CHECK-NEXT: 16 |       class D (primary base)
-// CHECK-NEXT: 16 |         (D vtable pointer)
+// CHECK-NEXT: 16 |         (D vftable pointer)
 // CHECK-NEXT: 24 |         double a
 // CHECK-NEXT: 32 |       class B (base)
-// CHECK-NEXT: 32 |         (B vtable pointer)
+// CHECK-NEXT: 32 |         (B vftable pointer)
 // CHECK-NEXT: 36 |         int b_field
 // CHECK-NEXT: 40 |       (C vbtable pointer)
 // CHECK-NEXT: 48 |       double c1_field
@@ -167,12 +174,12 @@
 // CHECK-NEXT: 72 |       int c4_field
 // CHECK-NEXT: 80 |       class A (virtual base)
 // CHECK-NEXT: 80 |         class B (primary base)
-// CHECK-NEXT: 80 |           (B vtable pointer)
+// CHECK-NEXT: 80 |           (B vftable pointer)
 // CHECK-NEXT: 84 |           int b_field
 // CHECK-NEXT: 88 |         int a_field
 // CHECK-NEXT: 92 |         char one
 // CHECK-NEXT: sizeof=80, dsize=80, align=8
-// CHECK-NEXT: nvsize=80, nvalign=8
+// CHECK-NEXT: nvsize=64, nvalign=8
 
 // CHECK: 96 |   int x
 // CHECK-NEXT: sizeof=104, dsize=104, align=8
@@ -183,14 +190,22 @@
 // CHECK-NEXT: sizeof=4, dsize=4, align=4
 // CHECK-NEXT: nvsize=4, nvalign=4
 
-// FIXME: Dump should not be showing vfptr, and vbptr is in the wrong order.
 // CHECK:       0 | struct H
-// CHECK-NEXT:  0 |   (H vtable pointer)
-// CHECK-NEXT:  4 |   (H vbtable pointer)
 // CHECK-NEXT:  0 |   struct G (base)
 // CHECK-NEXT:  0 |     int g_field
+// CHECK-NEXT:  4 |   (H vbtable pointer)
 // CHECK-NEXT:  8 |   class D (virtual base)
-// CHECK-NEXT:  8 |     (D vtable pointer)
+// CHECK-NEXT:  8 |     (D vftable pointer)
 // CHECK-NEXT: 16 |     double a
 // CHECK-NEXT: sizeof=24, dsize=24, align=8
+// CHECK-NEXT: nvsize=8, nvalign=4
+
+// CHECK:       0 | struct I
+// CHECK-NEXT:  0 |   (I vftable pointer)
+// CHECK-NEXT:  8 |   (I vbtable pointer)
+// CHECK-NEXT: 16 |   double q
+// CHECK-NEXT: 24 |   class D (virtual base)
+// CHECK-NEXT: 24 |     (D vftable pointer)
+// CHECK-NEXT: 32 |     double a
+// CHECK-NEXT: sizeof=40, dsize=40, align=8
 // CHECK-NEXT: nvsize=24, nvalign=8





More information about the cfe-commits mailing list