[cfe-commits] r87021 - in /cfe/trunk/lib/CodeGen: CGVtable.cpp CodeGenModule.h

Mike Stump mrs at apple.com
Thu Nov 12 12:47:58 PST 2009


Author: mrs
Date: Thu Nov 12 14:47:57 2009
New Revision: 87021

URL: http://llvm.org/viewvc/llvm-project?rev=87021&view=rev
Log:
Fix the offset calculations for non-virtual bases with overrides.

Refine the VTT entries for virtual bases to refer to the complete
object's vtable instead of constructor vtables.

Refine the AddressPoint calculations for VTT entries for virtual bases.

Modified:
    cfe/trunk/lib/CodeGen/CGVtable.cpp
    cfe/trunk/lib/CodeGen/CodeGenModule.h

Modified: cfe/trunk/lib/CodeGen/CGVtable.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGVtable.cpp?rev=87021&r1=87020&r2=87021&view=diff

==============================================================================
--- cfe/trunk/lib/CodeGen/CGVtable.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGVtable.cpp Thu Nov 12 14:47:57 2009
@@ -56,6 +56,12 @@
                                    CanQualType> > CovariantThunks_t;
   CovariantThunks_t CovariantThunks;
   std::vector<Index_t> VCalls;
+
+  typedef std::pair<const CXXRecordDecl *, uint64_t> CtorVtable_t;
+  // CtorVtable - Used to hold the AddressPoints (offsets) into the built vtable
+  // for use in computing the initializers for the VTT.
+  llvm::DenseMap<CtorVtable_t, int64_t> &AddressPoints;
+
   typedef CXXRecordDecl::method_iterator method_iter;
   // FIXME: Linkage should follow vtable
   const bool Extern;
@@ -69,7 +75,8 @@
                 CodeGenModule &cgm)
     : methods(meth), Class(c), BLayout(cgm.getContext().getASTRecordLayout(c)),
       rtti(cgm.GenerateRtti(c)), VMContext(cgm.getModule().getContext()),
-      CGM(cgm), Extern(true),
+      CGM(cgm), AddressPoints(*new llvm::DenseMap<CtorVtable_t, int64_t>),
+      Extern(true),
       LLVMPointerWidth(cgm.getContext().Target.getPointerWidth(0)) {
     Ptr8Ty = llvm::PointerType::get(llvm::Type::getInt8Ty(VMContext), 0);
 
@@ -85,6 +92,9 @@
   llvm::DenseMap<const CXXRecordDecl *, Index_t> &getVBIndex()
     { return VBIndex; }
 
+  llvm::DenseMap<CtorVtable_t, int64_t> *getAddressPoints()
+    { return &AddressPoints; }
+
   llvm::Constant *wrap(Index_t i) {
     llvm::Constant *m;
     m = llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext), i);
@@ -471,10 +481,25 @@
                     MorallyVirtual, Offset, CurrentVBaseOffset, Path);
 
     if (ForVirtualBase) {
-      insertVCalls(VCallInsertionPoint);
+      // FIXME: We're adding to VCalls in callers, we need to do the overrides
+      // in the inner part, so that we know the complete set of vcalls during
+      // the build and don't have to insert into methods.  Saving out the
+      // AddressPoint here, would need to be fixed, if we didn't do that.  Also
+      // retroactively adding vcalls for overrides later wind up in the wrong
+      // place, the vcall slot has to be alloted during the walk of the base
+      // when the function is first introduces.
       AddressPoint += VCalls.size();
+      insertVCalls(VCallInsertionPoint);
     }
     
+    if (MorallyVirtual) {
+      D1(printf("XXX address point for %s in %s at offset %d is %d\n",
+                RD->getNameAsCString(), Class->getNameAsCString(),
+                (int)Offset, (int)AddressPoint));
+      AddressPoints[std::make_pair(RD, Offset)] = AddressPoint;
+      
+    }
+
     if (alloc) {
       delete Path;
     }
@@ -606,9 +631,14 @@
         GenerateVtableForBase(Base, true, BaseOffset, true, CurrentVBaseOffset,
                               Path);
       }
-      int64_t BaseOffset = Offset;
+      int64_t BaseOffset;
       if (i->isVirtual())
         BaseOffset = BLayout.getVBaseClassOffset(Base);
+      else {
+        const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD);
+        BaseOffset = Offset + Layout.getBaseClassOffset(Base);
+      }
+        
       if (Base->getNumVBases()) {
         GenerateVtableForVBases(Base, BaseOffset, Path);
       }
@@ -681,13 +711,13 @@
   return I->second;
 }
 
