]> granicus.if.org Git - clang/commitdiff
Work in progress for setting the vtable pointers for all bases correctly in
authorEli Friedman <eli.friedman@gmail.com>
Fri, 18 Dec 2009 23:47:41 +0000 (23:47 +0000)
committerEli Friedman <eli.friedman@gmail.com>
Fri, 18 Dec 2009 23:47:41 +0000 (23:47 +0000)
the constructor.  This doesn't handle cases requiring the VTT at the moment,
and generates unnecessary stores, but I think it's essentially correct.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@91731 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/CGCXX.cpp
lib/CodeGen/CodeGenFunction.h
lib/CodeGen/CodeGenModule.h

index e860c295a53e38f8cea60a684fc8c6c03a5f93e5..0237a322a526eab0f87ccef1be9f17c13dbb9f49 100644 (file)
@@ -1700,21 +1700,65 @@ void CodeGenFunction::EmitCtorPrologue(const CXXConstructorDecl *CD,
 void CodeGenFunction::InitializeVtablePtrs(const CXXRecordDecl *ClassDecl) {
   if (!ClassDecl->isDynamicClass())
     return;
-  
-  // Initialize the vtable pointer.
-  // FIXME: This needs to initialize secondary vtable pointers too.
-  llvm::Value *ThisPtr = LoadCXXThis();
 
   llvm::Constant *Vtable = CGM.getVtableInfo().getVtable(ClassDecl);
-  uint64_t AddressPoint = CGM.getVtableInfo().getVtableAddressPoint(ClassDecl);
+  CodeGenModule::AddrSubMap_t& AddressPoints =
+      *(*CGM.AddressPoints[ClassDecl])[ClassDecl];
+  llvm::Value *ThisPtr = LoadCXXThis();
+  const ASTRecordLayout &Layout = getContext().getASTRecordLayout(ClassDecl);
+
+  // Store address points for virtual bases
+  for (CXXRecordDecl::base_class_const_iterator I = 
+       ClassDecl->vbases_begin(), E = ClassDecl->vbases_end(); I != E; ++I) {
+    const CXXBaseSpecifier &Base = *I;
+    CXXRecordDecl *BaseClassDecl
+      = cast<CXXRecordDecl>(Base.getType()->getAs<RecordType>()->getDecl());
+    uint64_t Offset = Layout.getVBaseClassOffset(BaseClassDecl);
+    InitializeVtablePtrsRecursive(BaseClassDecl, Vtable, AddressPoints,
+                                  ThisPtr, Offset);
+  }
+
+  // Store address points for non-virtual bases and current class
+  InitializeVtablePtrsRecursive(ClassDecl, Vtable, AddressPoints, ThisPtr, 0);
+}
+
+void CodeGenFunction::InitializeVtablePtrsRecursive(
+        const CXXRecordDecl *ClassDecl,
+        llvm::Constant *Vtable,
+        CodeGenModule::AddrSubMap_t& AddressPoints,
+        llvm::Value *ThisPtr,
+        uint64_t Offset) {
+  if (!ClassDecl->isDynamicClass())
+    return;
+
+  // Store address points for non-virtual bases
+  const ASTRecordLayout &Layout = getContext().getASTRecordLayout(ClassDecl);
+  for (CXXRecordDecl::base_class_const_iterator I = 
+       ClassDecl->bases_begin(), E = ClassDecl->bases_end(); I != E; ++I) {
+    const CXXBaseSpecifier &Base = *I;
+    if (Base.isVirtual())
+      continue;
+    CXXRecordDecl *BaseClassDecl
+      = cast<CXXRecordDecl>(Base.getType()->getAs<RecordType>()->getDecl());
+    uint64_t NewOffset = Offset + Layout.getBaseClassOffset(BaseClassDecl);
+    InitializeVtablePtrsRecursive(BaseClassDecl, Vtable, AddressPoints,
+                                  ThisPtr, NewOffset);
+  }
 
+  // Compute the address point
+  uint64_t AddressPoint = AddressPoints[std::make_pair(ClassDecl, Offset)];
   llvm::Value *VtableAddressPoint =
-    Builder.CreateConstInBoundsGEP2_64(Vtable, 0, AddressPoint);
-  
-  llvm::Value *VtableField = 
-    Builder.CreateBitCast(ThisPtr, 
-                          VtableAddressPoint->getType()->getPointerTo());
-  
+      Builder.CreateConstInBoundsGEP2_64(Vtable, 0, AddressPoint);
+
+  // Compute the address to store the address point
+  const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(CGM.getLLVMContext());
+  llvm::Value *VtableField = Builder.CreateBitCast(ThisPtr, Int8PtrTy);
+  VtableField = Builder.CreateConstInBoundsGEP1_64(VtableField, Offset/8);
+  const llvm::Type *AddressPointPtrTy =
+      VtableAddressPoint->getType()->getPointerTo();
+  VtableField = Builder.CreateBitCast(ThisPtr, AddressPointPtrTy);
+
+  // Store address point
   Builder.CreateStore(VtableAddressPoint, VtableField);
 }
 
index 4bacd16f9288cac42e00111c74e7dff13a0df1cd..c2e59c01eb2842afb71a713adfa1e3b268c222e1 100644 (file)
@@ -515,6 +515,12 @@ public:
 
   void InitializeVtablePtrs(const CXXRecordDecl *ClassDecl);
 
+  void InitializeVtablePtrsRecursive(const CXXRecordDecl *ClassDecl,
+                                     llvm::Constant *Vtable,
+                                     CodeGenModule::AddrSubMap_t& AddressPoints,
+                                     llvm::Value *ThisPtr,
+                                     uint64_t Offset);
+
   void SynthesizeCXXCopyConstructor(const CXXConstructorDecl *Ctor,
                                     CXXCtorType Type,
                                     llvm::Function *Fn,
index 814b1ef694655522db4fa6c2c3772ef3701b8724..939c66ca31478aaeca67ffe7092bbd8dce3b31ac 100644 (file)
@@ -233,8 +233,8 @@ public:
                       const CovariantThunkAdjustment &Adjustment);
 
   typedef std::pair<const CXXRecordDecl *, uint64_t> CtorVtable_t;
-  typedef llvm::DenseMap<const CXXRecordDecl *,
-                         llvm::DenseMap<CtorVtable_t, int64_t>*> AddrMap_t;
+  typedef llvm::DenseMap<CtorVtable_t, int64_t> AddrSubMap_t;
+  typedef llvm::DenseMap<const CXXRecordDecl *, AddrSubMap_t *> AddrMap_t;
   llvm::DenseMap<const CXXRecordDecl *, AddrMap_t*> AddressPoints;
 
   /// GetCXXBaseClassOffset - Returns the offset from a derived class to its