[cfe-commits] r90722 - in /cfe/trunk: lib/CodeGen/CGCXX.cpp lib/CodeGen/CGVtable.cpp lib/CodeGen/CGVtable.h lib/CodeGen/CodeGenModule.cpp lib/CodeGen/CodeGenModule.h test/CodeGenCXX/virt.cpp

Eli Friedman eli.friedman at gmail.com
Sun Dec 6 14:01:30 PST 2009


Author: efriedma
Date: Sun Dec  6 16:01:30 2009
New Revision: 90722

URL: http://llvm.org/viewvc/llvm-project?rev=90722&view=rev
Log:
Work-in-progess rewrite of thunks: move thunk generation outside of vtable
generation, and make sure we generate thunks when the function is defined
rather than when the vtable is defined.


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

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

==============================================================================
--- cfe/trunk/lib/CodeGen/CGCXX.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGCXX.cpp Sun Dec  6 16:01:30 2009
@@ -994,6 +994,102 @@
 }
 
 llvm::Constant *
+CodeGenModule::GetAddrOfThunk(GlobalDecl GD,
+                              const ThunkAdjustment &ThisAdjustment) {
+  const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
+
+  // Compute mangled name
+  llvm::SmallString<256> OutName;
+  if (const CXXDestructorDecl* DD = dyn_cast<CXXDestructorDecl>(MD))
+    getMangleContext().mangleCXXDtorThunk(DD, GD.getDtorType(), ThisAdjustment,
+                                          OutName);
+  else
+    getMangleContext().mangleThunk(MD, ThisAdjustment, OutName);
+  OutName += '\0';
+  const char* Name = UniqueMangledName(OutName.begin(), OutName.end());
+
+  // Get function for mangled name
+  const llvm::Type *Ty = getTypes().GetFunctionTypeForVtable(MD);
+  return GetOrCreateLLVMFunction(Name, Ty, GlobalDecl());
+}
+
+llvm::Constant *
+CodeGenModule::GetAddrOfCovariantThunk(GlobalDecl GD,
+                                   const CovariantThunkAdjustment &Adjustment) {
+  const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
+
+  // Compute mangled name
+  llvm::SmallString<256> OutName;
+  getMangleContext().mangleCovariantThunk(MD, Adjustment, OutName);
+  OutName += '\0';
+  const char* Name = UniqueMangledName(OutName.begin(), OutName.end());
+
+  // Get function for mangled name
+  const llvm::Type *Ty = getTypes().GetFunctionTypeForVtable(MD);
+  return GetOrCreateLLVMFunction(Name, Ty, GlobalDecl());
+}
+
+void CodeGenModule::BuildThunksForVirtual(GlobalDecl GD) {
+  BuildThunksForVirtualRecursive(GD, GD);
+}
+
+void
+CodeGenModule::BuildThunksForVirtualRecursive(GlobalDecl GD,
+                                              GlobalDecl BaseOGD) {
+  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);
+    QualType nc_oret = OMD->getType()->getAs<FunctionType>()->getResultType();
+    CanQualType oret = getContext().getCanonicalType(nc_oret);
+    QualType nc_ret = MD->getType()->getAs<FunctionType>()->getResultType();
+    CanQualType ret = getContext().getCanonicalType(nc_ret);
+    ThunkAdjustment ReturnAdjustment;
+    if (oret != ret) {
+      QualType qD = nc_ret->getPointeeType();
+      QualType qB = nc_oret->getPointeeType();
+      CXXRecordDecl *D = cast<CXXRecordDecl>(qD->getAs<RecordType>()->getDecl());
+      CXXRecordDecl *B = cast<CXXRecordDecl>(qB->getAs<RecordType>()->getDecl());
+      ReturnAdjustment = ComputeThunkAdjustment(D, B);
+    }
+    ThunkAdjustment ThisAdjustment =
+        getVtableInfo().getThisAdjustment(GD, OGD);
+    bool Extern = !cast<CXXRecordDecl>(OMD->getDeclContext())->isInAnonymousNamespace();
+    if (!ReturnAdjustment.isEmpty() || !ThisAdjustment.isEmpty()) {
+      CovariantThunkAdjustment CoAdj(ThisAdjustment, ReturnAdjustment);
+      llvm::Constant *FnConst;
+      if (!ReturnAdjustment.isEmpty())
+        FnConst = GetAddrOfCovariantThunk(GD, CoAdj);
+      else
+        FnConst = GetAddrOfThunk(GD, ThisAdjustment);
+      if (!isa<llvm::Function>(FnConst)) {
+        assert(0 && "Figure out how to handle incomplete-type cases!");
+      }
+      llvm::Function *Fn = cast<llvm::Function>(FnConst);
+      if (Fn->isDeclaration()) {
+        llvm::GlobalVariable::LinkageTypes linktype;
+        linktype = llvm::GlobalValue::WeakAnyLinkage;
+        if (!Extern)
+          linktype = llvm::GlobalValue::InternalLinkage;
+        Fn->setLinkage(linktype);
+        if (!Features.Exceptions && !Features.ObjCNonFragileABI)
+          Fn->addFnAttr(llvm::Attribute::NoUnwind);
+        Fn->setAlignment(2);
+        CodeGenFunction(*this).GenerateCovariantThunk(Fn, GD, Extern, CoAdj);
+      }
+    }
+    BuildThunksForVirtualRecursive(GD, OGD);
+  }
+}
+
+llvm::Constant *
 CodeGenModule::BuildThunk(GlobalDecl GD, bool Extern,
                           const ThunkAdjustment &ThisAdjustment) {
   const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());

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