-llvm::Constant *CodeGenModule::GenerateVtable(const CXXRecordDecl *RD,
-                                              const CXXRecordDecl *LayoutClass,
+llvm::Constant *CodeGenModule::GenerateVtable(const CXXRecordDecl *LayoutClass,
+                                              const CXXRecordDecl *RD,
                                               uint64_t Offset) {
   llvm::SmallString<256> OutName;
   llvm::raw_svector_ostream Out(OutName);
-  if (LayoutClass)
-    mangleCXXCtorVtable(getMangleContext(), LayoutClass, Offset, RD, Out);
+  if (LayoutClass != RD)
+    mangleCXXCtorVtable(getMangleContext(), LayoutClass, Offset/8, RD, Out);
   else
     mangleCXXVtable(getMangleContext(), RD, Out);
 
@@ -706,6 +736,9 @@
   // then the vtables for all the virtual bases.
   b.GenerateVtableForVBases(RD);
 
+  if (LayoutClass == RD)
+    AddressPoints[RD] = b.getAddressPoints();
+
   llvm::Constant *C;
   llvm::ArrayType *type = llvm::ArrayType::get(Ptr8Ty, methods.size());
   C = llvm::ConstantArray::get(type, methods);
@@ -717,7 +750,8 @@
   uint32_t LLVMPointerWidth = getContext().Target.getPointerWidth(0);
   AddressPointC = llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext),
                                          AddressPoint*LLVMPointerWidth/8);
-  vtable = llvm::ConstantExpr::getGetElementPtr(vtable, &AddressPointC, 1);
+  vtable = llvm::ConstantExpr::getInBoundsGetElementPtr(vtable, &AddressPointC,
+                                                        1);
 
   return vtable;
 }
@@ -732,8 +766,12 @@
   /// BLayout - Layout for the most derived class that this vtable is being
   /// built for.
   const ASTRecordLayout &BLayout;
+  // vtbl - A pointer to the vtable for Class.
+  llvm::Constant *ClassVtbl;
+  llvm::LLVMContext &VMContext;
 
-  /// Secondary - Add the secondary vtable pointers to Inits.
+  /// Secondary - Add the secondary vtable pointers to Inits.  Offset is the
+  /// current offset in bits to the object we're working on.
   void Secondary(const CXXRecordDecl *RD, uint64_t Offset=0,
                  bool MorallyVirtual=false) {
     if (RD->getNumVBases() == 0 && ! MorallyVirtual)
@@ -759,24 +797,37 @@
           && !NonVirtualPrimaryBase) {
         // FIXME: Slightly too many of these for __ZTT8test8_B2
         llvm::Constant *vtbl;
-        vtbl = CGM.getVtableInfo().getCtorVtable(Base, Class, BaseOffset/8);
+        vtbl = CGM.getVtableInfo().getCtorVtable(Class, Base, BaseOffset);
         Inits.push_back(vtbl);
       }
       Secondary(Base, BaseOffset, BaseMorallyVirtual);
     }
   }
 
-  /// BuiltVTT - Add the VTT to Inits.
-  void BuildVTT(const CXXRecordDecl *RD, uint64_t Offset,
-                bool MorallyVirtual=false) {
+  /// BuiltVTT - Add the VTT to Inits.  Offset is the offset in bits to the
+  /// currnet object we're working on.
+  void BuildVTT(const CXXRecordDecl *RD, uint64_t Offset, bool MorallyVirtual) {
     if (RD->getNumVBases() == 0 && !MorallyVirtual)
       return;
 
+    llvm::Constant *init;
     // First comes the primary virtual table pointer...
-    Inits.push_back(CGM.getVtableInfo().getCtorVtable(RD, Class, Offset));
+    if (MorallyVirtual) {
+      int64_t AddressPoint;
+      AddressPoint = (*CGM.AddressPoints[Class])[std::make_pair(RD, Offset)];
+      D1(printf("XXX address point for %s in %s at offset %d was %d\n",
+                RD->getNameAsCString(), Class->getNameAsCString(),
+                (int)Offset, (int)AddressPoint));
+      uint32_t LLVMPointerWidth = CGM.getContext().Target.getPointerWidth(0);
+      init = llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext),
+                                    AddressPoint*LLVMPointerWidth/8);
+      init = llvm::ConstantExpr::getInBoundsGetElementPtr(ClassVtbl, &init, 1);
+    } else
+      init = CGM.getVtableInfo().getCtorVtable(Class, RD, Offset);
+    Inits.push_back(init);
 
     // then the secondary VTTs....
-    SecondaryVTTs(RD, MorallyVirtual);
+    SecondaryVTTs(RD, Offset, MorallyVirtual);
 
     // and last the secondary vtable pointers.
     Secondary(RD, MorallyVirtual, Offset);
@@ -785,14 +836,17 @@
   /// SecondaryVTTs - Add the secondary VTTs to Inits.  The secondary VTTs are
   /// built from each direct non-virtual proper base that requires a VTT in
   /// declaration order.
