[cfe-commits] r111752 - in /cfe/trunk/lib/CodeGen: CGCXX.cpp CGCXXABI.h CGExprCXX.cpp ItaniumCXXABI.cpp

John McCall rjmccall at apple.com
Sat Aug 21 17:05:51 PDT 2010


Author: rjmccall
Date: Sat Aug 21 19:05:51 2010
New Revision: 111752

URL: http://llvm.org/viewvc/llvm-project?rev=111752&view=rev
Log:
Extract calls to method pointers out as an ABI routine.
No functionality change.


Modified:
    cfe/trunk/lib/CodeGen/CGCXX.cpp
    cfe/trunk/lib/CodeGen/CGCXXABI.h
    cfe/trunk/lib/CodeGen/CGExprCXX.cpp
    cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp

Modified: cfe/trunk/lib/CodeGen/CGCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCXX.cpp?rev=111752&r1=111751&r2=111752&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGCXX.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGCXX.cpp Sat Aug 21 19:05:51 2010
@@ -357,3 +357,25 @@
 }
 
 CGCXXABI::~CGCXXABI() {}
+
+llvm::Value *CGCXXABI::EmitLoadOfMemberFunctionPointer(CodeGenFunction &CGF,
+                                                       llvm::Value *&This,
+                                                       llvm::Value *MemPtr,
+                                                 const MemberPointerType *MPT) {
+  Diagnostic &Diags = CGF.CGM.getDiags();
+  unsigned DiagID =
+    Diags.getCustomDiagID(Diagnostic::Error,
+                          "cannot yet compile member pointer calls in this ABI");
+  Diags.Report(CGF.getContext().getFullLoc(CGF.CurCodeDecl->getLocation()),
+               DiagID);
+
+  const FunctionProtoType *FPT = 
+    MPT->getPointeeType()->getAs<FunctionProtoType>();
+  const CXXRecordDecl *RD = 
+    cast<CXXRecordDecl>(MPT->getClass()->getAs<RecordType>()->getDecl());
+  const llvm::FunctionType *FTy = 
+    CGF.CGM.getTypes().GetFunctionType(
+                                 CGF.CGM.getTypes().getFunctionInfo(RD, FPT),
+                                 FPT->isVariadic());
+  return llvm::Constant::getNullValue(FTy->getPointerTo());
+}

Modified: cfe/trunk/lib/CodeGen/CGCXXABI.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCXXABI.h?rev=111752&r1=111751&r2=111752&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGCXXABI.h (original)
+++ cfe/trunk/lib/CodeGen/CGCXXABI.h Sat Aug 21 19:05:51 2010
@@ -15,8 +15,15 @@
 #ifndef CLANG_CODEGEN_CXXABI_H
 #define CLANG_CODEGEN_CXXABI_H
 
+namespace llvm {
+  class Value;
+}
+
 namespace clang {
+  class MemberPointerType;
+
 namespace CodeGen {
+  class CodeGenFunction;
   class CodeGenModule;
   class MangleContext;
 
@@ -27,12 +34,19 @@
 
   /// Gets the mangle context.
   virtual MangleContext &getMangleContext() = 0;
+
+  virtual llvm::Value *
+  EmitLoadOfMemberFunctionPointer(CodeGenFunction &CGF,
+                                  llvm::Value *&This,
+                                  llvm::Value *MemPtr,
+                                  const MemberPointerType *MPT);
 };
 
 /// Creates an instance of a C++ ABI class.
 CGCXXABI *CreateARMCXXABI(CodeGenModule &CGM);
 CGCXXABI *CreateItaniumCXXABI(CodeGenModule &CGM);
 CGCXXABI *CreateMicrosoftCXXABI(CodeGenModule &CGM);
+
 }
 }
 

Modified: cfe/trunk/lib/CodeGen/CGExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprCXX.cpp?rev=111752&r1=111751&r2=111752&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGExprCXX.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExprCXX.cpp Sat Aug 21 19:05:51 2010
@@ -153,17 +153,12 @@
   
   const MemberPointerType *MPT = 
     MemFnExpr->getType()->getAs<MemberPointerType>();
+
   const FunctionProtoType *FPT = 
     MPT->getPointeeType()->getAs<FunctionProtoType>();
   const CXXRecordDecl *RD = 
     cast<CXXRecordDecl>(MPT->getClass()->getAs<RecordType>()->getDecl());
 
-  const llvm::FunctionType *FTy = 
-    CGM.getTypes().GetFunctionType(CGM.getTypes().getFunctionInfo(RD, FPT),
-                                   FPT->isVariadic());
-
-  const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(VMContext);
-
   // Get the member function pointer.
   llvm::Value *MemFnPtr = CreateMemTemp(MemFnExpr->getType(), "mem.fn");
   EmitAggExpr(MemFnExpr, MemFnPtr, /*VolatileDest=*/false);
