[cfe-commits] r123922 - in /cfe/trunk: lib/CodeGen/CGCXX.cpp lib/CodeGen/CGExprCXX.cpp lib/CodeGen/CodeGenFunction.h test/CodeGenCXX/apple-kext-indirect-call.C

Douglas Gregor dgregor at apple.com
Thu Jan 20 16:06:29 PST 2011


On Jan 20, 2011, at 9:19 AM, Fariborz Jahanian wrote:

> Author: fjahanian
> Date: Thu Jan 20 11:19:02 2011
> New Revision: 123922
> 
> URL: http://llvm.org/viewvc/llvm-project?rev=123922&view=rev
> Log:
> apple kext abi requires all vf calls, including qualified
> vf calls, be made indirect. This patch is towards that goal.
> 
> Added:
>    cfe/trunk/test/CodeGenCXX/apple-kext-indirect-call.C
> Modified:
>    cfe/trunk/lib/CodeGen/CGCXX.cpp
>    cfe/trunk/lib/CodeGen/CGExprCXX.cpp
>    cfe/trunk/lib/CodeGen/CodeGenFunction.h
> 
> Modified: cfe/trunk/lib/CodeGen/CGCXX.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCXX.cpp?rev=123922&r1=123921&r2=123922&view=diff
> ==============================================================================
> --- cfe/trunk/lib/CodeGen/CGCXX.cpp (original)
> +++ cfe/trunk/lib/CodeGen/CGCXX.cpp Thu Jan 20 11:19:02 2011
> @@ -306,6 +306,35 @@
>   return ::BuildVirtualCall(*this, VTableIndex, This, Ty);
> }
> 
> +/// BuildVirtualCall - This routine is to support gcc's kext ABI making
> +/// indirect call to virtual functions. It makes the call through indexing
> +/// into the vtable.
> +llvm::Value *
> +CodeGenFunction::BuildAppleKextVirtualCall(const CXXMethodDecl *MD, 
> +                                  NestedNameSpecifier *Qual,
> +                                  llvm::Value *This,
> +                                  const llvm::Type *Ty) {
> +  llvm::Value *VTable = 0;
> +  assert((Qual->getKind() == NestedNameSpecifier::TypeSpec) &&
> +         "BuildAppleKextVirtualCall - bad Qual kind");
> +  
> +  const Type *QTy = Qual->getAsType();
> +  QualType T = QualType(QTy, 0);
> +  const RecordType *RT = T->getAs<RecordType>();
> +  assert(RT && "BuildAppleKextVirtualCall - Qual type must be record");
> +  const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
> +  VTable = CGM.getVTables().GetAddrOfVTable(RD);
> +  Ty = Ty->getPointerTo()->getPointerTo();
> +  VTable = Builder.CreateBitCast(VTable, Ty);
> +  assert(VTable && "BuildVirtualCall = kext vtbl pointer is null");
> +  MD = MD->getCanonicalDecl();
> +  uint64_t VTableIndex = CGM.getVTables().getMethodVTableIndex(MD);
> +  VTableIndex += 2;
> +  llvm::Value *VFuncPtr = 
> +    CGF.Builder.CreateConstInBoundsGEP1_64(VTable, VTableIndex, "vfnkxt");
> +  return CGF.Builder.CreateLoad(VFuncPtr);
> +}

I'm really confused about something... why can't we just use BuildVirtualCall for kext calls? And where does the +2 adjustment for VTableIndex come from?

