[cfe-commits] r85677 - in /cfe/trunk: lib/CodeGen/CGVtable.cpp test/CodeGenCXX/virt.cpp

Mike Stump mrs at apple.com
Sat Oct 31 13:06:59 PDT 2009


Author: mrs
Date: Sat Oct 31 15:06:59 2009
New Revision: 85677

URL: http://llvm.org/viewvc/llvm-project?rev=85677&view=rev
Log:
Refine vcall/vbase ordering with vtable construction.

Modified:
    cfe/trunk/lib/CodeGen/CGVtable.cpp
    cfe/trunk/test/CodeGenCXX/virt.cpp

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

==============================================================================
--- cfe/trunk/lib/CodeGen/CGVtable.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGVtable.cpp Sat Oct 31 15:06:59 2009
@@ -95,8 +95,10 @@
     return llvm::ConstantExpr::getBitCast(m, Ptr8Ty);
   }
 
-  void GenerateVBaseOffsets(std::vector<llvm::Constant *> &offsets,
-                            const CXXRecordDecl *RD, uint64_t Offset,
+#define D1(x)
+//#define D1(X) do { if (getenv("DEBUG")) { X; } } while (0)
+
+  void GenerateVBaseOffsets(const CXXRecordDecl *RD, uint64_t Offset,
                             bool updateVBIndex, Index_t current_vbindex) {
     for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(),
            e = RD->bases_end(); i != e; ++i) {
@@ -105,22 +107,24 @@
       Index_t next_vbindex = current_vbindex;
       if (i->isVirtual() && !SeenVBase.count(Base)) {
         SeenVBase.insert(Base);
-        int64_t BaseOffset = -(Offset/8) + BLayout.getVBaseClassOffset(Base)/8;
-        llvm::Constant *m = wrap(BaseOffset);
-        m = wrap((0?700:0) + BaseOffset);
         if (updateVBIndex) {
-          next_vbindex = (ssize_t)(-(offsets.size()*LLVMPointerWidth/8)
+          next_vbindex = (ssize_t)(-(VCalls.size()*LLVMPointerWidth/8)
                                    - 3*LLVMPointerWidth/8);
           VBIndex[Base] = next_vbindex;
         }
-        offsets.push_back(m);
+        int64_t BaseOffset = -(Offset/8) + BLayout.getVBaseClassOffset(Base)/8;
+        VCalls.push_back((0?700:0) + BaseOffset);
+        D1(printf("  vbase for %s at %d delta %d most derived %s\n",
+                  Base->getNameAsCString(),
+                  (int)-VCalls.size()-3, (int)BaseOffset,
+                  Class->getNameAsCString()));
       }
       // We also record offsets for non-virtual bases to closest enclosing
       // virtual base.  We do this so that we don't have to search
       // for the nearst virtual base class when generating thunks.
       if (updateVBIndex && VBIndex.count(Base) == 0)
         VBIndex[Base] = next_vbindex;
-      GenerateVBaseOffsets(offsets, Base, Offset, updateVBIndex, next_vbindex);
+      GenerateVBaseOffsets(Base, Offset, updateVBIndex, next_vbindex);
     }
   }
 
@@ -237,9 +241,17 @@
             VCallOffset[MD] = OverrideOffset/8;
             idx = VCalls.size()+1;
             VCalls.push_back(0);
+            D1(printf("  vcall for %s at %d with delta %d most derived %s\n",
+                      MD->getNameAsCString(),
+                      (int)-VCalls.size()-3, (int)VCallOffset[MD],
+                      Class->getNameAsCString()));
           } else {
             VCallOffset[MD] = VCallOffset[OMD];
             VCalls[idx-1] = -VCallOffset[OMD] + OverrideOffset/8;
+            D1(printf("  vcall patch for %s at %d with delta %d most derived %s\n",
+                      MD->getNameAsCString(),
+                      (int)-VCalls.size()-3, (int)VCallOffset[MD],
+                      Class->getNameAsCString()));
           }
           VCall[MD] = idx;
           CallOffset ThisOffset;
@@ -340,7 +352,8 @@
     }
   }
 