@@ -175,67 +170,11 @@
     This = EmitScalarExpr(BaseExpr);
   else 
     This = EmitLValue(BaseExpr).getAddress();
-  
-  // Adjust it.
-  llvm::Value *Adj = Builder.CreateStructGEP(MemFnPtr, 1);
-  Adj = Builder.CreateLoad(Adj, "mem.fn.adj");
-  
-  llvm::Value *Ptr = Builder.CreateBitCast(This, Int8PtrTy, "ptr");
-  Ptr = Builder.CreateGEP(Ptr, Adj, "adj");
-  
-  This = Builder.CreateBitCast(Ptr, This->getType(), "this");
-  
-  llvm::Value *FnPtr = Builder.CreateStructGEP(MemFnPtr, 0, "mem.fn.ptr");
-  
-  const llvm::Type *PtrDiffTy = ConvertType(getContext().getPointerDiffType());
 
-  llvm::Value *FnAsInt = Builder.CreateLoad(FnPtr, "fn");
-  
-  // If the LSB in the function pointer is 1, the function pointer points to
-  // a virtual function.
-  llvm::Value *IsVirtual 
-    = Builder.CreateAnd(FnAsInt, llvm::ConstantInt::get(PtrDiffTy, 1),
-                        "and");
-  
-  IsVirtual = Builder.CreateTrunc(IsVirtual,
-                                  llvm::Type::getInt1Ty(VMContext));
+  // Ask the ABI to load the callee.  Note that This is modified.
+  llvm::Value *Callee =
+    CGM.getCXXABI().EmitLoadOfMemberFunctionPointer(CGF, This, MemFnPtr, MPT);
   
-  llvm::BasicBlock *FnVirtual = createBasicBlock("fn.virtual");
-  llvm::BasicBlock *FnNonVirtual = createBasicBlock("fn.nonvirtual");
-  llvm::BasicBlock *FnEnd = createBasicBlock("fn.end");
-  
-  Builder.CreateCondBr(IsVirtual, FnVirtual, FnNonVirtual);
-  EmitBlock(FnVirtual);
-  
-  const llvm::Type *VTableTy = 
-    FTy->getPointerTo()->getPointerTo();
-
-  llvm::Value *VTable = Builder.CreateBitCast(This, VTableTy->getPointerTo());
-  VTable = Builder.CreateLoad(VTable);
-  
-  VTable = Builder.CreateBitCast(VTable, Int8PtrTy);
-  llvm::Value *VTableOffset = 
-    Builder.CreateSub(FnAsInt, llvm::ConstantInt::get(PtrDiffTy, 1));
-  
-  VTable = Builder.CreateGEP(VTable, VTableOffset, "fn");
-  VTable = Builder.CreateBitCast(VTable, VTableTy);
-  
-  llvm::Value *VirtualFn = Builder.CreateLoad(VTable, "virtualfn");
-  
-  EmitBranch(FnEnd);
-  EmitBlock(FnNonVirtual);
-  
-  // If the function is not virtual, just load the pointer.
-  llvm::Value *NonVirtualFn = Builder.CreateLoad(FnPtr, "fn");
-  NonVirtualFn = Builder.CreateIntToPtr(NonVirtualFn, FTy->getPointerTo());
-  
-  EmitBlock(FnEnd);
-
-  llvm::PHINode *Callee = Builder.CreatePHI(FTy->getPointerTo());
-  Callee->reserveOperandSpace(2);
-  Callee->addIncoming(VirtualFn, FnVirtual);
-  Callee->addIncoming(NonVirtualFn, FnNonVirtual);
-
   CallArgList Args;
 
   QualType ThisType = 

Modified: cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp?rev=111752&r1=111751&r2=111752&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp (original)
+++ cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp Sat Aug 21 19:05:51 2010
@@ -19,21 +19,32 @@
 //===----------------------------------------------------------------------===//
 
 #include "CGCXXABI.h"
+#include "CodeGenFunction.h"
 #include "CodeGenModule.h"
 #include "Mangle.h"
+#include <clang/AST/Type.h>
+#include <llvm/Value.h>
 
 using namespace clang;