==============================================================================
--- cfe/trunk/lib/CodeGen/CGVtable.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGVtable.cpp Sun Dec  6 16:01:30 2009
@@ -73,6 +73,7 @@
     /// Methods - The methods, in vtable order.
     typedef llvm::SmallVector<GlobalDecl, 16> MethodsVectorTy;
     MethodsVectorTy Methods;
+    MethodsVectorTy OrigMethods;
 
   public:
     /// AddMethod - Add a method to the vtable methods.
@@ -82,6 +83,7 @@
       
       MethodToIndexMap[GD] = Methods.size();
       Methods.push_back(GD);
+      OrigMethods.push_back(GD);
     }
     
     /// OverrideMethod - Replace a method with another.
@@ -113,6 +115,10 @@
       return true;
     }
 
+    GlobalDecl getOrigMethod(uint64_t Index) const {
+      return OrigMethods[Index];
+    }
+
     MethodsVectorTy::size_type size() const {
       return Methods.size();
     }
@@ -120,6 +126,7 @@
     void clear() {
       MethodToIndexMap.clear();
       Methods.clear();
+      OrigMethods.clear();
     }
     
     GlobalDecl operator[](uint64_t Index) const {
@@ -135,6 +142,10 @@
   typedef llvm::DenseMap<uint64_t, ThunkAdjustment> ThisAdjustmentsMapTy;
   ThisAdjustmentsMapTy ThisAdjustments;
 
+  typedef std::vector<std::pair<std::pair<GlobalDecl, GlobalDecl>,
+                                ThunkAdjustment> > SavedThisAdjustmentsVectorTy;
+  SavedThisAdjustmentsVectorTy SavedThisAdjustments;
+
   /// BaseReturnTypes - Contains the base return types of methods who have been
   /// overridden with methods whose return types require adjustment. Used for
   /// generating covariant thunk information.
@@ -202,6 +213,9 @@
   llvm::DenseMap<const CXXRecordDecl *, Index_t> &getVBIndex()
     { return VBIndex; }
 
+  SavedThisAdjustmentsVectorTy &getSavedThisAdjustments()
+    { return SavedThisAdjustments; }
+
   llvm::Constant *wrap(Index_t i) {
     llvm::Constant *m;
     m = llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext), i);
@@ -762,11 +776,17 @@
     else
       OGD = OMD;
 
