[cfe-commits] r111776 - in /cfe/trunk: lib/CodeGen/CGCXX.cpp lib/CodeGen/CGCXXABI.h lib/CodeGen/CGExpr.cpp lib/CodeGen/CGExprAgg.cpp lib/CodeGen/CGExprCXX.cpp lib/CodeGen/CGExprConstant.cpp lib/CodeGen/CGExprScalar.cpp lib/CodeGen/CodeGenFunction.cpp lib/CodeGen/ItaniumCXXABI.cpp lib/CodeGen/MicrosoftCXXABI.cpp lib/CodeGen/TargetInfo.cpp test/CodeGenCXX/member-function-pointers.cpp test/CodeGenCXX/x86_32-arguments.cpp

John McCall rjmccall at apple.com
Sun Aug 22 03:59:02 PDT 2010


Author: rjmccall
Date: Sun Aug 22 05:59:02 2010
New Revision: 111776

URL: http://llvm.org/viewvc/llvm-project?rev=111776&view=rev
Log:
Experiment with using first-class aggregates to represent member function
pointers.  I find the resulting code to be substantially cleaner, and it
makes it very easy to use the same APIs for data member pointers (which I have
conscientiously avoided here), and it avoids a plethora of potential
inefficiencies due to excessive memory copying, but we'll have to see if it
actually works.


Modified:
    cfe/trunk/lib/CodeGen/CGCXX.cpp
    cfe/trunk/lib/CodeGen/CGCXXABI.h
    cfe/trunk/lib/CodeGen/CGExpr.cpp
    cfe/trunk/lib/CodeGen/CGExprAgg.cpp
    cfe/trunk/lib/CodeGen/CGExprCXX.cpp
    cfe/trunk/lib/CodeGen/CGExprConstant.cpp
    cfe/trunk/lib/CodeGen/CGExprScalar.cpp
    cfe/trunk/lib/CodeGen/CodeGenFunction.cpp
    cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp
    cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp
    cfe/trunk/lib/CodeGen/TargetInfo.cpp
    cfe/trunk/test/CodeGenCXX/member-function-pointers.cpp
    cfe/trunk/test/CodeGenCXX/x86_32-arguments.cpp

Modified: cfe/trunk/lib/CodeGen/CGCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCXX.cpp?rev=111776&r1=111775&r2=111776&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGCXX.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGCXX.cpp Sun Aug 22 05:59:02 2010
@@ -330,6 +330,11 @@
     << S;
 }
 
+static llvm::Constant *GetBogusMemberPointer(CodeGenModule &CGM,
+                                             QualType T) {
+  return llvm::Constant::getNullValue(CGM.getTypes().ConvertType(T));
+}
+
 llvm::Value *CGCXXABI::EmitLoadOfMemberFunctionPointer(CodeGenFunction &CGF,
                                                        llvm::Value *&This,
                                                        llvm::Value *MemPtr,
@@ -341,32 +346,16 @@
   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());
+    CGM.getTypes().GetFunctionType(CGM.getTypes().getFunctionInfo(RD, FPT),
+                                   FPT->isVariadic());
   return llvm::Constant::getNullValue(FTy->getPointerTo());
 }
 