+using namespace CodeGen;
 
 namespace {
 class ItaniumCXXABI : public CodeGen::CGCXXABI {
+protected:
+  CodeGenModule &CGM;
   CodeGen::MangleContext MangleCtx;
 public:
   ItaniumCXXABI(CodeGen::CodeGenModule &CGM) :
-    MangleCtx(CGM.getContext(), CGM.getDiags()) { }
+    CGM(CGM), MangleCtx(CGM.getContext(), CGM.getDiags()) { }
 
   CodeGen::MangleContext &getMangleContext() {
     return MangleCtx;
   }
+
+  llvm::Value *EmitLoadOfMemberFunctionPointer(CodeGenFunction &CGF,
+                                               llvm::Value *&This,
+                                               llvm::Value *MemFnPtr,
+                                               const MemberPointerType *MPT);
 };
 
 class ARMCXXABI : public ItaniumCXXABI {
@@ -50,3 +61,77 @@
   return new ARMCXXABI(CGM);
 }
 
+llvm::Value *
+ItaniumCXXABI::EmitLoadOfMemberFunctionPointer(CodeGenFunction &CGF,
+                                               llvm::Value *&This,
+                                               llvm::Value *MemFnPtr,
+                                               const MemberPointerType *MPT) {
+  CGBuilderTy &Builder = CGF.Builder;
+
+  const FunctionProtoType *FPT = 
+    MPT->getPointeeType()->getAs<FunctionProtoType>();
+  const CXXRecordDecl *RD = 
+    cast<CXXRecordDecl>(MPT->getClass()->getAs<RecordType>()->getDecl());
+
+  const llvm::FunctionType *FTy = 
+    CGM.getTypes().GetFunctionType(CGM.getTypes().getFunctionInfo(RD, FPT),
+                                   FPT->isVariadic());
+
+  llvm::BasicBlock *FnVirtual = CGF.createBasicBlock("fn.virtual");
+  llvm::BasicBlock *FnNonVirtual = CGF.createBasicBlock("fn.nonvirtual");
+  llvm::BasicBlock *FnEnd = CGF.createBasicBlock("fn.end");
+
+  // Load the adjustment, which is in the second field.
+  llvm::Value *Adj = Builder.CreateStructGEP(MemFnPtr, 1);
+  Adj = Builder.CreateLoad(Adj, "mem.fn.adj");
+
+  // Apply the adjustment and cast back to the original struct type
+  // for consistency.
+  llvm::Value *Ptr = Builder.CreateBitCast(This, Builder.getInt8PtrTy(), "ptr");
+  Ptr = Builder.CreateInBoundsGEP(Ptr, Adj, "adj");
+  This = Builder.CreateBitCast(Ptr, This->getType(), "this");
+  
+  // Load the function pointer.
+  llvm::Value *FnPtr = Builder.CreateStructGEP(MemFnPtr, 0, "mem.fn.ptr");
+  llvm::Value *FnAsInt = Builder.CreateLoad(FnPtr, "fn");
+  
+  // If the LSB in the function pointer is 1, the function pointer points to
+  // a virtual function.
+  llvm::Constant *iptr_1 = llvm::ConstantInt::get(FnAsInt->getType(), 1);
+  llvm::Value *IsVirtual = Builder.CreateAnd(FnAsInt, iptr_1);
+  IsVirtual = Builder.CreateIsNotNull(IsVirtual);
+  Builder.CreateCondBr(IsVirtual, FnVirtual, FnNonVirtual);
+
+  // In the virtual path, the adjustment left 'This' pointing to the
+  // vtable of the correct base subobject.  The "function pointer" is an
+  // offset within the vtable (+1 for the virtual flag).
+  CGF.EmitBlock(FnVirtual);
+
+  // Cast the adjusted this to a pointer to vtable pointer and load.
+  const llvm::Type *VTableTy = Builder.getInt8PtrTy();
+  llvm::Value *VTable = Builder.CreateBitCast(This, VTableTy->getPointerTo());
+  VTable = Builder.CreateLoad(VTable);
+
+  // Apply the offset.
+  llvm::Value *VTableOffset = Builder.CreateSub(FnAsInt, iptr_1);
+  VTable = Builder.CreateGEP(VTable, VTableOffset, "fn");
+
+  // Load the virtual function to call.
+  VTable = Builder.CreateBitCast(VTable, FTy->getPointerTo()->getPointerTo());
+  llvm::Value *VirtualFn = Builder.CreateLoad(VTable, "virtualfn");
+  CGF.EmitBranch(FnEnd);
+
+  // In the non-virtual path, the function pointer is actually a
+  // function pointer.
+  CGF.EmitBlock(FnNonVirtual);
+  llvm::Value *NonVirtualFn =
+    Builder.CreateIntToPtr(FnAsInt, FTy->getPointerTo());
+  
+  // We're done.
+  CGF.EmitBlock(FnEnd);
+  llvm::PHINode *Callee = Builder.CreatePHI(FTy->getPointerTo());
+  Callee->reserveOperandSpace(2);
+  Callee->addIncoming(VirtualFn, FnVirtual);
+  Callee->addIncoming(NonVirtualFn, FnNonVirtual);
+  return Callee;
+}





More information about the cfe-commits mailing list