diff options
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/AST/VTableBuilder.cpp | 19 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGCXX.cpp | 15 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGCXXABI.h | 30 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGCall.cpp | 16 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGClass.cpp | 2 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGExprCXX.cpp | 5 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGVTables.h | 4 | ||||
-rw-r--r-- | clang/lib/CodeGen/CodeGenFunction.h | 2 | ||||
-rw-r--r-- | clang/lib/CodeGen/CodeGenModule.h | 5 | ||||
-rw-r--r-- | clang/lib/CodeGen/ItaniumCXXABI.cpp | 21 | ||||
-rw-r--r-- | clang/lib/CodeGen/MicrosoftCXXABI.cpp | 122 |
11 files changed, 207 insertions, 34 deletions
diff --git a/clang/lib/AST/VTableBuilder.cpp b/clang/lib/AST/VTableBuilder.cpp index 9067b4bd59b..ffa01681c52 100644 --- a/clang/lib/AST/VTableBuilder.cpp +++ b/clang/lib/AST/VTableBuilder.cpp @@ -2490,6 +2490,10 @@ private: /// this method's base has, or zero. const uint64_t VBTableIndex; + /// VBase - If nonnull, holds the last vbase which contains the vfptr that + /// the method definition is adjusted to. + const CXXRecordDecl *VBase; + /// VFTableIndex - The index in the vftable that this method has. const uint64_t VFTableIndex; @@ -2498,11 +2502,13 @@ private: /// or used for vcalls in the most derived class. bool Shadowed; - MethodInfo(uint64_t VBTableIndex, uint64_t VFTableIndex) - : VBTableIndex(VBTableIndex), VFTableIndex(VFTableIndex), + MethodInfo(uint64_t VBTableIndex, const CXXRecordDecl *VBase, + uint64_t VFTableIndex) + : VBTableIndex(VBTableIndex), VBase(VBase), VFTableIndex(VFTableIndex), Shadowed(false) {} - MethodInfo() : VBTableIndex(0), VFTableIndex(0), Shadowed(false) {} + MethodInfo() + : VBTableIndex(0), VBase(0), VFTableIndex(0), Shadowed(false) {} }; typedef llvm::DenseMap<const CXXMethodDecl *, MethodInfo> MethodInfoMapTy; @@ -2584,8 +2590,8 @@ private: // and the entries shadowed by return adjusting thunks. if (MD->getParent() != MostDerivedClass || MI.Shadowed) continue; - MethodVFTableLocation Loc(MI.VBTableIndex, WhichVFPtr.VFPtrOffset, - MI.VFTableIndex); + MethodVFTableLocation Loc(MI.VBTableIndex, MI.VBase, + WhichVFPtr.VFPtrOffset, MI.VFTableIndex); if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD)) { MethodVFTableLocations[GlobalDecl(DD, Dtor_Deleting)] = Loc; } else { @@ -2838,6 +2844,7 @@ void VFTableBuilder::AddMethods(BaseSubobject Base, unsigned BaseDepth, // No return adjustment needed - just replace the overridden method info // with the current info. MethodInfo MI(OverriddenMethodInfo.VBTableIndex, + OverriddenMethodInfo.VBase, OverriddenMethodInfo.VFTableIndex); MethodInfoMap.erase(OverriddenMDIterator); @@ -2882,7 +2889,7 @@ void VFTableBuilder::AddMethods(BaseSubobject Base, unsigned BaseDepth, // it requires return adjustment. Insert the method info for this method. unsigned VBIndex = LastVBase ? GetVBTableIndex(MostDerivedClass, LastVBase) : 0; - MethodInfo MI(VBIndex, Components.size()); + MethodInfo MI(VBIndex, LastVBase, Components.size()); assert(!MethodInfoMap.count(MD) && "Should not have method info for this method yet!"); diff --git a/clang/lib/CodeGen/CGCXX.cpp b/clang/lib/CodeGen/CGCXX.cpp index 0453b73006b..4932c078441 100644 --- a/clang/lib/CodeGen/CGCXX.cpp +++ b/clang/lib/CodeGen/CGCXX.cpp @@ -272,23 +272,12 @@ CodeGenModule::GetAddrOfCXXDestructor(const CXXDestructorDecl *dtor, /*ForVTable=*/false)); } -llvm::Value * -CodeGenFunction::BuildVirtualCall(GlobalDecl GD, llvm::Value *This, - llvm::Type *Ty) { - GD = GD.getCanonicalDecl(); - uint64_t VTableIndex = CGM.getVTableContext().getMethodVTableIndex(GD); - - Ty = Ty->getPointerTo()->getPointerTo(); - llvm::Value *VTable = GetVTablePtr(This, Ty); - llvm::Value *VFuncPtr = - Builder.CreateConstInBoundsGEP1_64(VTable, VTableIndex, "vfn"); - return Builder.CreateLoad(VFuncPtr); -} - static llvm::Value *BuildAppleKextVirtualCall(CodeGenFunction &CGF, GlobalDecl GD, llvm::Type *Ty, const CXXRecordDecl *RD) { + assert(!CGF.CGM.getTarget().getCXXABI().isMicrosoft() && + "No kext in Microsoft ABI"); GD = GD.getCanonicalDecl(); CodeGenModule &CGM = CGF.CGM; llvm::Value *VTable = CGM.getVTables().GetAddrOfVTable(RD); diff --git a/clang/lib/CodeGen/CGCXXABI.h b/clang/lib/CodeGen/CGCXXABI.h index c5ff02488f5..5baedfba1a0 100644 --- a/clang/lib/CodeGen/CGCXXABI.h +++ b/clang/lib/CodeGen/CGCXXABI.h @@ -256,6 +256,23 @@ public: /// Emit destructor variants required by this ABI. virtual void EmitCXXDestructors(const CXXDestructorDecl *D) = 0; + /// Get the type of the implicit "this" parameter used by a method. May return + /// zero if no specific type is applicable, e.g. if the ABI expects the "this" + /// parameter to point to some artificial offset in a complete object due to + /// vbases being reordered. + virtual const CXXRecordDecl * + getThisArgumentTypeForMethod(const CXXMethodDecl *MD) { + return MD->getParent(); + } + + /// Perform ABI-specific "this" argument adjustment required prior to + /// a virtual function call. + virtual llvm::Value *adjustThisArgumentForVirtualCall(CodeGenFunction &CGF, + GlobalDecl GD, + llvm::Value *This) { + return This; + } + /// Build the ABI-specific portion of the parameter list for a /// function. This generally involves a 'this' parameter and /// possibly some extra data for constructors and destructors. @@ -267,6 +284,13 @@ public: QualType &ResTy, FunctionArgList &Params) = 0; + /// Perform ABI-specific "this" parameter adjustment in a virtual function + /// prologue. + virtual llvm::Value *adjustThisParameterInVirtualFunctionPrologue( + CodeGenFunction &CGF, GlobalDecl GD, llvm::Value *This) { + return This; + } + /// Emit the ABI-specific prolog for the function. virtual void EmitInstanceFunctionProlog(CodeGenFunction &CGF) = 0; @@ -279,6 +303,12 @@ public: CallExpr::const_arg_iterator ArgBeg, CallExpr::const_arg_iterator ArgEnd) = 0; + /// Build a virtual function pointer in the ABI-specific way. + virtual llvm::Value *getVirtualFunctionPointer(CodeGenFunction &CGF, + GlobalDecl GD, + llvm::Value *This, + llvm::Type *Ty) = 0; + /// Emit the ABI-specific virtual destructor call. virtual void EmitVirtualDestructorCall(CodeGenFunction &CGF, const CXXDestructorDecl *Dtor, diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp index 11ee3883b30..32dbfab07d4 100644 --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/lib/CodeGen/CGCall.cpp @@ -160,6 +160,8 @@ static CallingConv getCallingConventionForDecl(const Decl *D) { /// Arrange the argument and result information for a call to an /// unknown C++ non-static member function of the given abstract type. +/// (Zero value of RD means we don't have any meaningful "this" argument type, +/// so fall back to a generic pointer type). /// The member function must be an ordinary function, i.e. not a /// constructor or destructor. const CGFunctionInfo & @@ -168,7 +170,10 @@ CodeGenTypes::arrangeCXXMethodType(const CXXRecordDecl *RD, SmallVector<CanQualType, 16> argTypes; // Add the 'this' pointer. - argTypes.push_back(GetThisType(Context, RD)); + if (RD) + argTypes.push_back(GetThisType(Context, RD)); + else + argTypes.push_back(Context.VoidPtrTy); return ::arrangeCXXMethodType(*this, argTypes, FTP->getCanonicalTypeUnqualified().getAs<FunctionProtoType>()); @@ -187,7 +192,9 @@ CodeGenTypes::arrangeCXXMethodDeclaration(const CXXMethodDecl *MD) { if (MD->isInstance()) { // The abstract case is perfectly fine. - return arrangeCXXMethodType(MD->getParent(), prototype.getTypePtr()); + const CXXRecordDecl *ThisType = + CGM.getCXXABI().getThisArgumentTypeForMethod(MD); + return arrangeCXXMethodType(ThisType, prototype.getTypePtr()); } return arrangeFreeFunctionType(prototype); @@ -1341,6 +1348,11 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI, if (isPromoted) V = emitArgumentDemotion(*this, Arg, V); + if (const CXXMethodDecl *MD = dyn_cast_or_null<CXXMethodDecl>(CurCodeDecl)) { + if (MD->isVirtual() && Arg == CXXABIThisDecl) + V = CGM.getCXXABI().adjustThisParameterInVirtualFunctionPrologue(*this, CurGD, V); + } + // Because of merging of function types from multiple decls it is // possible for the type of an argument to not match the corresponding // type in the function type. Since we are codegening the callee diff --git a/clang/lib/CodeGen/CGClass.cpp b/clang/lib/CodeGen/CGClass.cpp index d00d1d062af..f47920d8b53 100644 --- a/clang/lib/CodeGen/CGClass.cpp +++ b/clang/lib/CodeGen/CGClass.cpp @@ -2125,7 +2125,7 @@ CodeGenFunction::EmitCXXOperatorMemberCallee(const CXXOperatorCallExpr *E, CGM.getTypes().arrangeCXXMethodDeclaration(MD)); if (UseVirtualCall(getContext(), E, MD)) - return BuildVirtualCall(MD, This, fnType); + return CGM.getCXXABI().getVirtualFunctionPointer(*this, MD, This, fnType); return CGM.GetAddrOfFunction(MD, fnType); } diff --git a/clang/lib/CodeGen/CGExprCXX.cpp b/clang/lib/CodeGen/CGExprCXX.cpp index 5ec135ea506..43318a73d56 100644 --- a/clang/lib/CodeGen/CGExprCXX.cpp +++ b/clang/lib/CodeGen/CGExprCXX.cpp @@ -299,7 +299,7 @@ RValue CodeGenFunction::EmitCXXMemberCallExpr(const CXXMemberCallExpr *CE, if (const CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(MD)) { Callee = CGM.GetAddrOfFunction(GlobalDecl(Ctor, Ctor_Complete), Ty); } else if (UseVirtualCall) { - Callee = BuildVirtualCall(MD, This, Ty); + Callee = CGM.getCXXABI().getVirtualFunctionPointer(*this, MD, This, Ty); } else { if (getLangOpts().AppleKext && MD->isVirtual() && @@ -312,6 +312,9 @@ RValue CodeGenFunction::EmitCXXMemberCallExpr(const CXXMemberCallExpr *CE, } } + if (MD->isVirtual()) + This = CGM.getCXXABI().adjustThisArgumentForVirtualCall(*this, MD, This); + return EmitCXXMemberCall(MD, CE->getExprLoc(), Callee, ReturnValue, This, /*ImplicitParam=*/0, QualType(), CE->arg_begin(), CE->arg_end()); diff --git a/clang/lib/CodeGen/CGVTables.h b/clang/lib/CodeGen/CGVTables.h index bd70b5c3594..e4f5366baee 100644 --- a/clang/lib/CodeGen/CGVTables.h +++ b/clang/lib/CodeGen/CGVTables.h @@ -31,6 +31,8 @@ namespace CodeGen { class CodeGenVTables { CodeGenModule &CGM; + // FIXME: Consider moving VTContext and VFTContext into respective CXXABI + // classes? VTableContext VTContext; OwningPtr<MicrosoftVFTableContext> VFTContext; @@ -78,6 +80,8 @@ public: VTableContext &getVTableContext() { return VTContext; } + MicrosoftVFTableContext &getVFTableContext() { return *VFTContext.get(); } + /// getSubVTTIndex - Return the index of the sub-VTT for the base class of the /// given record decl. uint64_t getSubVTTIndex(const CXXRecordDecl *RD, BaseSubobject Base); diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index 688b12fd45d..af9373a3c72 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -2102,8 +2102,6 @@ public: void EmitNoreturnRuntimeCallOrInvoke(llvm::Value *callee, ArrayRef<llvm::Value*> args); - llvm::Value *BuildVirtualCall(GlobalDecl GD, llvm::Value *This, - llvm::Type *Ty); llvm::Value *BuildAppleKextVirtualCall(const CXXMethodDecl *MD, NestedNameSpecifier *Qual, llvm::Type *Ty); diff --git a/clang/lib/CodeGen/CodeGenModule.h b/clang/lib/CodeGen/CodeGenModule.h index 393d96dc3a7..96b97bc1800 100644 --- a/clang/lib/CodeGen/CodeGenModule.h +++ b/clang/lib/CodeGen/CodeGenModule.h @@ -519,8 +519,13 @@ public: CodeGenTypes &getTypes() { return Types; } CodeGenVTables &getVTables() { return VTables; } + VTableContext &getVTableContext() { return VTables.getVTableContext(); } + MicrosoftVFTableContext &getVFTableContext() { + return VTables.getVFTableContext(); + } + llvm::MDNode *getTBAAInfo(QualType QTy); llvm::MDNode *getTBAAInfoForVTablePtr(); llvm::MDNode *getTBAAStructInfo(QualType QTy); diff --git a/clang/lib/CodeGen/ItaniumCXXABI.cpp b/clang/lib/CodeGen/ItaniumCXXABI.cpp index f3ac03dbce0..66387d32684 100644 --- a/clang/lib/CodeGen/ItaniumCXXABI.cpp +++ b/clang/lib/CodeGen/ItaniumCXXABI.cpp @@ -142,6 +142,9 @@ public: CallExpr::const_arg_iterator ArgBeg, CallExpr::const_arg_iterator ArgEnd); + llvm::Value *getVirtualFunctionPointer(CodeGenFunction &CGF, GlobalDecl GD, + llvm::Value *This, llvm::Type *Ty); + void EmitVirtualDestructorCall(CodeGenFunction &CGF, const CXXDestructorDecl *Dtor, CXXDtorType DtorType, SourceLocation CallLoc, @@ -885,6 +888,20 @@ void ItaniumCXXABI::EmitConstructorCall(CodeGenFunction &CGF, This, VTT, VTTTy, ArgBeg, ArgEnd); } +llvm::Value *ItaniumCXXABI::getVirtualFunctionPointer(CodeGenFunction &CGF, + GlobalDecl GD, + llvm::Value *This, + llvm::Type *Ty) { + GD = GD.getCanonicalDecl(); + Ty = Ty->getPointerTo()->getPointerTo(); + llvm::Value *VTable = CGF.GetVTablePtr(This, Ty); + + uint64_t VTableIndex = CGM.getVTableContext().getMethodVTableIndex(GD); + llvm::Value *VFuncPtr = + CGF.Builder.CreateConstInBoundsGEP1_64(VTable, VTableIndex, "vfn"); + return CGF.Builder.CreateLoad(VFuncPtr); +} + void ItaniumCXXABI::EmitVirtualDestructorCall(CodeGenFunction &CGF, const CXXDestructorDecl *Dtor, CXXDtorType DtorType, @@ -895,8 +912,8 @@ void ItaniumCXXABI::EmitVirtualDestructorCall(CodeGenFunction &CGF, const CGFunctionInfo *FInfo = &CGM.getTypes().arrangeCXXDestructor(Dtor, DtorType); llvm::Type *Ty = CGF.CGM.getTypes().GetFunctionType(*FInfo); - llvm::Value *Callee - = CGF.BuildVirtualCall(GlobalDecl(Dtor, DtorType), This, Ty); + llvm::Value *Callee = + getVirtualFunctionPointer(CGF, GlobalDecl(Dtor, DtorType), This, Ty); CGF.EmitCXXMemberCall(Dtor, CallLoc, Callee, ReturnValueSlot(), This, /*ImplicitParam=*/0, QualType(), 0, 0); diff --git a/clang/lib/CodeGen/MicrosoftCXXABI.cpp b/clang/lib/CodeGen/MicrosoftCXXABI.cpp index b2c9ef02132..79f142e0719 100644 --- a/clang/lib/CodeGen/MicrosoftCXXABI.cpp +++ b/clang/lib/CodeGen/MicrosoftCXXABI.cpp @@ -113,10 +113,34 @@ public: void EmitCXXDestructors(const CXXDestructorDecl *D); + const CXXRecordDecl *getThisArgumentTypeForMethod(const CXXMethodDecl *MD) { + MD = MD->getCanonicalDecl(); + if (MD->isVirtual() && !isa<CXXDestructorDecl>(MD)) { + MicrosoftVFTableContext::MethodVFTableLocation ML = + CGM.getVFTableContext().getMethodVFTableLocation(MD); + // The vbases might be ordered differently in the final overrider object + // and the complete object, so the "this" argument may sometimes point to + // memory that has no particular type (e.g. past the complete object). + // In this case, we just use a generic pointer type. + // FIXME: might want to have a more precise type in the non-virtual + // multiple inheritance case. + if (ML.VBase || !ML.VFTableOffset.isZero()) + return 0; + } + return MD->getParent(); + } + + llvm::Value *adjustThisArgumentForVirtualCall(CodeGenFunction &CGF, + GlobalDecl GD, + llvm::Value *This); + void BuildInstanceFunctionParams(CodeGenFunction &CGF, QualType &ResTy, FunctionArgList &Params); + llvm::Value *adjustThisParameterInVirtualFunctionPrologue( + CodeGenFunction &CGF, GlobalDecl GD, llvm::Value *This); + void EmitInstanceFunctionProlog(CodeGenFunction &CGF); void EmitConstructorCall(CodeGenFunction &CGF, @@ -125,7 +149,10 @@ public: llvm::Value *This, CallExpr::const_arg_iterator ArgBeg, CallExpr::const_arg_iterator ArgEnd); - + + llvm::Value *getVirtualFunctionPointer(CodeGenFunction &CGF, GlobalDecl GD, + llvm::Value *This, llvm::Type *Ty); + void EmitVirtualDestructorCall(CodeGenFunction &CGF, const CXXDestructorDecl *Dtor, CXXDtorType DtorType, SourceLocation CallLoc, @@ -423,6 +450,34 @@ void MicrosoftCXXABI::EmitCXXDestructors(const CXXDestructorDecl *D) { CGM.EmitGlobal(GlobalDecl(D, Dtor_Base)); } +llvm::Value *MicrosoftCXXABI::adjustThisArgumentForVirtualCall( + CodeGenFunction &CGF, GlobalDecl GD, llvm::Value *This) { + GD = GD.getCanonicalDecl(); + const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl()); + if (isa<CXXDestructorDecl>(MD)) + return This; + + MicrosoftVFTableContext::MethodVFTableLocation ML = + CGM.getVFTableContext().getMethodVFTableLocation(GD); + + unsigned AS = cast<llvm::PointerType>(This->getType())->getAddressSpace(); + llvm::Type *charPtrTy = CGF.Int8Ty->getPointerTo(AS); + if (ML.VBase) { + This = CGF.Builder.CreateBitCast(This, charPtrTy); + llvm::Value *VBaseOffset = CGM.getCXXABI() + .GetVirtualBaseClassOffset(CGF, This, MD->getParent(), ML.VBase); + This = CGF.Builder.CreateInBoundsGEP(This, VBaseOffset); + } + CharUnits StaticOffset = ML.VFTableOffset; + if (!StaticOffset.isZero()) { + assert(StaticOffset.isPositive()); + This = CGF.Builder.CreateBitCast(This, charPtrTy); + This = CGF.Builder + .CreateConstInBoundsGEP1_64(This, StaticOffset.getQuantity()); + } + return This; +} + static bool IsDeletingDtor(GlobalDecl GD) { const CXXMethodDecl* MD = cast<CXXMethodDecl>(GD.getDecl()); if (isa<CXXDestructorDecl>(MD)) { @@ -457,6 +512,41 @@ void MicrosoftCXXABI::BuildInstanceFunctionParams(CodeGenFunction &CGF, } } +llvm::Value *MicrosoftCXXABI::adjustThisParameterInVirtualFunctionPrologue( + CodeGenFunction &CGF, GlobalDecl GD, llvm::Value *This) { + GD = GD.getCanonicalDecl(); + const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl()); + if (isa<CXXDestructorDecl>(MD)) + return This; + + // In this ABI, every virtual function takes a pointer to one of the + // subobjects that first defines it as the 'this' parameter, rather than a + // pointer to ther final overrider subobject. Thus, we need to adjust it back + // to the final overrider subobject before use. + // See comments in the MicrosoftVFTableContext implementation for the details. + + MicrosoftVFTableContext::MethodVFTableLocation ML = + CGM.getVFTableContext().getMethodVFTableLocation(GD); + CharUnits Adjustment = ML.VFTableOffset; + if (ML.VBase) { + const ASTRecordLayout &DerivedLayout = + CGF.getContext().getASTRecordLayout(MD->getParent()); + Adjustment += DerivedLayout.getVBaseClassOffset(ML.VBase); + } + + if (Adjustment.isZero()) + return This; + + unsigned AS = cast<llvm::PointerType>(This->getType())->getAddressSpace(); + llvm::Type *charPtrTy = CGF.Int8Ty->getPointerTo(AS), + *thisTy = This->getType(); + + This = CGF.Builder.CreateBitCast(This, charPtrTy); + assert(Adjustment.isPositive()); + This = CGF.Builder.CreateConstGEP1_64(This, -Adjustment.getQuantity()); + return CGF.Builder.CreateBitCast(This, thisTy); +} + void MicrosoftCXXABI::EmitInstanceFunctionProlog(CodeGenFunction &CGF) { EmitThisParam(CGF); @@ -514,6 +604,24 @@ void MicrosoftCXXABI::EmitConstructorCall(CodeGenFunction &CGF, ImplicitParam, ImplicitParamTy, ArgBeg, ArgEnd); } +llvm::Value *MicrosoftCXXABI::getVirtualFunctionPointer(CodeGenFunction &CGF, + GlobalDecl GD, + llvm::Value *This, + llvm::Type *Ty) { + GD = GD.getCanonicalDecl(); + CGBuilderTy &Builder = CGF.Builder; + + Ty = Ty->getPointerTo()->getPointerTo(); + llvm::Value *VPtr = adjustThisArgumentForVirtualCall(CGF, GD, This); + llvm::Value *VTable = CGF.GetVTablePtr(VPtr, Ty); + + MicrosoftVFTableContext::MethodVFTableLocation ML = + CGM.getVFTableContext().getMethodVFTableLocation(GD); + llvm::Value *VFuncPtr = + Builder.CreateConstInBoundsGEP1_64(VTable, ML.Index, "vfn"); + return Builder.CreateLoad(VFuncPtr); +} + void MicrosoftCXXABI::EmitVirtualDestructorCall(CodeGenFunction &CGF, const CXXDestructorDecl *Dtor, CXXDtorType DtorType, @@ -523,15 +631,15 @@ void MicrosoftCXXABI::EmitVirtualDestructorCall(CodeGenFunction &CGF, // We have only one destructor in the vftable but can get both behaviors // by passing an implicit bool parameter. - const CGFunctionInfo *FInfo - = &CGM.getTypes().arrangeCXXDestructor(Dtor, Dtor_Deleting); + const CGFunctionInfo *FInfo = + &CGM.getTypes().arrangeCXXDestructor(Dtor, Dtor_Deleting); llvm::Type *Ty = CGF.CGM.getTypes().GetFunctionType(*FInfo); - llvm::Value *Callee - = CGF.BuildVirtualCall(GlobalDecl(Dtor, Dtor_Deleting), This, Ty); + llvm::Value *Callee = + getVirtualFunctionPointer(CGF, GlobalDecl(Dtor, Dtor_Deleting), This, Ty); ASTContext &Context = CGF.getContext(); - llvm::Value *ImplicitParam - = llvm::ConstantInt::get(llvm::IntegerType::getInt1Ty(CGF.getLLVMContext()), + llvm::Value *ImplicitParam = + llvm::ConstantInt::get(llvm::IntegerType::getInt1Ty(CGF.getLLVMContext()), DtorType == Dtor_Deleting); CGF.EmitCXXMemberCall(Dtor, CallLoc, Callee, ReturnValueSlot(), This, |