]> granicus.if.org Git - clang/commitdiff
Add a CovariantThunkAdjustment struct that represents the adjustments needed for...
authorAnders Carlsson <andersca@mac.com>
Thu, 26 Nov 2009 03:09:37 +0000 (03:09 +0000)
committerAnders Carlsson <andersca@mac.com>
Thu, 26 Nov 2009 03:09:37 +0000 (03:09 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@89933 91177308-0d34-0410-b5e6-96231b3b80d8

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

index 7dc4b1e96192ef80594a0ae8c665f39144ffd7ee..ceff7508b25bdc8df0f747bfb60f01a2ab93cb1c 100644 (file)
@@ -824,49 +824,50 @@ CodeGenFunction::GenerateThunk(llvm::Function *Fn, const CXXMethodDecl *MD,
                                bool Extern, 
                                const ThunkAdjustment &ThisAdjustment) {
   return GenerateCovariantThunk(Fn, MD, Extern, 
-                                ThisAdjustment.NonVirtual,
-                                ThisAdjustment.Virtual, 0, 0);
+                                CovariantThunkAdjustment(ThisAdjustment,
+                                                         ThunkAdjustment()));
 }
 
-llvm::Value *CodeGenFunction::DynamicTypeAdjust(llvm::Value *V, int64_t nv,
-                                                int64_t v) {
-  llvm::Type *Ptr8Ty = llvm::PointerType::get(llvm::Type::getInt8Ty(VMContext),
-                                              0);
+llvm::Value *
+CodeGenFunction::DynamicTypeAdjust(llvm::Value *V, 
+                                   const ThunkAdjustment &Adjustment) {
+  const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(VMContext);
+
   const llvm::Type *OrigTy = V->getType();
-  if (nv) {
+  if (Adjustment.NonVirtual) {
     // Do the non-virtual adjustment
-    V = Builder.CreateBitCast(V, Ptr8Ty);
-    V = Builder.CreateConstInBoundsGEP1_64(V, nv);
-    V = Builder.CreateBitCast(V, OrigTy);
-  }
-  if (v) {
-    // Do the virtual this adjustment
-    const llvm::Type *PtrDiffTy = 
-      ConvertType(getContext().getPointerDiffType());
-    llvm::Type *PtrPtr8Ty, *PtrPtrDiffTy;
-    PtrPtr8Ty = llvm::PointerType::get(Ptr8Ty, 0);
-    PtrPtrDiffTy = llvm::PointerType::get(PtrDiffTy, 0);
-    llvm::Value *ThisVal = Builder.CreateBitCast(V, Ptr8Ty);
-    V = Builder.CreateBitCast(V, PtrPtrDiffTy->getPointerTo());
-    V = Builder.CreateLoad(V, "vtable");
-    llvm::Value *VTablePtr = V;
-    assert(v % (LLVMPointerWidth/8) == 0 && "vtable entry unaligned");
-    v /= LLVMPointerWidth/8;
-    V = Builder.CreateConstInBoundsGEP1_64(VTablePtr, v);
-    V = Builder.CreateLoad(V);
-    V = Builder.CreateGEP(ThisVal, V);
+    V = Builder.CreateBitCast(V, Int8PtrTy);
+    V = Builder.CreateConstInBoundsGEP1_64(V, Adjustment.NonVirtual);
     V = Builder.CreateBitCast(V, OrigTy);
   }
-  return V;
+  
+  if (!Adjustment.Virtual)
+    return V;
+
+  assert(Adjustment.Virtual % (LLVMPointerWidth / 8) == 0 && 
+         "vtable entry unaligned");
+
+  // Do the virtual this adjustment
+  const llvm::Type *PtrDiffTy = ConvertType(getContext().getPointerDiffType());
+  const llvm::Type *PtrDiffPtrTy = PtrDiffTy->getPointerTo();
+  
+  llvm::Value *ThisVal = Builder.CreateBitCast(V, Int8PtrTy);
+  V = Builder.CreateBitCast(V, PtrDiffPtrTy->getPointerTo());
+  V = Builder.CreateLoad(V, "vtable");
+  
+  llvm::Value *VTablePtr = V;
+  uint64_t VirtualAdjustment = Adjustment.Virtual / (LLVMPointerWidth / 8);
+  V = Builder.CreateConstInBoundsGEP1_64(VTablePtr, VirtualAdjustment);
+  V = Builder.CreateLoad(V);
+  V = Builder.CreateGEP(ThisVal, V);
+  
+  return Builder.CreateBitCast(V, OrigTy);
 }
 
-llvm::Constant *CodeGenFunction::GenerateCovariantThunk(llvm::Function *Fn,
-                                                        const CXXMethodDecl *MD,
-                                                        bool Extern,
-                                                        int64_t nv_t,
-                                                        int64_t v_t,
-                                                        int64_t nv_r,
-                                                        int64_t v_r) {
+llvm::Constant *
+CodeGenFunction::GenerateCovariantThunk(llvm::Function *Fn,
+                                   const CXXMethodDecl *MD, bool Extern,
+                                   const CovariantThunkAdjustment &Adjustment) {
   QualType ResultType = MD->getType()->getAs<FunctionType>()->getResultType();
 
   FunctionArgList Args;
@@ -899,16 +900,23 @@ llvm::Constant *CodeGenFunction::GenerateCovariantThunk(llvm::Function *Fn,
   llvm::Value *Callee = CGM.GetAddrOfFunction(MD, Ty);
   CallArgList CallArgs;
 
+  bool ShouldAdjustReturnPointer = true;
   QualType ArgType = MD->getThisType(getContext());
   llvm::Value *Arg = Builder.CreateLoad(LocalDeclMap[ThisDecl], "this");
-  if (nv_t || v_t) {
+  if (!Adjustment.ThisAdjustment.isEmpty()) {
     // Do the this adjustment.
     const llvm::Type *OrigTy = Callee->getType();
-    Arg = DynamicTypeAdjust(Arg, nv_t, v_t);
-    if (nv_r || v_r) {
-      Callee = CGM.BuildCovariantThunk(MD, Extern, 0, 0, nv_r, v_r);
+    Arg = DynamicTypeAdjust(Arg, Adjustment.ThisAdjustment);
+    
+    if (!Adjustment.ReturnAdjustment.isEmpty()) {
+      const CovariantThunkAdjustment &ReturnAdjustment = 
+        CovariantThunkAdjustment(ThunkAdjustment(),
+                                 Adjustment.ReturnAdjustment);
+      
+      Callee = CGM.BuildCovariantThunk(MD, Extern, ReturnAdjustment);
+      
       Callee = Builder.CreateBitCast(Callee, OrigTy);
-      nv_r = v_r = 0;
+      ShouldAdjustReturnPointer = false;
     }
   }    
 
@@ -927,7 +935,7 @@ llvm::Constant *CodeGenFunction::GenerateCovariantThunk(llvm::Function *Fn,
 
   RValue RV = EmitCall(CGM.getTypes().getFunctionInfo(ResultType, CallArgs),
                        Callee, CallArgs, MD);
-  if (nv_r || v_r) {
+  if (ShouldAdjustReturnPointer && !Adjustment.ReturnAdjustment.isEmpty()) {
     bool CanBeZero = !(ResultType->isReferenceType()
     // FIXME: attr nonnull can't be zero either
                        /* || ResultType->hasAttr<NonNullAttr>() */ );
@@ -942,7 +950,8 @@ llvm::Constant *CodeGenFunction::GenerateCovariantThunk(llvm::Function *Fn,
       Builder.CreateCondBr(Builder.CreateICmpNE(RV.getScalarVal(), Zero),
                            NonZeroBlock, ZeroBlock);
       EmitBlock(NonZeroBlock);
-      llvm::Value *NZ = DynamicTypeAdjust(RV.getScalarVal(), nv_r, v_r);
+      llvm::Value *NZ = 
+        DynamicTypeAdjust(RV.getScalarVal(), Adjustment.ReturnAdjustment);
       EmitBranch(ContBlock);
       EmitBlock(ZeroBlock);
       llvm::Value *Z = RV.getScalarVal();
@@ -953,7 +962,8 @@ llvm::Constant *CodeGenFunction::GenerateCovariantThunk(llvm::Function *Fn,
       RVOrZero->addIncoming(Z, ZeroBlock);
       RV = RValue::get(RVOrZero);
     } else
-      RV = RValue::get(DynamicTypeAdjust(RV.getScalarVal(), nv_r, v_r));
+      RV = RValue::get(DynamicTypeAdjust(RV.getScalarVal(), 
+                                         Adjustment.ReturnAdjustment));
   }
 
   if (!ResultType->isVoidType())
@@ -987,12 +997,11 @@ CodeGenModule::BuildThunk(const CXXMethodDecl *MD, bool Extern,
   return m;
 }
 
-llvm::Constant *CodeGenModule::BuildCovariantThunk(const CXXMethodDecl *MD,
-                                                   bool Extern, int64_t nv_t,
-                                                   int64_t v_t, int64_t nv_r,
-                                                   int64_t v_r) {
+llvm::Constant *
+CodeGenModule::BuildCovariantThunk(const CXXMethodDecl *MD, bool Extern,
+                                   const CovariantThunkAdjustment &Adjustment) {
   llvm::SmallString<256> OutName;
-  getMangleContext().mangleCovariantThunk(MD, nv_t, v_t, nv_r, v_r, OutName);
+  getMangleContext().mangleCovariantThunk(MD, Adjustment, OutName);
   llvm::GlobalVariable::LinkageTypes linktype;
   linktype = llvm::GlobalValue::WeakAnyLinkage;
   if (!Extern)
@@ -1005,8 +1014,7 @@ llvm::Constant *CodeGenModule::BuildCovariantThunk(const CXXMethodDecl *MD,
 
   llvm::Function *Fn = llvm::Function::Create(FTy, linktype, OutName.str(),
                                               &getModule());
-  CodeGenFunction(*this).GenerateCovariantThunk(Fn, MD, Extern, nv_t, v_t, nv_r,
-                                               v_r);
+  CodeGenFunction(*this).GenerateCovariantThunk(Fn, MD, Extern, Adjustment);
   llvm::Constant *m = llvm::ConstantExpr::getBitCast(Fn, Ptr8Ty);
   return m;
 }
index 08690f23a8a8130eb2d1f2e951bb7f60f356eda8..69bf2e6ae1e5b01a1877be2521a7a6ab4a1e2018 100644 (file)
@@ -349,8 +349,10 @@ public:
       Index_t v_t = i->second.first.first.second;
       Index_t nv_r = i->second.first.second.first;
       Index_t v_r = i->second.first.second.second;
-      submethods[idx] = CGM.BuildCovariantThunk(MD, Extern, nv_t, v_t, nv_r,
-                                                v_r);
+      
+      CovariantThunkAdjustment Adjustment(ThunkAdjustment(nv_t, v_t),
+                                          ThunkAdjustment(nv_r, v_r));
+      submethods[idx] = CGM.BuildCovariantThunk(MD, Extern, Adjustment);
     }
     CovariantThunks.clear();
     for (Pures_t::iterator i = Pures.begin(), e = Pures.end();
index 1d98bed4b2aa4d24e68255a99364ed44f6be708a..9a25ce3033647ba73295e3897da5556ede1ab4be 100644 (file)
@@ -49,6 +49,19 @@ struct ThunkAdjustment {
   int64_t Virtual;
 };
 
+/// CovariantThunkAdjustment - Adjustment of the 'this' pointer and the
+/// return pointer for covariant thunks.
+struct CovariantThunkAdjustment {
+  CovariantThunkAdjustment(const ThunkAdjustment &ThisAdjustment,
+                           const ThunkAdjustment &ReturnAdjustment)
+  : ThisAdjustment(ThisAdjustment), ReturnAdjustment(ReturnAdjustment) { }
+
+  CovariantThunkAdjustment() { }
+
+  ThunkAdjustment ThisAdjustment;
+  ThunkAdjustment ReturnAdjustment;
+};
+
 class CGVtableInfo {
   CodeGenModule &CGM;
   
index b811c25b8a8d09d6901bec073f10aa5ebb5240f7..078beabd1ba86a4e8d1bd036099ad83feffb2d53 100644 (file)
@@ -437,16 +437,17 @@ public:
   /// DynamicTypeAdjust - Do the non-virtual and virtual adjustments on an
   /// object pointer to alter the dynamic type of the pointer.  Used by
   /// GenerateCovariantThunk for building thunks.
-  llvm::Value *DynamicTypeAdjust(llvm::Value *V, int64_t nv, int64_t v);
+  llvm::Value *DynamicTypeAdjust(llvm::Value *V, 
+                                 const ThunkAdjustment &Adjustment);
 
   /// GenerateThunk - Generate a thunk for the given method
   llvm::Constant *GenerateThunk(llvm::Function *Fn, const CXXMethodDecl *MD,
                                 bool Extern, 
                                 const ThunkAdjustment &ThisAdjustment);
-  llvm::Constant *GenerateCovariantThunk(llvm::Function *Fn,
-                                         const CXXMethodDecl *MD, bool Extern,
-                                         int64_t nv_t, int64_t v_t,
-                                         int64_t nv_r, int64_t v_r);
+  llvm::Constant *
+  GenerateCovariantThunk(llvm::Function *Fn, const CXXMethodDecl *MD, 
+                         bool Extern,
+                         const CovariantThunkAdjustment &Adjustment);
 
   void EmitCtorPrologue(const CXXConstructorDecl *CD, CXXCtorType Type);
 
index bc2d73edc1d9a209da37fb7b44c7745f311f419c..5c3e633daa29760530a966838ecddf635216d19e 100644 (file)
@@ -238,9 +238,9 @@ public:
                              const ThunkAdjustment &ThisAdjustment);
 
   /// BuildCoVariantThunk - Build a thunk for the given method
-  llvm::Constant *BuildCovariantThunk(const CXXMethodDecl *MD, bool Extern,
-                                      int64_t nv_t, int64_t v_t,
-                                      int64_t nv_r, int64_t v_r);
+  llvm::Constant *
+  BuildCovariantThunk(const CXXMethodDecl *MD, bool Extern,
+                      const CovariantThunkAdjustment &Adjustment);
 
   typedef std::pair<const CXXRecordDecl *, uint64_t> CtorVtable_t;
   typedef llvm::DenseMap<const CXXRecordDecl *,
index 37061f144c85e9c7a125b204213d4db753732ca6..4b7ab4f20e1f13e45122e20a0e56227a4cdbeb77 100644 (file)
@@ -1371,9 +1371,10 @@ void MangleContext::mangleThunk(const FunctionDecl *FD,
 
 /// \brief Mangles the a covariant thunk for the declaration D and emits that
 /// name to the given output stream.
-void MangleContext::mangleCovariantThunk(const FunctionDecl *FD, int64_t nv_t,
-                                         int64_t v_t, int64_t nv_r, int64_t v_r,
-                                         llvm::SmallVectorImpl<char> &Res) {
+void 
+MangleContext::mangleCovariantThunk(const FunctionDecl *FD,
+                                    const CovariantThunkAdjustment& Adjustment,
+                                    llvm::SmallVectorImpl<char> &Res) {
   // FIXME: Hum, we might have to thunk these, fix.
   assert(!isa<CXXDestructorDecl>(FD) &&
          "Use mangleCXXDtor for destructor decls!");
@@ -1384,8 +1385,8 @@ void MangleContext::mangleCovariantThunk(const FunctionDecl *FD, int64_t nv_t,
   //                      # second call-offset is result adjustment
   CXXNameMangler Mangler(*this, Res);
   Mangler.getStream() << "_ZTc";
-  Mangler.mangleCallOffset(ThunkAdjustment(nv_t, v_t));
-  Mangler.mangleCallOffset(ThunkAdjustment(nv_r, v_r));
+  Mangler.mangleCallOffset(Adjustment.ThisAdjustment);
+  Mangler.mangleCallOffset(Adjustment.ReturnAdjustment);
   Mangler.mangleFunctionEncoding(FD);
 }
 
index 81b73197d3c0d0fd15369f6b1529357845129865..65b1d9f9618dc82b6e833f0ab72ad587db5f5a27 100644 (file)
@@ -35,6 +35,7 @@ namespace clang {
   class VarDecl;
 
 namespace CodeGen {
+  class CovariantThunkAdjustment;
   class ThunkAdjustment;
    
 /// MangleContext - Context for tracking state which persists across multiple
@@ -66,8 +67,8 @@ public:
   void mangleThunk(const FunctionDecl *FD, 
                    const ThunkAdjustment &ThisAdjustment,
                    llvm::SmallVectorImpl<char> &);
-  void mangleCovariantThunk(const FunctionDecl *FD, int64_t nv_t, int64_t v_t,
-                            int64_t nv_r, int64_t v_r,
+  void mangleCovariantThunk(const FunctionDecl *FD, 
+                            const CovariantThunkAdjustment& Adjustment,
                             llvm::SmallVectorImpl<char> &);
   void mangleGuardVariable(const VarDecl *D, llvm::SmallVectorImpl<char> &);
   void mangleCXXVtable(const CXXRecordDecl *RD, llvm::SmallVectorImpl<char> &);