-    // FIXME: Explain why this is necessary!
+    // Check whether this is the method being overridden in this section of
+    // the vtable.
     uint64_t Index;
     if (!Methods.getIndex(OGD, Index))
       continue;
 
+    // Get the original method, which we should be computing thunks, etc,
+    // against.
+    OGD = Methods.getOrigMethod(Index);
+    OMD = cast<CXXMethodDecl>(OGD.getDecl());
+
     QualType ReturnType = 
       MD->getType()->getAs<FunctionType>()->getResultType();
     QualType OverriddenReturnType = 
@@ -777,10 +797,6 @@
                                           OverriddenReturnType)) {
       CanQualType &BaseReturnType = BaseReturnTypes[Index];
 
-      // Get the canonical return type.
-      CanQualType CanReturnType = 
-        CGM.getContext().getCanonicalType(ReturnType);
-
       // Insert the base return type.
       if (BaseReturnType.isNull())
         BaseReturnType =
@@ -820,8 +836,12 @@
       ThunkAdjustment ThisAdjustment(NonVirtualAdjustment,
                                       VirtualAdjustment);
 
-      if (!isPure && !ThisAdjustment.isEmpty())
+      if (!isPure && !ThisAdjustment.isEmpty()) {
         ThisAdjustments[Index] = ThisAdjustment;
+        // FIXME: Might this end up inserting some false adjustments?
+        SavedThisAdjustments.push_back(std::make_pair(std::make_pair(GD, OGD),
+                                                      ThisAdjustment));
+      }
       return true;
     }
 
@@ -882,10 +902,10 @@
     if (!ReturnAdjustment.isEmpty()) {
       // Build a covariant thunk.
       CovariantThunkAdjustment Adjustment(ThisAdjustment, ReturnAdjustment);
-      Method = CGM.BuildCovariantThunk(MD, Extern, Adjustment);
+      Method = wrap(CGM.GetAddrOfCovariantThunk(GD, Adjustment));
     } else if (!ThisAdjustment.isEmpty()) {
       // Build a "regular" thunk.
-      Method = CGM.BuildThunk(GD, Extern, ThisAdjustment);
+      Method = wrap(CGM.GetAddrOfThunk(GD, ThisAdjustment));
     } else if (MD->isPure()) {
       // We have a pure virtual method.
       Method = getPureVirtualFn();
@@ -1048,6 +1068,32 @@
   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;
+
+  const CXXRecordDecl *RD = cast<CXXRecordDecl>(GD.getDecl()->getDeclContext());
+  if (!SavedThisAdjustmentRecords.insert(RD).second)
+    return ThunkAdjustment();
+
+  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;
+
+  return ThunkAdjustment();
+}
+
 int64_t CGVtableInfo::getVirtualBaseOffsetIndex(const CXXRecordDecl *RD, 
                                                 const CXXRecordDecl *VBase) {
   ClassPairTy ClassPair(RD, VBase);
@@ -1416,5 +1462,17 @@
   
   // Emit the data.
   GenerateClassData(Linkage, RD);
+
+  for (CXXRecordDecl::method_iterator i = RD->method_begin(),
+       e = RD->method_end(); i != e; ++i) {
+    if ((*i)->isVirtual() && (*i)->hasInlineBody()) {
+      if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(*i)) {
+        CGM.BuildThunksForVirtual(GlobalDecl(DD, Dtor_Complete));
+        CGM.BuildThunksForVirtual(GlobalDecl(DD, Dtor_Deleting));
+      } else {
+        CGM.BuildThunksForVirtual(GlobalDecl(*i));
+      }
+    }
+  }
 }
 

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

==============================================================================
--- cfe/trunk/lib/CodeGen/CGVtable.h (original)
+++ cfe/trunk/lib/CodeGen/CGVtable.h Sun Dec  6 16:01:30 2009
@@ -15,6 +15,7 @@
 #define CLANG_CODEGEN_CGVTABLE_H
 
 #include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/DenseSet.h"
 #include "llvm/GlobalVariable.h"
 #include "GlobalDecl.h"
 
