[cfe-commits] r112588 - in /cfe/trunk: lib/CodeGen/ test/CodeGenCXX/

John McCall rjmccall at apple.com
Tue Aug 31 00:33:08 PDT 2010


Author: rjmccall
Date: Tue Aug 31 02:33:07 2010
New Revision: 112588

URL: http://llvm.org/viewvc/llvm-project?rev=112588&view=rev
Log:
Teach IR generation to return 'this' from constructors and destructors
under the ARM ABI.


Modified:
    cfe/trunk/lib/CodeGen/CGCXX.cpp
    cfe/trunk/lib/CodeGen/CGCXXABI.h
    cfe/trunk/lib/CodeGen/CGCall.cpp
    cfe/trunk/lib/CodeGen/CGDeclCXX.cpp
    cfe/trunk/lib/CodeGen/CGExpr.cpp
    cfe/trunk/lib/CodeGen/CGExprCXX.cpp
    cfe/trunk/lib/CodeGen/CGExprConstant.cpp
    cfe/trunk/lib/CodeGen/CGExprScalar.cpp
    cfe/trunk/lib/CodeGen/CGRTTI.cpp
    cfe/trunk/lib/CodeGen/CGVTT.cpp
    cfe/trunk/lib/CodeGen/CGVTables.cpp
    cfe/trunk/lib/CodeGen/CodeGenFunction.cpp
    cfe/trunk/lib/CodeGen/CodeGenFunction.h
    cfe/trunk/lib/CodeGen/CodeGenModule.cpp
    cfe/trunk/lib/CodeGen/CodeGenModule.h
    cfe/trunk/lib/CodeGen/CodeGenTypes.h
    cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp
    cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp
    cfe/trunk/test/CodeGenCXX/arm.cpp

Modified: cfe/trunk/lib/CodeGen/CGCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCXX.cpp?rev=112588&r1=112587&r2=112588&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGCXX.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGCXX.cpp Tue Aug 31 02:33:07 2010
@@ -410,3 +410,29 @@
   // Fake answer.
   return true;
 }
+
+void CGCXXABI::BuildThisParam(CodeGenFunction &CGF, FunctionArgList &Params) {
+  const CXXMethodDecl *MD = cast<CXXMethodDecl>(CGF.CurGD.getDecl());
+
+  // FIXME: I'm not entirely sure I like using a fake decl just for code
+  // generation. Maybe we can come up with a better way?
+  ImplicitParamDecl *ThisDecl
+    = ImplicitParamDecl::Create(CGM.getContext(), 0, MD->getLocation(),
+                                &CGM.getContext().Idents.get("this"),
+                                MD->getThisType(CGM.getContext()));
+  Params.push_back(std::make_pair(ThisDecl, ThisDecl->getType()));
+  getThisDecl(CGF) = ThisDecl;
+}
+
+void CGCXXABI::EmitThisParam(CodeGenFunction &CGF) {
+  /// Initialize the 'this' slot.
+  assert(getThisDecl(CGF) && "no 'this' variable for function");
+  getThisValue(CGF)
+    = CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(getThisDecl(CGF)),
+                             "this");
+}
+
+void CGCXXABI::EmitReturnFromThunk(CodeGenFunction &CGF,
+                                   RValue RV, QualType ResultType) {
+  CGF.EmitReturnOfRValue(RV, ResultType);
+}

Modified: cfe/trunk/lib/CodeGen/CGCXXABI.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCXXABI.h?rev=112588&r1=112587&r2=112588&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGCXXABI.h (original)
+++ cfe/trunk/lib/CodeGen/CGCXXABI.h Tue Aug 31 02:33:07 2010
@@ -15,19 +15,23 @@
 #ifndef CLANG_CODEGEN_CXXABI_H
 #define CLANG_CODEGEN_CXXABI_H
 