> llvm::Value *
> CodeGenFunction::BuildVirtualCall(const CXXDestructorDecl *DD, CXXDtorType Type, 
>                                   llvm::Value *This, const llvm::Type *Ty) {
> 
> Modified: cfe/trunk/lib/CodeGen/CGExprCXX.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprCXX.cpp?rev=123922&r1=123921&r2=123922&view=diff
> ==============================================================================
> --- cfe/trunk/lib/CodeGen/CGExprCXX.cpp (original)
> +++ cfe/trunk/lib/CodeGen/CGExprCXX.cpp Thu Jan 20 11:19:02 2011
> @@ -172,8 +172,12 @@
>   //
>   // We also don't emit a virtual call if the base expression has a record type
>   // because then we know what the type is.
> -  bool UseVirtualCall = MD->isVirtual() && !ME->hasQualifier()
> +  bool UseVirtualCall;
> +  if (!getContext().getLangOptions().AppleKext)
> +    UseVirtualCall = MD->isVirtual() && !ME->hasQualifier()
>                      && !canDevirtualizeMemberFunctionCalls(ME->getBase(), MD);
> +  else
> +    UseVirtualCall = MD->isVirtual();

I'd rather update canDevirtualizeMemberFunctionCalls() with a getLangOptions().AppleKext check, rather than updating all of the potentially-devirtualizing callers of canDevirtualizeMemberFunctionCalls().

>   llvm::Value *Callee;
>   if (const CXXDestructorDecl *Dtor = dyn_cast<CXXDestructorDecl>(MD)) {
> @@ -186,7 +190,12 @@
>                dyn_cast<CXXConstructorDecl>(MD)) {
>     Callee = CGM.GetAddrOfFunction(GlobalDecl(Ctor, Ctor_Complete), Ty);
>   } else if (UseVirtualCall) {
> -    Callee = BuildVirtualCall(MD, This, Ty); 
> +    if (getContext().getLangOptions().AppleKext &&
> +        ME->hasQualifier()) {
> +      Callee = BuildAppleKextVirtualCall(MD, ME->getQualifier(), This, Ty);
> +    }
> +    else
> +      Callee = BuildVirtualCall(MD, This, Ty); 
>   } else {
>     Callee = CGM.GetAddrOfFunction(MD, Ty);
>   }
> @@ -267,7 +276,9 @@
>     CGM.getTypes().GetFunctionType(CGM.getTypes().getFunctionInfo(MD),
>                                    FPT->isVariadic());
>   llvm::Value *Callee;
> -  if (MD->isVirtual() && !canDevirtualizeMemberFunctionCalls(E->getArg(0), MD))
> +  if (MD->isVirtual() && 
> +      (getContext().getLangOptions().AppleKext || 
> +       !canDevirtualizeMemberFunctionCalls(E->getArg(0), MD)))
>     Callee = BuildVirtualCall(MD, This, Ty);
>   else
>     Callee = CGM.GetAddrOfFunction(MD, Ty);
> 
> Modified: cfe/trunk/lib/CodeGen/CodeGenFunction.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.h?rev=123922&r1=123921&r2=123922&view=diff
> ==============================================================================
> --- cfe/trunk/lib/CodeGen/CodeGenFunction.h (original)
> +++ cfe/trunk/lib/CodeGen/CodeGenFunction.h Thu Jan 20 11:19:02 2011
> @@ -1500,6 +1500,10 @@
>                                 const llvm::Type *Ty);
>   llvm::Value *BuildVirtualCall(const CXXDestructorDecl *DD, CXXDtorType Type,
>                                 llvm::Value *This, const llvm::Type *Ty);
> +  llvm::Value *BuildAppleKextVirtualCall(const CXXMethodDecl *MD, 
> +                                         NestedNameSpecifier *Qual,
> +                                         llvm::Value *This,
> +                                         const llvm::Type *Ty);
> 
>   RValue EmitCXXMemberCall(const CXXMethodDecl *MD,
>                            llvm::Value *Callee,
> 
> Added: cfe/trunk/test/CodeGenCXX/apple-kext-indirect-call.C
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/apple-kext-indirect-call.C?rev=123922&view=auto
> ==============================================================================
> --- cfe/trunk/test/CodeGenCXX/apple-kext-indirect-call.C (added)
> +++ cfe/trunk/test/CodeGenCXX/apple-kext-indirect-call.C Thu Jan 20 11:19:02 2011
> @@ -0,0 +1,15 @@
> +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fapple-kext -emit-llvm -o - %s | FileCheck %s
> +
> +struct Base { 
> +  virtual void abc1(void) const; 
> +  virtual void abc2(void) const; 
> +  virtual void abc(void) const; 
> +};
> +
> +void Base::abc(void) const {}
> +
> +void FUNC(Base* p) {
> +  p->Base::abc();
> +}
> +
> +// CHECK-NOT: call void @_ZNK4Base3abcEv

I'd feel a little more comfortable if this check looked for the indirect call, rather than looking for the absence of a direct call. Plus, we should be checking for that +2 adjustment in the generated IR.

	- Doug



More information about the cfe-commits mailing list