[cfe-commits] r111772 - in /cfe/trunk: lib/CodeGen/CGCXX.cpp lib/CodeGen/CGCXXABI.h lib/CodeGen/CGExprAgg.cpp lib/CodeGen/CGExprConstant.cpp lib/CodeGen/CodeGenModule.h lib/CodeGen/ItaniumCXXABI.cpp lib/Frontend/ASTUnit.cpp lib/Frontend/CompilerInvocation.cpp test/CodeGenCXX/member-function-pointers.cpp

John McCall rjmccall at apple.com
Sat Aug 21 23:43:33 PDT 2010


Author: rjmccall
Date: Sun Aug 22 01:43:33 2010
New Revision: 111772

URL: http://llvm.org/viewvc/llvm-project?rev=111772&view=rev
Log:
Abstract out member-pointer creation.  I'm really unhappy about the current
duplication between the constant and non-constant paths in all of this.

Implement ARM ABI semantics for member pointer constants and conversion.


Modified:
    cfe/trunk/lib/CodeGen/CGCXX.cpp
    cfe/trunk/lib/CodeGen/CGCXXABI.h
    cfe/trunk/lib/CodeGen/CGExprAgg.cpp
    cfe/trunk/lib/CodeGen/CGExprConstant.cpp
    cfe/trunk/lib/CodeGen/CodeGenModule.h
    cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp
    cfe/trunk/lib/Frontend/ASTUnit.cpp
    cfe/trunk/lib/Frontend/CompilerInvocation.cpp
    cfe/trunk/test/CodeGenCXX/member-function-pointers.cpp

Modified: cfe/trunk/lib/CodeGen/CGCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCXX.cpp?rev=111772&r1=111771&r2=111772&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGCXX.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGCXX.cpp Sun Aug 22 01:43:33 2010
@@ -287,44 +287,6 @@
   return cast<llvm::Function>(GetOrCreateLLVMFunction(Name, FTy, GD));
 }
 
-llvm::Constant *
-CodeGenModule::GetCXXMemberFunctionPointerValue(const CXXMethodDecl *MD) {
-  assert(MD->isInstance() && "Member function must not be static!");
-    
-  MD = MD->getCanonicalDecl();
-
-  const llvm::Type *PtrDiffTy = Types.ConvertType(Context.getPointerDiffType());
-
-  // Get the function pointer (or index if this is a virtual function).
-  if (MD->isVirtual()) {
-    uint64_t Index = VTables.getMethodVTableIndex(MD);
-
-    // FIXME: We shouldn't use / 8 here.
-    uint64_t PointerWidthInBytes = Context.Target.getPointerWidth(0) / 8;
-
-    // Itanium C++ ABI 2.3:
-    //   For a non-virtual function, this field is a simple function pointer. 
-    //   For a virtual function, it is 1 plus the virtual table offset 
-    //   (in bytes) of the function, represented as a ptrdiff_t. 
-    return llvm::ConstantInt::get(PtrDiffTy, (Index * PointerWidthInBytes) + 1);
-  }
-
-  const FunctionProtoType *FPT = MD->getType()->getAs<FunctionProtoType>();
-  const llvm::Type *Ty;
-  // Check whether the function has a computable LLVM signature.
-  if (!CodeGenTypes::VerifyFuncTypeComplete(FPT)) {
-    // The function has a computable LLVM signature; use the correct type.
-    Ty = Types.GetFunctionType(Types.getFunctionInfo(MD), FPT->isVariadic());
-  } else {
-    // Use an arbitrary non-function type to tell GetAddrOfFunction that the
-    // function type is incomplete.
-    Ty = PtrDiffTy;
-  }
-
-  llvm::Constant *FuncPtr = GetAddrOfFunction(MD, Ty);
-  return llvm::ConstantExpr::getPtrToInt(FuncPtr, PtrDiffTy);
-}
-
 static llvm::Value *BuildVirtualCall(CodeGenFunction &CGF, uint64_t VTableIndex, 
                                      llvm::Value *This, const llvm::Type *Ty) {
   Ty = Ty->getPointerTo()->getPointerTo()->getPointerTo();
@@ -400,6 +362,13 @@
   ErrorUnsupportedABI(CGF, "null member function pointers");
 }
 