-void CGCXXABI::EmitMemberFunctionPointerConversion(CodeGenFunction &CGF,
-                                                   const CastExpr *E,
-                                                   llvm::Value *Src,
-                                                   llvm::Value *Dest,
-                                                   bool VolatileDest) {
+llvm::Value *CGCXXABI::EmitMemberFunctionPointerConversion(CodeGenFunction &CGF,
+                                                           const CastExpr *E,
+                                                           llvm::Value *Src) {
   ErrorUnsupportedABI(CGF, "member function pointer conversions");
-}
-
-void CGCXXABI::EmitNullMemberFunctionPointer(CodeGenFunction &CGF,
-                                             const MemberPointerType *MPT,
-                                             llvm::Value *Dest,
-                                             bool VolatileDest) {
-  ErrorUnsupportedABI(CGF, "null member function pointers");
-}
-
-void CGCXXABI::EmitMemberFunctionPointer(CodeGenFunction &CGF,
-                                         const CXXMethodDecl *MD,
-                                         llvm::Value *DestPtr,
-                                         bool VolatileDest) {
-  ErrorUnsupportedABI(CGF, "member function pointers");
+  return GetBogusMemberPointer(CGM, E->getType());
 }
 
 llvm::Value *
@@ -390,16 +379,18 @@
 llvm::Constant *
 CGCXXABI::EmitMemberFunctionPointerConversion(llvm::Constant *C,
                                               const CastExpr *E) {
-  return 0;
+  return GetBogusMemberPointer(CGM, E->getType());
 }
 
 llvm::Constant *
 CGCXXABI::EmitNullMemberFunctionPointer(const MemberPointerType *MPT) {
-  return 0;
+  return GetBogusMemberPointer(CGM, QualType(MPT, 0));
 }
 
 llvm::Constant *CGCXXABI::EmitMemberFunctionPointer(const CXXMethodDecl *MD) {
-  return 0;
+  return GetBogusMemberPointer(CGM,
+                         CGM.getContext().getMemberPointerType(MD->getType(),
+                                         MD->getParent()->getTypeForDecl()));
 }
 
 bool CGCXXABI::RequiresNonZeroInitializer(QualType T) {

Modified: cfe/trunk/lib/CodeGen/CGCXXABI.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCXXABI.h?rev=111776&r1=111775&r2=111776&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGCXXABI.h (original)
+++ cfe/trunk/lib/CodeGen/CGCXXABI.h Sun Aug 22 05:59:02 2010
@@ -34,7 +34,13 @@
 
 /// Implements C++ ABI-specific code generation functions.
 class CGCXXABI {
+protected:
+  CodeGenModule &CGM;
+
+  CGCXXABI(CodeGenModule &CGM) : CGM(CGM) {}
+
 public:
+
   virtual ~CGCXXABI();
 
   /// Gets the mangle context.
@@ -46,18 +52,11 @@
                                   llvm::Value *MemPtr,
                                   const MemberPointerType *MPT);
 
-  virtual void
+  virtual llvm::Value *
   EmitMemberFunctionPointerConversion(CodeGenFunction &CGF,
                                       const CastExpr *E,
-                                      llvm::Value *Src,
-                                      llvm::Value *Dest,
-                                      bool VolatileDest);
-
-  virtual void EmitNullMemberFunctionPointer(CodeGenFunction &CGF,
-                                             const MemberPointerType *MPT,
-                                             llvm::Value *Dest,
-                                             bool VolatileDest);
-  
+                                      llvm::Value *Src);
+
   // Manipulations on constant expressions.
 
   /// \brief Returns true if zero-initializing the given type requires
@@ -73,10 +72,6 @@
   EmitNullMemberFunctionPointer(const MemberPointerType *MPT);
 
   virtual llvm::Constant *EmitMemberFunctionPointer(const CXXMethodDecl *MD);
-  virtual void EmitMemberFunctionPointer(CodeGenFunction &CGF,
-                                         const CXXMethodDecl *MD,
-                                         llvm::Value *DestPtr,
-                                         bool VolatileDest);
 
   virtual llvm::Value *
   EmitMemberFunctionPointerComparison(CodeGenFunction &CGF,
@@ -87,7 +82,7 @@
 
   virtual llvm::Value *
   EmitMemberFunctionPointerIsNotNull(CodeGenFunction &CGF,
-                                     llvm::Value *Addr,
+                                     llvm::Value *MemPtr,
                                      const MemberPointerType *MPT);
 };
 

Modified: cfe/trunk/lib/CodeGen/CGExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExpr.cpp?rev=111776&r1=111775&r2=111776&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGExpr.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExpr.cpp Sun Aug 22 05:59:02 2010
@@ -67,10 +67,8 @@
 llvm::Value *CodeGenFunction::EvaluateExprAsBool(const Expr *E) {
   QualType BoolTy = getContext().BoolTy;
   if (E->getType()->isMemberFunctionPointerType()) {
-    LValue LV = EmitAggExprToLValue(E);
-
-    return CGM.getCXXABI().EmitMemberFunctionPointerIsNotNull(CGF,
-                                                              LV.getAddress(),
+    llvm::Value *MemPtr = EmitScalarExpr(E);
+    return CGM.getCXXABI().EmitMemberFunctionPointerIsNotNull(CGF, MemPtr,
                                     E->getType()->getAs<MemberPointerType>());
   }
   if (!E->getType()->isAnyComplexType())
@@ -614,18 +612,15 @@
 
   if (LV.isSimple()) {
     llvm::Value *Ptr = LV.getAddress();
-    const llvm::Type *EltTy =
-      cast<llvm::PointerType>(Ptr->getType())->getElementType();
 
-    // Simple scalar l-value.
-    //
-    // FIXME: We shouldn't have to use isSingleValueType here.
-    if (EltTy->isSingleValueType())
-      return RValue::get(EmitLoadOfScalar(Ptr, LV.isVolatileQualified(),
-                                          LV.getAlignment(), ExprType));
+    // Functions are l-values that don't require loading.
+    if (ExprType->isFunctionType())
+      return RValue::get(Ptr);
+
+    // Everything needs a load.
+    return RValue::get(EmitLoadOfScalar(Ptr, LV.isVolatileQualified(),
+                                        LV.getAlignment(), ExprType));
 
-    assert(ExprType->isFunctionType() && "Unknown scalar value");
-    return RValue::get(Ptr);
   }
 
   if (LV.isVectorElt()) {
@@ -1177,12 +1172,19 @@
     return LV;
   }
   
+  // If we're emitting an instance method as an independent lvalue,
+  // we're actually emitting a member pointer.
+  if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(ND))
+    if (MD->isInstance()) {
+      llvm::Value *V = CGM.getCXXABI().EmitMemberFunctionPointer(MD);
+      return MakeAddrLValue(V, MD->getType(), Alignment);
+    }
   if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(ND))
     return EmitFunctionDeclLValue(*this, E, FD);
   
-  // FIXME: the qualifier check does not seem sufficient here
-  if (E->getQualifier()) {
-    const FieldDecl *FD = cast<FieldDecl>(ND);
+  // If we're emitting a field as an independent lvalue, we're
+  // actually emitting a member pointer.
+  if (const FieldDecl *FD = dyn_cast<FieldDecl>(ND)) {
     llvm::Value *V = CGM.EmitPointerToDataMember(FD);
     return MakeAddrLValue(V, FD->getType(), Alignment);
   }

Modified: cfe/trunk/lib/CodeGen/CGExprAgg.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprAgg.cpp?rev=111776&r1=111775&r2=111776&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGExprAgg.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExprAgg.cpp Sun Aug 22 05:59:02 2010
@@ -108,7 +108,6 @@
   void VisitPointerToDataMemberBinaryOperator(const BinaryOperator *BO);
   void VisitBinAssign(const BinaryOperator *E);
   void VisitBinComma(const BinaryOperator *E);
-  void VisitUnaryAddrOf(const UnaryOperator *E);
 
   void VisitObjCMessageExpr(ObjCMessageExpr *E);
   void VisitObjCIvarRefExpr(ObjCIvarRefExpr *E) {
@@ -287,46 +286,9 @@
     Visit(E->getSubExpr());
     break;
 
-  case CastExpr::CK_NullToMemberPointer: {
-    // If the subexpression's type is the C++0x nullptr_t, emit the
-    // subexpression, which may have side effects.
-    if (E->getSubExpr()->getType()->isNullPtrType())
-      Visit(E->getSubExpr());
-
-    CGF.CGM.getCXXABI().EmitNullMemberFunctionPointer(CGF,
-                                    E->getType()->getAs<MemberPointerType>(),
-                                                      DestPtr, VolatileDest);
-
-    break;
-  }
-      
   case CastExpr::CK_LValueBitCast:
     llvm_unreachable("there are no lvalue bit-casts on aggregates");
     break;
-      
-  case CastExpr::CK_BitCast: {
-    // This must be a member function pointer cast.
-    Visit(E->getSubExpr());
-    break;
-  }
-
-  case CastExpr::CK_DerivedToBaseMemberPointer:
-  case CastExpr::CK_BaseToDerivedMemberPointer: {
-    QualType SrcType = E->getSubExpr()->getType();
-    
-    llvm::Value *Src = CGF.CreateMemTemp(SrcType, "tmp");
-    CGF.EmitAggExpr(E->getSubExpr(), Src, SrcType.isVolatileQualified());
-
-    // Note that the AST doesn't distinguish between checked and
-    // unchecked member pointer conversions, so we always have to
-    // implement checked conversions here.  This is inefficient for
-    // ABIs where an actual null check is thus required; fortunately,
-    // the Itanium and ARM ABIs ignore the adjustment value when
-    // considering null-ness.
-    CGF.CGM.getCXXABI().EmitMemberFunctionPointerConversion(CGF, E, Src,
-                                                   DestPtr, VolatileDest);
-    break;
-  }
   }
 }
 
@@ -362,23 +324,6 @@
                   /*IgnoreResult=*/false, IsInitializer);
 }
 
