From: Fariborz Jahanian Date: Tue, 1 Feb 2011 23:22:34 +0000 (+0000) Subject: -fapple-kext support for indirect call to virtuals dtors - wip. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=ccd5259d33cbbdd6f5fbf7ccab4cb4a2702309ea;p=clang -fapple-kext support for indirect call to virtuals dtors - wip. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@124701 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/CodeGen/CGCXX.cpp b/lib/CodeGen/CGCXX.cpp index c9c95883c7..a4145675b3 100644 --- a/lib/CodeGen/CGCXX.cpp +++ b/lib/CodeGen/CGCXX.cpp @@ -323,6 +323,10 @@ CodeGenFunction::BuildAppleKextVirtualCall(const CXXMethodDecl *MD, const RecordType *RT = T->getAs(); assert(RT && "BuildAppleKextVirtualCall - Qual type must be record"); const CXXRecordDecl *RD = cast(RT->getDecl()); + + if (const CXXDestructorDecl *DD = dyn_cast(MD)) + return BuildAppleKextVirtualDestructorCall(DD, Dtor_Complete, RD); + VTable = CGM.getVTables().GetAddrOfVTable(RD); Ty = Ty->getPointerTo()->getPointerTo(); VTable = Builder.CreateBitCast(VTable, Ty); @@ -337,6 +341,44 @@ CodeGenFunction::BuildAppleKextVirtualCall(const CXXMethodDecl *MD, return CGF.Builder.CreateLoad(VFuncPtr); } +/// BuildVirtualCall - This routine makes indirect vtable call for +/// call to virtual destructors. It returns 0 if it could not do it. +llvm::Value * +CodeGenFunction::BuildAppleKextVirtualDestructorCall( + const CXXDestructorDecl *DD, + CXXDtorType Type, + const CXXRecordDecl *RD) { + llvm::Value * Callee = 0; + const CXXMethodDecl *MD = cast(DD); + // FIXME. Dtor_Base dtor is always direct!! + // It need be somehow inline expanded into the caller. + // -O does that. But need to support -O0 as well. + if (MD->isVirtual() && Type != Dtor_Base) { + DD = cast(DD->getCanonicalDecl()); + // Compute the function type we're calling. + const CGFunctionInfo *FInfo = + &CGM.getTypes().getFunctionInfo(cast(MD), + Dtor_Complete); + const FunctionProtoType *FPT = MD->getType()->getAs(); + const llvm::Type *Ty + = CGM.getTypes().GetFunctionType(*FInfo, FPT->isVariadic()); + if (!RD) + RD = DD->getParent(); + llvm::Value *VTable = CGM.getVTables().GetAddrOfVTable(RD); + Ty = Ty->getPointerTo()->getPointerTo(); + VTable = Builder.CreateBitCast(VTable, Ty); + uint64_t VTableIndex = + CGM.getVTables().getMethodVTableIndex(GlobalDecl(DD, Type)); + uint64_t AddressPoint = + CGM.getVTables().getAddressPoint(BaseSubobject(RD, 0), RD); + VTableIndex += AddressPoint; + llvm::Value *VFuncPtr = + CGF.Builder.CreateConstInBoundsGEP1_64(VTable, VTableIndex, "vfnkxt"); + Callee = CGF.Builder.CreateLoad(VFuncPtr); + } + return Callee; +} + llvm::Value * CodeGenFunction::BuildVirtualCall(const CXXDestructorDecl *DD, CXXDtorType Type, llvm::Value *This, const llvm::Type *Ty) { diff --git a/lib/CodeGen/CGClass.cpp b/lib/CodeGen/CGClass.cpp index 7efd2bc807..f4a45e4f61 100644 --- a/lib/CodeGen/CGClass.cpp +++ b/lib/CodeGen/CGClass.cpp @@ -1264,7 +1264,12 @@ void CodeGenFunction::EmitCXXDestructorCall(const CXXDestructorDecl *DD, llvm::Value *This) { llvm::Value *VTT = GetVTTParameter(*this, GlobalDecl(DD, Type), ForVirtualBase); - llvm::Value *Callee = CGM.GetAddrOfCXXDestructor(DD, Type); + llvm::Value *Callee = 0; + if (getContext().getLangOptions().AppleKext) + Callee = BuildAppleKextVirtualDestructorCall(DD, Type); + + if (!Callee) + Callee = CGM.GetAddrOfCXXDestructor(DD, Type); EmitCXXMemberCall(DD, Callee, ReturnValueSlot(), This, VTT, 0, 0); } diff --git a/lib/CodeGen/CGExprCXX.cpp b/lib/CodeGen/CGExprCXX.cpp index 99c54f0456..cd61f85283 100644 --- a/lib/CodeGen/CGExprCXX.cpp +++ b/lib/CodeGen/CGExprCXX.cpp @@ -225,7 +225,12 @@ RValue CodeGenFunction::EmitCXXMemberCallExpr(const CXXMemberCallExpr *CE, if (UseVirtualCall) { Callee = BuildVirtualCall(Dtor, Dtor_Complete, This, Ty); } else { - Callee = CGM.GetAddrOfFunction(GlobalDecl(Dtor, Dtor_Complete), Ty); + if (getContext().getLangOptions().AppleKext && + MD->isVirtual() && + ME->hasQualifier()) + Callee = BuildAppleKextVirtualCall(MD, ME->getQualifier(), This, Ty); + else + Callee = CGM.GetAddrOfFunction(GlobalDecl(Dtor, Dtor_Complete), Ty); } } else if (const CXXConstructorDecl *Ctor = dyn_cast(MD)) { diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h index 4683c96974..5e91e0b1a5 100644 --- a/lib/CodeGen/CodeGenFunction.h +++ b/lib/CodeGen/CodeGenFunction.h @@ -1663,6 +1663,10 @@ public: NestedNameSpecifier *Qual, llvm::Value *This, const llvm::Type *Ty); + + llvm::Value *BuildAppleKextVirtualDestructorCall(const CXXDestructorDecl *DD, + CXXDtorType Type, + const CXXRecordDecl *RD=0); RValue EmitCXXMemberCall(const CXXMethodDecl *MD, llvm::Value *Callee,