+void CGCXXABI::EmitMemberFunctionPointer(CodeGenFunction &CGF,
+                                         const CXXMethodDecl *MD,
+                                         llvm::Value *DestPtr,
+                                         bool VolatileDest) {
+  ErrorUnsupportedABI(CGF, "member function pointers");
+}
+
 llvm::Constant *
 CGCXXABI::EmitMemberFunctionPointerConversion(llvm::Constant *C,
                                               const CastExpr *E) {
@@ -411,6 +380,10 @@
   return 0;
 }
 
+llvm::Constant *CGCXXABI::EmitMemberFunctionPointer(const CXXMethodDecl *MD) {
+  return 0;
+}
+
 bool CGCXXABI::RequiresNonZeroInitializer(QualType T) {
   return false;
 }

Modified: cfe/trunk/lib/CodeGen/CGCXXABI.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCXXABI.h?rev=111772&r1=111771&r2=111772&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGCXXABI.h (original)
+++ cfe/trunk/lib/CodeGen/CGCXXABI.h Sun Aug 22 01:43:33 2010
@@ -22,6 +22,7 @@
 
 namespace clang {
   class CastExpr;
+  class CXXMethodDecl;
   class CXXRecordDecl;
   class MemberPointerType;
   class QualType;
@@ -70,6 +71,12 @@
 
   virtual llvm::Constant *
   EmitNullMemberFunctionPointer(const MemberPointerType *MPT);
+
+  virtual llvm::Constant *EmitMemberFunctionPointer(const CXXMethodDecl *MD);
+  virtual void EmitMemberFunctionPointer(CodeGenFunction &CGF,
+                                         const CXXMethodDecl *MD,
+                                         llvm::Value *DestPtr,
+                                         bool VolatileDest);
 };
 
 /// Creates an instance of a C++ ABI class.

