[cfe-commits] r99775 - in /cfe/trunk/lib/CodeGen: CGClass.cpp CodeGenFunction.h

Anders Carlsson andersca at mac.com
Sun Mar 28 13:34:31 PDT 2010


Author: andersca
Date: Sun Mar 28 15:34:31 2010
New Revision: 99775

URL: http://llvm.org/viewvc/llvm-project?rev=99775&view=rev
Log:
More improvements to setting the vtable pointer. We now no longer set the vtable pointer for non-virtual primary bases. We also do a pre-order traversal of the class hierarchy; this is necessary in order to get the right vbase offset offsets in base ctors/dtors.

Modified:
    cfe/trunk/lib/CodeGen/CGClass.cpp
    cfe/trunk/lib/CodeGen/CodeGenFunction.h

Modified: cfe/trunk/lib/CodeGen/CGClass.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGClass.cpp?rev=99775&r1=99774&r2=99775&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGClass.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGClass.cpp Sun Mar 28 15:34:31 2010
@@ -690,7 +690,7 @@
     }
   }
 
-  InitializeVtablePtrs(ClassDecl);
+  InitializeVTablePointers(ClassDecl);
 }
 
 /// SynthesizeCXXCopyAssignment - Implicitly define copy assignment operator.
@@ -1010,7 +1010,7 @@
       MemberInitializers.push_back(Member);
   }
 
-  InitializeVtablePtrs(ClassDecl);
+  InitializeVTablePointers(ClassDecl);
 
   for (unsigned I = 0, E = MemberInitializers.size(); I != E; ++I) {
     assert(LiveTemporaries.empty() &&
@@ -1060,7 +1060,7 @@
   // Otherwise, we're in the base variant, so we need to ensure the
   // vtable ptrs are right before emitting the body.
   } else {
-    InitializeVtablePtrs(Dtor->getParent());
+    InitializeVTablePointers(Dtor->getParent());
   }
 
   // Emit the body of the statement.
@@ -1584,59 +1584,66 @@
   Builder.CreateStore(VTableAddressPoint, VTableField);
 }
 
-void CodeGenFunction::InitializeVtablePtrs(const CXXRecordDecl *RD) {
-  if (!RD->isDynamicClass())
-    return;
-
-  // Get the VTable.
-  llvm::Constant *VTable = CGM.getVTables().GetAddrOfVTable(RD);
-  
-  // Store address points for the current class and its non-virtual bases.
-  InitializeVtablePtrs(BaseSubobject(RD, 0), VTable, RD);
+void
+CodeGenFunction::InitializeVTablePointers(BaseSubobject Base, 
+                                          bool BaseIsMorallyVirtual,
+                                          bool BaseIsNonVirtualPrimaryBase,
+                                          llvm::Constant *VTable,
+                                          const CXXRecordDecl *VTableClass,
+                                          VisitedVirtualBasesSetTy& VBases) {
+  // If this base is a non-virtual primary base the address point has already
+  // been set.
+  if (true || !BaseIsNonVirtualPrimaryBase) {
+    // Initialize the vtable pointer for this base.
+    InitializeVTablePointer(Base, BaseIsMorallyVirtual, VTable, VTableClass);
+  }
   
-  if (!RD->getNumVBases())
-    return;
-
-  const ASTRecordLayout &Layout = getContext().getASTRecordLayout(RD);
+  const CXXRecordDecl *RD = Base.getBase();
 
-  // Store address points for virtual basess.
-  for (CXXRecordDecl::base_class_const_iterator I = RD->vbases_begin(), 
-       E = RD->vbases_end(); I != E; ++I) {
+  // Traverse bases.
+  for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(), 
+       E = RD->bases_end(); I != E; ++I) {
     CXXRecordDecl *BaseDecl
       = cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl());
     
-    uint64_t BaseOffset = Layout.getVBaseClassOffset(BaseDecl);
-    InitializeVtablePtrs(BaseSubobject(BaseDecl, BaseOffset), VTable, RD);
+    uint64_t BaseOffset;
+
+    if (I->isVirtual()) {
+      // Check if we've visited this virtual base before.
+      if (!VBases.insert(BaseDecl))
+        continue;
+
+      const ASTRecordLayout &Layout = 
+        getContext().getASTRecordLayout(VTableClass);
+
+      BaseIsMorallyVirtual = true;
+      BaseIsNonVirtualPrimaryBase = false;
+      
+      BaseOffset = Layout.getVBaseClassOffset(BaseDecl);
+    } else {
+      const ASTRecordLayout &Layout = getContext().getASTRecordLayout(RD);
+
+      BaseOffset = Base.getBaseOffset() + Layout.getBaseClassOffset(BaseDecl);
+      BaseIsNonVirtualPrimaryBase = Layout.getPrimaryBase() == BaseDecl;
+    }
+    
+    InitializeVTablePointers(BaseSubobject(BaseDecl, BaseOffset), 
+                             BaseIsMorallyVirtual, BaseIsNonVirtualPrimaryBase, 
+                             VTable, VTableClass, VBases);
   }
 }
 