-  void SecondaryVTTs(const CXXRecordDecl *RD, bool MorallyVirtual=false) {
+  void SecondaryVTTs(const CXXRecordDecl *RD, uint64_t Offset=0,
+                     bool MorallyVirtual=false) {
     for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(),
            e = RD->bases_end(); i != e; ++i) {
       const CXXRecordDecl *Base =
         cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
       if (i->isVirtual())
         continue;
-      BuildVTT(Base, MorallyVirtual);
+      const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD);
+      uint64_t BaseOffset = Offset + Layout.getBaseClassOffset(Base);
+      BuildVTT(Base, BaseOffset, MorallyVirtual);
     }
   }
 
@@ -805,7 +859,8 @@
         cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
       if (i->isVirtual() && !SeenVBase.count(Base)) {
         SeenVBase.insert(Base);
-        BuildVTT(Base, true);
+        uint64_t BaseOffset = BLayout.getVBaseClassOffset(Base);
+        BuildVTT(Base, BaseOffset, true);
       }
       VirtualVTTs(Base);
     }
@@ -814,11 +869,14 @@
   VTTBuilder(std::vector<llvm::Constant *> &inits, const CXXRecordDecl *c,
              CodeGenModule &cgm)
     : Inits(inits), Class(c), CGM(cgm),
-      BLayout(cgm.getContext().getASTRecordLayout(c)) {
+      BLayout(cgm.getContext().getASTRecordLayout(c)),
+      VMContext(cgm.getModule().getContext()) {
     
     // First comes the primary virtual table pointer for the complete class...
-    Inits.push_back(CGM.getVtableInfo().getVtable(Class));
-
+    ClassVtbl = CGM.getVtableInfo().getVtable(Class);
+    Inits.push_back(ClassVtbl);
+    ClassVtbl = dyn_cast<llvm::Constant>(ClassVtbl->getOperand(0));
+    
     // then the secondary VTTs...
     SecondaryVTTs(Class);
 
@@ -861,13 +919,13 @@
   llvm::Constant *&vtbl = Vtables[RD];
   if (vtbl)
     return vtbl;
-  vtbl = CGM.GenerateVtable(RD);
+  vtbl = CGM.GenerateVtable(RD, RD);
   CGM.GenerateVTT(RD);
   return vtbl;
 }
 
-llvm::Constant *CGVtableInfo::getCtorVtable(const CXXRecordDecl *RD,
-                                            const CXXRecordDecl *Class,
+llvm::Constant *CGVtableInfo::getCtorVtable(const CXXRecordDecl *LayoutClass,
+                                            const CXXRecordDecl *RD,
                                             uint64_t Offset) {
-  return CGM.GenerateVtable(RD, Class, Offset);
+  return CGM.GenerateVtable(LayoutClass, RD, Offset);
 }

Modified: cfe/trunk/lib/CodeGen/CodeGenModule.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.h?rev=87021&r1=87020&r2=87021&view=diff

==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenModule.h (original)
+++ cfe/trunk/lib/CodeGen/CodeGenModule.h Thu Nov 12 14:47:57 2009
@@ -250,9 +250,13 @@
   llvm::Constant *GetAddrOfFunction(GlobalDecl GD,
                                     const llvm::Type *Ty = 0);
 
-  /// GenerateVtable - Generate the vtable for the given type.
-  llvm::Constant *GenerateVtable(const CXXRecordDecl *RD,
-                                 const CXXRecordDecl *Class=0,
+  /// GenerateVtable - Generate the vtable for the given type.  LayoutClass is
+  /// the class to use for the virtual base layout information.  For
+  /// non-construction vtables, this is always the same as RD.  Offset is the
+  /// offset in bits for the RD object in the LayoutClass, if we're generating a
+  /// construction vtable, otherwise 0.
+  llvm::Constant *GenerateVtable(const CXXRecordDecl *LayoutClass,
+                                 const CXXRecordDecl *RD,
                                  uint64_t Offset=0);
 
   /// GenerateVTT - Generate the VTT for the given type.
@@ -269,6 +273,10 @@
                                       int64_t nv_t, int64_t v_t,
                                       int64_t nv_r, int64_t v_r);
 
+  typedef std::pair<const CXXRecordDecl *, uint64_t> CtorVtable_t;
+  llvm::DenseMap<const CXXRecordDecl *, llvm::DenseMap<CtorVtable_t,
+                                                       int64_t>*> AddressPoints;
+
   /// GetCXXBaseClassOffset - Returns the offset from a derived class to its
   /// base class. Returns null if the offset is 0.
   llvm::Constant *GetCXXBaseClassOffset(const CXXRecordDecl *ClassDecl,





More information about the cfe-commits mailing list