Modified: cfe/trunk/lib/CodeGen/CGExprAgg.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprAgg.cpp?rev=111772&r1=111771&r2=111772&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGExprAgg.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExprAgg.cpp Sun Aug 22 01:43:33 2010
@@ -364,9 +364,8 @@
 
 void AggExprEmitter::VisitUnaryAddrOf(const UnaryOperator *E) {
   // We have a member function pointer.
-  const MemberPointerType *MPT = E->getType()->getAs<MemberPointerType>();
-  (void) MPT;
-  assert(MPT->getPointeeType()->isFunctionProtoType() &&
+  assert(E->getType()->getAs<MemberPointerType>()
+          ->getPointeeType()->isFunctionProtoType() &&
          "Unexpected member pointer type!");
 
   // The creation of member function pointers has no side effects; if
@@ -375,20 +374,9 @@
     return;
   
   const DeclRefExpr *DRE = cast<DeclRefExpr>(E->getSubExpr());
-  const CXXMethodDecl *MD = 
-    cast<CXXMethodDecl>(DRE->getDecl())->getCanonicalDecl();
+  const CXXMethodDecl *MD = cast<CXXMethodDecl>(DRE->getDecl());
 
-  const llvm::Type *PtrDiffTy = 
-    CGF.ConvertType(CGF.getContext().getPointerDiffType());
-
-  llvm::Value *DstPtr = Builder.CreateStructGEP(DestPtr, 0, "dst.ptr");
-  llvm::Value *FuncPtr = CGF.CGM.GetCXXMemberFunctionPointerValue(MD);
-  Builder.CreateStore(FuncPtr, DstPtr, VolatileDest);
-
-  llvm::Value *AdjPtr = Builder.CreateStructGEP(DestPtr, 1, "dst.adj");
-  // The adjustment will always be 0.
-  Builder.CreateStore(llvm::ConstantInt::get(PtrDiffTy, 0), AdjPtr,
-                      VolatileDest);
+  CGF.CGM.getCXXABI().EmitMemberFunctionPointer(CGF, MD, DestPtr, VolatileDest);
 }
 
 void AggExprEmitter::VisitStmtExpr(const StmtExpr *E) {

Modified: cfe/trunk/lib/CodeGen/CGExprConstant.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprConstant.cpp?rev=111772&r1=111771&r2=111772&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGExprConstant.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExprConstant.cpp Sun Aug 22 01:43:33 2010
@@ -455,22 +455,7 @@
   }
     
   llvm::Constant *EmitMemberFunctionPointer(CXXMethodDecl *MD) {
-    assert(MD->isInstance() && "Member function must not be static!");
-    
-    MD = MD->getCanonicalDecl();
-
-    const llvm::Type *PtrDiffTy = 
-      CGM.getTypes().ConvertType(CGM.getContext().getPointerDiffType());
-    
-    llvm::Constant *Values[2];
-
-    Values[0] = CGM.GetCXXMemberFunctionPointerValue(MD);
-    
-    // The adjustment will always be 0.
-    Values[1] = llvm::ConstantInt::get(PtrDiffTy, 0);
-    
-    return llvm::ConstantStruct::get(CGM.getLLVMContext(),
-                                     Values, 2, /*Packed=*/false);
+    return CGM.getCXXABI().EmitMemberFunctionPointer(MD);
   }
 
   llvm::Constant *VisitUnaryAddrOf(UnaryOperator *E) {

Modified: cfe/trunk/lib/CodeGen/CodeGenModule.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.h?rev=111772&r1=111771&r2=111772&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenModule.h (original)
+++ cfe/trunk/lib/CodeGen/CodeGenModule.h Sun Aug 22 01:43:33 2010
@@ -371,10 +371,6 @@
   llvm::GlobalValue *GetAddrOfCXXDestructor(const CXXDestructorDecl *D,
                                             CXXDtorType Type);
 
-  // GetCXXMemberFunctionPointerValue - Given a method declaration, return the
-  // integer used in a member function pointer to refer to that value.
-  llvm::Constant *GetCXXMemberFunctionPointerValue(const CXXMethodDecl *MD);
-
   /// getBuiltinLibFunction - Given a builtin id for a function like
   /// "__builtin_fabsf", return a Function* for "fabsf".
   llvm::Value *getBuiltinLibFunction(const FunctionDecl *FD,

Modified: cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp?rev=111772&r1=111771&r2=111772&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp (original)
+++ cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp Sun Aug 22 01:43:33 2010
@@ -66,6 +66,16 @@
 
   llvm::Constant *EmitNullMemberFunctionPointer(const MemberPointerType *MPT);
 
+  void EmitMemberFunctionPointer(CodeGenFunction &CGF,
+                                 const CXXMethodDecl *MD,
+                                 llvm::Value *Dest,
+                                 bool VolatileDest);
+
+  llvm::Constant *EmitMemberFunctionPointer(const CXXMethodDecl *MD);
+
+private:
+  void GetMemberFunctionPointer(const CXXMethodDecl *MD,
+                                llvm::Constant *(&Array)[2]);
 };
 
 class ARMCXXABI : public ItaniumCXXABI {
@@ -82,6 +92,62 @@
   return new ARMCXXABI(CGM);
 }
 
+void ItaniumCXXABI::GetMemberFunctionPointer(const CXXMethodDecl *MD,
+                                             llvm::Constant *(&MemPtr)[2]) {
+  assert(MD->isInstance() && "Member function must not be static!");
+    
+  MD = MD->getCanonicalDecl();
+
+  CodeGenTypes &Types = CGM.getTypes();
+  const llvm::Type *ptrdiff_t = 
+    Types.ConvertType(CGM.getContext().getPointerDiffType());
+
+  // Get the function pointer (or index if this is a virtual function).
+  if (MD->isVirtual()) {
+    uint64_t Index = CGM.getVTables().getMethodVTableIndex(MD);
+
+    // FIXME: We shouldn't use / 8 here.
+    uint64_t PointerWidthInBytes =
+      CGM.getContext().Target.getPointerWidth(0) / 8;
+    uint64_t VTableOffset = (Index * PointerWidthInBytes);
+
+    if (IsARM) {
+      // ARM C++ ABI 3.2.1:
+      //   This ABI specifies that adj contains twice the this
+      //   adjustment, plus 1 if the member function is virtual. The
+      //   least significant bit of adj then makes exactly the same
+      //   discrimination as the least significant bit of ptr does for
+      //   Itanium.
+      MemPtr[0] = llvm::ConstantInt::get(ptrdiff_t, VTableOffset);
+      MemPtr[1] = llvm::ConstantInt::get(ptrdiff_t, 1);
+    } else {
+      // Itanium C++ ABI 2.3:
+      //   For a virtual function, [the pointer field] is 1 plus the
+      //   virtual table offset (in bytes) of the function,
+      //   represented as a ptrdiff_t.
+      MemPtr[0] = llvm::ConstantInt::get(ptrdiff_t, VTableOffset + 1);
+      MemPtr[1] = llvm::ConstantInt::get(ptrdiff_t, 0);
+    }
+  } else {
+    const FunctionProtoType *FPT = MD->getType()->getAs<FunctionProtoType>();
+    const llvm::Type *Ty;
+    // Check whether the function has a computable LLVM signature.
+    if (!CodeGenTypes::VerifyFuncTypeComplete(FPT)) {
+      // The function has a computable LLVM signature; use the correct type.
+      Ty = Types.GetFunctionType(Types.getFunctionInfo(MD), FPT->isVariadic());
+    } else {
+      // Use an arbitrary non-function type to tell GetAddrOfFunction that the
+      // function type is incomplete.
+      Ty = ptrdiff_t;
+    }
+
+    llvm::Constant *Addr = CGM.GetAddrOfFunction(MD, Ty);
+    MemPtr[0] = llvm::ConstantExpr::getPtrToInt(Addr, ptrdiff_t);
+    MemPtr[1] = llvm::ConstantInt::get(ptrdiff_t, 0);
+  }
+}
+
+
 /// In the Itanium and ARM ABIs, method pointers have the form:
 ///   struct { ptrdiff_t ptr; ptrdiff_t adj; } memptr;
 ///
@@ -231,6 +297,13 @@
         CGF.CGM.GetNonVirtualBaseClassOffset(DerivedDecl,
                                              E->path_begin(),
                                              E->path_end())) {
+    // The this-adjustment is left-shifted by 1 on ARM.
+    if (IsARM) {
+      uint64_t Offset = cast<llvm::ConstantInt>(Adj)->getZExtValue();
+      Offset <<= 1;
+      Adj = llvm::ConstantInt::get(Adj->getType(), Offset);
+    }
+
     if (DerivedToBase)
       SrcAdj = Builder.CreateSub(SrcAdj, Adj, "adj");
     else
@@ -265,6 +338,13 @@
   // If there's no offset, we're done.
   if (!Offset) return C;
 
+  // The this-adjustment is left-shifted by 1 on ARM.
+  if (IsARM) {
+    uint64_t OffsetV = cast<llvm::ConstantInt>(Offset)->getZExtValue();
+    OffsetV <<= 1;
+    Offset = llvm::ConstantInt::get(Offset->getType(), OffsetV);
+  }
+
   llvm::ConstantStruct *CS = cast<llvm::ConstantStruct>(C);
 
   llvm::Constant *Values[2] = {
@@ -300,6 +380,32 @@
   return CGM.EmitNullConstant(QualType(MPT, 0));
 }
 
+llvm::Constant *
+ItaniumCXXABI::EmitMemberFunctionPointer(const CXXMethodDecl *MD) {
+  llvm::Constant *Values[2];
+  GetMemberFunctionPointer(MD, Values);
+  
+  return llvm::ConstantStruct::get(CGM.getLLVMContext(),
+                                   Values, 2, /*Packed=*/false);
+}
+
+void ItaniumCXXABI::EmitMemberFunctionPointer(CodeGenFunction &CGF,
+                                              const CXXMethodDecl *MD,
+                                              llvm::Value *DestPtr,
+                                              bool VolatileDest) {
+  llvm::Constant *Values[2];
+  GetMemberFunctionPointer(MD, Values);
+
+  CGBuilderTy &Builder = CGF.Builder;
+  
+  llvm::Value *DstPtr = Builder.CreateStructGEP(DestPtr, 0, "memptr.ptr");
+  Builder.CreateStore(Values[0], DstPtr, VolatileDest);
+
+  llvm::Value *AdjPtr = Builder.CreateStructGEP(DestPtr, 1, "memptr.adj");
+  Builder.CreateStore(Values[1], AdjPtr, VolatileDest);
+}
+
+
 bool ItaniumCXXABI::RequiresNonZeroInitializer(QualType T) {
   return CGM.getTypes().ContainsPointerToDataMember(T);
 }

Modified: cfe/trunk/lib/Frontend/ASTUnit.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/ASTUnit.cpp?rev=111772&r1=111771&r2=111772&view=diff
==============================================================================
--- cfe/trunk/lib/Frontend/ASTUnit.cpp (original)
+++ cfe/trunk/lib/Frontend/ASTUnit.cpp Sun Aug 22 01:43:33 2010
@@ -484,7 +484,7 @@
   // FIXME: This is broken, we should store the TargetOptions in the AST file.
   TargetOptions TargetOpts;
   TargetOpts.ABI = "";
-  TargetOpts.CXXABI = "itanium";
+  TargetOpts.CXXABI = "";
   TargetOpts.CPU = "";
   TargetOpts.Features.clear();
   TargetOpts.Triple = TargetTriple;

Modified: cfe/trunk/lib/Frontend/CompilerInvocation.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/CompilerInvocation.cpp?rev=111772&r1=111771&r2=111772&view=diff
==============================================================================
--- cfe/trunk/lib/Frontend/CompilerInvocation.cpp (original)
+++ cfe/trunk/lib/Frontend/CompilerInvocation.cpp Sun Aug 22 01:43:33 2010
@@ -713,8 +713,10 @@
     Res.push_back("-target-linker-version");
     Res.push_back(Opts.LinkerVersion);
   }
-  Res.push_back("-cxx-abi");
-  Res.push_back(Opts.CXXABI);
+  if (!Opts.CXXABI.empty()) {
+    Res.push_back("-cxx-abi");
+    Res.push_back(Opts.CXXABI);
+  }
   for (unsigned i = 0, e = Opts.Features.size(); i != e; ++i) {
     Res.push_back("-target-feature");
     Res.push_back(Opts.Features[i]);
@@ -1471,10 +1473,6 @@
   // Use the host triple if unspecified.
   if (Opts.Triple.empty())
     Opts.Triple = llvm::sys::getHostTriple();
-
-  // Use the Itanium C++ ABI if unspecified.
-  if (Opts.CXXABI.empty())
-    Opts.CXXABI = "itanium";
 }
 
 //

Modified: cfe/trunk/test/CodeGenCXX/member-function-pointers.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/member-function-pointers.cpp?rev=111772&r1=111771&r2=111772&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/member-function-pointers.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/member-function-pointers.cpp Sun Aug 22 01:43:33 2010
@@ -1,5 +1,6 @@
 // RUN: %clang_cc1 %s -emit-llvm -o - -triple=x86_64-apple-darwin9 | FileCheck %s
 // RUN: %clang_cc1 %s -emit-llvm -o - -triple=i386-apple-darwin9 | FileCheck -check-prefix LP32 %s
+// RUN: %clang_cc1 %s -emit-llvm -o - -triple=armv7-unknown-unknown | FileCheck -check-prefix ARM %s
 
 struct A { int a; void f(); virtual void vf1(); virtual void vf2(); };
 struct B { int b; virtual void g(); };
@@ -190,3 +191,22 @@
   struct X { void test( ); };
   void testX() { &X::test; }
 }