@@ -83,6 +84,11 @@
   /// 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;
+
   /// getNumVirtualFunctionPointers - Return the number of virtual function
   /// pointers in the vtable for a given record decl.
   uint64_t getNumVirtualFunctionPointers(const CXXRecordDecl *RD);
@@ -122,6 +128,8 @@
   int64_t getVirtualBaseOffsetIndex(const CXXRecordDecl *RD,
                                     const CXXRecordDecl *VBase);
 
+  ThunkAdjustment getThisAdjustment(GlobalDecl GD, GlobalDecl OGD);
+
   /// getVtableAddressPoint - returns the address point of the vtable for the
   /// given record decl.
   /// FIXME: This should return a list of address points.

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

==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenModule.cpp (original)
+++ cfe/trunk/lib/CodeGen/CodeGenModule.cpp Sun Dec  6 16:01:30 2009
@@ -621,8 +621,13 @@
                                  Context.getSourceManager(),
                                  "Generating code for declaration");
   
-  if (isa<CXXMethodDecl>(D))
+  if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D)) {
     getVtableInfo().MaybeEmitVtable(GD);
+    if (MD->isVirtual() && MD->isOutOfLine() &&
+        (!isa<CXXDestructorDecl>(D) || GD.getDtorType() != Dtor_Base)) {
+      BuildThunksForVirtual(GD);
+    }
+  }
   
   if (const CXXConstructorDecl *CD = dyn_cast<CXXConstructorDecl>(D))
     EmitCXXConstructor(CD, GD.getCtorType());

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

==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenModule.h (original)
+++ cfe/trunk/lib/CodeGen/CodeGenModule.h Sun Dec  6 16:01:30 2009
@@ -223,6 +223,13 @@
   /// non-class type.
   llvm::Constant *GenerateRTTI(QualType Ty);
   
+  llvm::Constant *GetAddrOfThunk(GlobalDecl GD,
+                                 const ThunkAdjustment &ThisAdjustment);
+  llvm::Constant *GetAddrOfCovariantThunk(GlobalDecl GD,
+                                const CovariantThunkAdjustment &ThisAdjustment);
+  void BuildThunksForVirtual(GlobalDecl GD);
+  void BuildThunksForVirtualRecursive(GlobalDecl GD, GlobalDecl BaseOGD);
+
   /// BuildThunk - Build a thunk for the given method.
   llvm::Constant *BuildThunk(GlobalDecl GD, bool Extern, 
                              const ThunkAdjustment &ThisAdjustment);

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

==============================================================================
--- cfe/trunk/test/CodeGenCXX/virt.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/virt.cpp Sun Dec  6 16:01:30 2009
@@ -768,7 +768,7 @@
 
 // FIXME: This is the wrong thunk, but until these issues are fixed, better
 // than nothing.
-// CHECK-LPLL64:define weak %class.test8_D* @_ZTcvn16_n72_v16_n32_N8test16_D4foo1Ev(%class.test8_D*) {
+// CHECK-LPLL64:define weak %class.test8_D* @_ZTcvn16_n72_v16_n32_N8test16_D4foo1Ev(%class.test8_D*)
 // CHECK-LPLL64:entry:
 // CHECK-LPLL64:  %retval = alloca %class.test8_D*
 // CHECK-LPLL64:  %.addr = alloca %class.test8_D*
@@ -790,7 +790,7 @@
 // CHECK-LPLL64:  ret %class.test8_D* %10
 // CHECK-LPLL64:}
 
-// CHECK-LPLL64:define weak %class.test8_D* @_ZTch0_v16_n32_N8test16_D4foo1Ev(%class.test8_D*) {
+// CHECK-LPLL64:define weak %class.test8_D* @_ZTch0_v16_n32_N8test16_D4foo1Ev(%class.test8_D*)
 // CHECK-LPLL64:entry:
 // CHECK-LPLL64:  %retval = alloca %class.test8_D*
 // CHECK-LPLL64:  %.addr = alloca %class.test8_D*





More information about the cfe-commits mailing list