-  void AddMethod(const CXXMethodDecl *MD, bool MorallyVirtual, Index_t Offset) {
+  void AddMethod(const CXXMethodDecl *MD, bool MorallyVirtual, Index_t Offset,
+    bool ForVirtualBase) {
     llvm::Constant *m = WrapAddrOf(MD);
 
     // If we can find a previously allocated slot for this, reuse it.
@@ -350,6 +363,7 @@
     // else allocate a new slot.
     Index[MD] = submethods.size();
     submethods.push_back(m);
+    D1(printf("  vfn for %s at %d\n", MD->getNameAsCString(), (int)Index[MD]));
     if (MD->isPure())
       Pures[MD] = 1;
     if (MorallyVirtual) {
@@ -359,16 +373,19 @@
       if (idx == 0) {
         idx = VCalls.size()+1;
         VCalls.push_back(0);
+        D1(printf("  vcall for %s at %d with delta %d\n",
+                  MD->getNameAsCString(), (int)-VCalls.size()-3,
+                  (int)VCallOffset[MD]));
       }
     }
   }
 
   void AddMethods(const CXXRecordDecl *RD, bool MorallyVirtual,
-                  Index_t Offset) {
+                  Index_t Offset, bool RDisVirtualBase) {
     for (method_iter mi = RD->method_begin(), me = RD->method_end(); mi != me;
          ++mi)
       if (mi->isVirtual())
-        AddMethod(*mi, MorallyVirtual, Offset);
+        AddMethod(*mi, MorallyVirtual, Offset, RDisVirtualBase);
   }
 
   void NonVirtualBases(const CXXRecordDecl *RD, const ASTRecordLayout &Layout,
@@ -397,6 +414,7 @@
 
   void insertVCalls(int InsertionPoint) {
     llvm::Constant *e = 0;
+    D1(printf("============= combining vbase/vcall\n"));
     D(VCalls.insert(VCalls.begin(), 673));
     D(VCalls.push_back(672));
     methods.insert(methods.begin() + InsertionPoint, VCalls.size(), e);
@@ -408,11 +426,10 @@
     VCalls.clear();
   }
 
-  Index_t end(const CXXRecordDecl *RD, std::vector<llvm::Constant *> &offsets,
-              const ASTRecordLayout &Layout,
-              const CXXRecordDecl *PrimaryBase,
-              bool PrimaryBaseWasVirtual, bool MorallyVirtual,
-              int64_t Offset, bool ForVirtualBase, Path_t *Path) {
+  Index_t end(const CXXRecordDecl *RD, const ASTRecordLayout &Layout,
+              const CXXRecordDecl *PrimaryBase, bool PrimaryBaseWasVirtual,
+              bool MorallyVirtual, int64_t Offset, bool ForVirtualBase,
+              Path_t *Path) {
     bool alloc = false;
     if (Path == 0) {
       alloc = true;
@@ -421,16 +438,6 @@
 
     StartNewTable();
     extra = 0;
-    // FIXME: Cleanup.
-    if (!ForVirtualBase) {
-      D(methods.push_back(wrap(666)));
-      // then virtual base offsets...
-      for (std::vector<llvm::Constant *>::reverse_iterator i = offsets.rbegin(),
-             e = offsets.rend(); i != e; ++i)
-        methods.push_back(*i);
-      D(methods.push_back(wrap(667)));
-    }
-
     bool DeferVCalls = MorallyVirtual || ForVirtualBase;
     int VCallInsertionPoint = methods.size();
     if (!DeferVCalls) {
@@ -439,20 +446,12 @@
       // FIXME: just for extra, or for all uses of VCalls.size post this?
       extra = -VCalls.size();
 
-    if (ForVirtualBase) {
-      D(methods.push_back(wrap(668)));
-      // then virtual base offsets...
-      for (std::vector<llvm::Constant *>::reverse_iterator i = offsets.rbegin(),
-             e = offsets.rend(); i != e; ++i)
-        methods.push_back(*i);
-      D(methods.push_back(wrap(669)));
-    }
-
     methods.push_back(wrap(-(Offset/8)));
     methods.push_back(rtti);
     Index_t AddressPoint = methods.size();
 
     InstallThunks();
+    D1(printf("============= combining methods\n"));
     methods.insert(methods.end(), submethods.begin(), submethods.end());
     submethods.clear();
 
@@ -461,10 +460,8 @@
                     MorallyVirtual, Offset, Path);
 
     if (ForVirtualBase) {
-      D(methods.push_back(wrap(670)));
       insertVCalls(VCallInsertionPoint);
       AddressPoint += VCalls.size();
-      D(methods.push_back(wrap(671)));
     }
     
     if (alloc) {
@@ -473,7 +470,36 @@
     return AddressPoint;
   }
 
-  void Primaries(const CXXRecordDecl *RD, bool MorallyVirtual, int64_t Offset) {
+  void Primaries(const CXXRecordDecl *RD, bool MorallyVirtual, int64_t Offset,
+                 bool updateVBIndex, Index_t current_vbindex,
+                 bool RDisVirtualBase) {
+    if (!RD->isDynamicClass())
+      return;
+
+    const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD);
+    const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase();
+    const bool PrimaryBaseWasVirtual = Layout.getPrimaryBaseWasVirtual();
+
+    // vtables are composed from the chain of primaries.
+    if (PrimaryBase) {
+      D1(printf(" doing primaries for %s most derived %s\n",
+                RD->getNameAsCString(), Class->getNameAsCString()));
+      
+      if (!PrimaryBaseWasVirtual)
+        Primaries(PrimaryBase, PrimaryBaseWasVirtual|MorallyVirtual, Offset,
+                  updateVBIndex, current_vbindex, PrimaryBaseWasVirtual);
+    }
+
+    D1(printf(" doing vcall entries for %s most derived %s\n",
+              RD->getNameAsCString(), Class->getNameAsCString()));
+
+    // And add the virtuals for the class to the primary vtable.
+    AddMethods(RD, MorallyVirtual, Offset, RDisVirtualBase);
+  }
+
+  void VBPrimaries(const CXXRecordDecl *RD, bool MorallyVirtual, int64_t Offset,
+                   bool updateVBIndex, Index_t current_vbindex,
+                   bool RDisVirtualBase, bool bottom=false) {
     if (!RD->isDynamicClass())
       return;
 
@@ -485,11 +511,22 @@
     if (PrimaryBase) {
       if (PrimaryBaseWasVirtual)
         IndirectPrimary.insert(PrimaryBase);
-      Primaries(PrimaryBase, PrimaryBaseWasVirtual|MorallyVirtual, Offset);
+
+      D1(printf(" doing primaries for %s most derived %s\n",
+                RD->getNameAsCString(), Class->getNameAsCString()));
+      
+      VBPrimaries(PrimaryBase, PrimaryBaseWasVirtual|MorallyVirtual, Offset,
+                  updateVBIndex, current_vbindex, PrimaryBaseWasVirtual);
     }
 
-    // And add the virtuals for the class to the primary vtable.
-    AddMethods(RD, MorallyVirtual, Offset);
+    D1(printf(" doing vbase entries for %s most derived %s\n",
+              RD->getNameAsCString(), Class->getNameAsCString()));
+    GenerateVBaseOffsets(RD, Offset, updateVBIndex, current_vbindex);
+
+    if (RDisVirtualBase || bottom) {
+      Primaries(RD, MorallyVirtual, Offset, updateVBIndex, current_vbindex,
+                RDisVirtualBase);
+    }
   }
 
   int64_t GenerateVtableForBase(const CXXRecordDecl *RD,
@@ -503,19 +540,21 @@
     const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase();
     const bool PrimaryBaseWasVirtual = Layout.getPrimaryBaseWasVirtual();
 
-    std::vector<llvm::Constant *> offsets;
     extra = 0;
-    GenerateVBaseOffsets(offsets, RD, Offset, !ForVirtualBase, 0);
+    D1(printf("building entries for base %s most derived %s\n",
+              RD->getNameAsCString(), Class->getNameAsCString()));
+
     if (ForVirtualBase)
-      extra = offsets.size();
+      extra = VCalls.size();
 
-    Primaries(RD, MorallyVirtual, Offset);
+    VBPrimaries(RD, MorallyVirtual, Offset, !ForVirtualBase, 0, ForVirtualBase,
+                true);
 
     if (Path)
       OverrideMethods(Path, MorallyVirtual, Offset);
 
-    return end(RD, offsets, Layout, PrimaryBase, PrimaryBaseWasVirtual,
-               MorallyVirtual, Offset, ForVirtualBase, Path);
+    return end(RD, Layout, PrimaryBase, PrimaryBaseWasVirtual, MorallyVirtual,
+               Offset, ForVirtualBase, Path);
   }
 
   void GenerateVtableForVBases(const CXXRecordDecl *RD,
@@ -540,6 +579,8 @@
         VCall.clear();
         int64_t BaseOffset = BLayout.getVBaseClassOffset(Base);
         CurrentVBaseOffset = BaseOffset;
+        D1(printf("vtable %s virtual base %s\n",
+                  Class->getNameAsCString(), Base->getNameAsCString()));
         GenerateVtableForBase(Base, true, BaseOffset, true, Path);
       }
       int64_t BaseOffset = Offset;
@@ -575,6 +616,7 @@
   // FIXME: This seems expensive.  Can we do a partial job to get
   // just this data.
   VtableBuilder b(methods, RD, CGM);
+  D1(printf("vtable %s\n", RD->getNameAsCString()));
   b.GenerateVtableForBase(RD);
   b.GenerateVtableForVBases(RD);
   
@@ -599,6 +641,7 @@
   // FIXME: This seems expensive.  Can we do a partial job to get
   // just this data.
   VtableBuilder b(methods, RD, CGM);
+  D1(printf("vtable %s\n", RD->getNameAsCString()));
   b.GenerateVtableForBase(RD);
   b.GenerateVtableForVBases(RD);
   
@@ -629,6 +672,7 @@
 
   VtableBuilder b(methods, RD, CGM);
 
+  D1(printf("vtable %s\n", RD->getNameAsCString()));
   // First comes the vtables for all the non-virtual bases...
   AddressPoint = b.GenerateVtableForBase(RD);
 

Modified: cfe/trunk/test/CodeGenCXX/virt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/virt.cpp?rev=85677&r1=85676&r2=85677&view=diff

==============================================================================
--- cfe/trunk/test/CodeGenCXX/virt.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/virt.cpp Sat Oct 31 15:06:59 2009
@@ -306,10 +306,10 @@
 // CHECK-LP32-NEXT: .long __ZN9test5_B227funcB22Ev
 // CHECK-LP32-NEXT: .long __ZN9test5_B217funcB21Ev
 // CHECK-LP32-NEXT: .space 4
-// CHECK-LP32: .long 8
-// CHECK-LP32 .space 4
-// CHECK-LP32 .space 4                       FIXME
-// CHECK-LP32: .long 4
+// CHECK-LP32-NEXT: .long 8
+// CHECK-LP32-NEXT: .space 4
+// CHECK-LP32-NEXT: .space 4
+// CHECK-LP32-NEXT: .long 4
 // CHECK-LP32-NEXT: .space 4
 // CHECK-LP32-NEXT: .space 4
 // CHECK-LP32-NEXT: .long 4294967288
@@ -358,10 +358,10 @@
 // CHECK-LP64-NEXT: .quad __ZN9test5_B227funcB22Ev
 // CHECK-LP64-NEXT: .quad __ZN9test5_B217funcB21Ev
 // CHECK-LP64-NEXT: .space 8
-// CHECK-LP64: .quad 16
-// CHECK-LP64 .space 8
-// CHECK-LP64 .space 8
-// CHECK-LP64: .quad 8
+// CHECK-LP64-NEXT: .quad 16
+// CHECK-LP64-NEXT: .space 8
+// CHECK-LP64-NEXT: .space 8
+// CHECK-LP64-NEXT: .quad 8
 // CHECK-LP64-NEXT: .space 8
 // CHECK-LP64-NEXT: .space 8
 // CHECK-LP64-NEXT: .quad 18446744073709551600





More information about the cfe-commits mailing list