+
+namespace test7 {
+  struct A { void foo(); virtual void vfoo(); };
+  struct B { void foo(); virtual void vfoo(); };
+  struct C : A, B { void foo(); virtual void vfoo(); };
+
+  // CHECK-ARM: @_ZN5test74ptr0E = global {{.*}} { i32 ptrtoint ({{.*}}* @_ZN5test71A3fooEv to i32), i32 0 }
+  // CHECK-ARM: @_ZN5test74ptr1E = global {{.*}} { i32 ptrtoint ({{.*}}* @_ZN5test71B3fooEv to i32), i32 8 }
+  // CHECK-ARM: @_ZN5test74ptr2E = global {{.*}} { i32 ptrtoint ({{.*}}* @_ZN5test71C3fooEv to i32), i32 0 }
+  // CHECK-ARM: @_ZN5test74ptr3E = global {{.*}} { i32 0, i32 1 }
+  // CHECK-ARM: @_ZN5test74ptr4E = global {{.*}} { i32 0, i32 9 }
+  // CHECK-ARM: @_ZN5test74ptr5E = global {{.*}} { i32 0, i32 1 }
+  void (C::*ptr0)() = &A::foo;
+  void (C::*ptr1)() = &B::foo;
+  void (C::*ptr2)() = &C::foo;
+  void (C::*ptr3)() = &A::vfoo;
+  void (C::*ptr4)() = &B::vfoo;
+  void (C::*ptr5)() = &C::vfoo;
+}





More information about the cfe-commits mailing list