-void AggExprEmitter::VisitUnaryAddrOf(const UnaryOperator *E) {
-  // We have a member function pointer.
-  assert(E->getType()->getAs<MemberPointerType>()
-          ->getPointeeType()->isFunctionProtoType() &&
-         "Unexpected member pointer type!");
-
-  // The creation of member function pointers has no side effects; if
-  // there is no destination pointer, we have nothing to do.
-  if (!DestPtr)
-    return;
-  
-  const DeclRefExpr *DRE = cast<DeclRefExpr>(E->getSubExpr());
-  const CXXMethodDecl *MD = cast<CXXMethodDecl>(DRE->getDecl());
-
-  CGF.CGM.getCXXABI().EmitMemberFunctionPointer(CGF, MD, DestPtr, VolatileDest);
-}
-
 void AggExprEmitter::VisitStmtExpr(const StmtExpr *E) {
   CGF.EmitCompoundStmt(*E->getSubStmt(), true, DestPtr, VolatileDest);
 }

Modified: cfe/trunk/lib/CodeGen/CGExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprCXX.cpp?rev=111776&r1=111775&r2=111776&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGExprCXX.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExprCXX.cpp Sun Aug 22 05:59:02 2010
@@ -160,8 +160,7 @@
     cast<CXXRecordDecl>(MPT->getClass()->getAs<RecordType>()->getDecl());
 
   // Get the member function pointer.
-  llvm::Value *MemFnPtr = CreateMemTemp(MemFnExpr->getType(), "mem.fn");
-  EmitAggExpr(MemFnExpr, MemFnPtr, /*VolatileDest=*/false);
+  llvm::Value *MemFnPtr = EmitScalarExpr(MemFnExpr);
 
   // Emit the 'this' pointer.
   llvm::Value *This;

