]> granicus.if.org Git - clang/commitdiff
Add ability to generate vcall offsets for primary virtual base.
authorMike Stump <mrs@apple.com>
Fri, 7 Aug 2009 19:00:50 +0000 (19:00 +0000)
committerMike Stump <mrs@apple.com>
Fri, 7 Aug 2009 19:00:50 +0000 (19:00 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@78396 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/AST/RecordLayout.h
lib/AST/RecordLayoutBuilder.cpp
lib/AST/RecordLayoutBuilder.h
lib/CodeGen/CGCXX.cpp
test/CodeGenCXX/virt.cpp

index bb40da7647eee4fab8bc8f6498cf894a0d3380e1..68287a3b70b7ca5ebd066325ef7c0ca3bf789ff2 100644 (file)
@@ -56,6 +56,8 @@ class ASTRecordLayout {
     
     /// PrimaryBase - The primary base for our vtable.
     const CXXRecordDecl *PrimaryBase;
+    /// PrimaryBase - Wether or not the primary base was a virtual base.
+    bool PrimaryBaseWasVirtual;
 
     /// BaseOffsets - Contains a map from base classes to their offset.
     /// FIXME: Does it make sense to store offsets for virtual base classes
@@ -86,8 +88,9 @@ class ASTRecordLayout {
   ASTRecordLayout(uint64_t size, unsigned alignment, uint64_t datasize,
                   const uint64_t *fieldoffsets, unsigned fieldcount,
                   uint64_t nonvirtualsize, unsigned nonvirtualalign,
-                  const CXXRecordDecl *PB, const CXXRecordDecl **bases,
-                  const uint64_t *baseoffsets, unsigned basecount)
+                  const CXXRecordDecl *PB, bool PBVirtual,
+                  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)  {
@@ -97,6 +100,7 @@ class ASTRecordLayout {
     }
     
     CXXInfo->PrimaryBase = PB;
+    CXXInfo->PrimaryBaseWasVirtual = PBVirtual;
     CXXInfo->NonVirtualSize = nonvirtualsize;
     CXXInfo->NonVirtualAlign = nonvirtualalign;
     for (unsigned i = 0; i != basecount; ++i)
@@ -156,6 +160,12 @@ public:
     
     return CXXInfo->PrimaryBase;
   }
+  /// getPrimaryBaseWasVirtual - Indicates if the primary base was virtual.
+  bool getPrimaryBaseWasVirtual() const {
+    assert(CXXInfo && "Record layout does not have C++ specific info!");
+    
+    return CXXInfo->PrimaryBaseWasVirtual;
+  }
 
   /// getBaseClassOffset - Get the offset, in bits, for the given base class.
   uint64_t getBaseClassOffset(const CXXRecordDecl *Base) const {
index 5f23a8ca46c05a74a53f386f44102794998e2312..1d96c1a20b7cbcc6f5b1ef0fe00830b4605e32a9 100644 (file)
@@ -30,7 +30,7 @@ void ASTRecordLayoutBuilder::LayoutVtable(const CXXRecordDecl *RD) {
   // FIXME: audit indirect virtual bases
   if (!RD->isPolymorphic() && !RD->getNumVBases()) {
     // There is no primary base in this case.
-    setPrimaryBase(0);
+    setPrimaryBase(0, false);
     return;
   }
 
@@ -103,7 +103,7 @@ void ASTRecordLayoutBuilder::SelectPrimaryBase(const CXXRecordDecl *RD) {
       const CXXRecordDecl *Base = 
         cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
       if (Base->isDynamicClass()) {
-        setPrimaryBase(Base);
+        setPrimaryBase(Base, false);
         return;
       }
     }
@@ -116,7 +116,7 @@ void ASTRecordLayoutBuilder::SelectPrimaryBase(const CXXRecordDecl *RD) {
   // is expensive.
   // FIXME: audit indirect virtual bases
   if (RD->getNumVBases() == 0) {
-    setPrimaryBase(0);
+    setPrimaryBase(0, false);
     return;
   }
 
@@ -143,15 +143,15 @@ void ASTRecordLayoutBuilder::SelectPrimaryBase(const CXXRecordDecl *RD) {
       if (FirstPrimary==0)
         FirstPrimary = Base;
       if (!IndirectPrimary.count(Base)) {
-        setPrimaryBase(Base);
+        setPrimaryBase(Base, true);
         return;
       }
     }
   }
 
-  // Otherwise if is the first nearly empty base, if one exists, otherwise
-  // there is no primary base class.
-  setPrimaryBase(FirstPrimary);
+  // Otherwise if is the first nearly empty virtual base, if one exists,
+  // otherwise there is no primary base class.
+  setPrimaryBase(FirstPrimary, true);
   return;
 }
 
@@ -404,6 +404,7 @@ ASTRecordLayoutBuilder::ComputeLayout(ASTContext &Ctx,
                              NonVirtualSize,
                              Builder.NonVirtualAlignment,
                              Builder.PrimaryBase,
+                             Builder.PrimaryBaseWasVirtual,
                              Builder.Bases.data(),
                              Builder.BaseOffsets.data(),
                              Builder.Bases.size());
index a745c85db4e8c885692853353f4da67a3807b77e..75c6b51921145f4b0713ff28bba003aa7c2f037f 100644 (file)
@@ -37,6 +37,7 @@ class ASTRecordLayoutBuilder {
   uint64_t NonVirtualSize;
   unsigned NonVirtualAlignment;
   const CXXRecordDecl *PrimaryBase;
+  bool PrimaryBaseWasVirtual;
 
   llvm::SmallVector<const CXXRecordDecl *, 4> Bases;
   llvm::SmallVector<uint64_t, 4> BaseOffsets;
@@ -54,7 +55,10 @@ class ASTRecordLayoutBuilder {
   void SelectPrimaryBase(const CXXRecordDecl *RD);
   void SelectPrimaryForBase(const CXXRecordDecl *RD,
                      llvm::SmallSet<const CXXRecordDecl*, 32> &IndirectPrimary);
-  void setPrimaryBase(const CXXRecordDecl *PB) { PrimaryBase = PB; }
+  void setPrimaryBase(const CXXRecordDecl *PB, bool Virtual) {
+    PrimaryBase = PB;
+    PrimaryBaseWasVirtual = Virtual;
+  }
   bool IsNearlyEmpty(const CXXRecordDecl *RD);
   void LayoutVtable(const CXXRecordDecl *RD);
   void LayoutNonVirtualBases(const CXXRecordDecl *RD);
index 00993be161bd9164c182a203f99040577eae5858..d5b21345ea1e80197e8192033d9d87d942e145b9 100644 (file)
@@ -614,9 +614,11 @@ llvm::Value *CodeGenFunction::GenerateVtable(const CXXRecordDecl *RD) {
 
   const ASTRecordLayout &Layout = getContext().getASTRecordLayout(RD);
   const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase();
+  const bool PrimaryBaseWasVirtual = Layout.getPrimaryBase();
 
   // The primary base comes first.
-  GenerateVtableForBase(PrimaryBase, RD, rtti, methods, true);
+  GenerateVtableForBase(PrimaryBase, RD, rtti, methods, true,
+                        PrimaryBaseWasVirtual);
   for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(),
          e = RD->bases_end(); i != e; ++i) {
     if (i->isVirtual())
index aa1bca156c723c837ced9374350324f8c173b82a..04d7333310b1fc31d67ad7288903a6444a9d0942 100644 (file)
@@ -121,10 +121,10 @@ int main() {
 // CHECK-LP32: .long __ZN1C4bee1Ev
 // CHECK-LP32: .long __ZN1C4bee2Ev
 
-// CHECK-LP32: __ZTV1F:
-// CHECK-LP32 .space 4
+// CHECK-LP32:__ZTV1F:
+// CHECK-LP32: .space 4
 // CHECK-LP32 .long 8
-// CHECK-LP32 .space 4
+// CHECK-LP32: .space 4
 // CHECK-LP32: .space 4
 // CHECK-LP32: .long __ZTI1F
 // CHECK-LP32: .long __ZN1D3booEv
@@ -143,9 +143,9 @@ int main() {
 // CHECK-LP32: .long __ZN2D14bar5Ev
 
 // CHECK-LP64: __ZTV1F:
-// CHECK-LP64 .space 8
+// CHECK-LP64: .space 8
 // CHECK-LP64 .quad 16
-// CHECK-LP64 .space 8
+// CHECK-LP64: .space 8
 // CHECK-LP64: .space 8
 // CHECK-LP64: .quad __ZTI1F
 // CHECK-LP64: .quad __ZN1D3booEv