]> granicus.if.org Git - clang/commitdiff
A bunch more thunk fixes from misc testing.
authorEli Friedman <eli.friedman@gmail.com>
Mon, 7 Dec 2009 23:56:34 +0000 (23:56 +0000)
committerEli Friedman <eli.friedman@gmail.com>
Mon, 7 Dec 2009 23:56:34 +0000 (23:56 +0000)
(Yes, I do intend to commit some tests for this.)

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

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

index 77bee48b58b66ade1999f364711eab31e08b15bd..d82f9359716e954a84fbcf3614dadf3e34aca23d 100644 (file)
@@ -1030,23 +1030,14 @@ CodeGenModule::GetAddrOfCovariantThunk(GlobalDecl GD,
 }
 
 void CodeGenModule::BuildThunksForVirtual(GlobalDecl GD) {
-  BuildThunksForVirtualRecursive(GD, GD);
-}
-
-void
-CodeGenModule::BuildThunksForVirtualRecursive(GlobalDecl GD,
-                                              GlobalDecl BaseOGD) {
+  CGVtableInfo::AdjustmentVectorTy *AdjPtr = getVtableInfo().getAdjustments(GD);
+  if (!AdjPtr)
+    return;
+  CGVtableInfo::AdjustmentVectorTy &Adj = *AdjPtr;
   const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
-  const CXXMethodDecl *BaseOMD = cast<CXXMethodDecl>(BaseOGD.getDecl());
-  for (CXXMethodDecl::method_iterator mi = BaseOMD->begin_overridden_methods(),
-         e = BaseOMD->end_overridden_methods();
-       mi != e; ++mi) {
-    GlobalDecl OGD;
-    const CXXMethodDecl *OMD = *mi;
-    if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(OMD))
-      OGD = GlobalDecl(DD, GD.getDtorType());
-    else
-      OGD = GlobalDecl(OMD);
+  for (unsigned i = 0; i < Adj.size(); i++) {
+    GlobalDecl OGD = Adj[i].first;
+    const CXXMethodDecl *OMD = cast<CXXMethodDecl>(OGD.getDecl());
     QualType nc_oret = OMD->getType()->getAs<FunctionType>()->getResultType();
     CanQualType oret = getContext().getCanonicalType(nc_oret);
     QualType nc_ret = MD->getType()->getAs<FunctionType>()->getResultType();
@@ -1059,8 +1050,7 @@ CodeGenModule::BuildThunksForVirtualRecursive(GlobalDecl GD,
       CXXRecordDecl *B = cast<CXXRecordDecl>(qB->getAs<RecordType>()->getDecl());
       ReturnAdjustment = ComputeThunkAdjustment(D, B);
     }
-    ThunkAdjustment ThisAdjustment =
-        getVtableInfo().getThisAdjustment(GD, OGD);
+    ThunkAdjustment ThisAdjustment = Adj[i].second;
     bool Extern = !cast<CXXRecordDecl>(OMD->getDeclContext())->isInAnonymousNamespace();
     if (!ReturnAdjustment.isEmpty() || !ThisAdjustment.isEmpty()) {
       CovariantThunkAdjustment CoAdj(ThisAdjustment, ReturnAdjustment);
@@ -1070,7 +1060,24 @@ CodeGenModule::BuildThunksForVirtualRecursive(GlobalDecl GD,
       else
         FnConst = GetAddrOfThunk(GD, ThisAdjustment);
       if (!isa<llvm::Function>(FnConst)) {
-        assert(0 && "Figure out how to handle incomplete-type cases!");
+        llvm::Constant *SubExpr =
+            cast<llvm::ConstantExpr>(FnConst)->getOperand(0);
+        llvm::Function *OldFn = cast<llvm::Function>(SubExpr);
+        std::string Name = OldFn->getNameStr();
+        GlobalDeclMap.erase(UniqueMangledName(Name.data(),
+                                              Name.data() + Name.size() + 1));
+        llvm::Constant *NewFnConst;
+        if (!ReturnAdjustment.isEmpty())
+          NewFnConst = GetAddrOfCovariantThunk(GD, CoAdj);
+        else
+          NewFnConst = GetAddrOfThunk(GD, ThisAdjustment);
+        llvm::Function *NewFn = cast<llvm::Function>(NewFnConst);
+        NewFn->takeName(OldFn);
+        llvm::Constant *NewPtrForOldDecl =
+            llvm::ConstantExpr::getBitCast(NewFn, OldFn->getType());
+        OldFn->replaceAllUsesWith(NewPtrForOldDecl);
+        OldFn->eraseFromParent();
+        FnConst = NewFn;
       }
       llvm::Function *Fn = cast<llvm::Function>(FnConst);
       if (Fn->isDeclaration()) {
@@ -1085,7 +1092,6 @@ CodeGenModule::BuildThunksForVirtualRecursive(GlobalDecl GD,
         CodeGenFunction(*this).GenerateCovariantThunk(Fn, GD, Extern, CoAdj);
       }
     }
-    BuildThunksForVirtualRecursive(GD, OGD);
   }
 }
 
index bca893e5b6686c6c281aedef1d57ae2df49e59f0..7efa88b8e144082d2352838ce98a0941d7344ea6 100644 (file)
@@ -26,6 +26,9 @@ class VtableBuilder {
 public:
   /// Index_t - Vtable index type.
   typedef uint64_t Index_t;
+  typedef std::vector<std::pair<GlobalDecl,
+                                std::pair<GlobalDecl, ThunkAdjustment> > >
+      SavedAdjustmentsVectorTy;
 private:
   
   // VtableComponents - The components of the vtable being built.
@@ -142,9 +145,7 @@ private:
   typedef llvm::DenseMap<uint64_t, ThunkAdjustment> ThisAdjustmentsMapTy;
   ThisAdjustmentsMapTy ThisAdjustments;
 
-  typedef std::vector<std::pair<std::pair<GlobalDecl, GlobalDecl>,
-                                ThunkAdjustment> > SavedThisAdjustmentsVectorTy;
-  SavedThisAdjustmentsVectorTy SavedThisAdjustments;
+  SavedAdjustmentsVectorTy SavedAdjustments;
 
   /// BaseReturnTypes - Contains the base return types of methods who have been
   /// overridden with methods whose return types require adjustment. Used for
@@ -213,8 +214,8 @@ public:
   llvm::DenseMap<const CXXRecordDecl *, Index_t> &getVBIndex()
     { return VBIndex; }
 
-  SavedThisAdjustmentsVectorTy &getSavedThisAdjustments()
-    { return SavedThisAdjustments; }
+  SavedAdjustmentsVectorTy &getSavedAdjustments()
+    { return SavedAdjustments; }
 
   llvm::Constant *wrap(Index_t i) {
     llvm::Constant *m;
@@ -376,8 +377,9 @@ public:
 
     D1(printf("  vfn for %s at %d\n", MD->getNameAsString().c_str(),
               (int)Index[GD]));
+
+    VCallOffset[GD] = Offset/8;
     if (MorallyVirtual) {
-      VCallOffset[GD] = Offset/8;
       Index_t &idx = VCall[GD];
       // Allocate the first one, after that, we reuse the previous one.
       if (idx == 0) {
@@ -838,22 +840,21 @@ bool VtableBuilder::OverrideMethod(GlobalDecl GD, bool MorallyVirtual,
 
       if (!isPure && !ThisAdjustment.isEmpty()) {
         ThisAdjustments[Index] = ThisAdjustment;
-        SavedThisAdjustments.push_back(std::make_pair(std::make_pair(GD, OGD),
-                                                      ThisAdjustment));
+        SavedAdjustments.push_back(
+            std::make_pair(GD, std::make_pair(OGD, ThisAdjustment)));
       }
       return true;
     }
 
-    // FIXME: finish off
-    int64_t NonVirtualAdjustment = VCallOffset[OGD] - OverrideOffset/8;
+    int64_t NonVirtualAdjustment = -VCallOffset[OGD] + OverrideOffset/8;
 
     if (NonVirtualAdjustment) {
       ThunkAdjustment ThisAdjustment(NonVirtualAdjustment, 0);
       
       if (!isPure) {
         ThisAdjustments[Index] = ThisAdjustment;
-        SavedThisAdjustments.push_back(std::make_pair(std::make_pair(GD, OGD),
-                                                      ThisAdjustment));
+        SavedAdjustments.push_back(
+            std::make_pair(GD, std::make_pair(OGD, ThisAdjustment)));
       }
     }
     return true;
@@ -1070,30 +1071,31 @@ uint64_t CGVtableInfo::getMethodVtableIndex(GlobalDecl GD) {
   return I->second;
 }
 
-ThunkAdjustment CGVtableInfo::getThisAdjustment(GlobalDecl GD,
-                                                GlobalDecl OGD) {
-  SavedThisAdjustmentsTy::iterator I =
-    SavedThisAdjustments.find(std::make_pair(GD, OGD));
-  if (I != SavedThisAdjustments.end())
-    return I->second;
+CGVtableInfo::AdjustmentVectorTy*
+CGVtableInfo::getAdjustments(GlobalDecl GD) {
+  SavedAdjustmentsTy::iterator I = SavedAdjustments.find(GD);
+  if (I != SavedAdjustments.end())
+    return &I->second;
 
   const CXXRecordDecl *RD = cast<CXXRecordDecl>(GD.getDecl()->getDeclContext());
-  if (!SavedThisAdjustmentRecords.insert(RD).second)
-    return ThunkAdjustment();
+  if (!SavedAdjustmentRecords.insert(RD).second)
+    return 0;
 
   VtableBuilder b(RD, RD, 0, CGM, false);
   D1(printf("vtable %s\n", RD->getNameAsCString()));
   b.GenerateVtableForBase(RD);
   b.GenerateVtableForVBases(RD);
-  
-  SavedThisAdjustments.insert(b.getSavedThisAdjustments().begin(),
-                              b.getSavedThisAdjustments().end());
 
-  I = SavedThisAdjustments.find(std::make_pair(GD, OGD));
-  if (I != SavedThisAdjustments.end())
-    return I->second;
+  for (VtableBuilder::SavedAdjustmentsVectorTy::iterator
+       i = b.getSavedAdjustments().begin(),
+       e = b.getSavedAdjustments().end(); i != e; i++)
+    SavedAdjustments[i->first].push_back(i->second);
+
+  I = SavedAdjustments.find(GD);
+  if (I != SavedAdjustments.end())
+    return &I->second;
 
-  return ThunkAdjustment();
+  return 0;
 }
 
 int64_t CGVtableInfo::getVirtualBaseOffsetIndex(const CXXRecordDecl *RD, 
@@ -1470,7 +1472,7 @@ void CGVtableInfo::MaybeEmitVtable(GlobalDecl GD) {
 
   for (CXXRecordDecl::method_iterator i = RD->method_begin(),
        e = RD->method_end(); i != e; ++i) {
-    if ((*i)->isVirtual() && (*i)->hasInlineBody()) {
+    if ((*i)->isVirtual() && ((*i)->hasInlineBody() || (*i)->isImplicit())) {
       if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(*i)) {
         CGM.BuildThunksForVirtual(GlobalDecl(DD, Dtor_Complete));
         CGM.BuildThunksForVirtual(GlobalDecl(DD, Dtor_Deleting));
index 1507725f0fbd15f64f8c48fc171d9c4c73202122..eed5b64085b08a6d12664d4c5b5f144f55315725 100644 (file)
@@ -62,6 +62,11 @@ public:
 };
 
 class CGVtableInfo {
+public:
+  typedef std::vector<std::pair<GlobalDecl, ThunkAdjustment> >
+      AdjustmentVectorTy;
+
+private:
   CodeGenModule &CGM;
 
   /// MethodVtableIndices - Contains the index (relative to the vtable address
@@ -84,10 +89,9 @@ class CGVtableInfo {
   /// pointers in the vtable for a given record decl.
   llvm::DenseMap<const CXXRecordDecl *, uint64_t> NumVirtualFunctionPointers;
 
-  typedef llvm::DenseMap<std::pair<GlobalDecl, GlobalDecl>,
-                         ThunkAdjustment> SavedThisAdjustmentsTy;
-  SavedThisAdjustmentsTy SavedThisAdjustments;
-  llvm::DenseSet<const CXXRecordDecl*> SavedThisAdjustmentRecords;
+  typedef llvm::DenseMap<GlobalDecl, AdjustmentVectorTy> SavedAdjustmentsTy;
+  SavedAdjustmentsTy SavedAdjustments;
+  llvm::DenseSet<const CXXRecordDecl*> SavedAdjustmentRecords;
 
   /// getNumVirtualFunctionPointers - Return the number of virtual function
   /// pointers in the vtable for a given record decl.
@@ -128,7 +132,7 @@ public:
   int64_t getVirtualBaseOffsetIndex(const CXXRecordDecl *RD,
                                     const CXXRecordDecl *VBase);
 
-  ThunkAdjustment getThisAdjustment(GlobalDecl GD, GlobalDecl OGD);
+  AdjustmentVectorTy *getAdjustments(GlobalDecl GD);
 
   /// getVtableAddressPoint - returns the address point of the vtable for the
   /// given record decl.
index 5f822f509f81e18cdfd076418c478e7fadce6902..6250e6952d39b83e1610c5d153f328cb09c4e952 100644 (file)
@@ -625,7 +625,13 @@ void CodeGenModule::EmitGlobalDefinition(GlobalDecl GD) {
     getVtableInfo().MaybeEmitVtable(GD);
     if (MD->isVirtual() && MD->isOutOfLine() &&
         (!isa<CXXDestructorDecl>(D) || GD.getDtorType() != Dtor_Base)) {
-      BuildThunksForVirtual(GD);
+      if (isa<CXXDestructorDecl>(D)) {
+        GlobalDecl CanonGD(cast<CXXDestructorDecl>(D->getCanonicalDecl()),
+                           GD.getDtorType());
+        BuildThunksForVirtual(CanonGD);
+      } else {
+        BuildThunksForVirtual(MD->getCanonicalDecl());
+      }
     }
   }