]> granicus.if.org Git - clang/commitdiff
apple kext abi requires all vf calls, including qualified
authorFariborz Jahanian <fjahanian@apple.com>
Thu, 20 Jan 2011 17:19:02 +0000 (17:19 +0000)
committerFariborz Jahanian <fjahanian@apple.com>
Thu, 20 Jan 2011 17:19:02 +0000 (17:19 +0000)
vf calls, be made indirect. This patch is towards that goal.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@123922 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/CGCXX.cpp
lib/CodeGen/CGExprCXX.cpp
lib/CodeGen/CodeGenFunction.h
test/CodeGenCXX/apple-kext-indirect-call.C [new file with mode: 0644]

index bb217fbcc9dc1adab8ab220c8702244f86f6151b..b6381de0270273adca483d431477a29711c564e4 100644 (file)
@@ -306,6 +306,35 @@ CodeGenFunction::BuildVirtualCall(const CXXMethodDecl *MD, llvm::Value *This,
   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);
+}
+
 llvm::Value *
 CodeGenFunction::BuildVirtualCall(const CXXDestructorDecl *DD, CXXDtorType Type, 
                                   llvm::Value *This, const llvm::Type *Ty) {
index 01d671a2d9b3291e42dd2f853d5de5ba68ec15f9..08ff17e1fd7e1bbf46c2c3406522351412541542 100644 (file)
@@ -172,8 +172,12 @@ RValue CodeGenFunction::EmitCXXMemberCallExpr(const CXXMemberCallExpr *CE,
   //
   // 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();
 
   llvm::Value *Callee;
   if (const CXXDestructorDecl *Dtor = dyn_cast<CXXDestructorDecl>(MD)) {
@@ -186,7 +190,12 @@ RValue CodeGenFunction::EmitCXXMemberCallExpr(const CXXMemberCallExpr *CE,
                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 @@ CodeGenFunction::EmitCXXOperatorMemberCallExpr(const CXXOperatorCallExpr *E,
     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);
index 5f21d9fa4347e705b71cba8eeee9c64f14378a48..7686b333659c67619869ee8aa0f8fbc6fdb69d01 100644 (file)
@@ -1500,6 +1500,10 @@ public:
                                 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,
diff --git a/test/CodeGenCXX/apple-kext-indirect-call.C b/test/CodeGenCXX/apple-kext-indirect-call.C
new file mode 100644 (file)
index 0000000..401e743
--- /dev/null
@@ -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