+#include "CodeGenFunction.h"
+
 namespace llvm {
   class Constant;
   class Type;
   class Value;
+
+  template <class T> class SmallVectorImpl;
 }
 
 namespace clang {
   class CastExpr;
+  class CXXConstructorDecl;
+  class CXXDestructorDecl;
   class CXXMethodDecl;
   class CXXRecordDecl;
   class FieldDecl;
-  class MemberPointerType;
-  class QualType;
 
 namespace CodeGen {
   class CodeGenFunction;
@@ -41,6 +45,28 @@
 
   CGCXXABI(CodeGenModule &CGM) : CGM(CGM) {}
 
+protected:
+  ImplicitParamDecl *&getThisDecl(CodeGenFunction &CGF) {
+    return CGF.CXXThisDecl;
+  }
+  llvm::Value *&getThisValue(CodeGenFunction &CGF) {
+    return CGF.CXXThisValue;
+  }
+
+  ImplicitParamDecl *&getVTTDecl(CodeGenFunction &CGF) {
+    return CGF.CXXVTTDecl;
+  }
+  llvm::Value *&getVTTValue(CodeGenFunction &CGF) {
+    return CGF.CXXVTTValue;
+  }
+
+  /// Build a parameter variable suitable for 'this'.
+  void BuildThisParam(CodeGenFunction &CGF, FunctionArgList &Params);
+
+  /// Perform prolog initialization of the parameter variable suitable
+  /// for 'this' emitted by BuildThisParam.
+  void EmitThisParam(CodeGenFunction &CGF);
+
 public:
 
   virtual ~CGCXXABI();
@@ -99,6 +125,45 @@
   EmitMemberPointerIsNotNull(CodeGenFunction &CGF,
                              llvm::Value *MemPtr,
                              const MemberPointerType *MPT);
+
+  /// Build the signature of the given constructor variant by adding
+  /// any required parameters.  For convenience, ResTy has been
+  /// initialized to 'void', and ArgTys has been initialized with the
+  /// type of 'this' (although this may be changed by the ABI) and
+  /// will have the formal parameters added to it afterwards.
+  ///
+  /// If there are ever any ABIs where the implicit parameters are
+  /// intermixed with the formal parameters, we can address those
+  /// then.
+  virtual void BuildConstructorSignature(const CXXConstructorDecl *Ctor,
+                                         CXXCtorType T,
+                                         CanQualType &ResTy,
+                               llvm::SmallVectorImpl<CanQualType> &ArgTys) = 0;
+
+  /// Build the signature of the given destructor variant by adding
+  /// any required parameters.  For convenience, ResTy has been
+  /// initialized to 'void' and ArgTys has been initialized with the
+  /// type of 'this' (although this may be changed by the ABI).
+  virtual void BuildDestructorSignature(const CXXDestructorDecl *Dtor,
+                                        CXXDtorType T,
+                                        CanQualType &ResTy,
+                               llvm::SmallVectorImpl<CanQualType> &ArgTys) = 0;
+
+  /// Build the ABI-specific portion of the parameter list for a
+  /// function.  This generally involves a 'this' parameter and
+  /// possibly some extra data for constructors and destructors.
+  ///
+  /// ABIs may also choose to override the return type, which has been
+  /// initialized with the formal return type of the function.
+  virtual void BuildInstanceFunctionParams(CodeGenFunction &CGF,
+                                           QualType &ResTy,
+                                           FunctionArgList &Params) = 0;
+
+  /// Emit the ABI-specific prolog for the function.
+  virtual void EmitInstanceFunctionProlog(CodeGenFunction &CGF) = 0;
+
+  virtual void EmitReturnFromThunk(CodeGenFunction &CGF,
+                                   RValue RV, QualType ResultType);
 };
 
 /// Creates an instance of a C++ ABI class.

Modified: cfe/trunk/lib/CodeGen/CGCall.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCall.cpp?rev=112588&r1=112587&r2=112588&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGCall.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGCall.cpp Tue Aug 31 02:33:07 2010
@@ -13,6 +13,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "CGCall.h"
+#include "CGCXXABI.h"
 #include "ABIInfo.h"
 #include "CodeGenFunction.h"
 #include "CodeGenModule.h"
@@ -126,29 +127,32 @@
 const CGFunctionInfo &CodeGenTypes::getFunctionInfo(const CXXConstructorDecl *D, 
                                                     CXXCtorType Type) {
   llvm::SmallVector<CanQualType, 16> ArgTys;
-
-  // Add the 'this' pointer.
   ArgTys.push_back(GetThisType(Context, D->getParent()));
+  CanQualType ResTy = Context.VoidTy;
 
-  // Check if we need to add a VTT parameter (which has type void **).
-  if (Type == Ctor_Base && D->getParent()->getNumVBases() != 0)
-    ArgTys.push_back(Context.getPointerType(Context.VoidPtrTy));
+  TheCXXABI.BuildConstructorSignature(D, Type, ResTy, ArgTys);
 
-  return ::getFunctionInfo(*this, ArgTys, GetFormalType(D));
+  CanQual<FunctionProtoType> FTP = GetFormalType(D);
+
+  // Add the formal parameters.
+  for (unsigned i = 0, e = FTP->getNumArgs(); i != e; ++i)
+    ArgTys.push_back(FTP->getArgType(i));
+
+  return getFunctionInfo(ResTy, ArgTys, FTP->getExtInfo());
 }
 
 const CGFunctionInfo &CodeGenTypes::getFunctionInfo(const CXXDestructorDecl *D,
                                                     CXXDtorType Type) {
-  llvm::SmallVector<CanQualType, 16> ArgTys;
-  
-  // Add the 'this' pointer.
+  llvm::SmallVector<CanQualType, 2> ArgTys;
   ArgTys.push_back(GetThisType(Context, D->getParent()));
-  
-  // Check if we need to add a VTT parameter (which has type void **).
-  if (Type == Dtor_Base && D->getParent()->getNumVBases() != 0)
-    ArgTys.push_back(Context.getPointerType(Context.VoidPtrTy));
+  CanQualType ResTy = Context.VoidTy;
+
+  TheCXXABI.BuildDestructorSignature(D, Type, ResTy, ArgTys);
 
-  return ::getFunctionInfo(*this, ArgTys, GetFormalType(D));
+  CanQual<FunctionProtoType> FTP = GetFormalType(D);
+  assert(FTP->getNumArgs() == 0 && "dtor with formal parameters");
+
+  return getFunctionInfo(ResTy, ArgTys, FTP->getExtInfo());
 }
 
 const CGFunctionInfo &CodeGenTypes::getFunctionInfo(const FunctionDecl *FD) {
@@ -659,12 +663,18 @@
   return llvm::FunctionType::get(ResultType, ArgTys, IsVariadic);
 }
 
-const llvm::Type *
-CodeGenTypes::GetFunctionTypeForVTable(const CXXMethodDecl *MD) {
+const llvm::Type *CodeGenTypes::GetFunctionTypeForVTable(GlobalDecl GD) {
+  const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
   const FunctionProtoType *FPT = MD->getType()->getAs<FunctionProtoType>();
   
-  if (!VerifyFuncTypeComplete(FPT))
-    return GetFunctionType(getFunctionInfo(MD), FPT->isVariadic(), false);
+  if (!VerifyFuncTypeComplete(FPT)) {
+    const CGFunctionInfo *Info;
+    if (isa<CXXDestructorDecl>(MD))
+      Info = &getFunctionInfo(cast<CXXDestructorDecl>(MD), GD.getDtorType());
+    else
+      Info = &getFunctionInfo(MD);
+    return GetFunctionType(*Info, FPT->isVariadic(), false);
+  }
 
   return llvm::OpaqueType::get(getLLVMContext());
 }

Modified: cfe/trunk/lib/CodeGen/CGDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGDeclCXX.cpp?rev=112588&r1=112587&r2=112588&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGDeclCXX.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGDeclCXX.cpp Tue Aug 31 02:33:07 2010
@@ -12,6 +12,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "CodeGenFunction.h"
+#include "CGCXXABI.h"
 #include "clang/Frontend/CodeGenOptions.h"
 #include "llvm/Intrinsics.h"
 
@@ -350,7 +351,7 @@
   bool ThreadsafeStatics = getContext().getLangOptions().ThreadsafeStatics;
   
   llvm::SmallString<256> GuardVName;
-  CGM.getMangleContext().mangleGuardVariable(&D, GuardVName);
+  CGM.getCXXABI().getMangleContext().mangleGuardVariable(&D, GuardVName);
 
   // Create the guard variable.
   llvm::GlobalVariable *GuardVariable =

Modified: cfe/trunk/lib/CodeGen/CGExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExpr.cpp?rev=112588&r1=112587&r2=112588&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGExpr.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExpr.cpp Tue Aug 31 02:33:07 2010
@@ -14,6 +14,7 @@
 #include "CodeGenFunction.h"
 #include "CodeGenModule.h"
 #include "CGCall.h"
+#include "CGCXXABI.h"
 #include "CGRecordLayout.h"
 #include "CGObjCRuntime.h"
 #include "clang/AST/ASTContext.h"
@@ -160,7 +161,7 @@
   if (const VarDecl *VD = dyn_cast_or_null<VarDecl>(InitializedDecl)) {
     if (VD->hasGlobalStorage()) {
       llvm::SmallString<256> Name;
-      CGF.CGM.getMangleContext().mangleReferenceTemporary(VD, Name);
+      CGF.CGM.getCXXABI().getMangleContext().mangleReferenceTemporary(VD, Name);
       
       const llvm::Type *RefTempTy = CGF.ConvertTypeForMem(Type);
   

Modified: cfe/trunk/lib/CodeGen/CGExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprCXX.cpp?rev=112588&r1=112587&r2=112588&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGExprCXX.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExprCXX.cpp Tue Aug 31 02:33:07 2010
@@ -12,6 +12,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "CodeGenFunction.h"
+#include "CGCXXABI.h"
 #include "CGObjCRuntime.h"
 #include "llvm/Intrinsics.h"
 using namespace clang;

Modified: cfe/trunk/lib/CodeGen/CGExprConstant.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprConstant.cpp?rev=112588&r1=112587&r2=112588&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGExprConstant.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExprConstant.cpp Tue Aug 31 02:33:07 2010
@@ -13,6 +13,7 @@
 
 #include "CodeGenFunction.h"
 #include "CodeGenModule.h"
+#include "CGCXXABI.h"
 #include "CGObjCRuntime.h"
 #include "CGRecordLayout.h"
 #include "clang/AST/APValue.h"

Modified: cfe/trunk/lib/CodeGen/CGExprScalar.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprScalar.cpp?rev=112588&r1=112587&r2=112588&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGExprScalar.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExprScalar.cpp Tue Aug 31 02:33:07 2010
@@ -12,6 +12,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "CodeGenFunction.h"
+#include "CGCXXABI.h"
 #include "CGObjCRuntime.h"
 #include "CodeGenModule.h"
 #include "clang/AST/ASTContext.h"

Modified: cfe/trunk/lib/CodeGen/CGRTTI.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGRTTI.cpp?rev=112588&r1=112587&r2=112588&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGRTTI.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGRTTI.cpp Tue Aug 31 02:33:07 2010
@@ -12,6 +12,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "CodeGenModule.h"
+#include "CGCXXABI.h"
 #include "clang/AST/RecordLayout.h"
 #include "clang/AST/Type.h"
 #include "clang/Frontend/CodeGenOptions.h"
@@ -65,7 +66,7 @@
   llvm::Constant *BuildName(QualType Ty, bool Hidden, 
                             llvm::GlobalVariable::LinkageTypes Linkage) {
     llvm::SmallString<256> OutName;
-    CGM.getMangleContext().mangleCXXRTTIName(Ty, OutName);
+    CGM.getCXXABI().getMangleContext().mangleCXXRTTIName(Ty, OutName);
     llvm::StringRef Name = OutName.str();
 
     llvm::GlobalVariable *OGV = CGM.getModule().getNamedGlobal(Name);
@@ -164,7 +165,7 @@
 llvm::Constant *RTTIBuilder::GetAddrOfExternalRTTIDescriptor(QualType Ty) {
   // Mangle the RTTI name.
   llvm::SmallString<256> OutName;
-  CGM.getMangleContext().mangleCXXRTTI(Ty, OutName);
+  CGM.getCXXABI().getMangleContext().mangleCXXRTTI(Ty, OutName);
   llvm::StringRef Name = OutName.str();
 
   // Look for an existing global.
@@ -518,7 +519,7 @@
 
   // Check if we've already emitted an RTTI descriptor for this type.
   llvm::SmallString<256> OutName;
-  CGM.getMangleContext().mangleCXXRTTI(Ty, OutName);
+  CGM.getCXXABI().getMangleContext().mangleCXXRTTI(Ty, OutName);
   llvm::StringRef Name = OutName.str();
   
   llvm::GlobalVariable *OldGV = CGM.getModule().getNamedGlobal(Name);

Modified: cfe/trunk/lib/CodeGen/CGVTT.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGVTT.cpp?rev=112588&r1=112587&r2=112588&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGVTT.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGVTT.cpp Tue Aug 31 02:33:07 2010
@@ -12,6 +12,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "CodeGenModule.h"
+#include "CGCXXABI.h"
 #include "clang/AST/RecordLayout.h"
 using namespace clang;
 using namespace CodeGen;
@@ -373,7 +374,7 @@
     return 0;
 
   llvm::SmallString<256> OutName;
-  CGM.getMangleContext().mangleCXXVTT(RD, OutName);
+  CGM.getCXXABI().getMangleContext().mangleCXXVTT(RD, OutName);
   llvm::StringRef Name = OutName.str();
 
   D1(printf("vtt %s\n", RD->getNameAsCString()));

Modified: cfe/trunk/lib/CodeGen/CGVTables.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGVTables.cpp?rev=112588&r1=112587&r2=112588&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGVTables.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGVTables.cpp Tue Aug 31 02:33:07 2010
@@ -13,6 +13,7 @@
 
 #include "CodeGenModule.h"
 #include "CodeGenFunction.h"
+#include "CGCXXABI.h"
 #include "clang/AST/CXXInheritance.h"
 #include "clang/AST/RecordLayout.h"
 #include "clang/Frontend/CodeGenOptions.h"
@@ -2409,12 +2410,12 @@
   // Compute the mangled name.
   llvm::SmallString<256> Name;
   if (const CXXDestructorDecl* DD = dyn_cast<CXXDestructorDecl>(MD))
-    getMangleContext().mangleCXXDtorThunk(DD, GD.getDtorType(), Thunk.This,
-                                          Name);
+    getCXXABI().getMangleContext().mangleCXXDtorThunk(DD, GD.getDtorType(),
+                                                      Thunk.This, Name);
   else
-    getMangleContext().mangleThunk(MD, Thunk, Name);
+    getCXXABI().getMangleContext().mangleThunk(MD, Thunk, Name);
   
-  const llvm::Type *Ty = getTypes().GetFunctionTypeForVTable(MD);
+  const llvm::Type *Ty = getTypes().GetFunctionTypeForVTable(GD);
   return GetOrCreateLLVMFunction(Name, Ty, GD);
 }
 
@@ -2522,13 +2523,8 @@
   // CodeGenFunction::GenerateCode.
 
   // Create the implicit 'this' parameter declaration.
-  CXXThisDecl = ImplicitParamDecl::Create(getContext(), 0,
-                                          MD->getLocation(),
-                                          &getContext().Idents.get("this"),
-                                          ThisType);
-
-  // Add the 'this' parameter.
-  FunctionArgs.push_back(std::make_pair(CXXThisDecl, CXXThisDecl->getType()));
+  CurGD = GD;
+  CGM.getCXXABI().BuildInstanceFunctionParams(*this, ResultType, FunctionArgs);
 
   // Add the rest of the parameters.
   for (FunctionDecl::param_const_iterator I = MD->param_begin(),
@@ -2540,6 +2536,8 @@
   
   StartFunction(GlobalDecl(), ResultType, Fn, FunctionArgs, SourceLocation());
 
+  CGM.getCXXABI().EmitInstanceFunctionProlog(*this);
+
   // Adjust the 'this' pointer if necessary.
   llvm::Value *AdjustedThisPtr = 
     PerformTypeAdjustment(*this, LoadCXXThis(), 
@@ -2563,7 +2561,7 @@
 
   // Get our callee.
   const llvm::Type *Ty =
-    CGM.getTypes().GetFunctionType(CGM.getTypes().getFunctionInfo(MD),
+    CGM.getTypes().GetFunctionType(CGM.getTypes().getFunctionInfo(GD),
                                    FPT->isVariadic());
   llvm::Value *Callee = CGM.GetAddrOfFunction(GD, Ty);
 
@@ -2623,7 +2621,7 @@
   }
 
   if (!ResultType->isVoidType() && Slot.isNull())
-    EmitReturnOfRValue(RV, ResultType);
+    CGM.getCXXABI().EmitReturnFromThunk(CGF, RV, ResultType);
 
   FinishFunction();
 
@@ -2637,7 +2635,6 @@
 void CodeGenVTables::EmitThunk(GlobalDecl GD, const ThunkInfo &Thunk)
 {
   llvm::Constant *Entry = CGM.GetAddrOfThunk(GD, Thunk);
-  const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
   
   // Strip off a bitcast if we got one back.
   if (llvm::ConstantExpr *CE = dyn_cast<llvm::ConstantExpr>(Entry)) {
@@ -2648,7 +2645,7 @@
   // There's already a declaration with the same name, check if it has the same
   // type or if we need to replace it.
   if (cast<llvm::GlobalValue>(Entry)->getType()->getElementType() != 
-      CGM.getTypes().GetFunctionTypeForVTable(MD)) {
+      CGM.getTypes().GetFunctionTypeForVTable(GD)) {
     llvm::GlobalValue *OldThunkFn = cast<llvm::GlobalValue>(Entry);
     
     // If the types mismatch then we have to rewrite the definition.
@@ -2867,8 +2864,7 @@
         
           NextVTableThunkIndex++;
         } else {
-          const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
-          const llvm::Type *Ty = CGM.getTypes().GetFunctionTypeForVTable(MD);
+          const llvm::Type *Ty = CGM.getTypes().GetFunctionTypeForVTable(GD);
         
           Init = CGM.GetAddrOfFunction(GD, Ty);
         }
@@ -2935,7 +2931,7 @@
 
 llvm::GlobalVariable *CodeGenVTables::GetAddrOfVTable(const CXXRecordDecl *RD) {
   llvm::SmallString<256> OutName;
-  CGM.getMangleContext().mangleCXXVTable(RD, OutName);
+  CGM.getCXXABI().getMangleContext().mangleCXXVTable(RD, OutName);
   llvm::StringRef Name = OutName.str();
 
   ComputeVTableRelatedInformation(RD, true);
@@ -2995,8 +2991,8 @@
 
   // Get the mangled construction vtable name.
   llvm::SmallString<256> OutName;
-  CGM.getMangleContext().mangleCXXCtorVTable(RD, Base.getBaseOffset() / 8, 
-                                             Base.getBase(), OutName);
+  CGM.getCXXABI().getMangleContext().
+    mangleCXXCtorVTable(RD, Base.getBaseOffset() / 8, Base.getBase(), OutName);
   llvm::StringRef Name = OutName.str();
 
   const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(CGM.getLLVMContext());

Modified: cfe/trunk/lib/CodeGen/CodeGenFunction.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.cpp?rev=112588&r1=112587&r2=112588&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenFunction.cpp (original)
+++ cfe/trunk/lib/CodeGen/CodeGenFunction.cpp Tue Aug 31 02:33:07 2010
@@ -13,6 +13,7 @@
 
 #include "CodeGenFunction.h"
 #include "CodeGenModule.h"
+#include "CGCXXABI.h"
 #include "CGDebugInfo.h"
 #include "CGException.h"
 #include "clang/Basic/TargetInfo.h"
@@ -48,7 +49,7 @@
       
   Exceptions = getContext().getLangOptions().Exceptions;
   CatchUndefined = getContext().getLangOptions().CatchUndefined;
-  CGM.getMangleContext().startNewFunction();
+  CGM.getCXXABI().getMangleContext().startNewFunction();
 }
 
 ASTContext &CodeGenFunction::getContext() const {
@@ -56,17 +57,6 @@
 }
 
 
-llvm::Value *CodeGenFunction::GetAddrOfLocalVar(const VarDecl *VD) {
-  llvm::Value *Res = LocalDeclMap[VD];
-  assert(Res && "Invalid argument to GetAddrOfLocalVar(), no decl!");
-  return Res;
-}
-
-llvm::Constant *
-CodeGenFunction::GetAddrOfStaticLocalVar(const VarDecl *BVD) {
-  return cast<llvm::Constant>(GetAddrOfLocalVar(BVD));
-}
-
 const llvm::Type *CodeGenFunction::ConvertTypeForMem(QualType T) {
   return CGM.getTypes().ConvertTypeForMem(T);
 }
@@ -289,10 +279,8 @@
   EmitStartEHSpec(CurCodeDecl);
   EmitFunctionProlog(*CurFnInfo, CurFn, Args);
 
-  if (CXXThisDecl)
-    CXXThisValue = Builder.CreateLoad(LocalDeclMap[CXXThisDecl], "this");
-  if (CXXVTTDecl)
-    CXXVTTValue = Builder.CreateLoad(LocalDeclMap[CXXVTTDecl], "vtt");
+  if (D && isa<CXXMethodDecl>(D) && cast<CXXMethodDecl>(D)->isInstance())
+    CGM.getCXXABI().EmitInstanceFunctionProlog(*this);
 
   // If any of the arguments have a variably modified type, make sure to
   // emit the type size.
@@ -336,30 +324,11 @@
     DebugInfo = CGM.getDebugInfo();
 
   FunctionArgList Args;
+  QualType ResTy = FD->getResultType();
 
   CurGD = GD;
-  if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD)) {
-    if (MD->isInstance()) {
-      // Create the implicit 'this' decl.
-      // FIXME: I'm not entirely sure I like using a fake decl just for code
-      // generation. Maybe we can come up with a better way?
-      CXXThisDecl = ImplicitParamDecl::Create(getContext(), 0,
-                                              FD->getLocation(),
-                                              &getContext().Idents.get("this"),
-                                              MD->getThisType(getContext()));
-      Args.push_back(std::make_pair(CXXThisDecl, CXXThisDecl->getType()));
-      
-      // Check if we need a VTT parameter as well.
-      if (CodeGenVTables::needsVTTParameter(GD)) {
-        // FIXME: The comment about using a fake decl above applies here too.
-        QualType T = getContext().getPointerType(getContext().VoidPtrTy);
-        CXXVTTDecl = 
-          ImplicitParamDecl::Create(getContext(), 0, FD->getLocation(),
-                                    &getContext().Idents.get("vtt"), T);
-        Args.push_back(std::make_pair(CXXVTTDecl, CXXVTTDecl->getType()));
-      }
-    }
-  }
+  if (isa<CXXMethodDecl>(FD) && cast<CXXMethodDecl>(FD)->isInstance())
+    CGM.getCXXABI().BuildInstanceFunctionParams(*this, ResTy, Args);
 
   if (FD->getNumParams()) {
     const FunctionProtoType* FProto = FD->getType()->getAs<FunctionProtoType>();
@@ -374,7 +343,7 @@
   if (Stmt *Body = FD->getBody()) BodyRange = Body->getSourceRange();
 
   // Emit the standard function prologue.
-  StartFunction(GD, FD->getResultType(), Fn, Args, BodyRange.getBegin());
+  StartFunction(GD, ResTy, Fn, Args, BodyRange.getBegin());
 
   // Generate the body of the function.
   if (isa<CXXDestructorDecl>(FD))

Modified: cfe/trunk/lib/CodeGen/CodeGenFunction.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.h?rev=112588&r1=112587&r2=112588&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenFunction.h (original)
+++ cfe/trunk/lib/CodeGen/CodeGenFunction.h Tue Aug 31 02:33:07 2010
@@ -70,6 +70,7 @@
   class CGFunctionInfo;
   class CGRecordLayout;
   class CGBlockInfo;
+  class CGCXXABI;
 
 /// A branch fixup.  These are required when emitting a goto to a
 /// label which hasn't been emitted yet.  The goto is optimistically
@@ -406,6 +407,8 @@
 class CodeGenFunction : public BlockFunction {
   CodeGenFunction(const CodeGenFunction&); // DO NOT IMPLEMENT
   void operator=(const CodeGenFunction&);  // DO NOT IMPLEMENT
+
+  friend class CGCXXABI;
 public:
   /// A jump destination is an abstract label, branching to which may
   /// require a jump out through normal cleanups.
@@ -1034,10 +1037,16 @@
   void StartBlock(const char *N);
 
   /// GetAddrOfStaticLocalVar - Return the address of a static local variable.
-  llvm::Constant *GetAddrOfStaticLocalVar(const VarDecl *BVD);
+  llvm::Constant *GetAddrOfStaticLocalVar(const VarDecl *BVD) {
+    return cast<llvm::Constant>(GetAddrOfLocalVar(BVD));
+  }
 
   /// GetAddrOfLocalVar - Return the address of a local variable.
-  llvm::Value *GetAddrOfLocalVar(const VarDecl *VD);
+  llvm::Value *GetAddrOfLocalVar(const VarDecl *VD) {
+    llvm::Value *Res = LocalDeclMap[VD];
+    assert(Res && "Invalid argument to GetAddrOfLocalVar(), no decl!");
+    return Res;
+  }
 
   /// getAccessedFieldNo - Given an encoded value and a result number, return
   /// the input field number being accessed.

Modified: cfe/trunk/lib/CodeGen/CodeGenModule.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.cpp?rev=112588&r1=112587&r2=112588&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenModule.cpp (original)
+++ cfe/trunk/lib/CodeGen/CodeGenModule.cpp Tue Aug 31 02:33:07 2010
@@ -15,6 +15,7 @@
 #include "CGDebugInfo.h"
 #include "CodeGenFunction.h"
 #include "CGCall.h"
+#include "CGCXXABI.h"
 #include "CGObjCRuntime.h"
 #include "Mangle.h"
 #include "TargetInfo.h"
@@ -287,7 +288,7 @@
   if (!Str.empty())
     return Str;
 
-  if (!getMangleContext().shouldMangleDeclName(ND)) {
+  if (!getCXXABI().getMangleContext().shouldMangleDeclName(ND)) {
     IdentifierInfo *II = ND->getIdentifier();
     assert(II && "Attempt to mangle unnamed decl.");
 
@@ -297,13 +298,13 @@
   
   llvm::SmallString<256> Buffer;
   if (const CXXConstructorDecl *D = dyn_cast<CXXConstructorDecl>(ND))
-    getMangleContext().mangleCXXCtor(D, GD.getCtorType(), Buffer);
+    getCXXABI().getMangleContext().mangleCXXCtor(D, GD.getCtorType(), Buffer);
   else if (const CXXDestructorDecl *D = dyn_cast<CXXDestructorDecl>(ND))
-    getMangleContext().mangleCXXDtor(D, GD.getDtorType(), Buffer);
+    getCXXABI().getMangleContext().mangleCXXDtor(D, GD.getDtorType(), Buffer);
   else if (const BlockDecl *BD = dyn_cast<BlockDecl>(ND))
-    getMangleContext().mangleBlock(GD, BD, Buffer);
+    getCXXABI().getMangleContext().mangleBlock(GD, BD, Buffer);
   else
-    getMangleContext().mangleName(ND, Buffer);
+    getCXXABI().getMangleContext().mangleName(ND, Buffer);
 
   // Allocate space for the mangled name.
   size_t Length = Buffer.size();
@@ -317,7 +318,7 @@
 
 void CodeGenModule::getMangledName(GlobalDecl GD, MangleBuffer &Buffer,
                                    const BlockDecl *BD) {
-  getMangleContext().mangleBlock(GD, BD, Buffer.getBuffer());
+  getCXXABI().getMangleContext().mangleBlock(GD, BD, Buffer.getBuffer());
 }
 
 llvm::GlobalValue *CodeGenModule::GetGlobalValue(llvm::StringRef Name) {
@@ -1294,7 +1295,7 @@
 void CodeGenModule::EmitGlobalFunctionDefinition(GlobalDecl GD) {
   const FunctionDecl *D = cast<FunctionDecl>(GD.getDecl());
   const llvm::FunctionType *Ty = getTypes().GetFunctionType(GD);
-  getMangleContext().mangleInitDiscriminator();
+  getCXXABI().getMangleContext().mangleInitDiscriminator();
   // Get or create the prototype for the function.
   llvm::Constant *Entry = GetAddrOfFunction(GD, Ty);
 

Modified: cfe/trunk/lib/CodeGen/CodeGenModule.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.h?rev=112588&r1=112587&r2=112588&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenModule.h (original)
+++ cfe/trunk/lib/CodeGen/CodeGenModule.h Tue Aug 31 02:33:07 2010
@@ -22,7 +22,6 @@
 #include "CGCall.h"
 #include "CGCXX.h"
 #include "CGVTables.h"
-#include "CGCXXABI.h"
 #include "CodeGenTypes.h"
 #include "GlobalDecl.h"
 #include "Mangle.h"
@@ -71,6 +70,7 @@
 namespace CodeGen {
 
   class CodeGenFunction;
+  class CGCXXABI;
   class CGDebugInfo;
   class CGObjCRuntime;
   class MangleBuffer;
@@ -243,9 +243,6 @@
   const LangOptions &getLangOptions() const { return Features; }
   llvm::Module &getModule() const { return TheModule; }
   CodeGenTypes &getTypes() { return Types; }
-  MangleContext &getMangleContext() {
-    return ABI.getMangleContext();
-  }
   CodeGenVTables &getVTables() { return VTables; }
   Diagnostic &getDiags() const { return Diags; }
   const llvm::TargetData &getTargetData() const { return TheTargetData; }

Modified: cfe/trunk/lib/CodeGen/CodeGenTypes.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenTypes.h?rev=112588&r1=112587&r2=112588&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenTypes.h (original)
+++ cfe/trunk/lib/CodeGen/CodeGenTypes.h Tue Aug 31 02:33:07 2010
@@ -141,7 +141,7 @@
   /// GetFunctionTypeForVTable - Get the LLVM function type for use in a vtable,
   /// given a CXXMethodDecl. If the method to has an incomplete return type, 
   /// and/or incomplete argument types, this will return the opaque type.
-  const llvm::Type *GetFunctionTypeForVTable(const CXXMethodDecl *MD);
+  const llvm::Type *GetFunctionTypeForVTable(GlobalDecl GD);
                                                      
   const CGRecordLayout &getCGRecordLayout(const RecordDecl*) const;
 
@@ -171,7 +171,9 @@
   const CGFunctionInfo &getFunctionInfo(CanQual<FunctionNoProtoType> Ty,
                                         bool IsRecursive = false);
 
-  // getFunctionInfo - Get the function info for a member function.
+  /// getFunctionInfo - Get the function info for a member function of
+  /// the given type.  This is used for calls through member function
+  /// pointers.
   const CGFunctionInfo &getFunctionInfo(const CXXRecordDecl *RD,
                                         const FunctionProtoType *FTP);
   

Modified: cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp?rev=112588&r1=112587&r2=112588&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp (original)
+++ cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp Tue Aug 31 02:33:07 2010
@@ -87,11 +87,55 @@
   llvm::Value *EmitMemberPointerIsNotNull(CodeGenFunction &CGF,
                                           llvm::Value *Addr,
                                           const MemberPointerType *MPT);
+
+  void BuildConstructorSignature(const CXXConstructorDecl *Ctor,
+                                 CXXCtorType T,
+                                 CanQualType &ResTy,
+                                 llvm::SmallVectorImpl<CanQualType> &ArgTys);
+
+  void BuildDestructorSignature(const CXXDestructorDecl *Dtor,
+                                CXXDtorType T,
+                                CanQualType &ResTy,
+                                llvm::SmallVectorImpl<CanQualType> &ArgTys);
+
+  void BuildInstanceFunctionParams(CodeGenFunction &CGF,
+                                   QualType &ResTy,
+                                   FunctionArgList &Params);
+
+  void EmitInstanceFunctionProlog(CodeGenFunction &CGF);
 };
 
 class ARMCXXABI : public ItaniumCXXABI {
 public:
   ARMCXXABI(CodeGen::CodeGenModule &CGM) : ItaniumCXXABI(CGM, /*ARM*/ true) {}
+
+  void BuildConstructorSignature(const CXXConstructorDecl *Ctor,
+                                 CXXCtorType T,
+                                 CanQualType &ResTy,
+                                 llvm::SmallVectorImpl<CanQualType> &ArgTys);
+
+  void BuildDestructorSignature(const CXXDestructorDecl *Dtor,
+                                CXXDtorType T,
+                                CanQualType &ResTy,
+                                llvm::SmallVectorImpl<CanQualType> &ArgTys);
+
+  void BuildInstanceFunctionParams(CodeGenFunction &CGF,
+                                   QualType &ResTy,
+                                   FunctionArgList &Params);
+
+  void EmitInstanceFunctionProlog(CodeGenFunction &CGF);
+
+  void EmitReturnFromThunk(CodeGenFunction &CGF, RValue RV, QualType ResTy);
+
+
+private:
+  /// \brief Returns true if the given instance method is one of the
+  /// kinds that the ARM ABI says returns 'this'.
+  static bool HasThisReturn(GlobalDecl GD) {
+    const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
+    return ((isa<CXXDestructorDecl>(MD) && GD.getDtorType() != Dtor_Deleting) ||
+            (isa<CXXConstructorDecl>(MD)));
+  }
 };
 }
 
@@ -586,3 +630,120 @@
 bool ItaniumCXXABI::isZeroInitializable(const MemberPointerType *MPT) {
   return MPT->getPointeeType()->isFunctionType();
 }
+
+/// The generic ABI passes 'this', plus a VTT if it's initializing a
+/// base subobject.
+void ItaniumCXXABI::BuildConstructorSignature(const CXXConstructorDecl *Ctor,
+                                              CXXCtorType Type,
+                                              CanQualType &ResTy,
+                                llvm::SmallVectorImpl<CanQualType> &ArgTys) {
+  ASTContext &Context = CGM.getContext();
+
+  // 'this' is already there.
+
+  // Check if we need to add a VTT parameter (which has type void **).
+  if (Type == Ctor_Base && Ctor->getParent()->getNumVBases() != 0)
+    ArgTys.push_back(Context.getPointerType(Context.VoidPtrTy));
+}
+
+/// The ARM ABI does the same as the Itanium ABI, but returns 'this'.
+void ARMCXXABI::BuildConstructorSignature(const CXXConstructorDecl *Ctor,
+                                          CXXCtorType Type,
+                                          CanQualType &ResTy,
+                                llvm::SmallVectorImpl<CanQualType> &ArgTys) {
+  ItaniumCXXABI::BuildConstructorSignature(Ctor, Type, ResTy, ArgTys);
+  ResTy = ArgTys[0];
+}
+
+/// The generic ABI passes 'this', plus a VTT if it's destroying a
+/// base subobject.
+void ItaniumCXXABI::BuildDestructorSignature(const CXXDestructorDecl *Dtor,
+                                             CXXDtorType Type,
+                                             CanQualType &ResTy,
+                                llvm::SmallVectorImpl<CanQualType> &ArgTys) {
+  ASTContext &Context = CGM.getContext();
+
+  // 'this' is already there.
+
+  // Check if we need to add a VTT parameter (which has type void **).
+  if (Type == Dtor_Base && Dtor->getParent()->getNumVBases() != 0)
+    ArgTys.push_back(Context.getPointerType(Context.VoidPtrTy));
+}
+
+/// The ARM ABI does the same as the Itanium ABI, but returns 'this'
+/// for non-deleting destructors.
+void ARMCXXABI::BuildDestructorSignature(const CXXDestructorDecl *Dtor,
+                                         CXXDtorType Type,
+                                         CanQualType &ResTy,
+                                llvm::SmallVectorImpl<CanQualType> &ArgTys) {
+  ItaniumCXXABI::BuildDestructorSignature(Dtor, Type, ResTy, ArgTys);
+
+  if (Type != Dtor_Deleting)
+    ResTy = ArgTys[0];
+}
+
+void ItaniumCXXABI::BuildInstanceFunctionParams(CodeGenFunction &CGF,
+                                                QualType &ResTy,
+                                                FunctionArgList &Params) {
+  /// Create the 'this' variable.
+  BuildThisParam(CGF, Params);
+
+  const CXXMethodDecl *MD = cast<CXXMethodDecl>(CGF.CurGD.getDecl());
+  assert(MD->isInstance());
+
+  // Check if we need a VTT parameter as well.
+  if (CodeGenVTables::needsVTTParameter(CGF.CurGD)) {
+    ASTContext &Context = CGF.getContext();
+
+    // FIXME: avoid the fake decl
+    QualType T = Context.getPointerType(Context.VoidPtrTy);
+    ImplicitParamDecl *VTTDecl
+      = ImplicitParamDecl::Create(Context, 0, MD->getLocation(),
+                                  &Context.Idents.get("vtt"), T);
+    Params.push_back(std::make_pair(VTTDecl, VTTDecl->getType()));
+    getVTTDecl(CGF) = VTTDecl;
+  }
+}
+
+void ARMCXXABI::BuildInstanceFunctionParams(CodeGenFunction &CGF,
+                                            QualType &ResTy,
+                                            FunctionArgList &Params) {
+  ItaniumCXXABI::BuildInstanceFunctionParams(CGF, ResTy, Params);
+
+  // Return 'this' from certain constructors and destructors.
+  if (HasThisReturn(CGF.CurGD))
+    ResTy = Params[0].second;
+}
+
+void ItaniumCXXABI::EmitInstanceFunctionProlog(CodeGenFunction &CGF) {
+  /// Initialize the 'this' slot.
+  EmitThisParam(CGF);
+
+  /// Initialize the 'vtt' slot if needed.
+  if (getVTTDecl(CGF)) {
+    getVTTValue(CGF)
+      = CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(getVTTDecl(CGF)),
+                               "vtt");
+  }
+}
+
+void ARMCXXABI::EmitInstanceFunctionProlog(CodeGenFunction &CGF) {
+  ItaniumCXXABI::EmitInstanceFunctionProlog(CGF);
+
+  /// Initialize the return slot to 'this' at the start of the
+  /// function.
+  if (HasThisReturn(CGF.CurGD))
+    CGF.Builder.CreateStore(CGF.LoadCXXThis(), CGF.ReturnValue);
+}
+
+void ARMCXXABI::EmitReturnFromThunk(CodeGenFunction &CGF,
+                                    RValue RV, QualType ResultType) {
+  if (!isa<CXXDestructorDecl>(CGF.CurGD.getDecl()))
+    return ItaniumCXXABI::EmitReturnFromThunk(CGF, RV, ResultType);
+
+  // Destructor thunks in the ARM ABI have indeterminate results.
+  const llvm::Type *T =
+    cast<llvm::PointerType>(CGF.ReturnValue->getType())->getElementType();
+  RValue Undef = RValue::get(llvm::UndefValue::get(T));
+  return ItaniumCXXABI::EmitReturnFromThunk(CGF, Undef, ResultType);
+}

Modified: cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp?rev=112588&r1=112587&r2=112588&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp (original)
+++ cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp Tue Aug 31 02:33:07 2010
@@ -117,6 +117,34 @@
   MicrosoftMangleContext &getMangleContext() {
     return MangleCtx;
   }
+
+  void BuildConstructorSignature(const CXXConstructorDecl *Ctor,
+                                 CXXCtorType Type,
+                                 CanQualType &ResTy,
+                                 llvm::SmallVectorImpl<CanQualType> &ArgTys) {
+    // 'this' is already in place
+    // TODO: 'for base' flag
+  }  
+
+  void BuildDestructorSignature(const CXXDestructorDecl *Ctor,
+                                CXXDtorType Type,
+                                CanQualType &ResTy,
+                                llvm::SmallVectorImpl<CanQualType> &ArgTys) {
+    // 'this' is already in place
+    // TODO: 'for base' flag
+  }
+
+  void BuildInstanceFunctionParams(CodeGenFunction &CGF,
+                                   QualType &ResTy,
+                                   FunctionArgList &Params) {
+    BuildThisParam(CGF, Params);
+    // TODO: 'for base' flag
+  }
+
+  void EmitInstanceFunctionProlog(CodeGenFunction &CGF) {
+    EmitThisParam(CGF);
+    // TODO: 'for base' flag
+  }
 };
 
 }

Modified: cfe/trunk/test/CodeGenCXX/arm.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/arm.cpp?rev=112588&r1=112587&r2=112588&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/arm.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/arm.cpp Tue Aug 31 02:33:07 2010
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 %s -triple=thumbv7-apple-darwin3.0.0-iphoneos -fno-use-cxa-atexit -target-abi apcs-gnu -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 %s -triple=thumbv7-apple-darwin3.0.0-iphoneos -fno-use-cxa-atexit -target-abi apcs-gnu -emit-llvm -o - -fexceptions | FileCheck %s
 
 class foo {
 public:
@@ -13,7 +13,89 @@
 
 // The global dtor needs the right calling conv with -fno-use-cxa-atexit
 // rdar://7817590
+// Checked at end of file.
 bar baz;
 
+// Destructors and constructors must return this.
+namespace test1 {
+  void foo();
+
+  struct A {
+    A(int i) { foo(); }
+    ~A() { foo(); }
+    void bar() { foo(); }
+  };
+
+  // CHECK: define void @_ZN5test14testEv()
+  void test() {
+    // CHECK: [[AV:%.*]] = alloca [[A:%.*]], align 1
+    // CHECK: call [[A]]* @_ZN5test11AC1Ei([[A]]* [[AV]], i32 10)
+    // CHECK: invoke void @_ZN5test11A3barEv([[A]]* [[AV]])
+    // CHECK: call [[A]]* @_ZN5test11AD1Ev([[A]]* [[AV]])
+    // CHECK: ret void
+    A a = 10;
+    a.bar();
+  }
+
+  // CHECK: define linkonce_odr [[A]]* @_ZN5test11AC1Ei([[A]]*
+  // CHECK:   [[RET:%.*]] = alloca [[A]]*, align 4
+  // CHECK:   [[THIS:%.*]] = alloca [[A]]*, align 4
+  // CHECK:   store [[A]]* {{.*}}, [[A]]** [[THIS]]
+  // CHECK:   [[THIS1:%.*]] = load [[A]]** [[THIS]]
+  // CHECK:   store [[A]]* [[THIS1]], [[A]]** [[RET]]
+  // CHECK:   call [[A]]* @_ZN5test11AC2Ei(
+  // CHECK:   [[THIS2:%.*]] = load [[A]]** [[RET]]
+  // CHECK:   ret [[A]]* [[THIS2]]
+
+  // CHECK: define linkonce_odr [[A]]* @_ZN5test11AD1Ev([[A]]*
+  // CHECK:   [[RET:%.*]] = alloca [[A]]*, align 4
+  // CHECK:   [[THIS:%.*]] = alloca [[A]]*, align 4
+  // CHECK:   store [[A]]* {{.*}}, [[A]]** [[THIS]]
+  // CHECK:   [[THIS1:%.*]] = load [[A]]** [[THIS]]
+  // CHECK:   store [[A]]* [[THIS1]], [[A]]** [[RET]]
+  // CHECK:   call [[A]]* @_ZN5test11AD2Ev(
+  // CHECK:   [[THIS2:%.*]] = load [[A]]** [[RET]]
+  // CHECK:   ret [[A]]* [[THIS2]]
+}
+
+// Awkward virtual cases.
+namespace test2 {
+  void foo();
+
+  struct A {
+    int x;
+
+    A(int);
+    virtual ~A() { foo(); }
+  };
+
+  struct B {
+    int y;
+    int z;
+
+    B(int);
+    virtual ~B() { foo(); }
+  };
+
+  struct C : A, virtual B {
+    int q;
+
+    C(int i) : A(i), B(i) { foo(); }
+    ~C() { foo(); }
+  };
+
+  void test() {
+    C c = 10;
+  }
+
+  // CHECK: define linkonce_odr [[C:%.*]]* @_ZTv0_n12_N5test21CD1Ev(
+  // CHECK:   call [[C]]* @_ZN5test21CD1Ev(
+  // CHECK:   ret [[C]]* undef
+
+  // CHECK: define linkonce_odr void @_ZTv0_n12_N5test21CD0Ev(
+  // CHECK:   call void @_ZN5test21CD0Ev(
+  // CHECK:   ret void
+}
+
 // CHECK: @_GLOBAL__D_a()
-// CHECK: call void @_ZN3barD1Ev(%class.bar* @baz)
+// CHECK: call %class.bar* @_ZN3barD1Ev(%class.bar* @baz)





More information about the cfe-commits mailing list