Modified: cfe/trunk/lib/CodeGen/CGExprConstant.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprConstant.cpp?rev=111776&r1=111775&r2=111776&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGExprConstant.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExprConstant.cpp Sun Aug 22 05:59:02 2010
@@ -460,7 +460,7 @@
 
   llvm::Constant *VisitUnaryAddrOf(UnaryOperator *E) {
     if (const MemberPointerType *MPT = 
-        E->getType()->getAs<MemberPointerType>()) {
+          E->getType()->getAs<MemberPointerType>()) {
       QualType T = MPT->getPointeeType();
       DeclRefExpr *DRE = cast<DeclRefExpr>(E->getSubExpr());
 
@@ -533,13 +533,21 @@
         llvm::StructType::get(C->getType()->getContext(), Types, false);
       return llvm::ConstantStruct::get(STy, Elts);
     }
-    case CastExpr::CK_NullToMemberPointer:
-      return CGM.getCXXABI().EmitNullMemberFunctionPointer(
-                                   E->getType()->getAs<MemberPointerType>());
+    case CastExpr::CK_NullToMemberPointer: {
+      const MemberPointerType *MPT = E->getType()->getAs<MemberPointerType>();
+      if (MPT->getPointeeType()->isFunctionType())
+        return CGM.getCXXABI().EmitNullMemberFunctionPointer(MPT);
+      return CGM.EmitNullConstant(E->getType());
+    }
       
     case CastExpr::CK_BaseToDerivedMemberPointer: {
-      Expr *SubExpr = E->getSubExpr();
+      const MemberPointerType *MPT = E->getType()->getAs<MemberPointerType>();
 
+      // TODO: support data-member conversions here!
+      if (!MPT->getPointeeType()->isFunctionType())
+        return 0;
+
+      Expr *SubExpr = E->getSubExpr();
       llvm::Constant *C = 
         CGM.EmitConstantExpr(SubExpr, SubExpr->getType(), CGF);
       if (!C) return 0;

Modified: cfe/trunk/lib/CodeGen/CGExprScalar.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprScalar.cpp?rev=111776&r1=111775&r2=111776&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGExprScalar.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExprScalar.cpp Sun Aug 22 05:59:02 2010
@@ -238,6 +238,9 @@
 
     
   Value *VisitUnaryAddrOf(const UnaryOperator *E) {
+    // If the sub-expression is an instance member reference,
+    // EmitDeclRefLValue will magically emit it with the appropriate
+    // value as the "address".
     return EmitLValue(E->getSubExpr()).getAddress();
   }
   Value *VisitUnaryDeref(const Expr *E) { return EmitLoadOfLValue(E); }
@@ -995,11 +998,31 @@
     return EmitLValue(E).getAddress();
 
   case CastExpr::CK_NullToMemberPointer:
+    // If the subexpression's type is the C++0x nullptr_t, emit the
+    // subexpression, which may have side effects.
+    if (E->getType()->isNullPtrType())
+      (void) Visit(E);
+
+    if (CE->getType()->isMemberFunctionPointerType())
+      return CGF.CGM.getCXXABI().EmitNullMemberFunctionPointer(
+                                   CE->getType()->getAs<MemberPointerType>());
+
     return CGF.CGM.EmitNullConstant(DestTy);
 
   case CastExpr::CK_BaseToDerivedMemberPointer:
   case CastExpr::CK_DerivedToBaseMemberPointer: {
     Value *Src = Visit(E);
+    
+    // Note that the AST doesn't distinguish between checked and
+    // unchecked member pointer conversions, so we always have to
+    // implement checked conversions here.  This is inefficient when
+    // actual control flow may be required in order to perform the
+    // check, which it is for data member pointers (but not member
+    // function pointers on Itanium and ARM).
+
+    if (CE->getType()->isMemberFunctionPointerType())
+      return CGF.CGM.getCXXABI().EmitMemberFunctionPointerConversion(CGF, CE,
+                                                                     Src);
 
     // See if we need to adjust the pointer.
     const CXXRecordDecl *BaseDecl = 
@@ -1804,10 +1827,10 @@
   if (LHSTy->isMemberFunctionPointerType()) {
     assert(E->getOpcode() == BinaryOperator::EQ ||
            E->getOpcode() == BinaryOperator::NE);
-    Value *LHSPtr = CGF.EmitAnyExprToTemp(E->getLHS()).getAggregateAddr();
-    Value *RHSPtr = CGF.EmitAnyExprToTemp(E->getRHS()).getAggregateAddr();
+    Value *LHS = CGF.EmitScalarExpr(E->getLHS());
+    Value *RHS = CGF.EmitScalarExpr(E->getRHS());
     Result = CGF.CGM.getCXXABI().EmitMemberFunctionPointerComparison(
-                     CGF, LHSPtr, RHSPtr, LHSTy->getAs<MemberPointerType>(),
+                         CGF, LHS, RHS, LHSTy->getAs<MemberPointerType>(),
                                     E->getOpcode() == BinaryOperator::NE);
   } else if (!LHSTy->isAnyComplexType()) {
     Value *LHS = Visit(E->getLHS());

Modified: cfe/trunk/lib/CodeGen/CodeGenFunction.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.cpp?rev=111776&r1=111775&r2=111776&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenFunction.cpp (original)
+++ cfe/trunk/lib/CodeGen/CodeGenFunction.cpp Sun Aug 22 05:59:02 2010
@@ -77,7 +77,7 @@
 
 bool CodeGenFunction::hasAggregateLLVMType(QualType T) {
   return T->isRecordType() || T->isArrayType() || T->isAnyComplexType() ||
-    T->isMemberFunctionPointerType() || T->isObjCObjectType();
+    T->isObjCObjectType();
 }
 
 void CodeGenFunction::EmitReturnBlock() {

Modified: cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp?rev=111776&r1=111775&r2=111776&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp (original)
+++ cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp Sun Aug 22 05:59:02 2010
@@ -31,12 +31,11 @@
 namespace {
 class ItaniumCXXABI : public CodeGen::CGCXXABI {
 protected:
-  CodeGenModule &CGM;
   CodeGen::MangleContext MangleCtx;
   bool IsARM;
 public:
   ItaniumCXXABI(CodeGen::CodeGenModule &CGM, bool IsARM = false) :
-    CGM(CGM), MangleCtx(CGM.getContext(), CGM.getDiags()), IsARM(IsARM) { }
+    CGCXXABI(CGM), MangleCtx(CGM.getContext(), CGM.getDiags()), IsARM(IsARM) { }
 
   CodeGen::MangleContext &getMangleContext() {
     return MangleCtx;
@@ -50,27 +49,15 @@
                                                llvm::Value *MemFnPtr,
                                                const MemberPointerType *MPT);
 
-  void EmitMemberFunctionPointerConversion(CodeGenFunction &CGF,
-                                           const CastExpr *E,
-                                           llvm::Value *Src,
-                                           llvm::Value *Dest,
-                                           bool VolatileDest);
+  llvm::Value *EmitMemberFunctionPointerConversion(CodeGenFunction &CGF,
+                                                   const CastExpr *E,
+                                                   llvm::Value *Src);
 
   llvm::Constant *EmitMemberFunctionPointerConversion(llvm::Constant *C,
                                                       const CastExpr *E);
 
-  void EmitNullMemberFunctionPointer(CodeGenFunction &CGF,
-                                     const MemberPointerType *MPT,
-                                     llvm::Value *Dest,
-                                     bool VolatileDest);
-
   llvm::Constant *EmitNullMemberFunctionPointer(const MemberPointerType *MPT);
 
-  void EmitMemberFunctionPointer(CodeGenFunction &CGF,
-                                 const CXXMethodDecl *MD,
-                                 llvm::Value *Dest,
-                                 bool VolatileDest);
-
   llvm::Constant *EmitMemberFunctionPointer(const CXXMethodDecl *MD);
 
   llvm::Value *EmitMemberFunctionPointerComparison(CodeGenFunction &CGF,
@@ -104,57 +91,6 @@
 
 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);
-  }
 }
 
 
@@ -201,9 +137,8 @@
   llvm::BasicBlock *FnNonVirtual = CGF.createBasicBlock("memptr.nonvirtual");
   llvm::BasicBlock *FnEnd = CGF.createBasicBlock("memptr.end");
 
-  // Load memptr.adj, which is in the second field.
-  llvm::Value *RawAdj = Builder.CreateStructGEP(MemFnPtr, 1);
-  RawAdj = Builder.CreateLoad(RawAdj, "memptr.adj");
+  // Extract memptr.adj, which is in the second field.
+  llvm::Value *RawAdj = Builder.CreateExtractValue(MemFnPtr, 1, "memptr.adj");
 
   // Compute the true adjustment.
   llvm::Value *Adj = RawAdj;
@@ -217,8 +152,7 @@
   This = Builder.CreateBitCast(Ptr, This->getType(), "this.adjusted");
   
   // Load the function pointer.
-  llvm::Value *FnPtr = Builder.CreateStructGEP(MemFnPtr, 0);
-  llvm::Value *FnAsInt = Builder.CreateLoad(FnPtr, "memptr.ptr");
+  llvm::Value *FnAsInt = Builder.CreateExtractValue(MemFnPtr, 0, "memptr.ptr");
   
   // If the LSB in the function pointer is 1, the function pointer points to
   // a virtual function.
@@ -266,14 +200,16 @@
 }
 
 /// Perform a derived-to-base or base-to-derived member pointer conversion.
-void ItaniumCXXABI::EmitMemberFunctionPointerConversion(CodeGenFunction &CGF,
-                                                        const CastExpr *E,
-                                                        llvm::Value *Src,
-                                                        llvm::Value *Dest,
-                                                        bool VolatileDest) {
+llvm::Value *
+ItaniumCXXABI::EmitMemberFunctionPointerConversion(CodeGenFunction &CGF,
+                                                   const CastExpr *E,
+                                                   llvm::Value *Src) {
   assert(E->getCastKind() == CastExpr::CK_DerivedToBaseMemberPointer ||
          E->getCastKind() == CastExpr::CK_BaseToDerivedMemberPointer);
 
+  if (isa<llvm::Constant>(Src))
+    return EmitMemberFunctionPointerConversion(cast<llvm::Constant>(Src), E);
+
   CGBuilderTy &Builder = CGF.Builder;
 
   const MemberPointerType *SrcTy =
@@ -283,17 +219,6 @@
   const CXXRecordDecl *SrcDecl = SrcTy->getClass()->getAsCXXRecordDecl();
   const CXXRecordDecl *DestDecl = DestTy->getClass()->getAsCXXRecordDecl();
 
-  llvm::Value *SrcPtr = Builder.CreateStructGEP(Src, 0, "src.ptr");
-  SrcPtr = Builder.CreateLoad(SrcPtr);
-    
-  llvm::Value *SrcAdj = Builder.CreateStructGEP(Src, 1, "src.adj");
-  SrcAdj = Builder.CreateLoad(SrcAdj);
-    
-  llvm::Value *DstPtr = Builder.CreateStructGEP(Dest, 0, "dst.ptr");
-  Builder.CreateStore(SrcPtr, DstPtr, VolatileDest);
-    
-  llvm::Value *DstAdj = Builder.CreateStructGEP(Dest, 1, "dst.adj");
-
   bool DerivedToBase =
     E->getCastKind() == CastExpr::CK_DerivedToBaseMemberPointer;
 
@@ -303,24 +228,33 @@
   else
     BaseDecl = SrcDecl, DerivedDecl = DestDecl;
 
-  if (llvm::Constant *Adj = 
-        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);
-    }
+  llvm::Constant *Adj = 
+    CGF.CGM.GetNonVirtualBaseClassOffset(DerivedDecl,
+                                         E->path_begin(),
+                                         E->path_end());
+  if (!Adj) return Src;
 
-    if (DerivedToBase)
-      SrcAdj = Builder.CreateSub(SrcAdj, Adj, "adj");
-    else
-      SrcAdj = Builder.CreateAdd(SrcAdj, Adj, "adj");
-  }
+  llvm::Value *SrcPtr = Builder.CreateExtractValue(Src, 0, "src.ptr");
+  llvm::Value *SrcAdj = Builder.CreateExtractValue(Src, 1, "src.adj");
+
+  llvm::Value *Result = llvm::UndefValue::get(Src->getType());
+  Result = Builder.CreateInsertValue(Result, SrcPtr, 0);
     
-  Builder.CreateStore(SrcAdj, DstAdj, VolatileDest);
+  // 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);
+  }
+
+  llvm::Value *DstAdj;
+  if (DerivedToBase)
+    DstAdj = Builder.CreateSub(SrcAdj, Adj, "adj");
+  else
+    DstAdj = Builder.CreateAdd(SrcAdj, Adj, "adj");
+
+  Result = Builder.CreateInsertValue(Result, DstAdj, 1);
+  return Result;
 }
 
 llvm::Constant *
@@ -366,53 +300,73 @@
 }        
 
 
-void ItaniumCXXABI::EmitNullMemberFunctionPointer(CodeGenFunction &CGF,
-                                                  const MemberPointerType *MPT,
-                                                  llvm::Value *Dest,
-                                                  bool VolatileDest) {
-  // Should this be "unabstracted" and implemented in terms of the
-  // Constant version?
-
-  CGBuilderTy &Builder = CGF.Builder;
-
-  const llvm::IntegerType *PtrDiffTy = CGF.IntPtrTy;
-  llvm::Value *Zero = llvm::ConstantInt::get(PtrDiffTy, 0);
-
-  llvm::Value *Ptr = Builder.CreateStructGEP(Dest, 0, "ptr");
-  Builder.CreateStore(Zero, Ptr, VolatileDest);
-    
-  llvm::Value *Adj = Builder.CreateStructGEP(Dest, 1, "adj");
-  Builder.CreateStore(Zero, Adj, VolatileDest);
-}
-
 llvm::Constant *
 ItaniumCXXABI::EmitNullMemberFunctionPointer(const MemberPointerType *MPT) {
-  return CGM.EmitNullConstant(QualType(MPT, 0));
+  const llvm::Type *ptrdiff_t =
+    CGM.getTypes().ConvertType(CGM.getContext().getPointerDiffType());
+
+  llvm::Constant *Zero = llvm::ConstantInt::get(ptrdiff_t, 0);
+  llvm::Constant *Values[2] = { Zero, Zero };
+  return llvm::ConstantStruct::get(CGM.getLLVMContext(), Values, 2,
+                                   /*Packed=*/false);
 }
 
 llvm::Constant *
 ItaniumCXXABI::EmitMemberFunctionPointer(const CXXMethodDecl *MD) {
-  llvm::Constant *Values[2];
-  GetMemberFunctionPointer(MD, Values);
-  
-  return llvm::ConstantStruct::get(CGM.getLLVMContext(),
-                                   Values, 2, /*Packed=*/false);
-}
+  assert(MD->isInstance() && "Member function must not be static!");
+  MD = MD->getCanonicalDecl();
 
-void ItaniumCXXABI::EmitMemberFunctionPointer(CodeGenFunction &CGF,
-                                              const CXXMethodDecl *MD,
-                                              llvm::Value *DestPtr,
-                                              bool VolatileDest) {
-  llvm::Constant *Values[2];
-  GetMemberFunctionPointer(MD, Values);
+  CodeGenTypes &Types = CGM.getTypes();
+  const llvm::Type *ptrdiff_t = 
+    Types.ConvertType(CGM.getContext().getPointerDiffType());
 
-  CGBuilderTy &Builder = CGF.Builder;
-  
-  llvm::Value *DstPtr = Builder.CreateStructGEP(DestPtr, 0, "memptr.ptr");
-  Builder.CreateStore(Values[0], DstPtr, VolatileDest);
+  // Get the function pointer (or index if this is a virtual function).
+  llvm::Constant *MemPtr[2];
+  if (MD->isVirtual()) {
+    uint64_t Index = CGM.getVTables().getMethodVTableIndex(MD);
 
-  llvm::Value *AdjPtr = Builder.CreateStructGEP(DestPtr, 1, "memptr.adj");
-  Builder.CreateStore(Values[1], AdjPtr, VolatileDest);
+    // 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);
+  }
+  
+  return llvm::ConstantStruct::get(CGM.getLLVMContext(),
+                                   MemPtr, 2, /*Packed=*/false);
 }
 
 /// The comparison algorithm is pretty easy: the member pointers are
@@ -427,10 +381,8 @@
                                                    bool Inequality) {
   CGBuilderTy &Builder = CGF.Builder;
 
-  llvm::Value *LPtr = Builder.CreateLoad(Builder.CreateStructGEP(L, 0),
-                                         "lhs.memptr.ptr");
-  llvm::Value *RPtr = Builder.CreateLoad(Builder.CreateStructGEP(R, 0),
-                                         "rhs.memptr.ptr");
+  llvm::Value *LPtr = Builder.CreateExtractValue(L, 0, "lhs.memptr.ptr");
+  llvm::Value *RPtr = Builder.CreateExtractValue(R, 0, "rhs.memptr.ptr");
 
   // The Itanium tautology is:
   //   (L == R) <==> (L.ptr == R.ptr /\ (L.ptr == 0 \/ L.adj == R.adj))
@@ -465,10 +417,8 @@
 
   // This condition tests whether L.adj == R.adj.  If this isn't
   // true, the pointers are unequal unless they're both null.
-  llvm::Value *LAdj = Builder.CreateLoad(Builder.CreateStructGEP(L, 1),
-                                         "lhs.memptr.adj");
-  llvm::Value *RAdj = Builder.CreateLoad(Builder.CreateStructGEP(R, 1),
-                                         "rhs.memptr.adj");
+  llvm::Value *LAdj = Builder.CreateExtractValue(L, 1, "lhs.memptr.adj");
+  llvm::Value *RAdj = Builder.CreateExtractValue(R, 1, "rhs.memptr.adj");
   llvm::Value *AdjEq = Builder.CreateICmp(Eq, LAdj, RAdj, "cmp.adj");
 
   // Null member function pointers on ARM clear the low bit of Adj,
@@ -498,8 +448,7 @@
   CGBuilderTy &Builder = CGF.Builder;
   
   // In Itanium, a member function pointer is null if 'ptr' is null.
-  llvm::Value *Ptr =
-    Builder.CreateLoad(Builder.CreateStructGEP(MemPtr, 0), "memptr.ptr");
+  llvm::Value *Ptr = Builder.CreateExtractValue(MemPtr, 0, "memptr.ptr");
 
   llvm::Constant *Zero = llvm::ConstantInt::get(Ptr->getType(), 0);
   llvm::Value *Result = Builder.CreateICmpNE(Ptr, Zero, "memptr.tobool");
@@ -507,8 +456,7 @@
   // In ARM, it's that, plus the low bit of 'adj' must be zero.
   if (IsARM) {
     llvm::Constant *One = llvm::ConstantInt::get(Ptr->getType(), 1);
-    llvm::Value *Adj =
-      Builder.CreateLoad(Builder.CreateStructGEP(MemPtr, 1), "memptr.adj");
+    llvm::Value *Adj = Builder.CreateExtractValue(MemPtr, 1, "memptr.adj");
     llvm::Value *VirtualBit = Builder.CreateAnd(Adj, One, "memptr.virtualbit");
     llvm::Value *IsNotVirtual = Builder.CreateICmpEQ(VirtualBit, Zero,
                                                      "memptr.notvirtual");

Modified: cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp?rev=111776&r1=111775&r2=111776&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp (original)
+++ cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp Sun Aug 22 05:59:02 2010
@@ -112,7 +112,7 @@
   MicrosoftMangleContext MangleCtx;
 public:
   MicrosoftCXXABI(CodeGenModule &CGM)
-   : MangleCtx(CGM.getContext(), CGM.getDiags()) {}
+    : CGCXXABI(CGM), MangleCtx(CGM.getContext(), CGM.getDiags()) {}
 
   MicrosoftMangleContext &getMangleContext() {
     return MangleCtx;

Modified: cfe/trunk/lib/CodeGen/TargetInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/TargetInfo.cpp?rev=111776&r1=111775&r2=111776&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/TargetInfo.cpp (original)
+++ cfe/trunk/lib/CodeGen/TargetInfo.cpp Sun Aug 22 05:59:02 2010
@@ -36,6 +36,11 @@
   }
 }
 
+static bool isAggregateTypeForABI(QualType T) {
+  return CodeGenFunction::hasAggregateLLVMType(T) ||
+         T->isMemberFunctionPointerType();
+}
+
 ABIInfo::~ABIInfo() {}
 
 ASTContext &ABIInfo::getContext() const {
@@ -218,7 +223,7 @@
       FT = AT->getElementType();
     }
 
-    if (!CodeGenFunction::hasAggregateLLVMType(FT)) {
+    if (!isAggregateTypeForABI(FT)) {
       Found = FT.getTypePtr();
     } else {
       Found = isSingleElementStruct(FT, Context);
@@ -314,7 +319,7 @@
 }
 
 ABIArgInfo DefaultABIInfo::classifyArgumentType(QualType Ty) const {
-  if (CodeGenFunction::hasAggregateLLVMType(Ty))
+  if (isAggregateTypeForABI(Ty))
     return ABIArgInfo::getIndirect(0);
 
   // Treat an enum type as its underlying type.
@@ -467,7 +472,7 @@
     return ABIArgInfo::getDirect();
   }
   
-  if (CodeGenFunction::hasAggregateLLVMType(RetTy)) {
+  if (isAggregateTypeForABI(RetTy)) {
     if (const RecordType *RT = RetTy->getAs<RecordType>()) {
       // Structures with either a non-trivial destructor or a non-trivial
       // copy constructor are always indirect.
@@ -557,7 +562,7 @@
 
 ABIArgInfo X86_32ABIInfo::classifyArgumentType(QualType Ty) const {
   // FIXME: Set alignment on indirect arguments.
-  if (CodeGenFunction::hasAggregateLLVMType(Ty)) {
+  if (isAggregateTypeForABI(Ty)) {
     // Structures with flexible arrays are always indirect.
     if (const RecordType *RT = Ty->getAs<RecordType>()) {
       // Structures with either a non-trivial destructor or a non-trivial
@@ -1094,7 +1099,7 @@
 ABIArgInfo X86_64ABIInfo::getIndirectReturnResult(QualType Ty) const {
   // If this is a scalar LLVM value then assume LLVM will pass it in the right
   // place naturally.
-  if (!CodeGenFunction::hasAggregateLLVMType(Ty)) {
+  if (!isAggregateTypeForABI(Ty)) {
     // Treat an enum type as its underlying type.
     if (const EnumType *EnumTy = Ty->getAs<EnumType>())
       Ty = EnumTy->getDecl()->getIntegerType();
@@ -1109,7 +1114,7 @@
 ABIArgInfo X86_64ABIInfo::getIndirectResult(QualType Ty) const {
   // If this is a scalar LLVM value then assume LLVM will pass it in the right
   // place naturally.
-  if (!CodeGenFunction::hasAggregateLLVMType(Ty)) {
+  if (!isAggregateTypeForABI(Ty)) {
     // Treat an enum type as its underlying type.
     if (const EnumType *EnumTy = Ty->getAs<EnumType>())
       Ty = EnumTy->getDecl()->getIntegerType();
@@ -2079,7 +2084,7 @@
 }
 
 ABIArgInfo ARMABIInfo::classifyArgumentType(QualType Ty) const {
-  if (!CodeGenFunction::hasAggregateLLVMType(Ty)) {
+  if (!isAggregateTypeForABI(Ty)) {
     // Treat an enum type as its underlying type.
     if (const EnumType *EnumTy = Ty->getAs<EnumType>())
       Ty = EnumTy->getDecl()->getIntegerType();
@@ -2205,7 +2210,7 @@
   if (RetTy->isVoidType())
     return ABIArgInfo::getIgnore();
 
-  if (!CodeGenFunction::hasAggregateLLVMType(RetTy)) {
+  if (!isAggregateTypeForABI(RetTy)) {
     // Treat an enum type as its underlying type.
     if (const EnumType *EnumTy = RetTy->getAs<EnumType>())
       RetTy = EnumTy->getDecl()->getIntegerType();
@@ -2295,7 +2300,7 @@
   if (RetTy->isVoidType())
     return ABIArgInfo::getIgnore();
 
-  if (CodeGenFunction::hasAggregateLLVMType(RetTy))
+  if (isAggregateTypeForABI(RetTy))
     return ABIArgInfo::getIndirect(0);
 
   // Treat an enum type as its underlying type.
@@ -2370,7 +2375,7 @@
 ABIArgInfo SystemZABIInfo::classifyReturnType(QualType RetTy) const {
   if (RetTy->isVoidType())
     return ABIArgInfo::getIgnore();
-  if (CodeGenFunction::hasAggregateLLVMType(RetTy))
+  if (isAggregateTypeForABI(RetTy))
     return ABIArgInfo::getIndirect(0);
 
   return (isPromotableIntegerType(RetTy) ?
@@ -2378,7 +2383,7 @@
 }
 
 ABIArgInfo SystemZABIInfo::classifyArgumentType(QualType Ty) const {
-  if (CodeGenFunction::hasAggregateLLVMType(Ty))
+  if (isAggregateTypeForABI(Ty))
     return ABIArgInfo::getIndirect(0);
 
   return (isPromotableIntegerType(Ty) ?

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=111776&r1=111775&r2=111776&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/member-function-pointers.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/member-function-pointers.cpp Sun Aug 22 05:59:02 2010
@@ -29,50 +29,42 @@
 void (A::*pc3)() = &A::vf1;
 
 void f() {
-  // CHECK: store i64 0, i64* getelementptr inbounds (%0* @pa, i32 0, i32 0)
-  // CHECK: store i64 0, i64* getelementptr inbounds (%0* @pa, i32 0, i32 1)
+  // CHECK: store %0 zeroinitializer, %0* @pa
   pa = 0;
 
-  // CHECK: volatile store i64 0, i64* getelementptr inbounds (%0* @vpa, i32 0, i32 0)
-  // CHECK: volatile store i64 0, i64* getelementptr inbounds (%0* @vpa, i32 0, i32 1)
+  // Is this okay?  What are LLVM's volatile semantics for structs?
+  // CHECK: volatile store %0 zeroinitializer, %0* @vpa
   vpa = 0;
 
-  // CHECK: store i64 {{.*}}, i64* getelementptr inbounds (%0* @pc, i32 0, i32 0)
-  // CHECK: [[ADJ:%[a-zA-Z0-9\.]+]] = add i64 {{.*}}, 16
-  // CHECK: store i64 [[ADJ]], i64* getelementptr inbounds (%0* @pc, i32 0, i32 1)
+  // CHECK: [[TMP:%.*]] = load %0* @pa, align 8
+  // CHECK: [[TMPPTR:%.*]] = extractvalue %0 [[TMP]], 0
+  // CHECK: [[TMPADJ:%.*]] = extractvalue %0 [[TMP]], 1
+  // CHECK: [[RES0:%.*]] = insertvalue %0 undef, i64 [[TMPPTR]], 0
+  // CHECK: [[ADJ:%.*]] = add i64 [[TMPADJ]], 16
+  // CHECK: [[RES1:%.*]] = insertvalue %0 [[RES0]], i64 [[ADJ]], 1
+  // CHECK: store %0 [[RES1]], %0* @pc, align 8
   pc = pa;
 
-  // CHECK: store i64 {{.*}}, i64* getelementptr inbounds (%0* @pa, i32 0, i32 0)
-  // CHECK: [[ADJ:%[a-zA-Z0-9\.]+]] = sub i64 {{.*}}, 16
-  // CHECK: store i64 [[ADJ]], i64* getelementptr inbounds (%0* @pa, i32 0, i32 1)
+  // CHECK: [[TMP:%.*]] = load %0* @pc, align 8
+  // CHECK: [[TMPPTR:%.*]] = extractvalue %0 [[TMP]], 0
+  // CHECK: [[TMPADJ:%.*]] = extractvalue %0 [[TMP]], 1
+  // CHECK: [[RES0:%.*]] = insertvalue %0 undef, i64 [[TMPPTR]], 0
+  // CHECK: [[ADJ:%.*]] = sub i64 [[TMPADJ]], 16
+  // CHECK: [[RES1:%.*]] = insertvalue %0 [[RES0]], i64 [[ADJ]], 1
+  // CHECK: store %0 [[RES1]], %0* @pa, align 8
   pa = static_cast<void (A::*)()>(pc);
 }
 
 void f2() {
-  // CHECK: [[pa2ptr:%[a-zA-Z0-9\.]+]] = getelementptr inbounds %0* %pa2, i32 0, i32 0 
-  // CHECK: store i64 ptrtoint (void (%struct.A*)* @_ZN1A1fEv to i64), i64* [[pa2ptr]]
-  // CHECK: [[pa2adj:%[a-zA-Z0-9\.]+]] = getelementptr inbounds %0* %pa2, i32 0, i32 1
-  // CHECK: store i64 0, i64* [[pa2adj]]
+  // CHECK:      store %0 { i64 ptrtoint (void (%struct.A*)* @_ZN1A1fEv to i64), i64 0 }
   void (A::*pa2)() = &A::f;
   
-  // CHECK:      [[pa3ptr:%[a-zA-Z0-9\.]+]] = getelementptr inbounds %0* %pa3, i32 0, i32 0 
-  // CHECK:      store i64 1, i64* [[pa3ptr]]
-  // CHECK:      [[pa3adj:%[a-zA-Z0-9\.]+]] = getelementptr inbounds %0* %pa3, i32 0, i32 1
-  // CHECK:      store i64 0, i64* [[pa3adj]]
-  // CHECK-LP32: [[pa3ptr:%[a-zA-Z0-9\.]+]] = getelementptr inbounds %0* %pa3, i32 0, i32 0 
-  // CHECK-LP32: store i32 1, i32* [[pa3ptr]]
-  // CHECK-LP32: [[pa3adj:%[a-zA-Z0-9\.]+]] = getelementptr inbounds %0* %pa3, i32 0, i32 1
-  // CHECK-LP32: store i32 0, i32* [[pa3adj]]
+  // CHECK:      store %0 { i64 1, i64 0 }
+  // CHECK-LP32: store %0 { i32 1, i32 0 }
   void (A::*pa3)() = &A::vf1;
   
-  // CHECK:      [[pa4ptr:%[a-zA-Z0-9\.]+]] = getelementptr inbounds %0* %pa4, i32 0, i32 0 
-  // CHECK:      store i64 9, i64* [[pa4ptr]]
-  // CHECK:      [[pa4adj:%[a-zA-Z0-9\.]+]] = getelementptr inbounds %0* %pa4, i32 0, i32 1
-  // CHECK:      store i64 0, i64* [[pa4adj]]
-  // CHECK-LP32: [[pa4ptr:%[a-zA-Z0-9\.]+]] = getelementptr inbounds %0* %pa4, i32 0, i32 0 
-  // CHECK-LP32: store i32 5, i32* [[pa4ptr]]
-  // CHECK-LP32: [[pa4adj:%[a-zA-Z0-9\.]+]] = getelementptr inbounds %0* %pa4, i32 0, i32 1
-  // CHECK-LP32: store i32 0, i32* [[pa4adj]]
+  // CHECK:      store %0 { i64 9, i64 0 }
+  // CHECK-LP32: store %0 { i32 5, i32 0 }
   void (A::*pa4)() = &A::vf2;
 }
 

Modified: cfe/trunk/test/CodeGenCXX/x86_32-arguments.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/x86_32-arguments.cpp?rev=111776&r1=111775&r2=111776&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/x86_32-arguments.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/x86_32-arguments.cpp Sun Aug 22 05:59:02 2010
@@ -89,7 +89,7 @@
 s5 f5() { return s5(); }
 
 // CHECK: define i32 @_Z4f6_0M2s6i(i32 %a)
-// CHECK: define i64 @_Z4f6_1M2s6FivE(%{{.*}} byval %a)
+// CHECK: define i64 @_Z4f6_1M2s6FivE(%{{.*}} byval)
 // FIXME: It would be nice to avoid byval on the previous case.
 struct s6 {};
 typedef int s6::* s6_mdp;





More information about the cfe-commits mailing list