-void CodeGenFunction::InitializeVtablePtrs(BaseSubobject Base, 
-                                           llvm::Constant *VTable,
-                                           const CXXRecordDecl *VTableClass) {
-  const CXXRecordDecl *RD = Base.getBase();
-  
-  // Ignore classes without a vtable pointer.
+void CodeGenFunction::InitializeVTablePointers(const CXXRecordDecl *RD) {
   if (!RD->isDynamicClass())
     return;
-  
-  const ASTRecordLayout &Layout = getContext().getASTRecordLayout(RD);
 
-  // Store address points for non-virtual bases.
-  for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(), 
-       E = RD->bases_end(); I != E; ++I) {
-    if (I->isVirtual())
-      continue;
-    
-    CXXRecordDecl *BaseDecl
-      = cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl());
-    uint64_t BaseOffset = Base.getBaseOffset() + 
-      Layout.getBaseClassOffset(BaseDecl);
-    
-    InitializeVtablePtrs(BaseSubobject(BaseDecl, BaseOffset), 
-                         VTable, VTableClass);
-  }
+  // Get the VTable.
+  llvm::Constant *VTable = CGM.getVTables().GetAddrOfVTable(RD);
 
-  // FIXME: BaseIsMorallyVirtual is not correct here.
-  InitializeVTablePointer(Base, /*BaseIsMorallyVirtual=*/false, VTable, 
-                          VTableClass);
+  // Initialize the vtable pointers for this class and all of its bases.
+  VisitedVirtualBasesSetTy VBases;
+  InitializeVTablePointers(BaseSubobject(RD, 0),
+                           /*BaseIsMorallyVirtual=*/false, 
+                           /*BaseIsNonVirtualPrimaryBase=*/false, 
+                           VTable, RD, VBases);
 }

Modified: cfe/trunk/lib/CodeGen/CodeGenFunction.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.h?rev=99775&r1=99774&r2=99775&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenFunction.h (original)
+++ cfe/trunk/lib/CodeGen/CodeGenFunction.h Sun Mar 28 15:34:31 2010
@@ -519,11 +519,13 @@
                                const CXXRecordDecl *VTableClass);
 
   typedef llvm::SmallPtrSet<const CXXRecordDecl *, 4> VisitedVirtualBasesSetTy;
+  void InitializeVTablePointers(BaseSubobject Base, bool BaseIsMorallyVirtual,
+                                bool BaseIsNonVirtualPrimaryBase,
+                                llvm::Constant *VTable,
+                                const CXXRecordDecl *VTableClass,
+                                VisitedVirtualBasesSetTy& VBases);
 
-  void InitializeVtablePtrs(BaseSubobject Base, llvm::Constant *VTable,
-                            const CXXRecordDecl *VTableClass);
-
-  void InitializeVtablePtrs(const CXXRecordDecl *ClassDecl);
+  void InitializeVTablePointers(const CXXRecordDecl *ClassDecl);
 
 
   void SynthesizeCXXCopyConstructor(const FunctionArgList &Args);





More information about the cfe-commits mailing list